| 
 | 1 | +local tap = require('tap')  | 
 | 2 | +local test = tap.test('gh-9217-profile-parsers-error-handling'):skipcond({  | 
 | 3 | +  ['Profile tools are implemented for x86_64 only'] = jit.arch ~= 'x86' and  | 
 | 4 | +                                                      jit.arch ~= 'x64',  | 
 | 5 | +  ['Profile tools are implemented for Linux only'] = jit.os ~= 'Linux',  | 
 | 6 | +  -- XXX: Tarantool integration is required to run this test properly.  | 
 | 7 | +  -- luacheck: no global  | 
 | 8 | +  ['No profile tools CLI option integration'] = _TARANTOOL,  | 
 | 9 | +})  | 
 | 10 | + | 
 | 11 | +jit.off()  | 
 | 12 | +jit.flush()  | 
 | 13 | + | 
 | 14 | +local table_new = require('table.new')  | 
 | 15 | +local utils = require('utils')  | 
 | 16 | + | 
 | 17 | +local BAD_PATH = utils.tools.profilename('bad-path-tmp.bin')  | 
 | 18 | +local NON_PROFILE_DATA = utils.tools.profilename('not-profile-data.tmp.bin')  | 
 | 19 | +local CORRUPT_PROFILE = utils.tools.profilename('profdata.tmp.bin')  | 
 | 20 | + | 
 | 21 | +local EXECUTABLE = utils.exec.luacmd(arg)  | 
 | 22 | +local PARSERS = {  | 
 | 23 | +  memprof = EXECUTABLE .. ' -tm ',  | 
 | 24 | +  sysprof = EXECUTABLE .. ' -ts ',  | 
 | 25 | +}  | 
 | 26 | +local REDIRECT_OUTPUT = ' 2>&1'  | 
 | 27 | + | 
 | 28 | +local TABLE_SIZE = 20  | 
 | 29 | + | 
 | 30 | +local TEST_CASES = {  | 
 | 31 | +  {  | 
 | 32 | +    path = BAD_PATH,  | 
 | 33 | +    err_msg = 'Failed to open'  | 
 | 34 | +  },  | 
 | 35 | +  {  | 
 | 36 | +    path = NON_PROFILE_DATA,  | 
 | 37 | +    err_msg = 'Failed to parse symtab from'  | 
 | 38 | +  },  | 
 | 39 | +  {  | 
 | 40 | +    path = CORRUPT_PROFILE,  | 
 | 41 | +    err_msg = 'Failed to parse profile data from'  | 
 | 42 | +  },  | 
 | 43 | +}  | 
 | 44 | + | 
 | 45 | +test:plan(2 * #TEST_CASES)  | 
 | 46 | + | 
 | 47 | +local function generate_non_profile_data(path)  | 
 | 48 | +  local file = io.open(path, 'w')  | 
 | 49 | +  file:write('data')  | 
 | 50 | +  file:close()  | 
 | 51 | +end  | 
 | 52 | + | 
 | 53 | +local function generate_corrupt_profile(path)  | 
 | 54 | +  local res, err = misc.memprof.start(path)  | 
 | 55 | +  -- Should start successfully.  | 
 | 56 | +  assert(res, err)  | 
 | 57 | + | 
 | 58 | +  local _ = table_new(TABLE_SIZE, 0)  | 
 | 59 | +   _ = nil  | 
 | 60 | +  collectgarbage()  | 
 | 61 | + | 
 | 62 | +  res, err = misc.memprof.stop()  | 
 | 63 | +  -- Should stop successfully.  | 
 | 64 | +  assert(res, err)  | 
 | 65 | + | 
 | 66 | +  local file = io.open(path, 'r')  | 
 | 67 | +  local content = file:read('*all')  | 
 | 68 | +  file:close()  | 
 | 69 | +  local index = string.find(content, 'ljm')  | 
 | 70 | + | 
 | 71 | +  file = io.open(path, 'w')  | 
 | 72 | +  file:write(string.sub(content, 1, index - 1))  | 
 | 73 | +  file:close()  | 
 | 74 | +end  | 
 | 75 | + | 
 | 76 | +generate_non_profile_data(NON_PROFILE_DATA)  | 
 | 77 | +generate_corrupt_profile(CORRUPT_PROFILE)  | 
 | 78 | + | 
 | 79 | +for _, case in ipairs(TEST_CASES) do  | 
 | 80 | +  for profiler, parser in pairs(PARSERS) do  | 
 | 81 | +    local path = case.path  | 
 | 82 | +    local err_msg = case.err_msg  | 
 | 83 | +    local output = io.popen(parser .. path .. REDIRECT_OUTPUT):read('*all')  | 
 | 84 | +    test:like(output, err_msg, string.format('%s: %s', profiler, err_msg))  | 
 | 85 | +  end  | 
 | 86 | +end  | 
 | 87 | + | 
 | 88 | +os.remove(NON_PROFILE_DATA)  | 
 | 89 | +os.remove(CORRUPT_PROFILE)  | 
 | 90 | +test:done(true)  | 
0 commit comments