From 5c1d7fa40a5389805a7585c6a57d3e25c18540a0 Mon Sep 17 00:00:00 2001 From: Dmitri Karpovich Date: Wed, 6 Nov 2024 01:11:32 +0100 Subject: [PATCH 1/3] [gateio] Add configs for authenticated integration tests --- xchange-stream-gateio/.gitignore | 3 ++- xchange-stream-gateio/README.md | 21 +++++++++++++++++++ .../example.integration-test.env.properties | 2 ++ xchange-stream-gateio/pom.xml | 16 ++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 xchange-stream-gateio/README.md create mode 100644 xchange-stream-gateio/example.integration-test.env.properties diff --git a/xchange-stream-gateio/.gitignore b/xchange-stream-gateio/.gitignore index 42c7d2cd0eb..5b77a2510da 100644 --- a/xchange-stream-gateio/.gitignore +++ b/xchange-stream-gateio/.gitignore @@ -1 +1,2 @@ -http-client.private.env.json \ No newline at end of file +http-client.private.env.json +integration-test.env.properties diff --git a/xchange-stream-gateio/README.md b/xchange-stream-gateio/README.md new file mode 100644 index 00000000000..f728ba8eda6 --- /dev/null +++ b/xchange-stream-gateio/README.md @@ -0,0 +1,21 @@ +## Using IntelliJ Idea HTTP client + +There are *.http files stored in `src/test/resources/rest` that can be used with IntelliJ Idea HTTP Client. + +Some requests need authorization, so the api credentials have to be stored in `http-client.private.env.json` in module's root. Sample content can be found in `example.http-client.private.env.json` + +> [!CAUTION] +> Never commit your api credentials to the repository! + + +[HTTP Client documentation](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html) + +## Running integration tests that require API keys + +Integration tests that require API keys read them from environment variables. They can be defined in `integration-test.env.properties`. Sample content can be found in `example.integration-test.env.properties`. + +If no keys are provided the integration tests that need them are skipped. + +> [!CAUTION] +> Never commit your api credentials to the repository! + diff --git a/xchange-stream-gateio/example.integration-test.env.properties b/xchange-stream-gateio/example.integration-test.env.properties new file mode 100644 index 00000000000..d8421d99d6c --- /dev/null +++ b/xchange-stream-gateio/example.integration-test.env.properties @@ -0,0 +1,2 @@ +apiKey=change_me +secretKey=change_me diff --git a/xchange-stream-gateio/pom.xml b/xchange-stream-gateio/pom.xml index 8f818a9c237..10414f0bd1b 100644 --- a/xchange-stream-gateio/pom.xml +++ b/xchange-stream-gateio/pom.xml @@ -44,4 +44,20 @@ + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + integration-test.env.properties + + + + + + + From 3fae38db86187ece2c6da3155ecd856b049fedc1 Mon Sep 17 00:00:00 2001 From: Dmitri Karpovich Date: Wed, 6 Nov 2024 01:12:09 +0100 Subject: [PATCH 2/3] [gateio] Fix wrong channel id --- .../xchangestream/gateio/GateioStreamingService.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xchange-stream-gateio/src/main/java/info/bitrich/xchangestream/gateio/GateioStreamingService.java b/xchange-stream-gateio/src/main/java/info/bitrich/xchangestream/gateio/GateioStreamingService.java index fe01d4a04f4..02c0a91a53b 100644 --- a/xchange-stream-gateio/src/main/java/info/bitrich/xchangestream/gateio/GateioStreamingService.java +++ b/xchange-stream-gateio/src/main/java/info/bitrich/xchangestream/gateio/GateioStreamingService.java @@ -57,18 +57,22 @@ protected String getChannelNameFromMessage(GateioWsNotification message) { } @Override - public Observable subscribeChannel(String channelName, Object... args) { + public String getSubscriptionUniqueId(String channelName, Object... args) { final CurrencyPair currencyPair = (args.length > 0 && args[0] instanceof CurrencyPair) ? ((CurrencyPair) args[0]) : null; - String uniqueChannelName = - String.format("%s%s%s", channelName, Config.CHANNEL_NAME_DELIMITER, currencyPair); + return String.format("%s%s%s", channelName, Config.CHANNEL_NAME_DELIMITER, currencyPair); + } + + @Override + public Observable subscribeChannel(String channelName, Object... args) { + String uniqueChannelName = getSubscriptionUniqueId(channelName, args); // Example channel name key: spot.order_book-BTC/USDT if (!channels.containsKey(uniqueChannelName) && !subscriptions.containsKey(uniqueChannelName)) { // subscribe - Observable observable = super.subscribeChannel(uniqueChannelName, args); + Observable observable = super.subscribeChannel(channelName, args); // cache channel subscribtion subscriptions.put(uniqueChannelName, observable); From caa19b9ca5e3cc0c40a83f5b81d3d1de217a2173 Mon Sep 17 00:00:00 2001 From: Dmitri Karpovich Date: Wed, 6 Nov 2024 01:12:22 +0100 Subject: [PATCH 3/3] [gateio] Extend integration tests --- ...eioStreamingAccountServiceIntegration.java | 33 +++++----- .../gateio/GateioStreamingExchangeIT.java | 4 +- ...StreamingMarketDataServiceIntegration.java | 15 ++++- ...ateioStreamingTradeServiceIntegration.java | 61 ++++++++++++------- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingAccountServiceIntegration.java b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingAccountServiceIntegration.java index 979b6f39a47..caee7f5d4a8 100644 --- a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingAccountServiceIntegration.java +++ b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingAccountServiceIntegration.java @@ -1,27 +1,25 @@ package info.bitrich.xchangestream.gateio; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.assertj.core.api.Assumptions.assumeThat; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.observers.TestObserver; -import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.knowm.xchange.currency.Currency; import org.knowm.xchange.dto.account.Balance; -@Disabled( - "Needs authenticated exchange and real balance change. Set env vars GATEIO_API_KEY/GATEIO_API_SECRET") +@Slf4j class GateioStreamingAccountServiceIntegration extends GateioStreamingExchangeIT { - @BeforeEach - void authConfigured() { - assumeTrue( - StringUtils.isNotEmpty(exchange.getExchangeSpecification().getApiKey()), "Needs auth"); - assumeTrue( - StringUtils.isNotEmpty(exchange.getExchangeSpecification().getSecretKey()), "Needs auth"); + @BeforeAll + public static void credentialsPresent() { + // skip if there are no credentials + assumeThat(exchange.getExchangeSpecification().getApiKey()).isNotEmpty(); + assumeThat(exchange.getExchangeSpecification().getSecretKey()).isNotEmpty(); } @Test @@ -31,10 +29,17 @@ void spot_balances() { TestObserver testObserver = observable.test(); - Balance balance = testObserver.awaitCount(1).values().get(0); + List balances = testObserver +// .awaitDone(10, TimeUnit.MINUTES) + .awaitCount(1) + .values(); testObserver.dispose(); - assertThat(balance).hasNoNullFieldsOrProperties(); + log.info("Received balances: {}", balances); + + assumeThat(balances).overridingErrorMessage("Received nothing").isNotEmpty(); + + assertThat(balances).first().hasNoNullFieldsOrProperties(); } } diff --git a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingExchangeIT.java b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingExchangeIT.java index 43bfae14870..99a20f61f66 100644 --- a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingExchangeIT.java +++ b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingExchangeIT.java @@ -20,8 +20,8 @@ public static void setup() { StreamingExchangeFactory.INSTANCE .createExchangeWithoutSpecification(GateioStreamingExchange.class) .getDefaultExchangeSpecification(); - spec.setApiKey(System.getenv("GATEIO_API_KEY")); - spec.setSecretKey(System.getenv("GATEIO_API_SECRET")); + spec.setApiKey(System.getProperty("apiKey")); + spec.setSecretKey(System.getProperty("secretKey")); exchange = (GateioStreamingExchange) StreamingExchangeFactory.INSTANCE.createExchange(spec); diff --git a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingMarketDataServiceIntegration.java b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingMarketDataServiceIntegration.java index 8f9cc9bddb3..e2c13989163 100644 --- a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingMarketDataServiceIntegration.java +++ b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingMarketDataServiceIntegration.java @@ -22,7 +22,10 @@ void order_book() { TestObserver testObserver = observable.test(); - OrderBook orderBook = testObserver.awaitCount(1).values().get(0); + OrderBook orderBook = testObserver +// .awaitDone(1, TimeUnit.MINUTES) + .awaitCount(1) + .values().get(0); testObserver.dispose(); @@ -42,7 +45,10 @@ void trades() { TestObserver testObserver = observable.test(); - Trade trade = testObserver.awaitCount(1).values().get(0); + Trade trade = testObserver +// .awaitDone(1, TimeUnit.MINUTES) + .awaitCount(1) + .values().get(0); testObserver.dispose(); @@ -57,7 +63,10 @@ void ticker() { TestObserver testObserver = observable.test(); - Ticker ticker = testObserver.awaitCount(1).values().get(0); + Ticker ticker = testObserver + .awaitCount(1) +// .awaitDone(1, TimeUnit.MINUTES) + .values().get(0); testObserver.dispose(); diff --git a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingTradeServiceIntegration.java b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingTradeServiceIntegration.java index c41e96844e7..68f7a1e6f92 100644 --- a/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingTradeServiceIntegration.java +++ b/xchange-stream-gateio/src/test/java/info/bitrich/xchangestream/gateio/GateioStreamingTradeServiceIntegration.java @@ -1,54 +1,69 @@ package info.bitrich.xchangestream.gateio; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.assertj.core.api.Assumptions.assumeThat; +import static org.knowm.xchange.currency.CurrencyPair.BTC_USDT; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.observers.TestObserver; -import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.knowm.xchange.currency.CurrencyPair; import org.knowm.xchange.dto.trade.UserTrade; -@Disabled( - "Needs authenticated exchange and real user trade. Set env vars GATEIO_API_KEY/GATEIO_API_SECRET") +@Slf4j class GateioStreamingTradeServiceIntegration extends GateioStreamingExchangeIT { - @BeforeEach - void authConfigured() { - assumeTrue( - StringUtils.isNotEmpty(exchange.getExchangeSpecification().getApiKey()), "Needs auth"); - assumeTrue( - StringUtils.isNotEmpty(exchange.getExchangeSpecification().getSecretKey()), "Needs auth"); + @BeforeAll + public static void credentialsPresent() { + // skip if there are no credentials + assumeThat(exchange.getExchangeSpecification().getApiKey()).isNotEmpty(); + assumeThat(exchange.getExchangeSpecification().getSecretKey()).isNotEmpty(); } @Test - void user_trades_btc() { - Observable observable = - exchange.getStreamingTradeService().getUserTrades(CurrencyPair.BTC_USDT); + void user_trades_all() { + Observable observable = exchange.getStreamingTradeService().getUserTrades(); TestObserver testObserver = observable.test(); - UserTrade userTrade = testObserver.awaitCount(1).values().get(0); + List userTrades = testObserver +// .awaitDone(10, TimeUnit.MINUTES) + .awaitCount(1) + .values(); testObserver.dispose(); - assertThat(userTrade).hasNoNullFieldsOrPropertiesExcept("makerOrderId", "takerOrderId"); - assertThat(userTrade.getInstrument()).isEqualTo(CurrencyPair.BTC_USDT); + log.info("Received usertrades: {}", userTrades); + + assumeThat(userTrades).overridingErrorMessage("No trades happened").isNotEmpty(); + + assertThat(userTrades.get(0).getInstrument()).isNotNull(); + assertThat(userTrades.get(0).getId()).isNotNull(); + assertThat(userTrades.get(0).getOrderId()).isNotNull(); } @Test - void user_trades_all() { - Observable observable = exchange.getStreamingTradeService().getUserTrades(); + void user_trades_single_instrument() { + Observable observable = exchange.getStreamingTradeService().getUserTrades(BTC_USDT); TestObserver testObserver = observable.test(); - UserTrade userTrade = testObserver.awaitCount(1).values().get(0); + List userTrades = + testObserver + // .awaitDone(1, TimeUnit.MINUTES) + .awaitCount(1) + .values(); testObserver.dispose(); - assertThat(userTrade).hasNoNullFieldsOrPropertiesExcept("makerOrderId", "takerOrderId"); + log.info("Received usertrades: {}", userTrades); + + assumeThat(userTrades).overridingErrorMessage("No trades happened").isNotEmpty(); + + assertThat(userTrades.get(0).getInstrument()).isEqualTo(BTC_USDT); + assertThat(userTrades.get(0).getId()).isNotNull(); + assertThat(userTrades.get(0).getOrderId()).isNotNull(); } }