156 lines · plain
1-- Make lldb available in global2lldb = require('lldb')3 4-- Global assertion functions5function assertTrue(x)6 if not x then error('assertTrue failure') end7end8 9function assertFalse(x)10 if x then error('assertNotNil failure') end11end12 13function assertNotNil(x)14 if x == nil then error('assertNotNil failure') end15end16 17function assertEqual(x, y)18 if type(x) == 'table' and type(y) == 'table' then19 for k, _ in pairs(x) do20 assertEqual(x[k], y[k])21 end22 elseif type(x) ~= type(y) then23 error('assertEqual failure')24 elseif x ~= y then25 error('assertEqual failure')26 end27end28 29function assertStrContains(x, y)30 if not string.find(x, y, 1, true) then31 error('assertStrContains failure')32 end33end34 35-- Global helper functions36function read_file_non_empty_lines(f)37 local lines = {}38 while true do39 local line = f:read('*l')40 if not line then break end41 if line ~= '\n' then table.insert(lines, line) end42 end43 return lines44end45 46function split_lines(str)47 local lines = {}48 for line in str:gmatch("[^\r\n]+") do49 table.insert(lines, line)50 end51 return lines52end53 54function get_stopped_threads(process, reason)55 local threads = {}56 for i = 0, process:GetNumThreads() - 1 do57 local t = process:GetThreadAtIndex(i)58 if t:IsValid() and t:GetStopReason() == reason then59 table.insert(threads, t)60 end61 end62 return threads63end64 65function get_stopped_thread(process, reason)66 local threads = get_stopped_threads(process, reason)67 if #threads ~= 0 then return threads[1]68 else return nil end69end70 71-- Test helper72 73local _M = {}74local _m = {}75 76local _mt = { __index = _m }77 78function _M.create_test(name, exe, output, input)79 print('[lldb/lua] Create test ' .. name)80 exe = exe or os.getenv('TEST_EXE')81 output = output or os.getenv('TEST_OUTPUT')82 input = input or os.getenv('TEST_INPUT')83 lldb.SBDebugger.Initialize()84 local debugger = lldb.SBDebugger.Create()85 -- Ensure that debugger is created86 assertNotNil(debugger)87 assertTrue(debugger:IsValid())88 89 debugger:SetAsync(false)90 91 local lua_language = debugger:GetScriptingLanguage('lua')92 assertNotNil(lua_language)93 debugger:SetScriptLanguage(lua_language)94 95 local test = setmetatable({96 output = output,97 input = input,98 name = name,99 exe = exe,100 debugger = debugger101 }, _mt)102 _G[name] = test103 return test104end105 106function _m:create_target(exe)107 local target108 if not exe then exe = self.exe end109 target = self.debugger:CreateTarget(exe)110 -- Ensure that target is created111 assertNotNil(target)112 assertTrue(target:IsValid())113 return target114end115 116function _m:handle_command(command, collect)117 if collect == nil then collect = true end118 if collect then119 local ret = lldb.SBCommandReturnObject()120 local interpreter = self.debugger:GetCommandInterpreter()121 assertTrue(interpreter:IsValid())122 interpreter:HandleCommand(command, ret)123 self.debugger:GetOutputFile():Flush()124 self.debugger:GetErrorFile():Flush()125 assertTrue(ret:Succeeded())126 return ret:GetOutput()127 else128 self.debugger:HandleCommand(command)129 self.debugger:GetOutputFile():Flush()130 self.debugger:GetErrorFile():Flush()131 end132end133 134function _m:run()135 local tests = {}136 for k, v in pairs(self) do137 if string.sub(k, 1, 4) == 'Test' then138 table.insert(tests, k)139 end140 end141 table.sort(tests)142 for _, t in ipairs(tests) do143 print('[lldb/lua] Doing test ' .. self.name .. ' - ' .. t)144 local success = xpcall(self[t], function(e)145 print(debug.traceback())146 end, self)147 if not success then148 print('[lldb/lua] Failure in test ' .. self.name .. ' - ' .. t)149 return 1150 end151 end152 return 0153end154 155return _M156