CORAL and COOL functional tests

This twiki page describes the functional tests of CORAL and COOL executed against all supported backends (Oracle, MySQL, SQLite, Frontier and CoralServer) and some of their internal implementation details. More condensed practical recipes for running the tests to validate software builds can be found in the PersistencyReleaseValidation page. Additional information about the servers aganst which these tests are executed can be found in the PersistencyTestServers page.

1 Functional test suites

There are two sets of test suites for CORAL/COOL:

  • The full test suites include all functional tests developed over the years for CORAL and COOL. These tests take a long time (~15 minutes for CORAL, ~2 hours for COOL). They are meant to be manually executed by the development team to validate important code changes and new releases (see PersistencyReleaseValidation). They are launched using the qmtestRun.sh script, created by cmake from the qmtestRun.sh.in templates defined for CORAL and COOL.
  • The quick test suites for the nightlies are subsets of the full test suites. They have been specifically prepared for the builds and tests that are automatically executed every night, as described below. They contain few selected tests to fit within approximately 5 minutes of execution time, while still providing basic coverage of all supported backends for both CORAL and COOL. This was agreed with EP-SFT in January 2015. They are launched using the run_nightly_tests_cmake.sh script, created by cmake from the run_nightly_tests_cmake.sh.in templates defined for CORAL and COOL.

The test suites are implemented as qmtest suites (.qms files and directories, pointing to individual .qmt test configuration files):

Note that functional tests may be executed also individually (as described below), not only within qmtest suites.

  • For the tests executed within qmtest suites, some environment variables are set within the qmtest drivers, CoralTest/qmtest/LCG_QMTestExtensions.py for CORAL and CoolTest/qmtest/COOLTests.py for COOL.
  • For the tests executed individually, outside qmtest suites, these environment variables are not set automatically and it is necessary to configure them manually if necessary/appropriate.
  • Note in particular that the CORAL_AUTH_PATH and CORAL_DBLOOKUP_PATH described in the section below should normally be set manually for all manual tests, whether using qmtest driver scripts or not. These two variables are only set automatically by the qmtest drivers if the Linux $USER is sftnight, which happens during the automatic nightly tests.

2 Connection strings and table names for the tests (hardcoded values and how to override them)

Most CORAL and COOL tests involve creating and modifying tables on database servers. As many tests can be executed simultaneously by different developers and also for different slots and platforms within the nightlies, the configuration of the CORAL and COOL tests includes mechanisms to avoid clashes between these parallel threads of execution. For instance, this is meant to prevent an SLC6 test in the "dev3" nightly slot from deleting a table that has just been created by a CentOS7 test in the "dev4" slot.

Within the same database server, tables are uniquely identified by a name within a namespace. As the same Oracle server and the same MySQL server are used for all manual and automatic tests of CORAL and COOL (see PersistencyTestServers), the separation of different tests is achieved by properly configuring table names and their namespaces:

  • The namespace for the tables used in a test corresponds to the the name of the Oracle "schema" or MySQL "database" where those tables are created. This is configured by choosing the CORAL connection string for writing tables in that test. As described in CoolConnectionStrings, a CORAL connection string (which is also included in a COOL connection string) uniquely specifies an Oracle or MySQL server name and a schema or database name on that server. The configuration of connection strings in CORAL and COOL tests is described in the section below.
  • Each CORAL or COOL test may use several tables. However, all tables in the same test are configured to have names that start with a well defined table prefix. This table prefix, or "hash", is built to have distinct values on different nightly slots and platforms, as described in the section below.

2.1 Connection strings for the tests

The configuration of connection strings for individual tests relies on hardcoded defaults using database aliases, which can be overridden using runtime environment variables. The detailed strategy for configuring connection strings is different in CORAL and COOL. In both cases, the functional tests include both C++ and Python tests, which are configured using similar mechanisms, but in different parts of the code.

2.1.1 CORAL tests

Connection strings are defined in CoralCppUnitDBTest.h for CORAL C++ tests and in PyCoralTest.py for CORAL Python tests. These files are included by all relevant C++ and Python unit and integration tests. Unit tests hardcode the choice of a specific backend, while integration tests require the choice of database backend as their first command-line argument. The following mapping is defined for an integration test <test>:

  • <test> oracle[:oracle] writes to alias CORAL-Oracle-<qmuser>/admin and reads from alias CORAL-Oracle-<qmuser>/reader
  • <test> oracle:frontier writes to alias CORAL-Oracle-<qmuser>/admin and reads from alias CORAL-Frontier-<qmuser>/reader
  • <test> oracle:coral writes to alias CORAL-Oracle-<qmuser>/admin and reads from alias CORAL-CoralServer-Oracle-<qmuser>/reader
  • <test> mysql[:mysql] writes to alias CORAL-MySQL-<qmuser>/admin and reads from alias CORAL-MySQL-<qmuser>/reader
  • <test> mysql:coral writes to alias CORAL-MySQL-<qmuser>/admin and reads from alias CORAL-CoralServer-MySQL-<qmuser>/reader
  • <test> sqlite[:sqlite] writes and reads on sqlite_file:/tmp/<user>_<hash>.db

With the exception of SQLite tests (where <user> is the value of the $USER environment variable and <hash> is the table prefix described below), all other backends use CORAL aliases that depend on a variable <qmuser>. Up until the CORAL 3.1.5 release in LCG85 included, <qmuser> was actually hardcoded to sftnight: this was only changed after LCG85 and its value is now taken from the CORAL_QMTEST_USER environment variable (see CORALCOOL-2888). This is meant to provide more flexibility in the use of different database accounts for tests by different developers, as described in PersistencyReleaseValidation.

The CORAL test suite also includes one special test that does not use any of the aliases above. The "network glitch" test test_PyCoral_NetworkGlitch.py hardcodes a special connection string oracle://lcg_coral_nightly_proxy/<nguser>, where the Oracle network service name lcg_coral_nightly_proxy is actually a local ssh tunnel to an existing Oracle server. The schema name <nguser> for the test used to be hardcoded to lcg_coral_nightly until CORAL 3.1.5 in LCG85 included, but it is now possible to override it from the value of the CORAL_NETWORKGLITCHTEST_USER environment variable (see CORALCOOL-2888). This is also meant to provide more flexibility in the use of different database accounts for tests by different developers, as described in PersistencyReleaseValidation.

2.1.2 COOL tests

COOL tests are generally configured to use as COOL connection string the value of the environment variable COOLTESTDB. For COOL C++ tests, this is centrally defined in CoolDBUnitTest.h. For COOL Python tests, this is implemented independently, but in the same way, in each test, allowing also the option to use a command-line argument as connection string (see for instance test_IDatabaseSvc.py). Some special tests that involve copying data from a source to a destination database use two connection strings taken from the values of the two environment variables COOLTESTDB_SOURCE and COOLTESTDB_TARGET (see for instance test_Replication.py). Another special case is the "regression" test, where data is written using one connection string and possibly read back through another (e.g. written via Oracle and read back via Frontier or CoralServer): this is normally handled by using a CORAL alias in COOLTESTDB and resolving it for read-write or read-only replicas, but for faster manual tests the option to set the read-back connection string via environment variable COOLTESTDB_R is also provided in testReferenceDb_driver.py.

The value of COOLTESTDB (as well as COOLTESTDB_SOURCE or COOLTESTDB_TARGET when relevant) must be set manually when executing a single test, but it is automatically configured in COOLTests.py for tests executed within a qmtest suite:

  • Oracle tests use COOL connection string COOL-Oracle-<qmuser>/<hash>
  • MySQL tests use COOL connection string COOL-MySQL-<qmuser>/<hash>
  • Oracle tests with readback from Frontier use COOL connection strings COOL-Frontier-<qmuser>/<hash> and COOL-FrontierCache-<qmuser>/<hash> (for accessing Frontier servers or Squid caches, respectively)
  • Oracle tests with readback from CoralServer use COOL connection string COOL-CoralServer-Oracle-<qmuser>/<hash>
  • MySQL tests with readback from CoralServer use COOL connection string COOL-CoralServer-MySQL-<qmuser>/<hash>
  • SQLite tests use COOL connection string sqlite://;schema=/tmp/sqliteTest-<hash>.db;dname=<hash>, where <hash> is the table prefix described below

In the connection strings above, for all backends <hash> is the table prefix described below: for COOL, this is used to indicate the name of a COOL "database", i.e. a self-consistent set of tables, whose names all start with the database name as their prefix. With the exception of SQLite tests, the COOL connection strings for all other backends include CORAL aliases that depend on a variable <qmuser>. Up until the CORAL 3.1.3 release in LCG84 included, <qmuser> was always defined from the value of the environment variable $USER, i.e. the name of the Linux user running the tests: this was changed in CORAL 3.1.4 and its value is now taken from the COOL_QMTEST_USER environment variable (see CORALCOOL-2888). This is meant to provide more flexibility in the use of different database accounts for tests by different developers, as described in PersistencyReleaseValidation.

2.2 Table names for the tests

For all tests, table names are built by adding a test-specific suffix to a table name prefix that generally depends from the platform and nightly slot where tests are being executed. The motivation for using different table names for different platforms and slots, within the same table namespace (Oracle schema or MySQL database) is to avoid interference between the different simultaneous nightly builds that are executed every night. For instance, this prevents a dev3 SLC6 test from deleting a table that has just been created by a dev4 CC7 test. The mapping of any given platform and nightly slot is implemented in different ways in CORAL and COOL:

  • For CORAL, a unique table name prefix is built based on the values of the environment variables SLOTNAME and CORAL_BINARY_TAG_HASH. This is implemented in CoralCppUnitTest.h for C++ tests and in PyCoralTest.py for Python tests. The environment variable SLOTNAME (see CORALCOOL-2933 and SPI-918) is set by the package lcgjenkins, which is used together with lcgcmake by EP-SFT in their nightly build infrastructure: its value is "dev4" in the "dev4" nightly slot, for instance. The environment variable CORAL_BINARY_TAG_HASH is uniquely hardcoded depending on the BINARY_TAG platform identifier in the CMakeLists.txt file of the CoralTest package; this file must be modified every time a new platform is added (see for instance CORALCOOL-2895).
    • Note that a similar strategy is used in PyCoralTest.py to define a unique port number based on the values of SLOTNAME and CORAL_BINARY_TAG_HASH for the CORAL "network glitch" test. This is meant to avoid interferences between different instances of this test running simultaneously on the same client node for different nightly slots and/or platforms. a local port number is used by this test to create an ssh tunnel to an Oracle database, which can be stopped temporarely to simulate a network glitch.
  • For COOL, a unique table name prefix is defined in COOLTests.py, where a hash is built from the directory name where the tests are executed (which contains the slot name in lcgjenkins/lcgcmake) and from the BINARY_TAG platform identifier. For simplicity the table name prefix will be called a "hash" in the following also for CORAL, even if it is built as a hash only for COOL.

It should be noted that the mechanism above is useful not only for automatically executed nightly tests, but also for tests executed manually by the development team. Both the CORAL and COOL implementations avoid clashes between tests executed by the same developer on different platforms. They also avoid clashes between tests executed in a nightly slot and those executed on the same platform by a developer, as the SLOTNAME environment variabe should remain unset in the latter case. It is nevertheless recommended that different table namespaces (i.e. different Oracle schemas and MySQL databases) should be used by the automatic nightly tests and by each developer: this is described in the following subsection about connection strings for the tests.

how propagate unique hadh to tests?

add also port number!

3 Setting the runtime environment for the tests

CORAL and COOL builds are performed with cmake. This is described in the PersistencyCMake page, which also contains a section about the runtime environment setup for these builds. To use the libraries and executables from a specific local (e.g. trunk) or release (e.g. LCG84) build of CORAL or COOL, environment variables such as PATH and LD_LIBRARY_PATH must be set appropriately. In summary, this can be done using one of these two commands:

  • run cc-run <command> [<arguments>] to execute a command with the appropriate CORAL/COOL environment
  • run cc-sh to enter a temporary bash shell with the appropriate CORAL/COOL environment

The cc-run and cc-sh scripts are deployed in the install directory of each build and, in principle, can be directly used from there.

  • For local builds, this is always true. For instance, run /build/CORAL/trunk/x86_64-slc6-gcc49-dbg/cc-sh to enter a temporary shell and execute a CORAL test from there.
  • For release builds, which are prepared on build nodes and then copied/relocated to AFS or cvmfs, some issues affect all release up to LCG84 included (see CORALCOOL-2873 and SPI-855), but everything should be fixed as of the LCG85swan1 release. For instance, run /cvmfs/sft.cern.ch/lcg/releases/LCG_85swan1/COOL/3_1_4/x86_64-slc6-gcc49-dbg/cc-sh to enter a temporary shell and execute a COOL test from there.

As previously mentioned, CORAL/COOL tests can be executed either individually or within qmtest test suites. In the latter case, the qmtestRun.sh and run_nightly_tests_cmake.sh scripts, which can also be found in the install directory of each build, should be used. It should be noted that these scripts already take care of setting up the runtime environment by internally calling the appropriate cc-run script, hence it is not necessary to explicitly call cc-run to call them.

In summary, several options are available. For instance, after changing directory to the install directory of the relevant build with cd /home/avalassi/COOL/trunk/x86_64-slc6-gcc49-dbg, one can execute individual or subsets of COOL tests as follows:

  • run ./cc-run test_CoolKernel_Record to execute the Record test standalone from the original shell
  • run ./cc-sh and then test_CoolKernel_Record to execute the Record test standalone from a COOL shell
  • run ./qmtestRun.sh coolkernel.record to execute the Record test within the general qmtest wrapper (run ./cc-run qmtest -D CoolTest/qmtest/ ls -R to list all tests)
  • run ./qmtestRun.sh coolkernel.record coolkernel.recordadapter to execute the Record and RecordAdapter tests within the general qmtest wrapper
  • run ./qmtestRun.sh to execute the full test suite within the general qmtest wrapper (this defaults to executing the ALL test suite)
  • run ./qmtestRun.sh ALL to execute the full test suite within the general qmtest wrapper
  • run ./qmtestRun.sh QUICK to execute the quick (nightly) test suite within the general qmtest wrapper
  • run ./run_nightly_tests_cmake.sh to execute the quick (nightly) test suite within the nightly qmtest wrapper

export CORAL_TESTSUITE_SLEEPFOR01466=1

export CORAL_SQLITE_SYNCHRONOUS_OFF=1

4 The authentication.xml, dblookup.xml and tnsnames.ora files (CORAL_AUTH_PATH, CORAL_DBLOOKUP_PATH and TNS_ADMIN)

The functional tests of CORAL and COOL are executed against all supported backends (Oracle, MySQL, SQLite, Frontier and CoralServer). More information about the servers against which these tests are executed can be found in the PersistencyTestServers page. The configuration of connection strings for individual tests relies on hardcoded defaults using database aliases, which can be overridden using runtime environment variables as described in another section. In any case, three files are extremely important to all tests and must be located when the tests start:

  • The authentication.xml file contains usernames and passwords for the Oracle and MySQL connection strings used by the tests. It is looked up via the CORAL_AUTH_PATH environment variable.
  • The dblookup.xml file contains the mapping between the aliases used by the tests and the connection strings for the corresponding replicas. It is looked up via the CORAL_DBLOOKUP_PATH environment variable.
  • The tnsnames.ora file contains the mapping between the Oracle instance names used by the connection strings and the corresponding host names and ports. It is looked up via the TNS_ADMIN environment variable.

In most cases, CORAL_AUTH_PATH and CORAL_DBLOOKUP_PATH are set to the same value, indicating a directory that contains both authentication.xml and dblookup.xml. This directory must be access-restricted as authentication.xml contains database credentials.

Whenever available, AFS is used to simplify the distribution and access control for all of these files. By default, nightly tests on Linux look up these three files from the following AFS directories:

  • authentication.xml and dblookup.xml from /afs/cern.ch/sw/lcg/app/pool/db/ (access-protected and readable by sftnight and by CORAL/COOL team members with their AFS token)
  • tnsnames.ora from /afs/cern.ch/sw/lcg/app/releases/CORAL/internal/oracle/admin (where it is available as a symbolic link to the master copy on /afs/cern.ch/project/oracle/admin, together with a custom sqlnet.ora file for CORAL/COOL tests which is also needed to control Oracle client-server communication)

On platforms where AFS is not available (or where the AFS filesystem is available but AFS tokens are not available to the users running the jobs), various options are possible. In the nightlies (e.g. for Mac), Oracle and MySQL tests are skipped and only SQLite tests are executed. For manual tests, developers can work around the issue by copying the relevant files to a directory of their choice and setting the CORAL_AUTH_PATH, CORAL_DBLOOKUP_PATH and/or TNS_ADMIN environment variables accordingly. By default, if CORAL_AUTH_PATH and CORAL_DBLOOKUP_PATH are not set, their values often default to $HOME/private as this is where they typically reside. Using custom authentication.xml and dblookup.xml files (typically in $HOME/private) is also needed for developers who want to use their own Oracle or MySQL test accounts, for instance.

For the tests executed within qmtest test suites, the default configuration of these three environment variables is defined within the qmtest drivers, CoralTest/qmtest/LCG_QMTestExtensions.py for CORAL and CoolTest/qmtest/COOLTests.py for COOL. It is these two files that contain special settings for user sftnight (depending on the platform) and also set CORAL_AUTH_PATH and CORAL_DBLOOKUP_PATH to $HOME/private if not yet defined.

5 Running the tests

6 Nightly builds and tests (jenkins, cdash, lcgcmake)

The CORAL and COOL software is built and tested automatically every night, thanks to the infrastructure provided by the SPI team in EP-SFT.

The nightlies test the software "in three dimensions":

  • Platform (e.g. x86_64-slc6-gcc49-dbg). The tests are built on all production platforms, as well as a few development platforms. Linux SLC6/CC7 on Intel processors with 64-bit builds using gcc49 is currently the only supported platform in June 2016, but support for other platforms is being added, including MacOSX 10.11 El Capitan (e.g. CORALCOOL-2884), gcc6.1 (CORALCOOL-2895), clang 3.8 (CORALCOOL-2901), ARM64 (CORALCOOL-2857). Windows builds are no longer supported. Some of the nightlies are executed using virtual machines instead of the native O/S they are testing.
  • Day of the week (e.g. Mon, Tue... Sun). All projects are compiled every night. Usually the building and testing starts around midnight (using tarballs created from the appropriate software tags as collected at 23.15, i.e. 45 minutes in advance) and results are provided later in the morning. The produced binaries and results are kept for one week (but a summary of the results of earlier builds and tests can, in principle, be recovered from AFS backup even later - if they were installed on AFS in the first place, which is not the case for all platforms).
  • Slot (e.g. dev2, dev3, dev4, experimental...). Projects are built in different configurations, i.e. a set of versions of AA packages that are supposed to work together. For instance, one configuration slot may test a preview of the "HEAD" of all projects, while other configuration slots may test branches with patches over the current production release. The "dev" slots are generally more stable than the "experimental" slot, where new development platforms and new disruptive extenal package versions tend to appear first. Presently (June 2016), only results from the "dev" slots are copied to AFS, while those from the "experimental" slot stay on the build nodes and are published on the web. The top of the PersistencyReleaseNotes page normally contains a brief description of the differences between the currently active dev slots.

The tests are executed using jenkins and can be controlled on the "LCG Externals" tab of the phsft-jenkins.cern.ch web interface. This makes it possible to start new unscheduled tests (please check with the SPI team in EP-SFT before!), by clicking on "Build with Parameters" in the appropriate slot, e.g. lcg_experimental. If you made important changes to the code between 23.15 and midnight, and you want these to be included in the next nightly build, this inteface also allows you to recreate the tarballs from your software tags, by clicking on "Build with Parameters" in the lcg-prepare-builds section.

The results of the nightlies are available on the "LCGSoft" tab of cdash.cern.ch. For those platforms and slots that get installed on AFS, the binaries and results are also available under /afs/cern.ch/sw/lcg/app/nightlies, for instance on /afs/cern.ch/sw/lcg/app/nightlies/dev2/Fri/CORAL for the dev2 build on CORAL on the most recent Friday.

The nightly builds and tests of CORAL and COOL are started by jenkins within a job that performs a full build of the LCG stack using lcgcmake. The relevant configuration for CORAL and COOL builds and tests is all contained within the externals/CMakeLists.txt file. In particular, this is the file that sets up the nightly tests to use the run_nightly_tests_cmake.sh script.

The nightlies are all executed as user sftnight. On the main Linux platforms, a valid AFS token for sftnight is available for the duration of the build job.

-- AndreaValassi - 2016-06-24

Edit | Attach | Watch | Print version | History: r15 < r14 < r13 < r12 < r11 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r14 - 2016-08-09 - AndreaValassi
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Persistency All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback