brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 4e3c706 Raw
236 lines · python
1import lldb2import json3from intelpt_testcase import *4from lldbsuite.test.lldbtest import *5from lldbsuite.test import lldbutil6from lldbsuite.test.decorators import *7 8 9def find(predicate, seq):10    for item in seq:11        if predicate(item):12            return item13 14 15class TestTraceSave(TraceIntelPTTestCaseBase):16    def testErrorMessages(self):17        # We first check the output when there are no targets18        self.expect(19            "trace save",20            substrs=[21                "error: invalid target, create a target using the 'target create' command"22            ],23            error=True,24        )25 26        # We now check the output when there's a non-running target27        self.expect(28            "target create "29            + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")30        )31 32        self.expect(33            "trace save",34            substrs=["error: Command requires a current process."],35            error=True,36        )37 38        # Now we check the output when there's a running target without a trace39        self.expect("b main")40        self.expect("run")41 42        self.expect(43            "trace save", substrs=["error: Process is not being traced"], error=True44        )45 46    @skipIfNoIntelPT47    def testSaveToInvalidDir(self):48        self.expect(49            "target create "50            + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")51        )52        self.expect("b main")53        self.expect("r")54        self.expect("thread trace start")55        self.expect("n")56 57        # Check the output when saving without providing the directory argument58        self.expect(59            "trace save ",60            substrs=[61                "error: a single path to a directory where the trace bundle will be created is required"62            ],63            error=True,64        )65 66        # Check the output when saving to an invalid directory67        self.expect(68            "trace save /", substrs=["error: couldn't write to the file"], error=True69        )70 71    def testSaveWhenNotLiveTrace(self):72        self.expect(73            "trace load -v "74            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),75            substrs=["intel-pt"],76        )77 78        # Check the output when not doing live tracing79        self.expect(80            "trace save "81            + os.path.join(self.getBuildDir(), "intelpt-trace", "trace_not_live_dir")82        )83 84    def testSaveMultiCpuTrace(self):85        """86        This test starts a per-cpu tracing session, then saves the session to disk, and87        finally it loads it again.88        """89        self.skipIfPerCpuTracingIsNotSupported()90 91        self.expect(92            "target create "93            + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")94        )95        self.expect("b main")96        self.expect("r")97        self.expect("process trace start --per-cpu-tracing")98        self.expect("b 7")99 100        output_dir = os.path.join(self.getBuildDir(), "intelpt-trace", "trace_save")101        self.expect("trace save " + output_dir)102 103        def checkSessionBundle(session_file_path):104            with open(session_file_path) as session_file:105                session = json.load(session_file)106                # We expect tsc conversion info107                self.assertIn("tscPerfZeroConversion", session)108                # We expect at least one cpu109                self.assertGreater(len(session["cpus"]), 0)110 111                # We expect the required trace files to be created112                for cpu in session["cpus"]:113                    cpu_files_prefix = os.path.join(output_dir, "cpus", str(cpu["id"]))114                    self.assertTrue(os.path.exists(cpu_files_prefix + ".intelpt_trace"))115                    self.assertTrue(116                        os.path.exists(cpu_files_prefix + ".perf_context_switch_trace")117                    )118 119                # We expect at least one one process120                self.assertGreater(len(session["processes"]), 0)121                for process in session["processes"]:122                    # We expect at least one thread123                    self.assertGreater(len(process["threads"]), 0)124                    # We don't expect thread traces125                    for thread in process["threads"]:126                        self.assertTrue(127                            ("iptTrace" not in thread) or (thread["iptTrace"] is None)128                        )129 130        original_trace_session_file = os.path.join(output_dir, "trace.json")131        checkSessionBundle(original_trace_session_file)132 133        output_dir = os.path.join(self.getBuildDir(), "intelpt-trace", "trace_save")134        self.expect("trace load " + os.path.join(output_dir, "trace.json"))135        output_copy_dir = os.path.join(136            self.getBuildDir(), "intelpt-trace", "copy_trace_save"137        )138        self.expect("trace save " + output_copy_dir)139 140        # We now check that the new bundle is correct on its own141        copied_trace_session_file = os.path.join(output_copy_dir, "trace.json")142        checkSessionBundle(copied_trace_session_file)143 144        # We finally check that the new bundle has the same information as the original one145        with open(original_trace_session_file) as original_file:146            original = json.load(original_file)147            with open(copied_trace_session_file) as copy_file:148                copy = json.load(copy_file)149 150                self.assertEqual(len(original["processes"]), len(copy["processes"]))151 152                for process in original["processes"]:153                    copied_process = find(154                        lambda proc: proc["pid"] == process["pid"], copy["processes"]155                    )156                    self.assertIsNotNone(copied_process)157 158                    for thread in process["threads"]:159                        copied_thread = find(160                            lambda thr: thr["tid"] == thread["tid"],161                            copied_process["threads"],162                        )163                        self.assertIsNotNone(copied_thread)164 165                for cpu in original["cpus"]:166                    copied_cpu = find(lambda cor: cor["id"] == cpu["id"], copy["cpus"])167                    self.assertIsNotNone(copied_cpu)168 169    @skipIfNoIntelPT170    def testSaveTrace(self):171        self.expect(172            "target create "173            + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")174        )175        self.expect("b main")176        self.expect("r")177        self.expect("thread trace start")178        self.expect("b 7")179 180        ci = self.dbg.GetCommandInterpreter()181        res = lldb.SBCommandReturnObject()182 183        ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)184        self.assertTrue(res.Succeeded())185        first_ten_instructions = res.GetOutput()186 187        ci.HandleCommand("thread trace dump instructions -c 10", res)188        self.assertTrue(res.Succeeded())189        last_ten_instructions = res.GetOutput()190 191        # Now, save the trace to <trace_copy_dir>192        self.expect(193            "trace save "194            + os.path.join(self.getBuildDir(), "intelpt-trace", "trace_copy_dir")195        )196 197        # Load the trace just saved198        self.expect(199            "trace load -v "200            + os.path.join(201                self.getBuildDir(), "intelpt-trace", "trace_copy_dir", "trace.json"202            ),203            substrs=["intel-pt"],204        )205 206        # Compare with instructions saved at the first time207        ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)208        self.assertTrue(res.Succeeded())209        self.assertEqual(res.GetOutput(), first_ten_instructions)210 211        ci.HandleCommand("thread trace dump instructions -c 10", res)212        self.assertTrue(res.Succeeded())213        self.assertEqual(res.GetOutput(), last_ten_instructions)214 215    def testSaveKernelTrace(self):216        original_trace_file = os.path.join(217            self.getSourceDir(), "intelpt-kernel-trace", "trace.json"218        )219        copied_trace_dir = os.path.join(self.getBuildDir(), "intelpt-kernel-trace")220        copied_trace_file = os.path.join(copied_trace_dir, "trace.json")221 222        self.expect("trace load -v " + original_trace_file, substrs=["intel-pt"])223        self.expect("trace save " + copied_trace_dir)224 225        # We finally check that the new json has the same information as the original one226        with open(original_trace_file) as original_file:227            original_file = json.load(original_file)228            with open(copied_trace_file) as copy_file:229                copy_file = json.load(copy_file)230                self.assertIn("kernel", copy_file)231 232                self.assertEqual(233                    os.path.basename(original_file["kernel"]["file"]),234                    os.path.basename(copy_file["kernel"]["file"]),235                )236