js/client/modules/@arangodb/README.md
All the code structure and the test infrastructure works in a way
| Path / File | Description |
|---|---|
testutils/testing.js | invoked via unittest.js handles module structure for testsuites. |
testutils/result-processing.js | contains code to run various analyses on results and/or generate result representations for the user/ci |
testutils/test-utils.js | infrastructure for tests like filtering, bucketing, iterating, RPC or eval launch |
testutils/process-utils.js | start/stop/monitor all of the SUT-sub-processes |
testutils/portmanager.js | finds free tcp ports for arangods to launch. |
testutils/crash-utils.js | if something goes wrong, this contains the crash analysis tools |
testutils/client-tools.js | code to manage the arangodb client-tools for their respective tests |
testutils/instance-manager.js | manage a full installation, be it cluster or single server consisting of one or several instance.jses. |
testutils/instance.js | manage one arangod process - to be used via the instance-manager.js |
testutils/testrunner.js | base class to manage the lifecycle of one testsuite. |
testutils/testrunners.js | various derived classes of the lifecycle managager of testrunne.js. |
testutils/clusterstats.js | can be launched separately to monitor the cluster instances and their resource usage |
testsuites/ | modules with testframework that control one set of tests each utilizing the testrunner.js. |
testsuites/dump.js | complex infrastructure managing several instance lifecycles during serveral dump/restore/hotbackup attempts |
testsuites/[go|php|java|js|driver|rta_makedata].js | subsidize the lifecycle method of testRunner for other instance and testrunner controls. |
testsuites/[server_permissions|recovery[_cluster]].js | run several instances and run individual tests on them; vary parameters etc. of SUT |
testsuites/chaos.js | launches several sub-arangoshs to cause randomness, enables failurepoints and so on. |
js/common/modules[/jsunity]/jsunity.js | jsunity testing framework; invoked via jsunity.js next to the module |
js/common/modules/@arangodb/mocha-runner.js | wrapper for running mocha tests in arangodb |
client-tools/Shell/ProcessMonitoringFeature.[h|cpp] | establishes a thread that will watch after all registered subprocesses. Pull the plug to abort asap. |
client-tools/Shell/v8-deadline.cpp | infrastructure to implement a deadline which if engaged aborts all I/O + subprocesses immediately. |
The deadline handling is here so all http subrequests and waitpid()s are adjusted to end at this point in time. A busy polling is implemented to abort if the process monitor signals SUT-unstability.
The js infrastructure code will manage the deadline so test code must not exceed certain timeouts and ultimately abort the test execution on the deadline.
The js code will then terminate the SUT and aggregate its process states. This even moreso happenes if a crash of a subprocess leaves behind a cordeump.
The testing.js API conists of 3 main vectors, on top of it testing.js chooses which tests to run according to commandline options and how to present the test results.
The initial behaviour is different for users in their local development environment and the CI.
--extremeVerbosity true can be specified to closer follow & debug which way the infrastructure is working.
The suite API:
config.auto mechanism to associate a testfile with a suite.exports.setup function to:
allTestPaths to to the testsuite.testFnsfnDocsThe suite function. It should launch the SUT, identify & select the integration testsuites to run, shutdown the SUT and return the results. To achieve this it should lean on the various infrastructure presented below.
The result should be in a structure that can later be analyzed using result-processing.js.
The test infrastructure should be used by testsuites to do most of the heavy lifting; in best case it can contain just a few lines.
A testsuite receives a list of testfiles where each one is a single integration testsuite. Its files located by testing.js from the allTestPaths directory list.
Testing.js already filtered it, and split it to buckets (test-utils.js:filterTestcaseByOptions()) according to commandline options.
The testsuite then can use the default lifecycle management to launch these tests, or implement own logic, again best based on existing logic.
The test lifecycle management should be utilized to maintain the SUT, iterate over the tests.
It is implemented in testrunner.js, and its modularity is intended to reuse it partially or completely.
By default it comes without a way to launch an integration testsuite, this is implemented in the deriving classes.
An important part of the testRunner is its API to register tests that ensure SUT-cleanness after individual integration testsuites.
This way it is maintained, that individual integration testsuites don't leave things behind which may have influence on subsequent integration testsuites.
It consists of:
name of the ensurersetUp to be ran before the integration testsuite is launched to establish the "desired" datasetrunCheck to be ran after the integration testsuite to check the SUT has the same state as before.
Both setUp and runCheck can indicate the SUT is not fit for further tests, and abort the execution.The object manages its subprocesses in the instanceManager and uses it to manipulate processes.
The API consists of several default callback hooks that can be implemented dubbed pre*()/post*().
healthCheck is to be ran to ping the system and check whether its fit to be inspected for cleanness, or runningrunOneTest must be implemented to handle the invocation of one integration testsuite.
Several descendant implementations are available:
tu.runOnArangodRunner to launch testcode per remote execution within the arangod SUTtu.runInArangoshRunner to launch an isolated sub arangosh to launch the testtu.runLocalInArangoshRunner to launch the testsuites in the very same arangosh, being able to i.e. use the instanceManager of the testRunner to manipulate the instance.run - the main loop it will:
instanceManager and run certain pre/post hookssetUp of the ensurer modulesforceTerminate was registered on a previous run, abort.runOneTest integration point/proc, memory accounting interfacerunChecks are rightinstanceManager stop the SUTTests that work more outside of the default testRunner code by replacing more of it:
rta_makedata.js - rtaMakedataRunner will implement its own runOneTest hook which a method that runs all phases of the test in one go; hence the phases and results don't match directly into the structure.chaos.js - chaosRunner will launch the SUT, and run a set of arangoshs with parallel test executions on the SUT, and collect them in the end.[go|php|java|js|driver].js will replace the run hook by launching the SUT on their own, and running respective test-suites of these drivers, providing them with their instance, and convert their respective test-results back to testing.js own format.[server_permissions|recovery[_cluster]].js will also replace the run function. It will launch one SUT per iteration and run its respective tests with it.An arangodb deployment may consist of several instances that are to be orchestrated in order to form the SUT.
Depending on the options the deployment mode is chosen by the instanceManager.
It forms the instance objects of the respective arangods to be launched and stopped.
It knows the concepts of the agency and how to work with it.
It knows all tcp ports and can launch sniffing utilitise to track the tests.
It knows all PIDs and should be utilized to manipulate them.
It knows how to establish when the SUT is launched, and to maintain whether its healthy or not.
It knows via its instances which processes to start, stop, halt or maybe restart.
dump.js doesn't use the test lifecycle management in testrunner.js. It leans on instanceManager for SUT handling, and client-tools.js to launch client-tools -binaries.
Each phase of the dump suite will result in an aequivilant test status, that can individually fail. Once a failure occurs all subsequent test execution will be skipped, since they lean on proper preparation by the previous tests.
| Path / File | Description |
|---|---|
testsuites/dump.js | complex infrastructure managing several instance lifecycles during serveral dump/restore/hotbackup attempts |
tests/js/client/dump/ | test logic for all variations of deployments distributed over several files |
[dump-singleserver|dump-multiple|dump-cluster] | previously created dumps to be restored within the tests |
dump-setup-common.inc | contains all functions to create test data to create before creating the dump |
dump-test.inc | contains all functions to test data after restore |
dump-setup-*js | consists of calls to the respective set from dump-setup-common.inc of test data to be created |
dump-check*js | consists of calls to the respective set from dump-setup-common.inc of the test data to be checked |
check* | more checks that could be referenced from individual dump suites |
tests/js/client/dump/ filesTo create the individual initial provisioning dataset, setup .js files invoke the respective list of setup functions from dump-setup-common.inc.
To create the individual set of tests, the dump-test.inc files testsuide deriveTestSuite() is used by the file to create its respective subset.
Individual check files can be registered by tests in dump.js.
In general its probably beneficial to rather consider creating a rta-makedata testsuite than work on the above structure.
testsuites/dump.jsdump.js consists of 4 layers:
DumpRestoreHelper to abstract the invocation of individual client-tools, commandline argument handling, result handling and test phases.dump_backend_two_instances function orchestrating the phases using the DumpRestoreHelper depending on provided input structuresdumpMixedClusterSingle are individual testing.js-testsuites to create a list of checks to run, and orchestrate its sequenceThe individual testsuites (3) generate a set of parameters that create phases of instances to be launched, stuffed, dumped, stopped, launch subsequent fresh instance, restore into it, cleanup the data.