Skip to content

Latest commit

 

History

History
92 lines (56 loc) · 9.05 KB

README.md

File metadata and controls

92 lines (56 loc) · 9.05 KB

Tests

This module is where we store all of the tests that use the testing harness. This is not the place to test out the harness itself - that's what the TestHarness module is for!

Aion kernel setup

node_test_harness supports several node types, which represent the Aion implementation being tested. The node type must be specified when running the tests by passing in Java system property testNodes. For instance, if running with Gradle, to test against a Java kernel, the invocation is ./gradlew Tests:test -PtestNodes=java

The tests expect that a kernel be at a particular location (dependent on node type being tested), so this must be set up before running the tests. For instance, for testing against Java, the expected kernel location is Tests/aion within the node_test_harness cloned repo.

For details on node types and configuring non-Java node types, see Node type configuration

Concurrent testing framework

The tests in this module have the ability to be incorporated into a test suite that is run concurrently against a single node instance. This allows us to not only gain a huge speed-up in terms of how long it takes for all of the tests to run, but it also allows for our individual functional tests to come together and serve as a stress test of the kernel, by flooding it with transactions simultaneously.

All tests should be written for concurrent testing unless there is a very good reason why they do not fit into the concurrent model!

In general, ./gradlew :Tests:test -PtestNodes=<nodetype> is how you should be running tests. For Java kernel, use java as . This will use the concurrent runner and execute the tests against the Java kernel; for changing the kernel-under-test, see Node type configuration.

To run the saturation tests: ./gradlew :Tests:test -Psaturation To run the kernel-side (unsigned) saturation tests: ./gradlew :Tests:test -PunsignedSaturation

Every test defined in your class will be run on a unique instance of the class. This means if your test only accesses instance methods and fields then no synchronization is required on your part. If your tests access static other external resources, then you will need to synchronize them appropriately.

Your tests never touch the node! All node management and life-cycling is taken care of behind the scenes by the runner. The node is started up once before any tests are run, and shut down once all tests have been run, so that every test in the concurrent suite is interacting with the same node instance.

The following two JUnit Rules are provided: PreminedAccount should be used as the only safe means of interacting with a premined account; LocalNodeListener is used to listen for events on the node.

Your tests must use these rules! Since you have no access to the node itself, you cannot start up your own listener, and if you try and use the pre-mined account defined in the genesis block then you will introduce race conditions and concurrency issues into the system! These rules are here to simplify things for you and delegate concurrency concerns elsewhere.

Step 1. Write your tests like typical JUnit tests, using the two provided Rules.

Step 2. Annotate your test class with the following annotation: @RunWith(SequentialRunner.class). This allows your tests to be run sequentially (since you now depend on external node lifecycling, Rules, etc. for your test to run, you require a JUnit Runner that knows how to do this stuff).

Step 3. Open the ConcurrentSuite.java class and add your test class into the list of SuiteClasses. This allows your test to be run concurrently.

If you are running your tests from an IDE, then to run the tests concurrently simply run the ConcurrentSuite.java class as a test class. By default, the log files will be deleted when the tests finish. To prevent this from happening, set the System Property skipCleanLogs=true.

If you are running your tests from the command line, then navigate to the root directory of the node harness project and run ./gradlew :Tests:test. By default, the log files will be deleted when the tests finish. To prevent this from happening, run ./gradlew :Tests:test -PskipCleanLogs=true.

These log files are your best means of debugging if you run into problems. You can find the logs generated by a test in the logs directory in the Tests module. Do not modify these logs while tests are running!

If there is a very good reason why the tests you are writing cannot fit into the concurrent test suite model, then it is still recommended that you use the provided SequentialRunner custom JUnit runner. The runner takes the burden of node lifecycle management off you, and opens this test up to easily being integrated into the concurrent model in the future if this ever becomes a possibility.

If the SequentialRunner does not meet your needs for some reason then write your tests as regular JUnit tests.

Otherwise, write your tests as regular JUnit tests but use the provided Rule PreminedAccount to interact with your unique premined account, and LocalNodeListener to listen to the log messages of the node. The runner will start up and shut down the node for you, your tests should not ever need to touch an instance of the node itself.

Finally, annotate your test class with: @RunWith(SequentialRunner.class) to enable the sequential runner. That's all.

If you are running your tests from an IDE, then to run the test sequentially simply run your test class regularly. Note that the sequential runner will run every test in the class every time, there is no way to single out a specific test to run unless you @Ignore the other tests.

If you are running your tests from the command line, then navigate to the root directory of the node harness project and run ./gradlew :Tests:test -Psequential. By default, the log files will be deleted when the tests finish. To prevent this from happening, run ./gradlew :Tests:test -Psequential -PskipCleanLogs=true.

These log files are your best means of debugging if you run into problems. You can find the logs generated by a test in the logs directory in the Tests module. Do not modify these logs while tests are running!

By default, running tests sequentially will cause the test to be run twice -- once with Java kernel, then a second time with Rust kernel. This behaviour can be overridden (for invocation from IDE or Gradle) by adding the JVM system property testNodes. Value values are: rust, java, or rust,java. Example Gradle invocation: ./gradlew :Tests:test -Psequential -PskipCleanLogs=true -PtestNodes=java.

Node type configuration

Node type determines the Aion implementation that the tests will be executed against. By default, node type is Java, but can be overridden using the system property testNodes. If running tests from IDE, set the system property in your JUnit configuration. If running tests via Gradle, set the property using the -P argument; i.e. ./gradlew Tests:test -PtestNodes=java. Multiple node types can be provided, i.e. ./gradlew Tests:test -PtestNodes=java,rust.

Supported node types:

Node type name Description
java Tests implementation of Java kernel
rust Tests implementation of Rust kernel
proxy A special node type used for testing a network of kernels. The test harness communicates with a Java kernel that performs no mining; instead, that kernel acts as a proxy by peering with kernel(s) in a network, which processes the transactions.

Each node type expects the kernel-under-test to be placed in a directory within the test harness. Note that the test harness will overwrite config files in these directories.

  • for java, extract the release to node_test_harness/Tests/aion (so that aion.sh is present in that directory)
  • for rust, extract the release to node_test_harness/Tests/aionr (so that aion is present in that directory)
  • for proxy, extract a release of Java kernel to node_test_harness/Tests/aionproxy (so that aion.sh is present in that directory)

For proxy, there is an additional set-up step to configure peering. Modify the file node_test_harness/Tests/test_resources/proxy_java_custom/config.xml and add at least one peer from the network-under-test to the p2p nodes list.