def test_prepare_reports_dir(self): """Test test_control.run_test where the exec command returns non-zero""" previous_directory = os.getcwd() reports_dir = os.path.join(self.reports_path, "reports") reports_tarball = os.path.join(self.reports_container, "reports.tgz") def _test_prepare_reports_dir(): try: os.chdir(self.reports_path) prepare_reports_dir(reports_dir=reports_dir) finally: os.chdir(previous_directory) self.assertFalse(os.path.exists(reports_tarball)) self.assertTrue(os.path.exists(reports_dir)) self.assertTrue(os.path.islink(reports_dir)) _test_prepare_reports_dir() touch(reports_tarball) _test_prepare_reports_dir() os.remove(reports_dir) mkdir_p(reports_dir) self.assertRaises(OSError, _test_prepare_reports_dir)
def __init__( self, test_name=None, output_files=None, is_production=None, timeout=None, numactl_prefix_for_workload_client=None, ): """ :param test_name: the name of the test suite. obtained from test_control.id. :param output_files: the list of output files a test suite generates. Used for uploading after the test runs. Some test suites have a default list of output files in addition to what's specified here. :param is_production: whether this test is running in production or locally. :param timeout: test timeout :param numactl_prefix_for_workload_client: whether the test should be started with numactl. """ self.report_dir = os.path.join("reports", test_name) utils.mkdir_p(self.report_dir) self.report_file_name = os.path.join(self.report_dir, "test_output.log") self.output_files = output_files self.is_production = is_production self.timeout = timeout self.numactl_prefix_for_workload_client = numactl_prefix_for_workload_client
def checkout_repos(self, source, target, branch=None, verbose=False): """ Clone repository from GitHub into target directory. :param str source: Link to GitHub repository :param str target: Path to target directory :param branch: Specific branch to clone, if None clones default branch. :types branch: str, None :param bool verbose: Use the --quiet flag for clone and checkout if verbose is False. Defaults to False. """ quiet_arg = "" if verbose else "--quiet" if not os.path.isdir(target): LOG.info("checkout_repos target directory %s does not exist", target) mkdir_p(os.path.dirname(target)) self.exec_command(["git", "clone", quiet_arg, source, target]) if branch is not None: self.exec_command( ["cd", target, "&&", "git", "checkout", quiet_arg, branch]) elif self.exec_command(["cd", target, "&&", "git", "status"]) != 0: raise UserWarning( "{} exists and is not a git repository".format(target)) else: LOG.info( "checkout_repos target directory %s exists and is a git repository", target)
def setUp(self): """ Init a ConfigDict object and load the configuration files from docs/config-specs/ """ self.old_dir = os.getcwd() # Save the old path to restore self.config = ConfigDict( "mongodb_setup", whereami.dsi_repo_path("docs", "config-specs")) self.config.load() self.parent_dir = os.path.join(os.path.expanduser("~"), "checkout_repos_test") self._delete_fixtures() self.reports_container = os.path.join( FIXTURE_FILES.fixture_file_path(), "container") self.reports_path = os.path.join(self.reports_container, "reports_tests") mkdir_p(self.reports_path)
def prepare_reports_dir(reports_dir="reports"): """ Prepare the reports directory to receive test data (logs, diagnostics etc). Unlink the current reports directory and remove any tar ball. Then create a timestamped directory and sym link to reports_dir :param str reports_dir: the reports directory name. Defaults to reports :raises OSError: when reports_dir exists and it is a directory. """ if os.path.exists(reports_dir): os.remove(reports_dir) if os.path.exists("../reports.tgz"): os.remove("../reports.tgz") real_reports_dir = "{}-{}".format( reports_dir, datetime.datetime.now(tz.tzlocal()).isoformat()) utils.mkdir_p(real_reports_dir) os.symlink(real_reports_dir, reports_dir)
def test_local_host_tee(self): """ Test run command map retrieve_files """ local = local_host.LocalHost() utils.mkdir_p(os.path.dirname(self.filename)) expected = "10\n9\n8\n7\n6\n5\n4\n3\n2\n1\nblast off!\n" with open(self.filename, "w", encoding="utf-8") as the_file: out = StringIO() tee = TeeStream(the_file, out) err = StringIO() command = "seq 10 -1 1 | xargs -I % sh -c '{ echo %; sleep .1; }'; \ echo 'blast off!'" local.exec_command(command, tee, err) self.assertEqual(out.getvalue(), expected) self.assertEqual(err.getvalue(), "") with open(self.filename) as the_file: self.assertEqual(expected, "".join(the_file.readlines()))
def download_logs(self, log_job_id, local_path): """ Download a tar.gz file with logs from the given job id. GET groups/{groupId}/logCollectionJobs/{jobId}/download :param str log_job_id: A string previously returned by create_log_collection_job(). :param str local_path: The local file where to store the downloaded file. """ url = "{}groups/{}/logCollectionJobs/{}/download".format( self.root, self.group_id, log_job_id) with requests.get(url, auth=self.auth, stream=True) as response: if not response.ok: LOG.error("HTTP error in download_logs", response=response.json()) response.raise_for_status() else: LOG.info("Downloading Atlas log file.", local_path=local_path) mkdir_p(os.path.dirname(local_path)) with open(local_path, "w") as file_handle: shutil.copyfileobj(response.raw, file_handle)
def test_local_host_exec_command(self): """ Test LocalHost.exec_command """ local = local_host.LocalHost() utils.mkdir_p(os.path.dirname(self.filename)) self.assertEqual(local.exec_command("exit 0"), 0) # test that the correct warning is issued mock_logger = MagicMock(name="LOG") local_host.LOG.warning = mock_logger self.assertEqual(local.exec_command("exit 1"), 1) mock_logger.assert_called_once_with( ANY_IN_STRING("Failed with exit status"), ANY, ANY, ANY) local.exec_command("touch {}".format(self.filename)) self.assertTrue(os.path.isfile(self.filename)) local.exec_command("touch {}".format(self.filename)) self.assertTrue(os.path.isfile(self.filename)) with open(self.filename, "w", encoding="utf-8") as the_file: the_file.write("Hello\n") the_file.write("World\n") out = StringIO() err = StringIO() local.exec_command("cat {}".format(self.filename), out, err) self.assertEqual(out.getvalue(), "Hello\nWorld\n") out = StringIO() err = StringIO() self.assertEqual( local.exec_command("cat {}; exit 1".format(self.filename), out, err), 1) self.assertEqual(out.getvalue(), "Hello\nWorld\n") self.assertEqual(err.getvalue(), "") out = StringIO() err = StringIO() local.exec_command("cat {} >&2; exit 1".format(self.filename), out, err) self.assertEqual(out.getvalue(), "") self.assertEqual(err.getvalue(), "Hello\nWorld\n") out = StringIO() err = StringIO() command = """cat {filename} && cat -n {filename} >&2; \ exit 1""".format(filename=self.filename) local.exec_command(command, out, err) self.assertEqual(out.getvalue(), "Hello\nWorld\n") self.assertEqual(err.getvalue(), " 1\tHello\n 2\tWorld\n") out = StringIO() err = StringIO() command = "seq 10 -1 1 | xargs -I % sh -c '{ echo %; sleep .1; }'; \ echo 'blast off!'" local.exec_command(command, out, err) self.assertEqual(out.getvalue(), "10\n9\n8\n7\n6\n5\n4\n3\n2\n1\nblast off!\n") self.assertEqual(err.getvalue(), "") # test timeout and that the correct warning is issued out = StringIO() err = StringIO() command = "sleep 1" mock_logger = MagicMock(name="LOG") local_host.LOG.warning = mock_logger self.assertEqual( local.exec_command(command, out, err, max_time_ms=500), 1) mock_logger.assert_called_once_with(ANY_IN_STRING("Timeout after"), ANY, ANY, ANY, ANY)
def jstest_one_host(config, mongo_uri, reports_dir, current_test_id, name): """ Run a jstest against one host. :param dict(ConfigDict) config: The system configuration. :param string mongo_uri: The mongo URI of the host to check :param string reports_dir: the report directory. :param string current_test_id: The identifier for this test. :param string name: The name of the jstest to run. Valid names are the keys from SCRIPT_NAMES. """ directory = os.path.join(reports_dir, current_test_id, "db-correctness", name) filename = os.path.join(directory, mongo_uri) mkdir_p(directory) client_host = make_workload_runner_host(config) script_path = os.path.join(config["test_control"]["jstests_dir"], SCRIPT_NAMES[name]) with open(filename, "w+", encoding="utf-8") as out: script_template = jinja2.Template(""" TestData = new Object(); TestData.inEvergreen = true; {% if auth %} TestData.clusterAuthMode = "x509"; TestData.auth = true; TestData.keyFile = "dummyKeyFile"; TestData.authUser = {{user|tojson}}; TestData.keyFileData = {{password|tojson}}; load({{jstests_script_file|tojson}}); {% endif %} load({{jstests_script_file|tojson}}); """) if name == "db-hash-check": if mongodb_tls_configured(config["mongodb_setup"]["meta"]): jstests_script = script_template.render( auth=True, user=config["mongodb_setup"]["authentication"]["username"], password=config["mongodb_setup"]["authentication"] ["password"], jstests_script_file=script_path, ) else: jstests_script = script_template.render( auth=False, jstests_script_file=script_path, ) error = client_host.exec_mongo_command( script=jstests_script, remote_file_name="jstests_script.js", connection_string=mongo_uri, stdout=out, stderr=out, ) else: error = client_host.exec_command("bin/mongo {} {}".format( mongo_uri, script_path), stdout=out, stderr=out) if error: # The return code of the script call is significant. If it is non-zero we put 1 at the # end of the file to indicate failure. The analysis script rules.py checks the number of # the last line. out.write("ERROR\n1") LOG.error("Failed %s correctness check on %s", name, mongo_uri) else: # Indicate that the script returned 0. This is checked by the analysis script rules.py. out.write("0") client_host.close()