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

Add API test harness for Linux & OSX #4366

Merged
merged 88 commits into from Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
88b5e9d
Add configuration support
ghubstan Jul 9, 2020
e0c27ee
Add main resource files
ghubstan Jul 9, 2020
77b6878
Add script to get Bisq app pid
ghubstan Jul 9, 2020
c0c75e2
Support starting bitcoin & bisq apps on Linux
ghubstan Jul 9, 2020
ae3b263
Add :apitest main driver, setup task & dummy tests
ghubstan Jul 9, 2020
e9baebc
Add build tasks for installing dao-setup files
ghubstan Jul 9, 2020
2cd80aa
Add subproject :apitest to gradle build file
ghubstan Jul 9, 2020
09929c8
Fix codacy problems
ghubstan Jul 9, 2020
efbaa5b
Fix codacy problems
ghubstan Jul 9, 2020
05d0ce0
Fix codacy problem
ghubstan Jul 9, 2020
ca378cd
Fix error msg spacing
ghubstan Jul 10, 2020
798fde8
Fix error msgs
ghubstan Jul 10, 2020
e61a42d
Remove MaxRAM from DEFAULT_JVM_OPTS
ghubstan Jul 10, 2020
898219a
Assume bitcoin-core is statically linked to berkeley-db
ghubstan Jul 11, 2020
a1e2536
Fix hanging background process problem
ghubstan Jul 11, 2020
8519021
Add line break in front of port config
ghubstan Jul 12, 2020
87525ca
Move test setup scaffolding into new Scaffold class
ghubstan Jul 12, 2020
2c10836
Expose grpc service stubs
ghubstan Jul 12, 2020
ffe376e
Fix codacy problems
ghubstan Jul 12, 2020
390cba1
Fix codacy problem
ghubstan Jul 12, 2020
96cabfb
Support @Skip on test classes and methods
ghubstan Jul 13, 2020
0edcc3b
Add first method test cases
ghubstan Jul 13, 2020
81aeedd
Add MethodTestSuite
ghubstan Jul 13, 2020
8da4646
Update bats version test
ghubstan Jul 13, 2020
db5a685
Make init() method public
ghubstan Jul 13, 2020
65e3370
Add license note, format tearDown(), fix comment
ghubstan Jul 13, 2020
fae661c
Run MethodTestSuite
ghubstan Jul 13, 2020
458d2f3
Add license note
ghubstan Jul 13, 2020
4d5c767
Fix codacy problem
ghubstan Jul 13, 2020
35ff4e5
Delete commented statement
ghubstan Jul 13, 2020
d782e8d
Do not run dummy test from driver
ghubstan Jul 13, 2020
84976fe
Fix varible names
ghubstan Jul 13, 2020
2678b31
Remove test scaffolding logic from ApiTestConfig
ghubstan Jul 13, 2020
486f06b
Refresh dao-setup files in Scaffold setup
ghubstan Jul 13, 2020
e17480a
Remove hacked method tests
ghubstan Jul 13, 2020
080952b
Support @Order-ing of JUnit tests
ghubstan Jul 13, 2020
4f08ec3
Add first JUnit 'method' tests
ghubstan Jul 13, 2020
84af092
Add driver for running method tests
ghubstan Jul 14, 2020
1acf340
Get rid of references to removed @Skip annotation
ghubstan Jul 14, 2020
8ed44b8
Remove @Skip annotaion
ghubstan Jul 14, 2020
45c1a97
Fix codacy problem in bash script
ghubstan Jul 14, 2020
6b738f7
Replace config 'numSetupTasks' with 'supportingApps'
ghubstan Jul 14, 2020
498939a
Allow more time for background app shutdown
ghubstan Jul 14, 2020
5df0b1e
Refactor ApiTestCase class hierarchy
ghubstan Jul 14, 2020
2cf7915
Add wallet protect method tests
ghubstan Jul 14, 2020
28aefc5
Add tests for resetting a wallet password
ghubstan Jul 14, 2020
a00bc4b
Add --bisqAppInitTime=<Long> config option
ghubstan Jul 15, 2020
cf3b545
Fix hardcoded bitcoin.conf property values
ghubstan Jul 15, 2020
d108d89
Fix comment and code styling
ghubstan Jul 15, 2020
c19afeb
Fix 'bitcoind not found' error message
ghubstan Jul 15, 2020
b2417d3
Delete throws clause from method signature
ghubstan Jul 15, 2020
e0ea9db
Fix bitcoind startup error handling
ghubstan Jul 15, 2020
431cbe7
Bump bisqAppInitTime default back up to 5s
ghubstan Jul 15, 2020
4296d96
Remove all sudo related logic from the linux pkg
ghubstan Jul 16, 2020
7d664d9
Do not "killall bitcoind" processes
ghubstan Jul 16, 2020
6edab1a
Create convenient way to call bitcoin-cli from tests
ghubstan Jul 16, 2020
687bcf1
Add FundWalletScenarioTest
ghubstan Jul 16, 2020
2852e3d
Add JUnitHelper to run tests from JUnitCore
ghubstan Jul 16, 2020
5d7133a
Do not subtract fee from 'bitcoin-cli sendtoaddress'
ghubstan Jul 17, 2020
8269a0d
Remove final modifier
ghubstan Jul 17, 2020
f7d8c0e
Do not use bitcoin.conf files
ghubstan Jul 17, 2020
1847da0
Delete unused bitcoin.conf from resources dir
ghubstan Jul 17, 2020
19346bb
Delete all JUnit related class from main sources
ghubstan Jul 19, 2020
7c974b2
Moving GrpcStubs to test sources
ghubstan Jul 19, 2020
bf584c2
Move test cases into subproject test sources
ghubstan Jul 19, 2020
591c8b2
Change :apitest:test task system property name
ghubstan Jul 20, 2020
b4d3ea7
Add comment about Bisq DAO dev environment
ghubstan Jul 20, 2020
999e9ec
Fix @BeforeClass error handling and use jupiter api
ghubstan Jul 20, 2020
13a8396
Remove unnecessary curly braces
ghubstan Jul 20, 2020
cf031e6
Change 'missing bitcoind path' error msg
ghubstan Jul 22, 2020
27ee4b8
Do not leave orphaned processes after failed teardown
ghubstan Jul 27, 2020
e2f00b7
Remove extra whiteline
ghubstan Jul 27, 2020
8bb7e12
Clarify scaffold tear down error handling
ghubstan Jul 28, 2020
685839d
Add fallbackfee param to bitcoind start cmd
ghubstan Aug 12, 2020
176f0b2
Fix BitcoinCli wrapper error handling
ghubstan Aug 13, 2020
9637cc0
Fix test fail() msg
ghubstan Aug 13, 2020
72ff4dc
Use non-default regtest bitcoind -rpcport
ghubstan Aug 15, 2020
e88bdb9
Add regtest-port-conflicts.md doc
ghubstan Aug 15, 2020
12d52e8
Fix port number typo
ghubstan Aug 15, 2020
fc54125
Add build / run / test categories docs
ghubstan Aug 17, 2020
f85ae2b
Explain how to run test cases from Intellij
ghubstan Aug 17, 2020
af7252e
Fix typo
ghubstan Aug 17, 2020
8b081ad
Update README
ghubstan Aug 17, 2020
c3abd4e
Remove white lines
ghubstan Aug 18, 2020
fa11dab
Add punctuation & re-phrase sentence in README
ghubstan Aug 19, 2020
2ba0ee9
Change access modifer
ghubstan Aug 19, 2020
ba8b9cc
Put 'empty' comments inside ignored catch blocks
ghubstan Aug 19, 2020
1de6239
Shorten line length < 120 chars
ghubstan Aug 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions apitest/src/main/java/bisq/apitest/JUnitHelper.java
@@ -0,0 +1,51 @@
package bisq.apitest;

import lombok.extern.slf4j.Slf4j;

import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

import static java.lang.String.format;

@Slf4j
public class JUnitHelper {

public static void runTests(Class... testClasses) {
JUnitCore jUnitCore = new JUnitCore();
jUnitCore.addListener(new RunListener() {
public void testStarted(Description description) {
log.info("{}", description);
}

public void testIgnored(Description description) {
log.info("Ignored {}", description);
}

public void testFailure(Failure failure) {
log.error("Failed {}", failure.getTrace());
}
});
Result result = jUnitCore.run(testClasses);
printTestResults(result);
}

public static void printTestResults(Result result) {
log.info("Total tests: {}, Failed: {}, Ignored: {}",
result.getRunCount(),
result.getFailureCount(),
result.getIgnoreCount());

if (result.wasSuccessful()) {
log.info("All {} tests passed", result.getRunCount());
} else if (result.getFailureCount() > 0) {
log.error("{} test(s) failed", result.getFailureCount());
result.getFailures().iterator().forEachRemaining(f -> log.error(format("%s.%s()%n\t%s",
f.getDescription().getTestClass().getName(),
f.getDescription().getMethodName(),
f.getTrace())));
}
}
}
28 changes: 25 additions & 3 deletions apitest/src/main/java/bisq/apitest/method/BitcoinCliHelper.java
Expand Up @@ -20,6 +20,7 @@
import java.io.IOException;

import static java.lang.String.format;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;


Expand All @@ -39,7 +40,9 @@ public BitcoinCliHelper(ApiTestConfig config) {

public String getNewBtcAddress() {
try {
return new BitcoinCli(config, "getnewaddress").run().getOutput();
String newAddress = new BitcoinCli(config, "getnewaddress").run().getOutput();
assertNotNull(newAddress);
return newAddress;
} catch (IOException | InterruptedException ex) {
fail(ex.getMessage());
return null;
Expand All @@ -50,8 +53,9 @@ public String[] generateToAddress(int blocks, String address) {
try {
String generateToAddressCmd = format("generatetoaddress %d \"%s\"", blocks, address);
BitcoinCli generateToAddress = new BitcoinCli(config, generateToAddressCmd).run();
// Return an array of transaction ids.
return generateToAddress.getOutputValueAsStringArray();
String[] txids = generateToAddress.getOutputValueAsStringArray();
assertNotNull(txids);
return txids;
} catch (IOException | InterruptedException ex) {
fail(ex.getMessage());
return null;
Expand All @@ -61,4 +65,22 @@ public String[] generateToAddress(int blocks, String address) {
public void generateBlocks(int blocks) {
generateToAddress(blocks, getNewBtcAddress());
}

public String sendToAddress(String address, double amount) {
// sendtoaddress "address" amount \
// ( "comment" "comment_to" subtractfeefromamount \
// replaceable conf_target "estimate_mode" )
// returns a transaction id
try {
String sendToAddressCmd = format("sendtoaddress \"%s\" %s \"\" \"\" true",
address, amount);
BitcoinCli sendToAddress = new BitcoinCli(config, sendToAddressCmd).run();
String txid = sendToAddress.getOutput();
assertNotNull(txid);
return txid;
} catch (IOException | InterruptedException ex) {
fail(ex.getMessage());
return null;
}
}
}
18 changes: 18 additions & 0 deletions apitest/src/main/java/bisq/apitest/method/MethodTest.java
Expand Up @@ -18,6 +18,7 @@
package bisq.apitest.method;

import bisq.proto.grpc.GetBalanceRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
import bisq.proto.grpc.LockWalletRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
Expand Down Expand Up @@ -55,17 +56,34 @@ protected final LockWalletRequest createLockWalletRequest() {
return LockWalletRequest.newBuilder().build();
}

protected final GetFundingAddressesRequest createGetFundingAddressesRequest() {
return GetFundingAddressesRequest.newBuilder().build();
}

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

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

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

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

protected final String getUnusedBtcAddress() {
return grpcStubs.walletsService.getFundingAddresses(createGetFundingAddressesRequest())
.getAddressBalanceInfoList()
.stream()
.filter(a -> a.getBalance() == 0 && a.getNumConfirmations() == 0)
.findFirst()
.get()
.getAddress();

}
}
46 changes: 3 additions & 43 deletions apitest/src/main/java/bisq/apitest/method/MethodTestMain.java
Expand Up @@ -2,19 +2,13 @@

import lombok.extern.slf4j.Slf4j;

import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

import static java.lang.String.format;
import static bisq.apitest.JUnitHelper.runTests;

/**
* Driver for running API method tests.
*
* This may not seem necessary, but test cases are contained in the apitest sub
* project's main sources, not its test sources. An IDE will not automatically configure
* project's main sources, not its test sources. An IDE may not automatically configure
* JUnit test launchers, and a gradle build will not automatically run the test cases.
*
* However, it is easy to manually configure an IDE launcher to run all, some or one
Expand All @@ -24,40 +18,6 @@
public class MethodTestMain {

public static void main(String[] args) {
JUnitCore jUnitCore = new JUnitCore();
jUnitCore.addListener(new RunListener() {
public void testStarted(Description description) {
log.info("{}", description);
}

public void testIgnored(Description description) {
log.info("Ignored {}", description);
}

public void testFailure(Failure failure) {
log.error("Failed {}", failure.getTrace());
}
});
Result result = jUnitCore.run(GetVersionTest.class, GetBalanceTest.class, WalletProtectionTest.class);
ResultUtil.printResult(result);
}

private static class ResultUtil {
public static void printResult(Result result) {
log.info("Total tests: {}, Failed: {}, Ignored: {}",
result.getRunCount(),
result.getFailureCount(),
result.getIgnoreCount());

if (result.wasSuccessful()) {
log.info("All tests passed");
} else if (result.getFailureCount() > 0) {
log.error("{} test(s) failed", result.getFailureCount());
result.getFailures().iterator().forEachRemaining(f -> log.error(format("%s.%s()%n\t%s",
f.getDescription().getTestClass().getName(),
f.getDescription().getMethodName(),
f.getTrace())));
}
}
runTests(GetVersionTest.class, GetBalanceTest.class, WalletProtectionTest.class);
}
}
@@ -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.apitest.scenario;

import lombok.extern.slf4j.Slf4j;

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

import static java.lang.Double.parseDouble;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;



import bisq.apitest.OrderedRunner;
import bisq.apitest.annotation.Order;

@Slf4j
@RunWith(OrderedRunner.class)
public class FundWalletScenarioTest extends ScenarioTest {

@BeforeClass
public static void setUp() {
try {
setUpScaffold("bitcoind,seednode,alicedaemon");
bitcoinCli.generateBlocks(1);
MILLISECONDS.sleep(1500);
} catch (InterruptedException ex) {
fail(ex.getMessage());
}
}

@Test
@Order(1)
public void testFundWallet() {
long balance = getBalance(); // bisq wallet was initialized with 10 btc
assertEquals(1000000000, balance);

String unusedAddress = getUnusedBtcAddress();

// Given the default tx fee rate, we want to send 2.5 + the fee,
// so the new wallet balance will be exactly 12.5 btc.
// We should calculate the fee based on the fee rate and tx size
// instead of hard coding the fee amount.
double btc = parseDouble("2.5") + parseDouble("0.0000336");
ghubstan marked this conversation as resolved.
Show resolved Hide resolved
bitcoinCli.sendToAddress(unusedAddress, btc);

bitcoinCli.generateBlocks(1);
sleep(1500);
ghubstan marked this conversation as resolved.
Show resolved Hide resolved

balance = getBalance();
assertEquals(1250000000L, balance); // new balance is 12.5 btc
}

@AfterClass
public static void tearDown() {
tearDownScaffold();
}
}
22 changes: 22 additions & 0 deletions apitest/src/main/java/bisq/apitest/scenario/ScenarioTest.java
@@ -1,6 +1,28 @@
/*
* 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.scenario;

import lombok.extern.slf4j.Slf4j;



import bisq.apitest.method.MethodTest;

@Slf4j
public class ScenarioTest extends MethodTest {
}
23 changes: 23 additions & 0 deletions apitest/src/main/java/bisq/apitest/scenario/ScenarioTestMain.java
@@ -0,0 +1,23 @@
package bisq.apitest.scenario;

import lombok.extern.slf4j.Slf4j;

import static bisq.apitest.JUnitHelper.runTests;

/**
* Driver for running API scenario tests.
*
* This may not seem necessary, but test cases are contained in the apitest sub
* project's main sources, not its test sources. An IDE may not automatically configure
* JUnit test launchers, and a gradle build will not automatically run the test cases.
*
* However, it is easy to manually configure an IDE launcher to run all, some or one
* JUnit test, and new gradle tasks should be provided to run all, some, or one test.
*/
@Slf4j
public class ScenarioTestMain {

public static void main(String[] args) {
runTests(FundWalletScenarioTest.class);
}
}