From cff75712fd31a7322e53f2849c3145cc536ec5e9 Mon Sep 17 00:00:00 2001 From: Ben Caimano <bcaimano@gmail.com> Date: Tue, 8 Jan 2019 17:43:36 -0500 Subject: [PATCH] TIG-1334 Fix segfault in test_gennylib_with_server (#103) --- evergreen.yml | 43 +++-------------- scripts/run-resmoke.sh | 55 ++++++++++++++++++++++ src/gennylib/test/MongoTestFixture.cpp | 18 ++++--- src/gennylib/test/MongoTestFixture.hpp | 6 ++- src/gennylib/test/RunCommandActor_test.cpp | 5 +- 5 files changed, 76 insertions(+), 51 deletions(-) create mode 100755 scripts/run-resmoke.sh diff --git a/evergreen.yml b/evergreen.yml index d40b2648d3..b862a9b1d7 100644 --- a/evergreen.yml +++ b/evergreen.yml @@ -244,46 +244,15 @@ functions: # Requires f_compile to have been run first. ## f_resmoke_test: - - command: shell.exec + - command: subprocess.exec params: continue_on_err: true working_dir: src - script: | - set -o errexit - set -o pipefail - # set -o nounset # the "activate" script has an unbound variable - - source build/venv/bin/activate - - # We rely on catch2 to report test failures, but it doesn't always do so. - # See https://github.com/catchorg/Catch2/issues/1210 - # As a workaround, we generate a dummy report with a failed test that is deleted if resmoke - # succeeds. - - cat << EOF >> "build/sentinel.junit.xml" - <?xml version="1.0" encoding="UTF-8"?> - <testsuites> - <testsuite name="resmoke_failure_sentinel" errors="0" failures="1" tests="1" hostname="tbd" time="1.0" timestamp="2019-01-01T00:00:00Z"> - <testcase classname="resmoke_failure_sentinel" name="Dummy testcase to signal that resmoke failed because a report may not be generated" time="1.0"> - <failure message="resmoke did not exit cleanly, see task log for detail" type=""> - </failure> - </testcase> - <system-out/> - <system-err/> - </testsuite> - </testsuites> - EOF - - # The tests themselves do the reporting instead of using resmoke. - python build/mongo/buildscripts/resmoke.py \ - --suite src/resmokeconfig/${resmoke_suite} \ - --mongod mongod \ - --mongo mongo \ - --mongos mongos - - # Remove the sentinel report if resmoke succeeds. This line won't be executed if - # resmoke fails because we've set errexit on this shell. - rm build/sentinel.junit.xml + binary: /bin/bash + args: + - ${workdir}/src/scripts/run-resmoke.sh + env: + RESMOKE_SUITE: ${resmoke_suite} ## # Runs python nosetests. diff --git a/scripts/run-resmoke.sh b/scripts/run-resmoke.sh new file mode 100755 index 0000000000..3f643fae71 --- /dev/null +++ b/scripts/run-resmoke.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +# set -o nounset # the "activate" script has an unbound variable + +SCRIPTS_DIR="$(dirname "${BASH_SOURCE[0]}")" +ROOT_DIR="$(cd "${SCRIPTS_DIR}/.." && pwd)" +BUILD_DIR="${ROOT_DIR}/build" + +VENV_DIR="${VENV_DIR:-${BUILD_DIR}/venv}" +MONGO_DIR="${MONGO_DIR:-${BUILD_DIR}/mongo}" +RESMOKE_SUITE="${RESMOKE_SUITE:-genny_standalone.yml}" +SENTINEL_XML="${BUILD_DIR}/sentinel.junit.xml" + +if [[ -z $VIRTUAL_ENV ]]; then + # shellcheck disable=SC1090 + . "${VENV_DIR}/bin/activate" +fi + +# Move to the root dir because of how resmoke paths +cd "${ROOT_DIR}" + +# We rely on catch2 to report test failures, but it doesn't always do so. +# See https://github.com/catchorg/Catch2/issues/1210 +# As a workaround, we generate a dummy report with a failed test that is deleted if resmoke +# succeeds. + +cat << EOF >> "${SENTINEL_XML}" +<?xml version="1.0" encoding="UTF-8"?> +<testsuites> + <testsuite name="resmoke_failure_sentinel" errors="0" failures="1" tests="1" hostname="tbd" time="1.0" timestamp="2019-01-01T00:00:00Z"> + <testcase classname="resmoke_failure_sentinel" name="Dummy testcase to signal that resmoke failed because a report may not be generated" time="1.0"> + <failure message="resmoke did not exit cleanly, see task log for detail" type=""> + </failure> + </testcase> + <system-out/> + <system-err/> + </testsuite> +</testsuites> +EOF + +# Add the mongo dir to the end of the path so we can find mongo executables +export PATH="${PATH}:${MONGO_DIR}" + +# The tests themselves do the reporting instead of using resmoke. +python2 "${MONGO_DIR}/buildscripts/resmoke.py" \ + --suite "${ROOT_DIR}/src/resmokeconfig/${RESMOKE_SUITE}" \ + --mongod mongod \ + --mongo mongo \ + --mongos mongos + +# Remove the sentinel report if resmoke succeeds. This line won't be executed if +# resmoke fails because we've set errexit on this shell. +rm "${SENTINEL_XML}" diff --git a/src/gennylib/test/MongoTestFixture.cpp b/src/gennylib/test/MongoTestFixture.cpp index ac75363f49..a660414314 100644 --- a/src/gennylib/test/MongoTestFixture.cpp +++ b/src/gennylib/test/MongoTestFixture.cpp @@ -9,20 +9,17 @@ namespace genny::testing { -const mongocxx::uri MongoTestFixture::kConnectionString = []() { +mongocxx::uri MongoTestFixture::connectionUri() { const char* connChar = getenv("MONGO_CONNECTION_STRING"); - std::string connStr; - - if (!connChar) { - connStr = mongocxx::uri::k_default_uri; - BOOST_LOG_TRIVIAL(info) << "MONGO_CONNECTION_STRING not set, using default value: " - << connStr; - } else { - connStr = connChar; + + if (connChar != nullptr) { + return mongocxx::uri(connChar); } + auto& connStr = mongocxx::uri::k_default_uri; + BOOST_LOG_TRIVIAL(info) << "MONGO_CONNECTION_STRING not set, using default value: " << connStr; return mongocxx::uri(connStr); -}(); +}; void MongoTestFixture::dropAllDatabases() { for (auto&& dbDoc : client.list_databases()) { @@ -33,4 +30,5 @@ void MongoTestFixture::dropAllDatabases() { } } } + } // namespace genny::testing diff --git a/src/gennylib/test/MongoTestFixture.hpp b/src/gennylib/test/MongoTestFixture.hpp index 58975a97c0..5ccb149ae1 100644 --- a/src/gennylib/test/MongoTestFixture.hpp +++ b/src/gennylib/test/MongoTestFixture.hpp @@ -2,19 +2,21 @@ #define HEADER_D9091084_CB09_4108_A553_5D0EC18C132F_INCLUDED #include <mongocxx/client.hpp> +#include <mongocxx/instance.hpp> namespace genny::testing { class MongoTestFixture { public: - MongoTestFixture() : client(kConnectionString) {} + MongoTestFixture() : instance(mongocxx::instance::current()), client(connectionUri()) {} protected: void dropAllDatabases(); + mongocxx::instance & instance; mongocxx::client client; - static const mongocxx::uri kConnectionString; + static mongocxx::uri connectionUri(); }; } // namespace genny::testing diff --git a/src/gennylib/test/RunCommandActor_test.cpp b/src/gennylib/test/RunCommandActor_test.cpp index 9e2ce747f2..3eb315bc71 100644 --- a/src/gennylib/test/RunCommandActor_test.cpp +++ b/src/gennylib/test/RunCommandActor_test.cpp @@ -6,10 +6,11 @@ #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> -#include <MongoTestFixture.hpp> #include <cast_core/actors/RunCommand.hpp> #include <gennylib/MongoException.hpp> +#include "MongoTestFixture.hpp" + namespace genny { namespace { @@ -35,7 +36,7 @@ TEST_CASE_METHOD(MongoTestFixture, OperationCommand: {someKey: 1} )"); - ActorHelper ah(config, 1, MongoTestFixture::kConnectionString.to_string()); + ActorHelper ah(config, 1, MongoTestFixture::connectionUri().to_string()); SECTION("throws error with full context on operation_exception") { bool has_exception = true;