1import lldb
2from intelpt_testcase import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5from lldbsuite.test.decorators import *
6
7class TestTraceSave(TraceIntelPTTestCaseBase):
8    mydir = TestBase.compute_mydir(__file__)
9
10    def testErrorMessages(self):
11        # We first check the output when there are no targets
12        self.expect("process trace save",
13            substrs=["error: invalid target, create a target using the 'target create' command"],
14            error=True)
15
16        # We now check the output when there's a non-running target
17        self.expect("target create " +
18            os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
19
20        self.expect("process trace save",
21            substrs=["error: invalid process"],
22            error=True)
23
24        # Now we check the output when there's a running target without a trace
25        self.expect("b main")
26        self.expect("run")
27
28        self.expect("process trace save",
29            substrs=["error: Process is not being traced"],
30            error=True)
31
32    def testSaveToInvalidDir(self):
33        self.expect("target create " +
34            os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
35        self.expect("b main")
36        self.expect("r")
37        self.expect("thread trace start")
38        self.expect("n")
39
40        # Check the output when saving without providing the directory argument
41        self.expect("process trace save -d",
42            substrs=["error: last option requires an argument"],
43            error=True)
44
45        # Check the output when saving to an invalid directory
46        self.expect("process trace save -d /",
47            substrs=["error: couldn't write to the file"],
48            error=True)
49
50    def testSaveWhenNotLiveTrace(self):
51        self.expect("trace load -v " +
52            os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),
53            substrs=["intel-pt"])
54
55        # Check the output when not doing live tracing
56        self.expect("process trace save -d " +
57            os.path.join(self.getBuildDir(), "intelpt-trace", "trace_not_live_dir"),
58            substrs=["error: Saving a trace requires a live process."],
59            error=True)
60
61
62    def testSaveTrace(self):
63        self.expect("target create " +
64            os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
65        self.expect("b main")
66        self.expect("r")
67        self.expect("thread trace start")
68        self.expect("b 7")
69
70        ci = self.dbg.GetCommandInterpreter()
71        res = lldb.SBCommandReturnObject()
72
73        ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)
74        self.assertEqual(res.Succeeded(), True)
75        first_ten_instructions = res.GetOutput()
76
77        ci.HandleCommand("thread trace dump instructions -c 10", res)
78        self.assertEqual(res.Succeeded(), True)
79        last_ten_instructions = res.GetOutput()
80
81        # Now, save the trace to <trace_copy_dir>
82        self.expect("process trace save -d " +
83            os.path.join(self.getBuildDir(), "intelpt-trace", "trace_copy_dir"))
84
85        # Load the trace just saved
86        self.expect("trace load -v " +
87            os.path.join(self.getBuildDir(), "intelpt-trace", "trace_copy_dir", "trace.json"),
88            substrs=["intel-pt"])
89
90        # Compare with instructions saved at the first time
91        ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)
92        self.assertEqual(res.Succeeded(), True)
93        self.assertEqual(res.GetOutput(), first_ten_instructions)
94
95        ci.HandleCommand("thread trace dump instructions -c 10", res)
96        self.assertEqual(res.Succeeded(), True)
97        self.assertEqual(res.GetOutput(), last_ten_instructions)
98