Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor apitest for api calls to any daemon type #4525

Merged
merged 9 commits into from
Sep 16, 2020
4 changes: 2 additions & 2 deletions apitest/scripts/mainnet-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@
run ./bisq-cli --password="xyz" getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
[ "$output" = "1.3.7" ]
[ "$output" = "1.3.8" ]
}

@test "test getversion" {
run ./bisq-cli --password=xyz getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
[ "$output" = "1.3.7" ]
[ "$output" = "1.3.8" ]
}

@test "test setwalletpassword \"a b c\"" {
Expand Down
4 changes: 3 additions & 1 deletion apitest/src/main/java/bisq/apitest/config/ApiTestConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import java.net.InetAddress;

import java.nio.file.Paths;

import java.io.File;
Expand Down Expand Up @@ -169,7 +171,7 @@ public ApiTestConfig(String... args) {
ArgumentAcceptingOptionSpec<String> bitcoinRegtestHostOpt =
parser.accepts(BITCOIN_REGTEST_HOST, "Bitcoin Core regtest host")
.withRequiredArg()
.ofType(String.class).defaultsTo("localhost");
.ofType(String.class).defaultsTo(InetAddress.getLoopbackAddress().getHostAddress());

ArgumentAcceptingOptionSpec<Integer> bitcoinRpcPortOpt =
parser.accepts(BITCOIN_RPC_PORT, "Bitcoin Core rpc port (non-default)")
Expand Down
27 changes: 19 additions & 8 deletions apitest/src/test/java/bisq/apitest/ApiTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@

package bisq.apitest;

import java.net.InetAddress;

import java.io.IOException;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static java.util.concurrent.TimeUnit.MILLISECONDS;



import bisq.apitest.config.ApiTestConfig;
import bisq.apitest.config.BisqAppConfig;
import bisq.apitest.method.BitcoinCliHelper;
import bisq.cli.GrpcStubs;

Expand Down Expand Up @@ -57,34 +61,41 @@
*/
public class ApiTestCase {

// The gRPC service stubs are used by method & scenario tests, but not e2e tests.
protected static GrpcStubs grpcStubs;

protected static Scaffold scaffold;
protected static ApiTestConfig config;
protected static BitcoinCliHelper bitcoinCli;

// gRPC service stubs are used by method & scenario tests, but not e2e tests.
private static final Map<BisqAppConfig, GrpcStubs> grpcStubsCache = new HashMap<>();

public static void setUpScaffold(String supportingApps)
throws InterruptedException, ExecutionException, IOException {
scaffold = new Scaffold(supportingApps).setUp();
config = scaffold.config;
bitcoinCli = new BitcoinCliHelper((config));
// For now, all grpc requests are sent to the alicedaemon, but this will need to
// be made configurable for new test cases that call arb or bob node daemons.
grpcStubs = new GrpcStubs("localhost", alicedaemon.apiPort, config.apiPassword);
}

public static void setUpScaffold(String[] params)
throws InterruptedException, ExecutionException, IOException {
scaffold = new Scaffold(params).setUp();
config = scaffold.config;
grpcStubs = new GrpcStubs("localhost", alicedaemon.apiPort, config.apiPassword);
}

public static void tearDownScaffold() {
scaffold.tearDown();
}

protected static GrpcStubs grpcStubs(BisqAppConfig bisqAppConfig) {
if (grpcStubsCache.containsKey(bisqAppConfig)) {
return grpcStubsCache.get(bisqAppConfig);
} else {
GrpcStubs stubs = new GrpcStubs(InetAddress.getLoopbackAddress().getHostAddress(),
bisqAppConfig.apiPort, config.apiPassword);
grpcStubsCache.put(bisqAppConfig, stubs);
return stubs;
}
}

protected void sleep(long ms) {
try {
MILLISECONDS.sleep(ms);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
Expand Down Expand Up @@ -57,7 +58,8 @@ public static void setUp() {
public void testGetBalance() {
// All tests depend on the DAO / regtest environment, and Alice's wallet is
// initialized with 10 BTC during the scaffolding setup.
var balance = grpcStubs.walletsService.getBalance(GetBalanceRequest.newBuilder().build()).getBalance();
var balance = grpcStubs(alicedaemon).walletsService
.getBalance(GetBalanceRequest.newBuilder().build()).getBalance();
assertEquals(1000000000, balance);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public static void setUp() {
@Test
@Order(1)
public void testGetVersion() {
var version = grpcStubs.versionService.getVersion(GetVersionRequest.newBuilder().build()).getVersion();
var version = grpcStubs(alicedaemon).versionService
.getVersion(GetVersionRequest.newBuilder().build()).getVersion();
assertEquals(VERSION, version);
}

Expand Down
27 changes: 19 additions & 8 deletions apitest/src/test/java/bisq/apitest/method/MethodTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@
import bisq.proto.grpc.GetBalanceRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
import bisq.proto.grpc.LockWalletRequest;
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
import bisq.proto.grpc.UnlockWalletRequest;

import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY;



import bisq.apitest.ApiTestCase;
import bisq.apitest.config.BisqAppConfig;

public class MethodTest extends ApiTestCase {

Expand Down Expand Up @@ -60,24 +64,31 @@ protected final GetFundingAddressesRequest createGetFundingAddressesRequest() {
return GetFundingAddressesRequest.newBuilder().build();
}

protected final RegisterDisputeAgentRequest createRegisterDisputeAgentRequest(String disputeAgentType) {
return RegisterDisputeAgentRequest.newBuilder()
.setDisputeAgentType(disputeAgentType)
.setRegistrationKey(DEV_PRIVILEGE_PRIV_KEY).build();
}

// Convenience methods for calling frequently used & thoroughly tested gRPC services.

protected final long getBalance() {
return grpcStubs.walletsService.getBalance(createBalanceRequest()).getBalance();
protected final long getBalance(BisqAppConfig bisqAppConfig) {
return grpcStubs(bisqAppConfig).walletsService.getBalance(createBalanceRequest()).getBalance();
}

protected final void unlockWallet(String password, long timeout) {
protected final void unlockWallet(BisqAppConfig bisqAppConfig, String password, long timeout) {
//noinspection ResultOfMethodCallIgnored
grpcStubs.walletsService.unlockWallet(createUnlockWalletRequest(password, timeout));
grpcStubs(bisqAppConfig).walletsService.unlockWallet(createUnlockWalletRequest(password, timeout));
}

protected final void lockWallet() {
protected final void lockWallet(BisqAppConfig bisqAppConfig) {
//noinspection ResultOfMethodCallIgnored
grpcStubs.walletsService.lockWallet(createLockWalletRequest());
grpcStubs(bisqAppConfig).walletsService.lockWallet(createLockWalletRequest());
}

protected final String getUnusedBtcAddress() {
return grpcStubs.walletsService.getFundingAddresses(createGetFundingAddressesRequest())
protected final String getUnusedBtcAddress(BisqAppConfig bisqAppConfig) {
//noinspection OptionalGetWithoutIsPresent
return grpcStubs(bisqAppConfig).walletsService.getFundingAddresses(createGetFundingAddressesRequest())
.getAddressBalanceInfoList()
.stream()
.filter(a -> a.getBalance() == 0 && a.getNumConfirmations() == 0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* 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.apitest.method;

import bisq.proto.grpc.RegisterDisputeAgentRequest;

import io.grpc.StatusRuntimeException;

import lombok.extern.slf4j.Slf4j;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static bisq.apitest.config.BisqAppConfig.arbdaemon;
import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation;


@SuppressWarnings("ResultOfMethodCallIgnored")
@Slf4j
@TestMethodOrder(OrderAnnotation.class)
public class RegisterDisputeAgentsTest extends MethodTest {

@BeforeAll
public static void setUp() {
try {
setUpScaffold("bitcoind,seednode,arbdaemon");
} catch (Exception ex) {
fail(ex);
}
}

@Test
@Order(1)
public void testRegisterArbitratorShouldThrowException() {
var req =
createRegisterDisputeAgentRequest("arbitrator");
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req));
assertEquals("INVALID_ARGUMENT: arbitrators must be registered in a Bisq UI",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on string matching for tests makes them fragile. At a minimum we should probably add a note for strings that are used in this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix this in another PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this happens quite a bit in other tests as well iirc. Not urgent, but good to have a better solution for the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string matching problem has bitten me a few times, when I misspelled "bitciond" in some test case setups.
PR 4540 fixes it.

exception.getMessage());
}

@Test
@Order(2)
public void testInvalidDisputeAgentTypeArgShouldThrowException() {
var req =
createRegisterDisputeAgentRequest("badagent");
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req));
assertEquals("INVALID_ARGUMENT: unknown dispute agent type badagent",
exception.getMessage());
}

@Test
@Order(3)
public void testInvalidRegistrationKeyArgShouldThrowException() {
var req = RegisterDisputeAgentRequest.newBuilder()
.setDisputeAgentType("refundagent")
.setRegistrationKey("invalid" + DEV_PRIVILEGE_PRIV_KEY).build();
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req));
assertEquals("INVALID_ARGUMENT: invalid registration key",
exception.getMessage());
}

@Test
@Order(4)
public void testRegisterMediator() {
var req =
createRegisterDisputeAgentRequest("mediator");
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req);
}

@Test
@Order(5)
public void testRegisterRefundAgent() {
var req =
createRegisterDisputeAgentRequest("refundagent");
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req);
}

@AfterAll
public static void tearDown() {
tearDownScaffold();
}
}
Loading