def upgrade_when_license_is_expired(self):
     """Check that upgrade can be performed with expired license"""
     with step("Create test data"):
         self.runner.leader_starter_instance.arangosh.run_command(
             ("create collection",
              'db._create("upgrade_when_license_is_expired");'),
             True,
             expect_to_fail=False)
         self.runner.leader_starter_instance.arangosh.run_command(
             (
                 "create documents",
                 'for(let i = 0; i < 100; ++i){ db.upgrade_when_license_is_expired.save({"id": i, "a": Math.random(1)})};',
             ),
             True,
             expect_to_fail=False,
         )
     self.expire_license()
     self.upgrade_leader_follower()
     with step("check that data is present after the upgrade"):
         try:
             self.runner.leader_starter_instance.arangosh.run_command(
                 (
                     "check that data is present",
                     'console.assert(db._query("for d in upgrade_when_license_is_expired collect with count into l return l==100").data.result[0])',
                 ),
                 True,
                 expect_to_fail=False,
             )
         except CliExecutionException as ex:
             raise Exception(
                 "Can't read data that was created before the upgrade."
             ) from ex
     self.check_readonly()
Esempio n. 2
0
def create_arangosh_dump(installer, dump_file_dir: str):
    """create arangosh memory dump file"""
    dump_filename = None
    with step("Start arangosh process"):
        exe_file = installer.cfg.bin_dir / "arangosh.exe"
        cmd = [str(exe_file)]
        arangosh_proc = psutil.Popen(cmd,
                                     bufsize=-1,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
        arangosh_pid = arangosh_proc.pid
    with step("Create a dump of arangosh process"):
        cmd = ["procdump", "-ma", str(arangosh_pid), dump_file_dir]
        lh.log_cmd(cmd)
        with psutil.Popen(cmd,
                          bufsize=-1,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE) as proc:
            (procdump_out, procdump_err) = proc.communicate()
            procdump_str = str(procdump_out, "UTF-8")
            attach(procdump_str, "procdump sdtout")
            attach(str(procdump_err), "procdump stderr")
            success_string = "Dump 1 complete"
            filename_regex = re.compile(
                r"^(\[\d{2}:\d{2}:\d{2}\] Dump 1 initiated: )(?P<filename>.*)$",
                re.MULTILINE)
            match = re.search(filename_regex, procdump_str)
            if procdump_str.find(success_string) < 0 or not match:
                raise Exception(
                    "procdump wasn't able to create a dump file: " +
                    procdump_str)
            dump_filename = match.group("filename")
    with step("Kill arangosh process"):
        arangosh_proc.kill()
    return dump_filename
Esempio n. 3
0
def create_dump_for_exe(exe_file: str, dump_file_dir: str):
    """run given executable with \"-?\" command line parameter and create a memory dump when it terminates"""
    exe_file = Path(exe_file)
    exe_name = exe_file.name
    with step(f"Create a memory dump of the program: {exe_name}"):
        dump_filename = None
        cmd = [
            "procdump", "-ma", "-t", "-x", dump_file_dir,
            str(exe_file), "-?"
        ]
        lh.log_cmd(cmd)
        with psutil.Popen(cmd,
                          bufsize=-1,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE) as proc:
            (procdump_out, procdump_err) = proc.communicate()
            procdump_str = str(procdump_out, "UTF-8")
            attach(procdump_str, "procdump sdtout")
            attach(str(procdump_err), "procdump stderr")
            success_string = "Dump 1 complete"
            filename_regex = re.compile(
                r"^(\[\d{2}:\d{2}:\d{2}\] Dump 1 initiated: )(?P<filename>.*)$",
                re.MULTILINE)
            match = re.search(filename_regex, procdump_str)
            if procdump_str.find(success_string) < 0 or not match:
                raise Exception(
                    "procdump wasn't able to create a dump file: " +
                    procdump_str)
            dump_filename = match.group("filename")
        return dump_filename
Esempio n. 4
0
 def run_command(self,
                 cmd,
                 verbose=True,
                 timeout=300,
                 result_line=dummy_line_result,
                 expect_to_fail=False,
                 use_default_auth=True):
     """run a command in arangosh"""
     title = f"run a command in arangosh: {cmd[0]}"
     with step(title):
         executable = self.cfg.bin_dir / "arangosh"
         arangosh_args = self.cfg.default_arangosh_args + [
             "--log.level", "v8=debug",
             "--javascript.execute-string"
         ]
         arangosh_args += cmd[1:]
         return self.run_arango_tool_monitored(
             executeable=executable,
             more_args=arangosh_args,
             timeout=timeout,
             result_line=result_line,
             verbose=verbose,
             expect_to_fail=expect_to_fail,
             use_default_auth=use_default_auth
         )
 def test_debug_network_symbol_server_windows(self):
     """Check that debug symbols can be found on the ArangoDB symbol server and then used to debug arangod executable"""
     # This testcase is needed to check the state of the symbol server and is not meant to run during ArangoDB product testing.
     version = semver.VersionInfo.parse(self.installer.cfg.version)
     symsrv_dir = "\\\\symbol.arangodb.biz\\symbol\\symsrv_arangodb" + str(
         version.major) + str(version.minor)
     dump_file = create_arangod_dump(self.installer,
                                     str(DebuggerTestSuite.STARTER_DIR),
                                     str(DebuggerTestSuite.DUMP_FILES_DIR))
     with step(
             "Check that stack trace with function names and line numbers can be acquired from cdb"
     ):
         cmd = " ".join([
             "cdb",
             "-z",
             dump_file,
             "-y",
             f"srv*{DebuggerTestSuite.SYMSRV_CACHE_DIR}*{symsrv_dir}",
             "-lines",
             "-n",
         ])
         attach(cmd, "CDB command", attachment_type=AttachmentType.TEXT)
         cdb = wexpect.spawn(cmd)
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=900)
         cdb.sendline("k")
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=900)
         stack = cdb.before
         cdb.sendline("q")
         attach(stack,
                "Stacktrace from cdb output",
                attachment_type=AttachmentType.TEXT)
         assert "arangod!main" in stack, "Stack must contain real function names."
         assert "arangod.cpp" in stack, "Stack must contain real source file names."
 def test_debug_symbols_windows(self, executable):
     """Check that debug symbols can be used to debug arango executable using a memory dump file (Windows)"""
     exe_file = [
         str(file.path) for file in self.installer.arango_binaries
         if file.path.name == executable + ".exe"
     ][0]
     dump_file = create_dump_for_exe(exe_file,
                                     DebuggerTestSuite.DUMP_FILES_DIR)
     pdb_dir = str(self.installer.cfg.debug_install_prefix)
     with step(
             "Check that stack trace with function names and line numbers can be acquired from cdb"
     ):
         cmd = " ".join(
             ["cdb", "-z", dump_file, "-y", pdb_dir, "-lines", "-n"])
         attach(cmd, "CDB command", attachment_type=AttachmentType.TEXT)
         cdb = wexpect.spawn(cmd)
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=180)
         cdb.sendline("k")
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=180)
         stack = cdb.before
         cdb.sendline("q")
         attach(stack,
                "Stacktrace from cdb output",
                attachment_type=AttachmentType.TEXT)
         assert f"{executable}!main" in stack, "Stack must contain real function names."
         assert f"{executable}.cpp" in stack, "Stack must contain real source file names."
 def test_debug_symbols_symsrv_windows(self):
     """Debug arangod executable using symbol server (Windows)"""
     symsrv_dir = str(DebuggerTestSuite.SYMSRV_DIR)
     store(str(self.installer.cfg.debug_install_prefix / "arangod.pdb"),
           symsrv_dir)
     exe_file = [
         str(file.path) for file in self.installer.arango_binaries
         if file.path.name == "arangod.exe"
     ][0]
     dump_file = create_dump_for_exe(exe_file,
                                     DebuggerTestSuite.DUMP_FILES_DIR)
     with step(
             "Check that stack trace with function names and line numbers can be acquired from cdb"
     ):
         cmd = " ".join([
             "cdb",
             "-z",
             dump_file,
             "-y",
             f"srv*{DebuggerTestSuite.SYMSRV_CACHE_DIR}*{DebuggerTestSuite.SYMSRV_DIR}",
             "-lines",
             "-n",
         ])
         attach(cmd, "CDB command", attachment_type=AttachmentType.TEXT)
         cdb = wexpect.spawn(cmd)
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=900)
         cdb.sendline("k")
         cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=900)
         stack = cdb.before
         cdb.sendline("q")
         attach(stack,
                "Stacktrace from cdb output",
                attachment_type=AttachmentType.TEXT)
         assert "arangod!main" in stack, "Stack must contain real function names."
         assert "arangod.cpp" in stack, "Stack must contain real source file names."
Esempio n. 8
0
 def progress(self, msg):
     """add something to the state..."""
     logging.info("UI-Test: " + msg)
     with step("UI test progress: " + msg):
         pass
     if len(self.state) > 0:
         self.state += "\n"
     self.state += "UI: " + msg
Esempio n. 9
0
def create_arangod_dump(installer, starter_dir: str, dump_file_dir: str):
    """create arangod memory dump file"""
    starter = StarterManager(
        basecfg=installer.cfg,
        install_prefix=Path(starter_dir),
        instance_prefix="single",
        expect_instances=[InstanceType.SINGLE],
        mode="single",
        jwt_str="single",
    )
    dump_filename = None
    try:
        with step("Start a single server deployment"):
            starter.run_starter()
            starter.detect_instances()
            starter.detect_instance_pids()
            starter.set_passvoid("")
            pid = starter.all_instances[0].pid
        with step("Create a dump of arangod process"):
            cmd = ["procdump", "-ma", str(pid), dump_file_dir]
            lh.log_cmd(cmd)
            with psutil.Popen(cmd,
                              bufsize=-1,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE) as proc:
                (procdump_out, procdump_err) = proc.communicate()
                procdump_str = str(procdump_out, "UTF-8")
                attach(procdump_str, "procdump sdtout")
                attach(str(procdump_err), "procdump stderr")
                success_string = "Dump 1 complete"
                filename_regex = re.compile(
                    r"^(\[\d{2}:\d{2}:\d{2}\] Dump 1 initiated: )(?P<filename>.*)$",
                    re.MULTILINE)
                match = re.search(filename_regex, procdump_str)
                if procdump_str.find(success_string) < 0 or not match:
                    raise Exception(
                        "procdump wasn't able to create a dump file: " +
                        procdump_str)
                dump_filename = match.group("filename")
    finally:
        starter.terminate_instance()
        kill_all_processes()
    return dump_filename
Esempio n. 10
0
def store(pdb_filename: str, target_dir: str):
    """store pdb file in symbol server directory"""
    with step(f"Store pdb file {pdb_filename} in symbol server directory"):
        print(f"Storing file {pdb_filename}")
        command = [
            "symstore.exe", "add", "/f", pdb_filename, "/s", target_dir, "/t",
            "ArangoDB", "/compress"
        ]
        run_cmd_and_log_stdout(command)
        print(f"File {pdb_filename} successfully stored to {target_dir}")
Esempio n. 11
0
 def replace_binary_for_upgrade(self, new_install_cfg, relaunch=True):
     """
     - replace the parts of the installation with information
       after an upgrade
     - kill the starter processes of the old version
     - revalidate that the old arangods are still running and alive
     - replace the starter binary with a new one.
       this has not yet spawned any children
     """
     # On windows the install prefix may change,
     # since we can't overwrite open files:
     self.replace_binary_setup_for_upgrade(new_install_cfg)
     with step("kill the starter processes of the old version"):
         logging.info("StarterManager: Killing my instance [%s]", str(self.instance.pid))
         self.kill_instance()
     with step("revalidate that the old arangods are still running and alive"):
         self.detect_instance_pids_still_alive()
     if relaunch:
         with step("replace the starter binary with a new one," + " this has not yet spawned any children"):
             self.respawn_instance()
             logging.info("StarterManager: respawned instance as [%s]", str(self.instance.pid))
 def test_debug_symbols_attach_to_process_windows(self):
     """Debug arangod executable by attaching debugger to a running process (Windows)"""
     starter = StarterManager(
         basecfg=self.installer.cfg,
         install_prefix=Path(DebuggerTestSuite.STARTER_DIR),
         instance_prefix="single",
         expect_instances=[InstanceType.SINGLE],
         mode="single",
         jwt_str="single",
     )
     try:
         with step("Start a single server deployment"):
             starter.run_starter()
             starter.detect_instances()
             starter.detect_instance_pids()
             starter.set_passvoid("")
             pid = starter.all_instances[0].pid
         pdb_dir = str(self.installer.cfg.debug_install_prefix)
         with step(
                 "Check that stack trace with function names and line numbers can be acquired from cdb"
         ):
             cmd = " ".join([
                 "cdb", "-pv", "-p",
                 str(pid), "-y", pdb_dir, "-lines", "-n"
             ])
             attach(cmd, "CDB command", attachment_type=AttachmentType.TEXT)
             cdb = wexpect.spawn(cmd)
             cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=300)
             cdb.sendline("k")
             cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=300)
             stack = cdb.before
             cdb.sendline("q")
             attach(stack,
                    "Stacktrace from cdb output",
                    attachment_type=AttachmentType.TEXT)
             assert "arangod!main" in stack, "Stack must contain real function names."
             assert "arangod.cpp" in stack, "Stack must contain real source file names."
     finally:
         starter.terminate_instance()
         kill_all_processes()
Esempio n. 13
0
 def expire_license_on_follower_cluster(self):
     """Check that follower cluster goes to read-only mode when license is expired"""
     with step("Expire license on follower"):
         # pylint: disable=attribute-defined-outside-init
         self.starter = self.runner.cluster1["instance"]
         self.expire_license()
         self.starter = self.runner.cluster2["instance"]
     with step("Create collection on leader cluster"):
         self.starter.arangosh.run_command(
             ("create collection", 'db._create("checkExpireLicenseOnFollower");'), True, expect_to_fail=False
         )
     with step("Check that collection wasn't replicated to follower cluster"):
         try:
             self.runner.cluster1["instance"].arangosh.run_command(
                 ("try to read collection", "db._query('FOR doc IN checkExpireLicenseOnFollower RETURN doc');"),
                 True,
                 expect_to_fail=True,
             )
         except CliExecutionException as ex:
             raise Exception(
                 "Collection was replicated to follower cluster after license expiry. Follower must be in read-only mode!"
             ) from ex
Esempio n. 14
0
    def progress(self, is_sub, msg, separator="x", supress_allure=False):
        """report user message, record for error handling."""
        if self.selenium:
            self.state += self.selenium.get_progress()
        if is_sub:
            if separator == "x":
                separator = "="
            lh.subsection(msg, separator)
            self.state += "   - " + msg
        else:
            if separator == "x":
                separator = "#"
            lh.section(msg, separator)
            self.state += "*** " + msg

        if not supress_allure:
            with step("Progress: " + msg):
                pass
Esempio n. 15
0
 def run_before_fixtures(self, funcs):
     """run a set of fixtures before the test suite or test case"""
     for func in funcs:
         name = func.__doc__ if func.__doc__ else func.__name__
         with step(name):
             fixture_uuid = str(uuid4())
             self.test_suite_context.test_listener.start_before_fixture(
                 fixture_uuid, name)
             exc_type = None
             exc_val = None
             exc_tb = None
             try:
                 func()
             # pylint: disable=bare-except
             except:
                 exc_type, exc_val, exc_tb = sys.exc_info()
         self.test_suite_context.test_listener.stop_before_fixture(
             fixture_uuid, exc_type, exc_val, exc_tb)
         if exc_val:
             raise Exception("Fixture failed.") from exc_val