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

Allow remote debugging of background Bisq apps #4433

Merged
merged 5 commits into from
Aug 31, 2020
Merged
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
14 changes: 7 additions & 7 deletions cli/test.sh → apitest/scripts/mainnet-test.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env bats
#
# Integration tests for bisq-cli running against a live bisq-daemon
# Smoke tests for bisq-cli running against a live bisq-daemon (on mainnet)
#
# Prerequisites:
#
# - bats v0.4.0 must be installed (brew install bats on macOS)
# see https://github.com/sstephenson/bats/tree/v0.4.0
# - bats-core 1.2.0+ must be installed (brew install bats-core on macOS)
# see https://github.com/bats-core/bats-core
#
# - Run `./bisq-daemon --apiPassword=xyz --appDataDir=$TESTDIR` where $TESTDIR
# is empty or otherwise contains an unencrypted wallet with a 0 BTC balance
Expand Down Expand Up @@ -48,14 +48,14 @@
run ./bisq-cli --password="xyz" getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
[ "$output" = "1.3.5" ]
[ "$output" = "1.3.7" ]
}

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

@test "test setwalletpassword \"a b c\"" {
Expand Down Expand Up @@ -190,8 +190,8 @@
[ "$output" = "Error: incorrect parameter count, expecting direction (buy|sell), currency code" ]
}

@test "test getoffers buy eur check return status" {
run ./bisq-cli --password=xyz getoffers buy eur
@test "test getoffers sell eur check return status" {
run ./bisq-cli --password=xyz getoffers sell eur
[ "$status" -eq 0 ]
}

Expand Down
26 changes: 15 additions & 11 deletions apitest/src/main/java/bisq/apitest/Scaffold.java
Original file line number Diff line number Diff line change
Expand Up @@ -311,46 +311,50 @@ private void startBackgroundProcesses(ExecutorService executor,
bitcoinDaemon.verifyBitcoindRunning();
}

// Start Bisq apps defined by the supportingApps option, in the in proper order.

if (config.hasSupportingApp(seednode.name()))
startBisqApp(seednode, executor, countdownLatch);

if (config.hasSupportingApp(arbdaemon.name(), arbdesktop.name()))
startBisqApp(config.runArbNodeAsDesktop ? arbdesktop : arbdaemon, executor, countdownLatch);
if (config.hasSupportingApp(arbdaemon.name()))
startBisqApp(arbdaemon, executor, countdownLatch);
else if (config.hasSupportingApp(arbdesktop.name()))
startBisqApp(arbdesktop, executor, countdownLatch);

if (config.hasSupportingApp(alicedaemon.name(), alicedesktop.name()))
startBisqApp(config.runAliceNodeAsDesktop ? alicedesktop : alicedaemon, executor, countdownLatch);
if (config.hasSupportingApp(alicedaemon.name()))
startBisqApp(alicedaemon, executor, countdownLatch);
else if (config.hasSupportingApp(alicedesktop.name()))
startBisqApp(alicedesktop, executor, countdownLatch);

if (config.hasSupportingApp(bobdaemon.name(), bobdesktop.name()))
startBisqApp(config.runBobNodeAsDesktop ? bobdesktop : bobdaemon, executor, countdownLatch);
if (config.hasSupportingApp(bobdaemon.name()))
startBisqApp(bobdaemon, executor, countdownLatch);
else if (config.hasSupportingApp(bobdesktop.name()))
startBisqApp(bobdesktop, executor, countdownLatch);
}

private void startBisqApp(BisqAppConfig bisqAppConfig,
ExecutorService executor,
CountDownLatch countdownLatch)
throws IOException, InterruptedException {

BisqApp bisqApp;
BisqApp bisqApp = createBisqApp(bisqAppConfig);
switch (bisqAppConfig) {
case seednode:
bisqApp = createBisqApp(seednode);
seedNodeTask = new SetupTask(bisqApp, countdownLatch);
seedNodeTaskFuture = executor.submit(seedNodeTask);
break;
case arbdaemon:
case arbdesktop:
bisqApp = createBisqApp(config.runArbNodeAsDesktop ? arbdesktop : arbdaemon);
arbNodeTask = new SetupTask(bisqApp, countdownLatch);
arbNodeTaskFuture = executor.submit(arbNodeTask);
break;
case alicedaemon:
case alicedesktop:
bisqApp = createBisqApp(config.runAliceNodeAsDesktop ? alicedesktop : alicedaemon);
aliceNodeTask = new SetupTask(bisqApp, countdownLatch);
aliceNodeTaskFuture = executor.submit(aliceNodeTask);
break;
case bobdaemon:
case bobdesktop:
bisqApp = createBisqApp(config.runBobNodeAsDesktop ? bobdesktop : bobdaemon);
bobNodeTask = new SetupTask(bisqApp, countdownLatch);
bobNodeTaskFuture = executor.submit(bobNodeTask);
break;
Expand Down
39 changes: 9 additions & 30 deletions apitest/src/main/java/bisq/apitest/config/ApiTestConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,11 @@ public class ApiTestConfig {
static final String ROOT_APP_DATA_DIR = "rootAppDataDir";
static final String API_PASSWORD = "apiPassword";
static final String RUN_SUBPROJECT_JARS = "runSubprojectJars";
static final String RUN_ARB_NODE_AS_DESKTOP = "runArbNodeAsDesktop";
static final String RUN_ALICE_NODE_AS_DESKTOP = "runAliceNodeAsDesktop";
static final String RUN_BOB_NODE_AS_DESKTOP = "runBobNodeAsDesktop";
static final String BISQ_APP_INIT_TIME = "bisqAppInitTime";
static final String SKIP_TESTS = "skipTests";
static final String SHUTDOWN_AFTER_TESTS = "shutdownAfterTests";
static final String SUPPORTING_APPS = "supportingApps";
static final String ENABLE_BISQ_DEBUGGING = "enableBisqDebugging";

// Default values for certain options
static final String DEFAULT_CONFIG_FILE_NAME = "apitest.properties";
Expand All @@ -98,13 +96,11 @@ public class ApiTestConfig {
// Daemon instances can use same gRPC password, but each needs a different apiPort.
public final String apiPassword;
public final boolean runSubprojectJars;
public final boolean runArbNodeAsDesktop;
public final boolean runAliceNodeAsDesktop;
public final boolean runBobNodeAsDesktop;
public final long bisqAppInitTime;
public final boolean skipTests;
public final boolean shutdownAfterTests;
public final List<String> supportingApps;
public final boolean enableBisqDebugging;

// Immutable system configurations set in the constructor.
public final String bitcoinDatadir;
Expand Down Expand Up @@ -202,27 +198,6 @@ public ApiTestConfig(String... args) {
.ofType(Boolean.class)
.defaultsTo(false);

ArgumentAcceptingOptionSpec<Boolean> runArbNodeAsDesktopOpt =
parser.accepts(RUN_ARB_NODE_AS_DESKTOP,
"Run Arbitration node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false); // TODO how do I register mediator?

ArgumentAcceptingOptionSpec<Boolean> runAliceNodeAsDesktopOpt =
parser.accepts(RUN_ALICE_NODE_AS_DESKTOP,
"Run Alice node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);

ArgumentAcceptingOptionSpec<Boolean> runBobNodeAsDesktopOpt =
parser.accepts(RUN_BOB_NODE_AS_DESKTOP,
"Run Bob node as desktop")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);

ArgumentAcceptingOptionSpec<Long> bisqAppInitTimeOpt =
parser.accepts(BISQ_APP_INIT_TIME,
"Amount of time (ms) to wait on a Bisq instance's initialization")
Expand Down Expand Up @@ -251,6 +226,12 @@ public ApiTestConfig(String... args) {
.ofType(String.class)
.defaultsTo("bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon");

ArgumentAcceptingOptionSpec<Boolean> enableBisqDebuggingOpt =
parser.accepts(ENABLE_BISQ_DEBUGGING,
"Start Bisq apps with remote debug options")
.withRequiredArg()
.ofType(Boolean.class)
.defaultsTo(false);
try {
CompositeOptionSet options = new CompositeOptionSet();

Expand Down Expand Up @@ -302,13 +283,11 @@ public ApiTestConfig(String... args) {
this.bitcoinRpcPassword = options.valueOf(bitcoinRpcPasswordOpt);
this.apiPassword = options.valueOf(apiPasswordOpt);
this.runSubprojectJars = options.valueOf(runSubprojectJarsOpt);
this.runArbNodeAsDesktop = options.valueOf(runArbNodeAsDesktopOpt);
this.runAliceNodeAsDesktop = options.valueOf(runAliceNodeAsDesktopOpt);
this.runBobNodeAsDesktop = options.valueOf(runBobNodeAsDesktopOpt);
this.bisqAppInitTime = options.valueOf(bisqAppInitTimeOpt);
this.skipTests = options.valueOf(skipTestsOpt);
this.shutdownAfterTests = options.valueOf(shutdownAfterTestsOpt);
this.supportingApps = asList(options.valueOf(supportingAppsOpt).split(","));
this.enableBisqDebugging = options.valueOf(enableBisqDebuggingOpt);

// Assign values to special-case static fields.
BASH_PATH_VALUE = bashPath;
Expand Down
42 changes: 26 additions & 16 deletions apitest/src/main/java/bisq/apitest/config/BisqAppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,58 +30,64 @@
@see <a href="https://github.com/bisq-network/bisq/blob/master/docs/dev-setup.md">dev-setup.md</a>
@see <a href="https://github.com/bisq-network/bisq/blob/master/docs/dao-setup.md">dao-setup.md</a>
*/
@SuppressWarnings("unused")
public enum BisqAppConfig {

seednode("bisq-BTC_REGTEST_Seed_2002",
"bisq-seednode",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
SeedNodeMain.class.getName(),
2002,
5120,
-1),
-1,
49996),
arbdaemon("bisq-BTC_REGTEST_Arb_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
4444,
5121,
9997),
9997,
49997),
arbdesktop("bisq-BTC_REGTEST_Arb_dao",
"bisq-desktop",
"\"-XX:MaxRAM=3g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=3g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
4444,
5121,
-1),
-1,
49997),
alicedaemon("bisq-BTC_REGTEST_Alice_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
7777,
5122,
9998),
9998,
49998),
alicedesktop("bisq-BTC_REGTEST_Alice_dao",
"bisq-desktop",
"\"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
7777,
5122,
-1),
-1,
49998),
bobdaemon("bisq-BTC_REGTEST_Bob_dao",
"bisq-daemon",
"\"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=2g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqDaemonMain.class.getName(),
8888,
5123,
9999),
9999,
49999),
bobdesktop("bisq-BTC_REGTEST_Bob_dao",
"bisq-desktop",
"\"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml\"",
"-XX:MaxRAM=4g -Dlogback.configurationFile=apitest/build/resources/main/logback.xml",
BisqAppMain.class.getName(),
8888,
5123,
-1);
-1,
49999);

public final String appName;
public final String startupScript;
Expand All @@ -91,21 +97,24 @@ public enum BisqAppConfig {
public final int rpcBlockNotificationPort;
// Daemons can use a global gRPC password, but each needs a unique apiPort.
public final int apiPort;
public final int remoteDebugPort;

BisqAppConfig(String appName,
String startupScript,
String javaOpts,
String mainClassName,
int nodePort,
int rpcBlockNotificationPort,
int apiPort) {
int apiPort,
int remoteDebugPort) {
this.appName = appName;
this.startupScript = startupScript;
this.javaOpts = javaOpts;
this.mainClassName = mainClassName;
this.nodePort = nodePort;
this.rpcBlockNotificationPort = rpcBlockNotificationPort;
this.apiPort = apiPort;
this.remoteDebugPort = remoteDebugPort;
}

@Override
Expand All @@ -118,6 +127,7 @@ public String toString() {
", nodePort=" + nodePort + "\n" +
", rpcBlockNotificationPort=" + rpcBlockNotificationPort + "\n" +
", apiPort=" + apiPort + "\n" +
", remoteDebugPort=" + remoteDebugPort + "\n" +
'}';
}
}
7 changes: 5 additions & 2 deletions apitest/src/main/java/bisq/apitest/linux/BisqApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class BisqApp extends AbstractLinuxProcess implements LinuxProcess {
private final boolean useLocalhostForP2P;
public final boolean useDevPrivilegeKeys;
private final String findBisqPidScript;
private final String debugOpts;

public BisqApp(BisqAppConfig bisqAppConfig, ApiTestConfig config) {
super(bisqAppConfig.appName, config);
Expand All @@ -67,6 +68,9 @@ public BisqApp(BisqAppConfig bisqAppConfig, ApiTestConfig config) {
this.useDevPrivilegeKeys = true;
this.findBisqPidScript = (config.isRunningTest ? "." : "./apitest")
+ "/scripts/get-bisq-pid.sh";
this.debugOpts = config.enableBisqDebugging
? " -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:" + bisqAppConfig.remoteDebugPort
: "";
}

@Override
Expand Down Expand Up @@ -112,7 +116,6 @@ public void shutdown() {

if (isAlive(pid)) {
this.shutdownExceptions.add(new IllegalStateException(format("%s shutdown did not work", bisqAppConfig.appName)));
return;
}

} catch (Exception e) {
Expand Down Expand Up @@ -209,7 +212,7 @@ private long findBisqAppPid() throws IOException, InterruptedException {
}

private String getJavaOptsSpec() {
return "export JAVA_OPTS=" + bisqAppConfig.javaOpts + "; ";
return "export JAVA_OPTS=\"" + bisqAppConfig.javaOpts + debugOpts + "\"; ";
}

private List<String> getOptsList() {
Expand Down
13 changes: 7 additions & 6 deletions apitest/src/test/java/bisq/apitest/ApiTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

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

/**
* Base class for all test types: 'method', 'scenario' and 'e2e'.
Expand Down Expand Up @@ -65,19 +66,19 @@ public class ApiTestCase {

public static void setUpScaffold(String supportingApps)
throws InterruptedException, ExecutionException, IOException {
// The supportingApps argument is a comma delimited string of supporting app
// names, e.g. "bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon"
scaffold = new Scaffold(supportingApps).setUp();
config = scaffold.config;
bitcoinCli = new BitcoinCliHelper((config));
grpcStubs = new GrpcStubs(alicedaemon, config).init();
// 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()
public static void setUpScaffold(String[] params)
throws InterruptedException, ExecutionException, IOException {
scaffold = new Scaffold(new String[]{}).setUp();
scaffold = new Scaffold(params).setUp();
config = scaffold.config;
grpcStubs = new GrpcStubs(alicedaemon, config).init();
grpcStubs = new GrpcStubs("localhost", alicedaemon.apiPort, config.apiPassword);
}

public static void tearDownScaffold() {
Expand Down
Loading