Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ apikit-tools/apikit-studio-plugin/org.mule.tooling.apikit.deps/lib/
apikit-tools/apikit-studio-plugin/org.mule.tooling.apikit/examples/
build.log
.mule
.codegenie
.vscode/
mule-apikit-module/logs/
13 changes: 11 additions & 2 deletions build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ enableAllureTestReportStage: false
mavenSettingsXmlId: ab7820eb-e393-4e88-9962-92104044ed75
projectType: extension
additionalTestConfigs:
testsJava17:
jdk17-4.9.x:
testJdkTool: OPEN-JDK17
mavenAdditionalArgs: -DruntimeProduct=MULE_EE -DruntimeVersion=4.6.0
mavenAdditionalArgs: -DruntimeVersion=4.9.7-rc2 -DruntimeProduct=MULE_EE
jdk17-4.8.x:
testJdkTool: OPEN-JDK17
mavenAdditionalArgs: -DruntimeVersion=4.8.5 -DruntimeProduct=MULE_EE
jdk17-4.7.x:
testJdkTool: OPEN-JDK17
mavenAdditionalArgs: -DruntimeVersion=4.7.4 -DruntimeProduct=MULE_EE
jdk17-4.6.x:
testJdkTool: OPEN-JDK17
mavenAdditionalArgs: -DruntimeVersion=4.6.16 -DruntimeProduct=MULE_EE
17 changes: 12 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<testExtensionModelLoaderId>crafted</testExtensionModelLoaderId>

<mule.api.version>1.1.5</mule.api.version>
<mule.http.connector.version>1.9.0</mule.http.connector.version>
<mule.http.connector.version>1.10.3</mule.http.connector.version>
<mule.metadata.model.version>1.1.6</mule.metadata.model.version>

<mule.service.weave.version>2.1.8</mule.service.weave.version>
Expand All @@ -35,19 +35,20 @@
<commons.io.version>2.15.1</commons.io.version>
<commons.collections4.version>4.4</commons.collections4.version>
<log4j.version>2.17.1</log4j.version>
<sdk-api.version>0.7.5</sdk-api.version>

<!-- PARSERS -->
<parser.service.version>2.7.9</parser.service.version>
<parser.service.version>3.0.0-SNAPSHOT</parser.service.version>

<!-- API Console -->
<apiconsole.version>6.6.73</apiconsole.version>

<!-- TESTING -->
<munit.input.directory>src/test/munit</munit.input.directory>
<munit.output.directory>${basedir}/target/test-mule/munit</munit.output.directory>
<munit.extensions.maven.plugin.version>1.2.0</munit.extensions.maven.plugin.version>
<munit.version>3.1.0</munit.version>
<munit.tools.version>3.1.0</munit.tools.version>
<munit.extensions.maven.plugin.version>1.5.0</munit.extensions.maven.plugin.version>
<munit.version>3.4.0</munit.version>
<munit.tools.version>3.3.2</munit.tools.version>
<mavenResourcesVersion>3.0.2</mavenResourcesVersion>
<mockServerVersion>5.8.0</mockServerVersion>
<jacoco.version>0.8.10</jacoco.version>
Expand Down Expand Up @@ -116,6 +117,12 @@
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mule.sdk</groupId>
<artifactId>mule-sdk-api</artifactId>
<version>${sdk-api.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.mule.apikit</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
*/
public enum ArrayHeaderDelimiter {

COMMA(',');
COMMA(','),
SEMICOLON(';');

private final char delimiter;

Expand Down
15 changes: 13 additions & 2 deletions src/main/java/org/mule/module/apikit/api/uri/URIResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,24 @@ private URIPattern findBest(Set<URIPattern> patterns) {
}
URIPattern best = null;
for (URIPattern p : patterns) {
if (p.match(this._uri) && (!this._uri.endsWith("/") || p.toString().endsWith("/"))) {
if (p.match(this._uri) && (!this._uri.endsWith("/") || p.toString().endsWith("/")))
if (best == null || p.score() > best.score()) {
best = p;
}
}
}
if (best == null) {
best = findBestMethodWithEmptyParams(patterns);
}
return best;
}

private URIPattern findBestMethodWithEmptyParams(Set<URIPattern> patterns) {
URIPattern currentBest = null;
for (URIPattern p : patterns) {
if (p.match(this._uri) && (currentBest == null || p.score() > currentBest.score())) {
currentBest = p;
}
}
return currentBest;
}
}
10 changes: 8 additions & 2 deletions src/main/java/org/mule/module/apikit/deserializing/MimeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.mule.module.apikit.api.deserializing.ArrayHeaderDelimiter.SEMICOLON;

public class MimeType {

private String type;
Expand Down Expand Up @@ -228,9 +230,13 @@ private String nextQuotedString() throws MimeTypeParseException {
private boolean trySkip(char expected) {
if (atEnd() || peek() != expected) {
return false;
} else if ((peek() == SEMICOLON.getDelimiterChar() && i + 1 == input.length())) {
i++;
return false;
} else {
skip();
return true;
}
skip();
return true;
}

private void skip(char expected) throws MimeTypeParseException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public RewindableInputStream(InputStream in) {
this.in = in;
}

@Override
public void close() throws IOException {
if (saving) {
curBlockAvail = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -91,7 +92,7 @@ public Multipart build() throws InvalidFormParameterException {
APIKitMultipartStream multipartStream =
new APIKitMultipartStream(inputStream, boundary.getBytes(MIME.UTF8_CHARSET), BUFFER_SIZE, sizeLimit);

Set<String> parametersInPayload = new HashSet<>();
Map<String, Integer> parametersInPayloadToCount = new HashMap<>();
MultipartEntityBuilder multipartEntityBuilder =
defaultValues.isEmpty() && cursorProvider != null
? new MultipartEntityBuilderWithoutDefaults(contentType, cursorProvider, boundary, sizeLimit, byteLength)
Expand All @@ -106,16 +107,16 @@ public Multipart build() throws InvalidFormParameterException {
String fileName = getFileName(headers);
String contentType = getContentType(headers);

parametersInPayload.add(name);
parametersInPayloadToCount.put(name, parametersInPayloadToCount.getOrDefault(name, 0) + 1);

multipartEntityBuilder.handlePart(multipartStream, formParameters.get(name), name, contentType, fileName, headers);

nextPart = multipartStream.readBoundary();
nextPart = multipartStream.readBoundary(); //Checking the next part items here
multipartEntityBuilder.handleBoundary(false);
}

for (Entry<String, String> defaultValue : defaultValues.entrySet()) {
if (!parametersInPayload.contains(defaultValue.getKey())) {
if (!parametersInPayloadToCount.containsKey(defaultValue.getKey())) {
multipartEntityBuilder.addDefault(defaultValue.getKey(), defaultValue.getValue());
multipartEntityBuilder.handleBoundary(false);
}
Expand All @@ -125,9 +126,18 @@ public Multipart build() throws InvalidFormParameterException {
multipartStream.readEpilogue(multipartEntityBuilder);

for (Entry<String, Parameter> formParameter : formParameters.entrySet()) {
if (!parametersInPayload.contains(formParameter.getKey()) && formParameter.getValue().isRequired()
if (!parametersInPayloadToCount.containsKey(formParameter.getKey()) && formParameter.getValue().isRequired()
&& formParameter.getValue().getDefaultValues().isEmpty()) {
throw new InvalidFormParameterException("Required form parameter " + formParameter.getKey() + " not specified");
throw new InvalidFormParameterException("Required form parameter " + formParameter.getKey() + " not specified");//We can also validate the minItems and maxItem count here
} else if (parametersInPayloadToCount.containsKey(formParameter.getKey()) && formParameter.getValue().isRequired()) {
Optional<Integer> minItemsCount = formParameter.getValue().getMinItems();
if (minItemsCount.isPresent() && (minItemsCount.get() > parametersInPayloadToCount.get(formParameter.getKey()))) {
throw new InvalidFormParameterException("parameter does not comply with minItems for " + formParameter.getKey());
}
Optional<Integer> maxItemsCount = formParameter.getValue().getMaxItems();
if (maxItemsCount.isPresent() && parametersInPayloadToCount.get(formParameter.getKey()) > maxItemsCount.get()) {
throw new InvalidFormParameterException("parameter does not comply with maxItems for " + formParameter.getKey());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import static org.hamcrest.core.IsEqual.equalTo;

import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.mule.apikit.ApiType;
import org.mule.module.apikit.exception.NotAcceptableException;

public class ConfigurationTestCase {

Expand All @@ -20,4 +22,10 @@ public void avoidNullPointerWhenConfigNotInitialised() {

assertThat(configuration.getType(), equalTo(ApiType.AMF));
}

@Test
public void testNotAcceptableException() {
NotAcceptableException notAcceptableException = new NotAcceptableException();
Assertions.assertEquals(notAcceptableException.getStringRepresentation(), NotAcceptableException.STRING_REPRESENTATION);
}
}
57 changes: 55 additions & 2 deletions src/test/java/org/mule/module/apikit/RoutingTableTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ public void URIWithTrailingForwardSlashAreNotMatched() {
patterns.add(new URIPattern("/api/"));

URIResolver resolver1 = new URIResolver("/api/hello/");
Assert.assertNull(resolver1.find(patterns, URIResolver.MatchRule.BEST_MATCH));
Assert.assertNotNull(resolver1.find(patterns, URIResolver.MatchRule.BEST_MATCH));

URIResolver resolver3 = new URIResolver("/api");
Assert.assertNull(resolver3.find(patterns, URIResolver.MatchRule.BEST_MATCH));

patterns.add(new URIPattern("/{param}"));
URIResolver resolver2 = new URIResolver("/");
Assert.assertNull(resolver2.find(patterns, URIResolver.MatchRule.BEST_MATCH));
Assert.assertNotNull(resolver2.find(patterns, URIResolver.MatchRule.BEST_MATCH));
}

@Test
Expand All @@ -127,4 +127,57 @@ public void getResourceByString() {
Assert.assertNotNull(routingTable.getResource("/single-resource"));
Assert.assertNotNull(routingTable.getResource("/api/sub-resource"));
}

@Test
public void testFindBestMethodWithEmptyParams() {
// Test Case 1: Empty parameter in the last
HashSet<URIPattern> patterns1 = new HashSet<>();
patterns1.add(new URIPattern("/api/users/{id}"));

URIResolver resolver1 = new URIResolver("/api/users/");
URIPattern bestPattern1 = resolver1.find(patterns1, URIResolver.MatchRule.BEST_MATCH);
Assert.assertNotNull(bestPattern1);
Assert.assertEquals("/api/users/{id}", bestPattern1.toString());


// Test Case 2: Testing empty parameter in middle
HashSet<URIPattern> patterns2 = new HashSet<>();
patterns2.add(new URIPattern("/users/{id}/posts"));
patterns2.add(new URIPattern("/users/{id}"));
patterns2.add(new URIPattern("/users"));

URIResolver resolver2 = new URIResolver("/users//posts");
URIPattern bestPattern2 = resolver2.find(patterns2, URIResolver.MatchRule.BEST_MATCH);
Assert.assertEquals("/users/{id}/posts", bestPattern2.toString());

// Test Case 3: Testing multiple empty parameters
HashSet<URIPattern> patterns3 = new HashSet<>();
patterns3.add(new URIPattern("/api/{version}/users/{id}"));
patterns3.add(new URIPattern("/users/{id}"));
patterns3.add(new URIPattern("/users"));

URIResolver resolver3 = new URIResolver("/api//users/");
URIPattern bestPattern3 = resolver3.find(patterns3, URIResolver.MatchRule.BEST_MATCH);
Assert.assertEquals("/api/{version}/users/{id}", bestPattern3.toString());

// Test Case 4: Testing empty parameter with nested resources
HashSet<URIPattern> patterns4 = new HashSet<>();
patterns4.add(new URIPattern("/users/{id}/posts/{postId}/comments"));
patterns4.add(new URIPattern("/users/{id}/posts/{postId}"));
patterns4.add(new URIPattern("/users/{id}/posts"));

URIResolver resolver4 = new URIResolver("/users//posts//comments");
URIPattern bestPattern4 = resolver4.find(patterns4, URIResolver.MatchRule.BEST_MATCH);
Assert.assertEquals("/users/{id}/posts/{postId}/comments", bestPattern4.toString());

// Test Case 5: Testing empty parameter with root path
HashSet<URIPattern> patterns5 = new HashSet<>();
patterns5.add(new URIPattern("/{version}"));
patterns5.add(new URIPattern("/"));
patterns5.add(new URIPattern(""));

URIResolver resolver12 = new URIResolver("//");
URIPattern bestPattern12 = resolver12.find(patterns5, URIResolver.MatchRule.BEST_MATCH);
Assert.assertNull(bestPattern12);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ public void supportsRepeatedParameters() throws MimeTypeParseException {
assertEquals(expected, MimeType.from("text/plain; param=value1; param=value2"));
}

@Test
public void supportsEndSemiColon() throws MimeTypeParseException {
MimeType expected = new MimeType("text", "plain",
list(new Parameter("param", "value1"),
new Parameter("param", "value2")));
assertEquals(expected, MimeType.from("text/plain; param=value1; param=value2;"));
}

@Test
public void ignoresEscapedQuotesInsideQuotes() throws MimeTypeParseException {
MimeType expected = new MimeType("text", "plain",
Expand All @@ -91,10 +99,8 @@ public void failsIfAdditionalTextIsAtTheEndOfAValidMime() {
@Test
public void failsIfTextIsMissing() {
assertThrows(MimeTypeParseException.class, () -> MimeType.from("text/"));
assertThrows(MimeTypeParseException.class, () -> MimeType.from("text/plain;"));
assertThrows(MimeTypeParseException.class, () -> MimeType.from("text/plain; param"));
assertThrows(MimeTypeParseException.class, () -> MimeType.from("text/plain; param="));
assertThrows(MimeTypeParseException.class, () -> MimeType.from("text/plain; param=value;"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.module.apikit.error;

import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.mule.runtime.api.event.Event;

import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;

public class EventProcessingExceptionHandlerTest {

@Test
public void testHandle() throws Exception {
MuleMessagingExceptionHandler handler = new MuleMessagingExceptionHandler();
Event event = mock(Event.class);
Exception exception = mock(Exception.class);
Assertions.assertThrows(IllegalArgumentException.class, () -> handler.handle(event, exception));
}

@Test
public void testGetMessagingExceptionConstructor() throws Exception {
MuleMessagingExceptionHandler handler = new MuleMessagingExceptionHandler();
assertNotNull(handler);
}
}
Loading