Skip to content

Commit

Permalink
Configure integration tests bisq-network#5
Browse files Browse the repository at this point in the history
  • Loading branch information
Bernard Labno committed Oct 11, 2019
1 parent 51aff9a commit a28d9ca
Show file tree
Hide file tree
Showing 14 changed files with 704 additions and 1 deletion.
16 changes: 16 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,19 @@ Some features will be not sufficiently tested and will only be enabled if you ad
--seedNodes=localhost:8000 --btcNodes=localhost:18445 --baseCurrencyNetwork=BTC_REGTEST --logLevel=info
--useDevPrivilegeKeys=true --bitcoinRegtestHost=NONE --myAddress=172.17.0.1:8003
--enableHttpApiExperimentalFeatures"

## Integration tests

Integration tests leverage Docker and run in headless mode. First you need to build docker images for the api:

cd api
docker-compose build
../gradlew testIntegration

IntelliJ Idea has awesome integration so just right click on `api/src/testIntegration` directory and select
`Debug All Tests`.

### Integration tests logging

Due to Travis log length limitations the log level is set to WARN, but if you need to see more details locally
go to `ContainerFactory` class and set `ENV_LOG_LEVEL_VALUE` property to `debug`.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
Expand All @@ -37,7 +38,7 @@ public UserEndpoint(ApiPasswordManager apiPasswordManager) {
@Operation(summary = "Change password")
@POST
@Path("/password")
public void changePassword(@Suspended AsyncResponse asyncResponse, @Valid ChangePassword data) {
public void changePassword(@Suspended AsyncResponse asyncResponse, @NotNull @Valid ChangePassword data) {
UserThread.execute(() -> {
try {
apiPasswordManager.changePassword(data.oldPassword, data.newPassword);
Expand Down
30 changes: 30 additions & 0 deletions api/src/testIntegration/java/bisq/api/http/ApiTestHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.api.http;

@SuppressWarnings("WeakerAccess")
public final class ApiTestHelper {

public static void waitForAllServicesToBeReady() throws InterruptedException {
// TODO it would be nice to expose endpoint that would respond with 200
// PaymentMethod initializes it's static values after all services get initialized
int ALL_SERVICES_INITIALIZED_DELAY = 5000;
Thread.sleep(ALL_SERVICES_INITIALIZED_DELAY);
}

}
101 changes: 101 additions & 0 deletions api/src/testIntegration/java/bisq/api/http/ContainerFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.api.http;

import org.arquillian.cube.docker.impl.client.config.Await;
import org.arquillian.cube.docker.impl.client.containerobject.dsl.Container;
import org.arquillian.cube.docker.impl.client.containerobject.dsl.ContainerBuilder;

@SuppressWarnings("WeakerAccess")
public final class ContainerFactory {

public static final String BITCOIN_NODE_CONTAINER_NAME = "bisq-api-bitcoin-node";
public static final String BITCOIN_NODE_HOST_NAME = "bitcoin";
public static final String SEED_NODE_CONTAINER_NAME = "bisq-seednode";
public static final String SEED_NODE_HOST_NAME = SEED_NODE_CONTAINER_NAME;
public static final String SEED_NODE_ADDRESS = SEED_NODE_HOST_NAME + ":8000";
public static final String CONTAINER_NAME_PREFIX = "bisq-api-";
public static final String API_IMAGE = "bisq/api";
public static final String ENV_NODE_PORT_KEY = "NODE_PORT";
public static final String ENV_ENABLE_HTTP_API_EXPERIMENTAL_FEATURES_KEY = "ENABLE_HTTP_API_EXPERIMENTAL_FEATURES";
public static final String ENV_HTTP_API_HOST_KEY = "HTTP_API_HOST";
public static final String ENV_HTTP_API_HOST_VALUE = "0.0.0.0";
public static final String ENV_USE_DEV_PRIVILEGE_KEYS_KEY = "USE_DEV_PRIVILEGE_KEYS";
public static final String ENV_USE_DEV_PRIVILEGE_KEYS_VALUE = "true";
public static final String ENV_USE_LOCALHOST_FOR_P2P_KEY = "USE_LOCALHOST_FOR_P2P";
public static final String ENV_USE_LOCALHOST_FOR_P2P_VALUE = "true";
public static final String ENV_BASE_CURRENCY_NETWORK_KEY = "BASE_CURRENCY_NETWORK";
public static final String ENV_BASE_CURRENCY_NETWORK_VALUE = "BTC_REGTEST";
public static final String ENV_BITCOIN_REGTEST_HOST_KEY = "BITCOIN_REGTEST_HOST";
public static final String ENV_BITCOIN_REGTEST_HOST_VALUE = "LOCALHOST";
public static final String ENV_BTC_NODES_KEY = "BTC_NODES";
public static final String ENV_BTC_NODES_VALUE = "bitcoin:18444";
public static final String ENV_SEED_NODES_KEY = "SEED_NODES";
public static final String ENV_SEED_NODES_VALUE = SEED_NODE_ADDRESS;
public static final String ENV_LOG_LEVEL_KEY = "LOG_LEVEL";
public static final String ENV_LOG_LEVEL_VALUE = "warn";

@SuppressWarnings("WeakerAccess")
public static ContainerBuilder.ContainerOptionsBuilder createApiContainerBuilder(String nameSuffix, String portBinding, int nodePort, boolean linkToSeedNode, boolean linkToBitcoin, boolean enableExperimentalFeatures) {
ContainerBuilder.ContainerOptionsBuilder containerOptionsBuilder = Container.withContainerName(CONTAINER_NAME_PREFIX + nameSuffix)
.fromImage(API_IMAGE)
.withPortBinding(portBinding)
.withEnvironment(ENV_NODE_PORT_KEY, nodePort)
.withEnvironment(ENV_HTTP_API_HOST_KEY, ENV_HTTP_API_HOST_VALUE)
.withEnvironment(ENV_ENABLE_HTTP_API_EXPERIMENTAL_FEATURES_KEY, enableExperimentalFeatures)
.withEnvironment(ENV_USE_DEV_PRIVILEGE_KEYS_KEY, ENV_USE_DEV_PRIVILEGE_KEYS_VALUE)
.withAwaitStrategy(getAwaitStrategy());
if (linkToSeedNode) {
containerOptionsBuilder.withLink(SEED_NODE_CONTAINER_NAME);
}
if (linkToBitcoin) {
containerOptionsBuilder.withLink(BITCOIN_NODE_CONTAINER_NAME, BITCOIN_NODE_HOST_NAME);
}
return withRegtestEnv(containerOptionsBuilder);
}

public static Await getAwaitStrategy() {
Await awaitStrategy = new Await();
awaitStrategy.setStrategy("polling");
int sleepPollingTime = 250;
awaitStrategy.setIterations(60000 / sleepPollingTime);
awaitStrategy.setSleepPollingTime(sleepPollingTime);
return awaitStrategy;
}

public static Container createApiContainer(String nameSuffix, String portBinding, int nodePort, boolean linkToSeedNode, boolean linkToBitcoin, boolean enableExperimentalFeatures) {
Container container = createApiContainerBuilder(nameSuffix, portBinding, nodePort, linkToSeedNode, linkToBitcoin, enableExperimentalFeatures).build();
container.getCubeContainer().setKillContainer(true);
return container;
}

public static Container createApiContainer(String nameSuffix, String portBinding, int nodePort, boolean linkToSeedNode, boolean linkToBitcoin) {
return createApiContainer(nameSuffix, portBinding, nodePort, linkToSeedNode, linkToBitcoin, true);
}

public static ContainerBuilder.ContainerOptionsBuilder withRegtestEnv(ContainerBuilder.ContainerOptionsBuilder builder) {
return builder
.withEnvironment(ENV_USE_LOCALHOST_FOR_P2P_KEY, ENV_USE_LOCALHOST_FOR_P2P_VALUE)
.withEnvironment(ENV_BASE_CURRENCY_NETWORK_KEY, ENV_BASE_CURRENCY_NETWORK_VALUE)
.withEnvironment(ENV_BITCOIN_REGTEST_HOST_KEY, ENV_BITCOIN_REGTEST_HOST_VALUE)
.withEnvironment(ENV_BTC_NODES_KEY, ENV_BTC_NODES_VALUE)
.withEnvironment(ENV_SEED_NODES_KEY, ENV_SEED_NODES_VALUE)
.withEnvironment(ENV_LOG_LEVEL_KEY, ENV_LOG_LEVEL_VALUE);
}

}
45 changes: 45 additions & 0 deletions api/src/testIntegration/java/bisq/api/http/RegexMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.api.http;

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class RegexMatcher extends TypeSafeMatcher<String> {

private final String regex;

private RegexMatcher(String regex) {
this.regex = regex;
}

@SuppressWarnings("WeakerAccess")
public static RegexMatcher matchesRegex(String regex) {
return new RegexMatcher(regex);
}

@Override
public void describeTo(Description description) {
description.appendText("matches regex=`" + regex + "`");
}

@Override
public boolean matchesSafely(String string) {
return string.matches(regex);
}
}
78 changes: 78 additions & 0 deletions api/src/testIntegration/java/bisq/api/http/SwaggerIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.api.http;

import org.junit.Test;
import org.junit.runner.RunWith;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;



import org.arquillian.cube.docker.impl.client.containerobject.dsl.Container;
import org.arquillian.cube.docker.impl.client.containerobject.dsl.DockerContainer;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;

@RunWith(Arquillian.class)
public class SwaggerIT {

@DockerContainer
private Container alice = ContainerFactory.createApiContainer("alice", "8081->8080", 3333, false, false);

@InSequence(1)
@Test
public void getDocs_always_returns200() {
int alicePort = getAlicePort();

given().
port(alicePort).
//
when().
get("/docs").
//
then().
statusCode(200).
and().body(containsString("Swagger UI"))
;
}

@InSequence(1)
@Test
public void getOpenApiJson_always_returns200() {
int alicePort = getAlicePort();

given().
port(alicePort).
//
when().
get("/openapi.json").
//
then().
statusCode(200).
and().body("info.title", equalTo("Bisq HTTP API"))
;
}

private int getAlicePort() {
return alice.getBindPort(8080);
}

}
Loading

0 comments on commit a28d9ca

Please sign in to comment.