Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/maven/junit-jupiter.version-5.10.1
Browse files Browse the repository at this point in the history
  • Loading branch information
sappenin committed Jul 19, 2024
2 parents d284814 + 44bac5a commit 1d6f84d
Show file tree
Hide file tree
Showing 79 changed files with 4,145 additions and 516 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ current [BOM](https://howtodoinjava.com/maven/maven-bom-bill-of-materials-depend
<dependency>
<groupId>org.xrpl</groupId>
<artifactId>xrpl4j-bom</artifactId>
<version>3.2.1</version>
<version>3.3.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
2 changes: 1 addition & 1 deletion checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="accessModifiers" value="public, protected"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
Expand Down
38 changes: 15 additions & 23 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@
</goals>
</execution>
</executions>
<configuration>
<rerunFailingTestsCount>2</rerunFailingTestsCount>
</configuration>
</plugin>

<!-- org.apache.maven.plugins:maven-source-plugin -->
Expand Down Expand Up @@ -432,7 +435,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.36.1</version>
<version>9.3</version>
</dependency>
</dependencies>
<executions>
Expand Down Expand Up @@ -498,19 +501,18 @@
</configuration>
</plugin>

<!-- org.sonatype.plugins:nexus-staging-maven-plugin -->
<!-- org.sonatype.central:central-publishing-maven-plugin -->
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.13</version>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.5.0</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh-snapshots</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>


<!-- org.codehaus.mojo:license-maven-plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
Expand Down Expand Up @@ -608,10 +610,10 @@
<artifactId>maven-surefire-plugin</artifactId>
</plugin>

<!-- org.sonatype.plugins:nexus-staging-maven-plugin -->
<!-- org.sonatype.central:central-publishing-maven-plugin -->
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
</plugin>

<plugin>
Expand Down Expand Up @@ -651,7 +653,8 @@
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<inputEncoding>UTF-8</inputEncoding>
<outputEncoding>UTF-8</outputEncoding>
<consoleOutput>true</consoleOutput>
<linkXRef>false</linkXRef>
<excludes>**/generated-sources/**/*,**/generated-test-sources/**/*</excludes>
Expand All @@ -678,15 +681,4 @@
</plugins>
</reporting>

<distributionManagement>
<snapshotRepository>
<id>ossrh-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>

</project>
2 changes: 1 addition & 1 deletion xrpl4j-bom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ POM file. For example:
<dependency>
<groupId>org.xrpl.xrpl4j</groupId>
<artifactId>xrpl4j-bom</artifactId>
<version>3.2.1</version>
<version>3.3.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public interface JsonRpcClient {
int SERVICE_UNAVAILABLE_STATUS = 503;
Duration RETRY_INTERVAL = Duration.ofSeconds(1);

String RESULT = "result";
String STATUS = "status";
String ERROR = "error";
String ERROR_EXCEPTION = "error_exception";
String ERROR_MESSAGE = "error_message";
String N_A = "n/a";

/**
* Constructs a new client for the given url.
*
Expand Down Expand Up @@ -134,7 +141,7 @@ default <T extends XrplResult> T send(
JavaType resultType
) throws JsonRpcClientErrorException {
JsonNode response = postRpcRequest(request);
JsonNode result = response.get("result");
JsonNode result = response.get(RESULT);
checkForError(response);
try {
return objectMapper.readValue(result.toString(), resultType);
Expand All @@ -151,13 +158,25 @@ default <T extends XrplResult> T send(
* @throws JsonRpcClientErrorException If rippled returns an error message.
*/
default void checkForError(JsonNode response) throws JsonRpcClientErrorException {
if (response.has("result")) {
JsonNode result = response.get("result");
if (result.has("error")) {
String errorMessage = Optional.ofNullable(result.get("error_exception"))
.map(JsonNode::asText)
.orElseGet(() -> result.get("error_message").asText());
throw new JsonRpcClientErrorException(errorMessage);
if (response.has(RESULT)) {
JsonNode result = response.get(RESULT);
if (result.has(STATUS)) {
String status = result.get(STATUS).asText();
if (status.equals(ERROR)) { // <-- Only an error if result.status == "error"
if (result.has(ERROR)) {
String errorCode = result.get(ERROR).asText();

final String errorMessage;
if (result.hasNonNull(ERROR_EXCEPTION)) {
errorMessage = result.get(ERROR_EXCEPTION).asText();
} else if (result.hasNonNull(ERROR_MESSAGE)) {
errorMessage = result.get(ERROR_MESSAGE).asText();
} else {
errorMessage = N_A;
}
throw new JsonRpcClientErrorException(String.format("%s (%s)", errorCode, errorMessage));
}
}
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions xrpl4j-client/src/main/java/org/xrpl/xrpl4j/client/XrplClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
import org.xrpl.xrpl4j.model.client.nft.NftInfoResult;
import org.xrpl.xrpl4j.model.client.nft.NftSellOffersRequestParams;
import org.xrpl.xrpl4j.model.client.nft.NftSellOffersResult;
import org.xrpl.xrpl4j.model.client.oracle.GetAggregatePriceRequestParams;
import org.xrpl.xrpl4j.model.client.oracle.GetAggregatePriceResult;
import org.xrpl.xrpl4j.model.client.path.BookOffersRequestParams;
import org.xrpl.xrpl4j.model.client.path.BookOffersResult;
import org.xrpl.xrpl4j.model.client.path.DepositAuthorizedRequestParams;
Expand Down Expand Up @@ -810,6 +812,28 @@ public AmmInfoResult ammInfo(
return jsonRpcClient.send(request, AmmInfoResult.class);
}

/**
* Retreive the aggregate price of specified oracle objects, returning three price statistics: mean, median, and
* trimmed mean.
*
* @param params A {@link GetAggregatePriceRequestParams}.
*
* @return A {@link GetAggregatePriceResult}.
*
* @throws JsonRpcClientErrorException if {@code jsonRpcClient} throws an error.
*/
@Beta
public GetAggregatePriceResult getAggregatePrice(
GetAggregatePriceRequestParams params
) throws JsonRpcClientErrorException {
JsonRpcRequest request = JsonRpcRequest.builder()
.method(XrplMethods.GET_AGGREGATE_PRICE)
.addParams(params)
.build();

return jsonRpcClient.send(request, GetAggregatePriceResult.class);
}

public JsonRpcClient getJsonRpcClient() {
return jsonRpcClient;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package org.xrpl.xrpl4j.client;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
* Unit test for {@link JsonRpcClient}.
*/
class JsonRpcClientTest {

private JsonRpcClient jsonRpcClient;

@Mock
JsonNode jsonResponseNodeMock; // <-- The main response

@Mock
JsonNode jsonResultNodeMock; // <-- resp.result

@Mock
JsonNode jsonStatusNodeMock; // <-- result.status

@Mock
JsonNode jsonErrorNodeMock; // <-- result.error

@Mock
JsonNode jsonErrorMessageNodeMock; // <-- result.error_message

@Mock
JsonNode jsonErrorExceptionNodeMock; // <-- result.error_exception

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
jsonRpcClient = rpcRequest -> jsonResponseNodeMock;

// See https://xrpl.org/docs/references/http-websocket-apis/api-conventions/error-formatting/#json-rpc-format
when(jsonStatusNodeMock.asText()).thenReturn(JsonRpcClient.ERROR);

when(jsonErrorNodeMock.asText()).thenReturn("error_foo");
when(jsonErrorMessageNodeMock.asText()).thenReturn("error_message_foo");
when(jsonErrorExceptionNodeMock.asText()).thenReturn("error_exception_foo");

// By default, there's a result.
when(jsonResponseNodeMock.has("result")).thenReturn(true);
when(jsonResponseNodeMock.get("result")).thenReturn(jsonResultNodeMock);

// By default, there's an error.
when(jsonResultNodeMock.has("status")).thenReturn(true);
when(jsonResultNodeMock.get("status")).thenReturn(jsonStatusNodeMock);

hasError(true); // <-- By default, there's a `result.error`
hasErrorMessage(false); // <-- By default, there's no `result.error_message`
hasErrorException(false); // <-- By default, there's no `result.error_exception`
}

//////////////////
// checkForError()
//////////////////

@Test
void testCheckForErrorWhenResponseHasNoResultField() throws JsonRpcClientErrorException {
// Do nothing if no "result" field
when(jsonResponseNodeMock.has("result")).thenReturn(false);
jsonRpcClient.checkForError(jsonResponseNodeMock); // <-- No error should be thrown.
}

@Test
void testCheckForErrorWhenResponseHasNoStatusFields() throws JsonRpcClientErrorException {
when(jsonResultNodeMock.has("status")).thenReturn(false);
jsonRpcClient.checkForError(jsonResponseNodeMock);
}

@Test
void testCheckForErrorWhenResponseHasNoErrorFields() throws JsonRpcClientErrorException {
hasError(false);
jsonRpcClient.checkForError(jsonResponseNodeMock);
}

@Test
void testCheckForErrorWhenResponseHasResultErrorException() {
hasErrorException(true);

JsonRpcClientErrorException error = assertThrows(
JsonRpcClientErrorException.class,
() -> jsonRpcClient.checkForError(jsonResponseNodeMock)
);
assertThat(error.getMessage()).isEqualTo("error_foo (error_exception_foo)");
}

@Test
void testCheckForErrorWhenResponseHasResultErrorMessage() {
hasErrorMessage(true);

JsonRpcClientErrorException error = assertThrows(
JsonRpcClientErrorException.class,
() -> jsonRpcClient.checkForError(jsonResponseNodeMock)
);
assertThat(error.getMessage()).isEqualTo("error_foo (error_message_foo)");
}

@Test
void testCheckForErrorWhenResponseHasResultError() {
hasError(true);

JsonRpcClientErrorException error = assertThrows(JsonRpcClientErrorException.class,
() -> jsonRpcClient.checkForError(jsonResponseNodeMock));
assertThat(error.getMessage()).isEqualTo("error_foo (n/a)");
}

@Test
void testCheckForErrorWhenResponseHasAll() {
hasError(true);
hasErrorMessage(true);
hasErrorMessage(true);

JsonRpcClientErrorException error = assertThrows(
JsonRpcClientErrorException.class,
() -> jsonRpcClient.checkForError(jsonResponseNodeMock)
);
assertThat(error.getMessage()).isEqualTo("error_foo (error_message_foo)");
}

//////////////////
// Private Helpers
//////////////////

private void hasError(boolean hasError) {
when(jsonResultNodeMock.has(JsonRpcClient.ERROR)).thenReturn(hasError);
if (hasError) {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR)).thenReturn(jsonErrorNodeMock);
when(jsonResultNodeMock.hasNonNull(JsonRpcClient.ERROR)).thenReturn(true);
} else {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR)).thenReturn(null);
}
}

private void hasErrorMessage(boolean hasErrorMessage) {
when(jsonResultNodeMock.has(JsonRpcClient.ERROR_MESSAGE)).thenReturn(hasErrorMessage);
if (hasErrorMessage) {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR_MESSAGE)).thenReturn(jsonErrorMessageNodeMock);
when(jsonResultNodeMock.hasNonNull(JsonRpcClient.ERROR_MESSAGE)).thenReturn(true);
} else {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR_MESSAGE)).thenReturn(null);
}
}

private void hasErrorException(boolean hasErrorException) {
when(jsonResultNodeMock.has(JsonRpcClient.ERROR_EXCEPTION)).thenReturn(hasErrorException);
if (hasErrorException) {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR_EXCEPTION)).thenReturn(jsonErrorExceptionNodeMock);
when(jsonResultNodeMock.hasNonNull(JsonRpcClient.ERROR_EXCEPTION)).thenReturn(true);
} else {
when(jsonResultNodeMock.get(JsonRpcClient.ERROR_EXCEPTION)).thenReturn(null);
}
}
}
Loading

0 comments on commit 1d6f84d

Please sign in to comment.