def testDeregister(self): manager = Manager() output = manager.list() # will be transferred to a different process logger = Logger(output.append, output.append) self.setup(logger=logger) script = self.service.register_script( Script('kretprobe:vfs_read { @bytes = hist(retval); }')) self.assertEqual(script.state.status, 'starting') script = self.waitForData(script.script_id) self.assertTrue(script.state.data) self.service.deregister_script(script.script_id) self.service.stop_daemon() # verify if events happen in the correct order by checking the log messages full_output = "\n".join(output) print(f"testDeregister output: {full_output}") log_msgs_order = [ "starting script", "started script", "stopping script", "stopped script", "deregistered script", "deregister: script .* not found" ] idx = [] for log_msg in log_msgs_order: m = re.search(log_msg, full_output) if not m: raise Exception(f"cannot find '{log_msg}' in:\n{full_output}") idx.append(m.span()[0]) self.assertEqual(len(idx), len(log_msgs_order)) self.assertEqual(idx, sorted(idx))
def testStart(self): self.setup() script = self.service.register_script(Script('kretprobe:vfs_read { @bytes = hist(retval); }')) self.assertEqual(script.state.status, 'starting') script = self.waitForData(script.script_id) self.assertTrue(script.state.data) self.service.stop_script(script.script_id)
def testExpiry(self): config = PMDAConfig() config.script_expiry_time = 2 self.setup(config) script = self.service.register_script(Script('kretprobe:vfs_read { @bytes = hist(retval); }')) time.sleep(4) script = self.service.refresh_script(script.script_id) self.assertIsNone(script)
def testTooMuchOutput(self): config = PMDAConfig() config.max_throughput = 64 * 1024 self.setup(config) script = self.service.register_script(Script('profile:hz:9999 { printf("test"); }')) time.sleep(15) script = self.service.refresh_script(script.script_id) self.assertEqual(script.state.status, 'error') self.assertRegex(script.state.error, 'BPFtrace output exceeds limit of .+ bytes per second')
def testParseHist(self): script = Script(""" if ($ns) { @usecs = hist((nsecs - $ns) / 1000); } delete(@qtime[args->next_pid]); """) script = parse_code(script) self.assertEqual(script.variables['@usecs'].metrictype, MetricType.Histogram) self.assertEqual(script.variables['@usecs'].semantics, PM_SEM_COUNTER)
def testParseLhist(self): script = Script(""" profile:hz:99 /pid/ { @cpu = lhist(cpu, 0, 1000, 1); } """) script = parse_code(script) self.assertEqual(script.variables['@cpu'].metrictype, MetricType.Histogram) self.assertEqual(script.variables['@cpu'].semantics, PM_SEM_COUNTER)
def testTooManyKeys(self): config = PMDAConfig() config.max_throughput = 4 * 1024 self.setup(config) script = self.service.register_script(Script('profile:hz:999 { @test1[kstack,ustack] = count(); }')) for _i in range(20): script = self.service.refresh_script(script.script_id) if script.state.status == 'error': break time.sleep(1) script = self.service.refresh_script(script.script_id) self.assertEqual(script.state.status, 'error') self.assertRegex(script.state.error, 'BPFtrace output exceeds limit of .+ bytes per second')
def testTableRetainLines(self): runtime_info = RuntimeInfo() runtime_info.bpftrace_version = (0, 9, 2) script = Script('// table-retain-lines: 3\n' 'printf("test");') script = parse_code(script) self.assertEqual(script.metadata.table_retain_lines, 3) def add_output(s): process_bpftrace_output_obj(runtime_info, script, { "type": "printf", "msg": s }) def assert_output(o): self.assertEqual(script.state.data["@output"], o) add_output('head') assert_output('head') add_output('er\n') assert_output('header\n') add_output('line ') assert_output('header\nline ') add_output('1\n') assert_output('header\nline 1\n') add_output('line ') assert_output('header\nline 1\nline ') add_output('2\n') assert_output('header\nline 1\nline 2\n') add_output('line ') assert_output('header\nline 1\nline 2\nline ') add_output('3\n') assert_output('header\nline 1\nline 2\nline 3\n') add_output('line ') assert_output('header\nline 2\nline 3\nline ') add_output('4\n') assert_output('header\nline 2\nline 3\nline 4\n') add_output('line ') assert_output('header\nline 3\nline 4\nline ') add_output('5\n') assert_output('header\nline 3\nline 4\nline 5\n') add_output('line 10\nline 11\nline 12\n') assert_output('header\nline 10\nline 11\nline 12\n')
def testParseStackProfiler(self): script = Script(""" profile:hz:99 { @[kstack] = count(); } @ck[comm,kstack] = count(); @u[ustack] = count(); @a[comm,kstack,ustack] = count(); @n[nokstack] = count(); """) script = parse_code(script) self.assertEqual(script.variables['@'].metrictype, MetricType.Stacks) self.assertEqual(script.variables['@'].semantics, PM_SEM_COUNTER) self.assertEqual(script.variables['@ck'].metrictype, MetricType.Stacks) self.assertEqual(script.variables['@ck'].semantics, PM_SEM_COUNTER) self.assertEqual(script.variables['@u'].metrictype, MetricType.Stacks) self.assertEqual(script.variables['@u'].semantics, PM_SEM_COUNTER) self.assertEqual(script.variables['@a'].metrictype, MetricType.Stacks) self.assertEqual(script.variables['@a'].semantics, PM_SEM_COUNTER) self.assertEqual(script.variables['@n'].metrictype, None) self.assertEqual(script.variables['@n'].semantics, PM_SEM_COUNTER)
def testParseStackProfiler(self): script = Script('profile:hz:99 { @[kstack] = count(); }') script = parse_code(script) self.assertEqual(script.variables['@'].metrictype, MetricType.Stacks) self.assertEqual(script.variables['@'].semantics, PM_SEM_COUNTER)