1from lldbsuite.test.lldbtest import *
2import os
3import time
4import json
5
6ADDRESS_REGEX = '0x[0-9a-fA-F]*'
7
8# Decorator that runs a test with both modes of USE_SB_API.
9# It assumes that no tests can be executed in parallel.
10def testSBAPIAndCommands(func):
11    def wrapper(*args, **kwargs):
12        TraceIntelPTTestCaseBase.USE_SB_API = True
13        func(*args, **kwargs)
14        TraceIntelPTTestCaseBase.USE_SB_API = False
15        func(*args, **kwargs)
16    return wrapper
17
18# Class that should be used by all python Intel PT tests.
19#
20# It has a handy check that skips the test if the intel-pt plugin is not enabled.
21#
22# It also contains many functions that can test both the SB API or the command line version
23# of the most important tracing actions.
24class TraceIntelPTTestCaseBase(TestBase):
25
26    NO_DEBUG_INFO_TESTCASE = True
27
28    # If True, the trace test methods will use the SB API, otherwise they'll use raw commands.
29    USE_SB_API = False
30
31    def setUp(self):
32        TestBase.setUp(self)
33        if 'intel-pt' not in configuration.enabled_plugins:
34            self.skipTest("The intel-pt test plugin is not enabled")
35
36    def getTraceOrCreate(self):
37        if not self.target().GetTrace().IsValid():
38            error = lldb.SBError()
39            self.target().CreateTrace(error)
40        return self.target().GetTrace()
41
42    def assertSBError(self, sberror, error=False):
43        if error:
44            self.assertTrue(sberror.Fail())
45        else:
46            self.assertSuccess(sberror)
47
48    def createConfiguration(self, threadBufferSize=None,
49                            processBufferSizeLimit=None, enableTsc=False,
50                            psbPeriod=None):
51        obj = {}
52        if processBufferSizeLimit is not None:
53            obj["processBufferSizeLimit"] = processBufferSizeLimit
54        if threadBufferSize is not None:
55            obj["threadBufferSize"] = threadBufferSize
56        if psbPeriod is not None:
57            obj["psbPeriod"] = psbPeriod
58        obj["enableTsc"] = enableTsc
59
60        configuration = lldb.SBStructuredData()
61        configuration.SetFromJSON(json.dumps(obj))
62        return configuration
63
64    def traceStartThread(self, thread=None, error=False, substrs=None,
65                         threadBufferSize=None, enableTsc=False, psbPeriod=None):
66        if self.USE_SB_API:
67            trace = self.getTraceOrCreate()
68            thread = thread if thread is not None else self.thread()
69            configuration = self.createConfiguration(
70                threadBufferSize=threadBufferSize, enableTsc=enableTsc,
71                psbPeriod=psbPeriod)
72            self.assertSBError(trace.Start(thread, configuration), error)
73        else:
74            command = "thread trace start"
75            if thread is not None:
76                command += " " + str(thread.GetIndexID())
77            if threadBufferSize is not None:
78                command += " -s " + str(threadBufferSize)
79            if enableTsc:
80                command += " --tsc"
81            if psbPeriod is not None:
82                command += " --psb-period " + str(psbPeriod)
83            self.expect(command, error=error, substrs=substrs)
84
85    def traceStartProcess(self, processBufferSizeLimit=None, error=False,
86                          substrs=None, enableTsc=False, psbPeriod=None):
87        if self.USE_SB_API:
88            trace = self.getTraceOrCreate()
89            configuration = self.createConfiguration(
90                processBufferSizeLimit=processBufferSizeLimit, enableTsc=enableTsc,
91                psbPeriod=psbPeriod)
92            self.assertSBError(trace.Start(configuration), error=error)
93        else:
94            command = "process trace start"
95            if processBufferSizeLimit != None:
96                command += " -l " + str(processBufferSizeLimit)
97            if enableTsc:
98                command += " --tsc"
99            if psbPeriod is not None:
100                command += " --psb-period " + str(psbPeriod)
101            self.expect(command, error=error, substrs=substrs)
102
103    def traceStopProcess(self):
104        if self.USE_SB_API:
105            self.assertSuccess(self.target().GetTrace().Stop())
106        else:
107            self.expect("process trace stop")
108
109    def traceStopThread(self, thread=None, error=False):
110        if self.USE_SB_API:
111            thread = thread if thread is not None else self.thread()
112            self.assertSBError(self.target().GetTrace().Stop(thread), error)
113
114        else:
115            command = "thread trace stop"
116            if thread is not None:
117                command += " " + str(thread.GetIndexID())
118            self.expect(command, error=error)
119