1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
-- Make lldb available in global
lldb = require('lldb')
-- Global assertion functions
function assertTrue(x)
if not x then error('assertTrue failure') end
end
function assertFalse(x)
if x then error('assertNotNil failure') end
end
function assertNotNil(x)
if x == nil then error('assertNotNil failure') end
end
function assertEqual(x, y)
if type(x) == 'table' and type(y) == 'table' then
for k, _ in pairs(x) do
assertEqual(x[k], y[k])
end
elseif type(x) ~= type(y) then
error('assertEqual failure')
elseif x ~= y then
error('assertEqual failure')
end
end
function assertStrContains(x, y)
if not string.find(x, y, 1, true) then
error('assertStrContains failure')
end
end
-- Global helper functions
function read_file_non_empty_lines(f)
local lines = {}
while true do
local line = f:read('*l')
if not line then break end
if line ~= '\n' then table.insert(lines, line) end
end
return lines
end
function split_lines(str)
local lines = {}
for line in str:gmatch("[^\r\n]+") do
table.insert(lines, line)
end
return lines
end
function get_stopped_threads(process, reason)
local threads = {}
for i = 0, process:GetNumThreads() - 1 do
local t = process:GetThreadAtIndex(i)
if t:IsValid() and t:GetStopReason() == reason then
table.insert(threads, t)
end
end
return threads
end
function get_stopped_thread(process, reason)
local threads = get_stopped_threads(process, reason)
if #threads ~= 0 then return threads[1]
else return nil end
end
-- Test helper
local _M = {}
local _m = {}
local _mt = { __index = _m }
function _M.create_test(name, exe, output, input)
print('[lldb/lua] Create test ' .. name)
exe = exe or os.getenv('TEST_EXE')
output = output or os.getenv('TEST_OUTPUT')
input = input or os.getenv('TEST_INPUT')
lldb.SBDebugger.Initialize()
local debugger = lldb.SBDebugger.Create()
-- Ensure that debugger is created
assertNotNil(debugger)
assertTrue(debugger:IsValid())
debugger:SetAsync(false)
local lua_language = debugger:GetScriptingLanguage('lua')
assertNotNil(lua_language)
debugger:SetScriptLanguage(lua_language)
local test = setmetatable({
output = output,
input = input,
name = name,
exe = exe,
debugger = debugger
}, _mt)
_G[name] = test
return test
end
function _m:create_target(exe)
local target
if not exe then exe = self.exe end
target = self.debugger:CreateTarget(exe)
-- Ensure that target is created
assertNotNil(target)
assertTrue(target:IsValid())
return target
end
function _m:handle_command(command, collect)
if collect == nil then collect = true end
if collect then
local ret = lldb.SBCommandReturnObject()
local interpreter = self.debugger:GetCommandInterpreter()
assertTrue(interpreter:IsValid())
interpreter:HandleCommand(command, ret)
self.debugger:GetOutputFile():Flush()
self.debugger:GetErrorFile():Flush()
assertTrue(ret:Succeeded())
return ret:GetOutput()
else
self.debugger:HandleCommand(command)
self.debugger:GetOutputFile():Flush()
self.debugger:GetErrorFile():Flush()
end
end
function _m:run()
local tests = {}
for k, v in pairs(self) do
if string.sub(k, 1, 4) == 'Test' then
table.insert(tests, k)
end
end
table.sort(tests)
for _, t in ipairs(tests) do
print('[lldb/lua] Doing test ' .. self.name .. ' - ' .. t)
local success = xpcall(self[t], function(e)
print(debug.traceback())
end, self)
if not success then
print('[lldb/lua] Failure in test ' .. self.name .. ' - ' .. t)
return 1
end
end
return 0
end
return _M
|