--- /dev/null
+#!/usr/bin/env python3
+
+import sys
+import os
+import shutil
+import tempfile
+import difflib
+import subprocess
+from babeltrace import CTFWriter, CTFStringEncoding
+
+
+class TraceTest():
+ def __init__(self, delete_trace=True):
+ self.delete_trace = delete_trace
+ self.trace_root = tempfile.mkdtemp()
+ self.trace_path = os.path.join(self.trace_root, "kernel")
+ self.create_writer()
+ self.create_stream_class()
+ self.define_base_types()
+ self.define_events()
+ self.create_stream()
+
+ def __del__(self):
+ if self.delete_trace:
+ self.rm_trace()
+
+ def get_trace_root(self):
+ return self.trace_root
+
+ def rm_trace(self):
+ shutil.rmtree(self.trace_root)
+
+ def flush(self):
+ self.writer.flush_metadata()
+ self.stream.flush()
+
+ def create_writer(self):
+ self.clock = CTFWriter.Clock("A_clock")
+ self.clock.description = "Simple clock"
+ self.writer = CTFWriter.Writer(self.trace_path)
+ self.writer.add_clock(self.clock)
+ self.writer.add_environment_field("Python_version",
+ str(sys.version_info))
+ self.writer.add_environment_field("tracer_major", 2)
+ self.writer.add_environment_field("tracer_minor", 8)
+ self.writer.add_environment_field("tracer_patchlevel", 0)
+
+ def create_stream_class(self):
+ self.stream_class = CTFWriter.StreamClass("test_stream")
+ self.stream_class.clock = self.clock
+
+ def define_base_types(self):
+ self.char8_type = CTFWriter.IntegerFieldDeclaration(8)
+ self.char8_type.signed = True
+ self.char8_type.encoding = CTFStringEncoding.UTF8
+ self.char8_type.alignment = 8
+
+ self.int16_type = CTFWriter.IntegerFieldDeclaration(16)
+ self.int16_type.signed = True
+ self.int16_type.alignment = 8
+
+ self.uint16_type = CTFWriter.IntegerFieldDeclaration(16)
+ self.uint16_type.signed = False
+ self.uint16_type.alignment = 8
+
+ self.int32_type = CTFWriter.IntegerFieldDeclaration(32)
+ self.int32_type.signed = True
+ self.int32_type.alignment = 8
+
+ self.uint32_type = CTFWriter.IntegerFieldDeclaration(32)
+ self.uint32_type.signed = False
+ self.uint32_type.alignment = 8
+
+ self.int64_type = CTFWriter.IntegerFieldDeclaration(64)
+ self.int64_type.signed = True
+ self.int64_type.alignment = 8
+
+ self.uint64_type = CTFWriter.IntegerFieldDeclaration(64)
+ self.uint64_type.signed = False
+ self.uint64_type.alignment = 8
+
+ self.array16_type = CTFWriter.ArrayFieldDeclaration(self.char8_type,
+ 16)
+
+ self.string_type = CTFWriter.StringFieldDeclaration()
+
+ def add_event(self, event):
+ event.add_field(self.uint32_type, "_cpu_id")
+ self.stream_class.add_event_class(event)
+
+ def define_sched_switch(self):
+ self.sched_switch = CTFWriter.EventClass("sched_switch")
+ self.sched_switch.add_field(self.array16_type, "_prev_comm")
+ self.sched_switch.add_field(self.int32_type, "_prev_tid")
+ self.sched_switch.add_field(self.int32_type, "_prev_prio")
+ self.sched_switch.add_field(self.int64_type, "_prev_state")
+ self.sched_switch.add_field(self.array16_type, "_next_comm")
+ self.sched_switch.add_field(self.int32_type, "_next_tid")
+ self.sched_switch.add_field(self.int32_type, "_next_prio")
+ self.add_event(self.sched_switch)
+
+ def define_softirq_raise(self):
+ self.softirq_raise = CTFWriter.EventClass("softirq_raise")
+ self.softirq_raise.add_field(self.uint32_type, "_vec")
+ self.add_event(self.softirq_raise)
+
+ def define_softirq_entry(self):
+ self.softirq_entry = CTFWriter.EventClass("softirq_entry")
+ self.softirq_entry.add_field(self.uint32_type, "_vec")
+ self.add_event(self.softirq_entry)
+
+ def define_softirq_exit(self):
+ self.softirq_exit = CTFWriter.EventClass("softirq_exit")
+ self.softirq_exit.add_field(self.uint32_type, "_vec")
+ self.add_event(self.softirq_exit)
+
+ def define_irq_handler_entry(self):
+ self.irq_handler_entry = CTFWriter.EventClass("irq_handler_entry")
+ self.irq_handler_entry.add_field(self.int32_type, "_irq")
+ self.irq_handler_entry.add_field(self.string_type, "_name")
+ self.add_event(self.irq_handler_entry)
+
+ def define_irq_handler_exit(self):
+ self.irq_handler_exit = CTFWriter.EventClass("irq_handler_exit")
+ self.irq_handler_exit.add_field(self.int32_type, "_irq")
+ self.irq_handler_exit.add_field(self.int32_type, "_ret")
+ self.add_event(self.irq_handler_exit)
+
+ def define_syscall_entry_write(self):
+ self.syscall_entry_write = CTFWriter.EventClass("syscall_entry_write")
+ self.syscall_entry_write.add_field(self.uint32_type, "_fd")
+ self.syscall_entry_write.add_field(self.uint64_type, "_buf")
+ self.syscall_entry_write.add_field(self.uint64_type, "_count")
+ self.add_event(self.syscall_entry_write)
+
+ def define_syscall_exit_write(self):
+ self.syscall_exit_write = CTFWriter.EventClass("syscall_exit_write")
+ self.syscall_exit_write.add_field(self.int64_type, "_ret")
+ self.add_event(self.syscall_exit_write)
+
+ def define_syscall_entry_read(self):
+ self.syscall_entry_read = CTFWriter.EventClass("syscall_entry_read")
+ self.syscall_entry_read.add_field(self.uint32_type, "_fd")
+ self.syscall_entry_read.add_field(self.uint64_type, "_count")
+ self.add_event(self.syscall_entry_read)
+
+ def define_syscall_exit_read(self):
+ self.syscall_exit_read = CTFWriter.EventClass("syscall_exit_read")
+ self.syscall_exit_read.add_field(self.uint64_type, "_buf")
+ self.syscall_exit_read.add_field(self.int64_type, "_ret")
+ self.add_event(self.syscall_exit_read)
+
+ def define_syscall_entry_open(self):
+ self.syscall_entry_open = CTFWriter.EventClass("syscall_entry_open")
+ self.syscall_entry_open.add_field(self.string_type, "_filename")
+ self.syscall_entry_open.add_field(self.int32_type, "_flags")
+ self.syscall_entry_open.add_field(self.uint16_type, "_mode")
+ self.add_event(self.syscall_entry_open)
+
+ def define_syscall_exit_open(self):
+ self.syscall_exit_open = CTFWriter.EventClass("syscall_exit_open")
+ self.syscall_exit_open.add_field(self.int64_type, "_ret")
+ self.add_event(self.syscall_exit_open)
+
+ def define_lttng_statedump_process_state(self):
+ self.lttng_statedump_process_state = CTFWriter.EventClass(
+ "lttng_statedump_process_state")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_tid")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_vtid")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_pid")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_vpid")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_ppid")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_vppid")
+ self.lttng_statedump_process_state.add_field(self.array16_type,
+ "_name")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_type")
+ self.lttng_statedump_process_state.add_field(self.int32_type, "_mode")
+ self.lttng_statedump_process_state.add_field(self.int32_type,
+ "_submode")
+ self.lttng_statedump_process_state.add_field(self.int32_type,
+ "_status")
+ self.lttng_statedump_process_state.add_field(self.int32_type,
+ "_ns_level")
+ self.add_event(self.lttng_statedump_process_state)
+
+ def define_lttng_statedump_file_descriptor(self):
+ self.lttng_statedump_file_descriptor = CTFWriter.EventClass(
+ "lttng_statedump_file_descriptor")
+ self.lttng_statedump_file_descriptor.add_field(self.int32_type, "_pid")
+ self.lttng_statedump_file_descriptor.add_field(self.int32_type, "_fd")
+ self.lttng_statedump_file_descriptor.add_field(self.uint32_type,
+ "_flags")
+ self.lttng_statedump_file_descriptor.add_field(self.uint32_type,
+ "_fmode")
+ self.lttng_statedump_file_descriptor.add_field(self.string_type,
+ "_filename")
+ self.add_event(self.lttng_statedump_file_descriptor)
+
+ def define_sched_wakeup(self):
+ self.sched_wakeup = CTFWriter.EventClass("sched_wakeup")
+ self.sched_wakeup.add_field(self.array16_type, "_comm")
+ self.sched_wakeup.add_field(self.int32_type, "_tid")
+ self.sched_wakeup.add_field(self.int32_type, "_prio")
+ self.sched_wakeup.add_field(self.int32_type, "_success")
+ self.sched_wakeup.add_field(self.int32_type, "_target_cpu")
+ self.add_event(self.sched_wakeup)
+
+ def define_sched_waking(self):
+ self.sched_waking = CTFWriter.EventClass("sched_waking")
+ self.sched_waking.add_field(self.array16_type, "_comm")
+ self.sched_waking.add_field(self.int32_type, "_tid")
+ self.sched_waking.add_field(self.int32_type, "_prio")
+ self.sched_waking.add_field(self.int32_type, "_target_cpu")
+ self.add_event(self.sched_waking)
+
+ def define_block_rq_complete(self):
+ self.block_rq_complete = CTFWriter.EventClass("block_rq_complete")
+ self.block_rq_complete.add_field(self.uint32_type, "_dev")
+ self.block_rq_complete.add_field(self.uint64_type, "_sector")
+ self.block_rq_complete.add_field(self.uint32_type, "_nr_sector")
+ self.block_rq_complete.add_field(self.int32_type, "_errors")
+ self.block_rq_complete.add_field(self.uint32_type, "_rwbs")
+ self.block_rq_complete.add_field(self.uint64_type, "__cmd_length")
+ self.block_rq_complete.add_field(self.array16_type, "_cmd")
+ self.add_event(self.block_rq_complete)
+
+ def define_block_rq_issue(self):
+ self.block_rq_issue = CTFWriter.EventClass("block_rq_issue")
+ self.block_rq_issue.add_field(self.uint32_type, "_dev")
+ self.block_rq_issue.add_field(self.uint64_type, "_sector")
+ self.block_rq_issue.add_field(self.uint32_type, "_nr_sector")
+ self.block_rq_issue.add_field(self.uint32_type, "_bytes")
+ self.block_rq_issue.add_field(self.int32_type, "_tid")
+ self.block_rq_issue.add_field(self.uint32_type, "_rwbs")
+ self.block_rq_issue.add_field(self.uint64_type, "__cmd_length")
+ self.block_rq_issue.add_field(self.array16_type, "_cmd")
+ self.block_rq_issue.add_field(self.array16_type, "_comm")
+ self.add_event(self.block_rq_issue)
+
+ def define_net_dev_xmit(self):
+ self.net_dev_xmit = CTFWriter.EventClass("net_dev_xmit")
+ self.net_dev_xmit.add_field(self.uint64_type, "_skbaddr")
+ self.net_dev_xmit.add_field(self.int32_type, "_rc")
+ self.net_dev_xmit.add_field(self.uint32_type, "_len")
+ self.net_dev_xmit.add_field(self.string_type, "_name")
+ self.add_event(self.net_dev_xmit)
+
+ def define_netif_receive_skb(self):
+ self.netif_receive_skb = CTFWriter.EventClass("netif_receive_skb")
+ self.netif_receive_skb.add_field(self.uint64_type, "_skbaddr")
+ self.netif_receive_skb.add_field(self.uint32_type, "_len")
+ self.netif_receive_skb.add_field(self.string_type, "_name")
+ self.add_event(self.netif_receive_skb)
+
+ def define_events(self):
+ self.define_sched_switch()
+ self.define_softirq_raise()
+ self.define_softirq_entry()
+ self.define_softirq_exit()
+ self.define_irq_handler_entry()
+ self.define_irq_handler_exit()
+ self.define_syscall_entry_write()
+ self.define_syscall_exit_write()
+ self.define_syscall_entry_read()
+ self.define_syscall_exit_read()
+ self.define_syscall_entry_open()
+ self.define_syscall_exit_open()
+ self.define_lttng_statedump_process_state()
+ self.define_lttng_statedump_file_descriptor()
+ self.define_sched_wakeup()
+ self.define_sched_waking()
+ self.define_block_rq_complete()
+ self.define_block_rq_issue()
+ self.define_net_dev_xmit()
+ self.define_netif_receive_skb()
+
+ def create_stream(self):
+ self.stream = self.writer.create_stream(self.stream_class)
+
+ def set_char_array(self, event, string):
+ if len(string) > 16:
+ string = string[0:16]
+ else:
+ string = "%s" % (string + "\0" * (16 - len(string)))
+
+ for i in range(len(string)):
+ a = event.field(i)
+ a.value = ord(string[i])
+
+ def set_int(self, event, value):
+ event.value = value
+
+ def set_string(self, event, value):
+ event.value = value
+
+ def write_softirq_raise(self, time_ms, cpu_id, vec):
+ event = CTFWriter.Event(self.softirq_raise)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_vec"), vec)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_softirq_entry(self, time_ms, cpu_id, vec):
+ event = CTFWriter.Event(self.softirq_entry)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_vec"), vec)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_softirq_exit(self, time_ms, cpu_id, vec):
+ event = CTFWriter.Event(self.softirq_exit)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_vec"), vec)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_irq_handler_entry(self, time_ms, cpu_id, irq, name):
+ event = CTFWriter.Event(self.irq_handler_entry)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_irq"), irq)
+ self.set_string(event.payload("_name"), name)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_irq_handler_exit(self, time_ms, cpu_id, irq, ret):
+ event = CTFWriter.Event(self.irq_handler_exit)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_irq"), irq)
+ self.set_int(event.payload("_ret"), ret)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_syscall_write(self, time_ms, cpu_id, delay, fd, buf, count, ret):
+ entry = CTFWriter.Event(self.syscall_entry_write)
+ self.clock.time = time_ms * 1000000
+ self.set_int(entry.payload("_cpu_id"), cpu_id)
+ self.set_int(entry.payload("_fd"), fd)
+ self.set_int(entry.payload("_buf"), buf)
+ self.set_int(entry.payload("_count"), count)
+ self.stream.append_event(entry)
+
+ exit = CTFWriter.Event(self.syscall_exit_write)
+ self.clock.time = (time_ms + delay) * 1000000
+ self.set_int(exit.payload("_cpu_id"), cpu_id)
+ self.set_int(exit.payload("_ret"), ret)
+ self.stream.append_event(exit)
+ self.stream.flush()
+
+ def write_syscall_read(self, time_ms, cpu_id, delay, fd, buf, count, ret):
+ entry = CTFWriter.Event(self.syscall_entry_read)
+ self.clock.time = time_ms * 1000000
+ self.set_int(entry.payload("_cpu_id"), cpu_id)
+ self.set_int(entry.payload("_fd"), fd)
+ self.set_int(entry.payload("_count"), count)
+ self.stream.append_event(entry)
+
+ exit = CTFWriter.Event(self.syscall_exit_read)
+ self.clock.time = (time_ms + delay) * 1000000
+ self.set_int(exit.payload("_cpu_id"), cpu_id)
+ self.set_int(exit.payload("_buf"), buf)
+ self.set_int(exit.payload("_ret"), ret)
+ self.stream.append_event(exit)
+ self.stream.flush()
+
+ def write_syscall_open(self, time_ms, cpu_id, delay, filename, flags,
+ mode, ret):
+ event = CTFWriter.Event(self.syscall_entry_open)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_string(event.payload("_filename"), filename)
+ self.set_int(event.payload("_flags"), flags)
+ self.set_int(event.payload("_mode"), mode)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ event = CTFWriter.Event(self.syscall_exit_open)
+ self.clock.time = (time_ms + delay) * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_ret"), ret)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_lttng_statedump_file_descriptor(self, time_ms, cpu_id, pid, fd,
+ flags, fmode, filename):
+ event = CTFWriter.Event(self.lttng_statedump_file_descriptor)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_pid"), pid)
+ self.set_int(event.payload("_fd"), fd)
+ self.set_int(event.payload("_flags"), flags)
+ self.set_int(event.payload("_fmode"), fmode)
+ self.set_string(event.payload("_filename"), filename)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_lttng_statedump_process_state(self, time_ms, cpu_id, tid, vtid,
+ pid, vpid, ppid, vppid, name, type,
+ mode, submode, status, ns_level):
+ event = CTFWriter.Event(self.lttng_statedump_process_state)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_tid"), tid)
+ self.set_int(event.payload("_vtid"), vtid)
+ self.set_int(event.payload("_pid"), pid)
+ self.set_int(event.payload("_vpid"), vpid)
+ self.set_int(event.payload("_ppid"), ppid)
+ self.set_int(event.payload("_vppid"), vppid)
+ self.set_char_array(event.payload("_name"), name)
+ self.set_int(event.payload("_type"), type)
+ self.set_int(event.payload("_mode"), mode)
+ self.set_int(event.payload("_submode"), submode)
+ self.set_int(event.payload("_status"), status)
+ self.set_int(event.payload("_ns_level"), ns_level)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_sched_wakeup(self, time_ms, cpu_id, comm, tid, prio, target_cpu):
+ event = CTFWriter.Event(self.sched_wakeup)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_char_array(event.payload("_comm"), comm)
+ self.set_int(event.payload("_tid"), tid)
+ self.set_int(event.payload("_prio"), prio)
+ self.set_int(event.payload("_target_cpu"), target_cpu)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_sched_waking(self, time_ms, cpu_id, comm, tid, prio, target_cpu):
+ event = CTFWriter.Event(self.sched_waking)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_char_array(event.payload("_comm"), comm)
+ self.set_int(event.payload("_tid"), tid)
+ self.set_int(event.payload("_prio"), prio)
+ self.set_int(event.payload("_target_cpu"), target_cpu)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_block_rq_complete(self, time_ms, cpu_id, dev, sector, nr_sector,
+ errors, rwbs, _cmd_length, cmd):
+ event = CTFWriter.Event(self.block_rq_complete)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_dev"), dev)
+ self.set_int(event.payload("_sector"), sector)
+ self.set_int(event.payload("_nr_sector"), nr_sector)
+ self.set_int(event.payload("_errors"), errors)
+ self.set_int(event.payload("_rwbs"), rwbs)
+ self.set_int(event.payload("__cmd_length"), _cmd_length)
+ self.set_char_array(event.payload("_cmd"), cmd)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_block_rq_issue(self, time_ms, cpu_id, dev, sector, nr_sector,
+ bytes, tid, rwbs, _cmd_length, cmd, comm):
+ event = CTFWriter.Event(self.block_rq_issue)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_dev"), dev)
+ self.set_int(event.payload("_sector"), sector)
+ self.set_int(event.payload("_nr_sector"), nr_sector)
+ self.set_int(event.payload("_bytes"), bytes)
+ self.set_int(event.payload("_tid"), tid)
+ self.set_int(event.payload("_rwbs"), rwbs)
+ self.set_int(event.payload("__cmd_length"), _cmd_length)
+ self.set_char_array(event.payload("_cmd"), cmd)
+ self.set_char_array(event.payload("_comm"), comm)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_net_dev_xmit(self, time_ms, cpu_id, skbaddr, rc, len, name):
+ event = CTFWriter.Event(self.net_dev_xmit)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_skbaddr"), skbaddr)
+ self.set_int(event.payload("_rc"), rc)
+ self.set_int(event.payload("_len"), len)
+ self.set_string(event.payload("_name"), name)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_netif_receive_skb(self, time_ms, cpu_id, skbaddr, len, name):
+ event = CTFWriter.Event(self.netif_receive_skb)
+ self.clock.time = time_ms * 1000000
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.set_int(event.payload("_skbaddr"), skbaddr)
+ self.set_int(event.payload("_len"), len)
+ self.set_string(event.payload("_name"), name)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def write_sched_switch(self, time_ms, cpu_id, prev_comm, prev_tid,
+ next_comm, next_tid, prev_prio=20, prev_state=1,
+ next_prio=20):
+ event = CTFWriter.Event(self.sched_switch)
+ self.clock.time = time_ms * 1000000
+ self.set_char_array(event.payload("_prev_comm"), prev_comm)
+ self.set_int(event.payload("_prev_tid"), prev_tid)
+ self.set_int(event.payload("_prev_prio"), prev_prio)
+ self.set_int(event.payload("_prev_state"), prev_state)
+ self.set_char_array(event.payload("_next_comm"), next_comm)
+ self.set_int(event.payload("_next_tid"), next_tid)
+ self.set_int(event.payload("_next_prio"), next_prio)
+ self.set_int(event.payload("_cpu_id"), cpu_id)
+ self.stream.append_event(event)
+ self.stream.flush()
+
+ def sched_switch_50pc(self, start_time_ms, end_time_ms, cpu_id, period,
+ comm1, tid1, comm2, tid2):
+ current = start_time_ms
+ while current < end_time_ms:
+ self.write_sched_switch(current, cpu_id, comm1, tid1, comm2, tid2)
+ current += period
+ self.write_sched_switch(current, cpu_id, comm2, tid2, comm1, tid1)
+ current += period
+
+ def compare_output(self, cmd, expected):
+ result = subprocess.getoutput(cmd)
+ diff = difflib.ndiff(expected.split('\n'), result.split('\n'))
+ txt = ""
+ ok = True
+ for l in diff:
+ if l[0] != ' ':
+ ok = False
+ txt = txt + (l) + '\n'
+ if not ok:
+ print(txt)
+ return ok
+
+
+class AnalyzesTest():
+ def __init__(self, delete_trace=True, verbose=False):
+ self.verbose = verbose
+ self.t = TraceTest(delete_trace=delete_trace)
+ self.common_options = '--no-progress --skip-validation'
+ self.cmd_root = './'
+ self.log('Trace in %s' % (self.t.get_trace_root()))
+
+ def log(self, msg):
+ if self.verbose:
+ print(msg)
+
+ def compare_output(self, cmd, expected):
+ return self.t.compare_output(cmd, expected)
+
+ def run(self):
+ ok = True
+ self.write_trace()
+ for t in self.test_list:
+ ret = t[1]()
+ self.log('%s: %s' % (t[0], ret))
+ if not ret:
+ ok = False
+ return ok
--- /dev/null
+#!/usr/bin/env python3
+
+from TraceTest import AnalyzesTest
+import sys
+
+
+class IoTest(AnalyzesTest):
+ def __init__(self, delete_trace=False, verbose=False):
+ super().__init__(delete_trace=delete_trace,
+ verbose=verbose)
+ self.test_list = [('iousagetop', self.run_iousagetop),
+ ('iolatencytop', self.run_iolatencytop)]
+
+ def write_trace(self):
+ # app (99) is known at statedump
+ self.t.write_lttng_statedump_process_state(1000, 0, 99, 99, 99, 99, 98,
+ 98, "app", 0, 5, 0, 5, 0)
+ # app2 (100) unknown at statedump has testfile, FD 3 defined at
+ # statedump
+ self.t.write_lttng_statedump_file_descriptor(1001, 0, 100, 3, 0, 0,
+ "testfile")
+ # app write 10 bytes to FD 4
+ self.t.write_sched_switch(1002, 0, "swapper/0", 0, "app", 99)
+ self.t.write_syscall_write(1004, 0, 1, 4, 0xabcd, 10, 10)
+ # app2 reads 100 bytes in FD 3
+ self.t.write_sched_switch(1006, 0, "app", 99, "app2", 100)
+ self.t.write_syscall_read(1008, 0, 1, 3, 0xcafe, 100, 100)
+ # app3 and its FD 3 are completely unknown at statedump, tries to read 100
+ # bytes from FD 3 but only gets 42
+ self.t.write_sched_switch(1010, 0, "app2", 100, "app3", 101)
+ self.t.write_syscall_read(1012, 0, 1, 3, 0xcafe, 100, 42)
+ # block write
+ self.t.write_block_rq_issue(1015, 0, 264241152, 33, 10, 40, 99, 0, 0, "", "app")
+ self.t.write_block_rq_complete(1016, 0, 264241152, 33, 10, 0, 0, 0, "")
+ # block read
+ # FIXME: does not look right
+ self.t.write_block_rq_issue(1017, 0, 8388608, 33, 11, 90, 101, 1, 0, "", "app3")
+ self.t.write_block_rq_complete(1018, 0, 8388608, 33, 11, 0, 1, 0, "")
+ # net xmit
+ # FIXME: does not look right
+ self.t.write_net_dev_xmit(1020, 2, 0xff, 32, 0, "wlan0")
+ # net receive
+ self.t.write_netif_receive_skb(1021, 1, 0xff, 100, "wlan1")
+ self.t.write_netif_receive_skb(1022, 1, 0xff, 200, "wlan0")
+ # syscall open
+ self.t.write_syscall_open(1023, 0, 1, "test/open/file", 0, 0, 42)
+ self.t.flush()
+
+ def run_iousagetop(self):
+ expected = """Timerange: [1969-12-31 19:00:01.000000000, 1969-12-31 19:00:01.022000000]
+Per-process I/O Read
+###############################################################################
+██████████████████████████████████████████████████ 100.00 B (100) 0 B file 0 B net 100.00 B unknown
+█████████████████████ 42.00 B app3 (unknown (tid=101)) 0 B file 0 B net 42.00 B unknown
+ 0 B app (99) 0 B file 0 B net 0 B unknown
+Per-process I/O Write
+###############################################################################
+██████████████████████████████████████████████████ 10.00 B app (99) 0 B file 0 B net 10.00 B unknown
+ 0 B (100) 0 B file 0 B net 0 B unknown
+ 0 B app3 (unknown (tid=101)) 0 B file 0 B net 0 B unknown
+Files read
+###############################################################################
+██████████████████████████████████████████████████ 100.00 B testfile fd 3 in (100)
+█████████████████████ 42.00 B unknown(app3) fd 3 in app3 (101)
+Files write
+###############################################################################
+██████████████████████████████████████████████████ 10.00 B unknown(app) fd 4 in app (99)
+Block I/O Read
+###############################################################################
+██████████████████████████████████████████████████ 5.00 KB app (pid=99)
+Block I/O Write
+###############################################################################
+██████████████████████████████████████████████████ 5.00 KB app (pid=99)
+Disk requests sector count
+###############################################################################
+██████████████████████████████████████████████████████████████████ 11.00 sectors (8,0)
+████████████████████████████████████████████████████████████ 10.00 sectors (252,0)
+Disk request count
+###############################################################################
+███████████████████████████████████████████████████████████████████ 1.00 requests (252,0)
+███████████████████████████████████████████████████████████████████ 1.00 requests (8,0)
+Disk request average latency
+###############################################################################
+█████████████████████████████████████████████████████████████████ 1.00 ms (252,0)
+█████████████████████████████████████████████████████████████████ 1.00 ms (8,0)
+Network received bytes
+###############################################################################
+██████████████████████████████████████████████████████████ 200.00 B wlan0
+█████████████████████████████ 100.00 B wlan1
+Network sent bytes
+###############################################################################
+ 0 B wlan0
+ 0 B wlan1"""
+
+ return self.compare_output('%slttng-iousagetop %s "%s"' % (
+ self.cmd_root, self.common_options, self.t.get_trace_root()),
+ expected)
+
+ def run_iolatencytop(self):
+ expected = """Timerange: [1969-12-31 19:00:01.000000000, 1969-12-31 19:00:01.022000000]
+
+Top system call latencies read (usec)
+Begin End Name Duration (usec) Size Proc PID Filename
+[19:00:01.008000000,19:00:01.009000000] read 1000.000 100.00 B 100 testfile (fd=3)
+[19:00:01.008000000,19:00:01.009000000] read 1000.000 100.00 B 100 testfile (fd=3)
+[19:00:01.012000000,19:00:01.013000000] read 1000.000 42.00 B app3 101 unknown (fd=3)
+[19:00:01.012000000,19:00:01.013000000] read 1000.000 42.00 B app3 101 unknown (fd=3)
+
+Top system call latencies write (usec)
+Begin End Name Duration (usec) Size Proc PID Filename
+[19:00:01.004000000,19:00:01.005000000] write 1000.000 10.00 B app 99 unknown (fd=4)
+[19:00:01.004000000,19:00:01.005000000] write 1000.000 10.00 B app 99 unknown (fd=4)"""
+
+ return self.compare_output('%slttng-iolatencytop %s "%s"' % (
+ self.cmd_root, self.common_options,
+ self.t.get_trace_root()), expected)
+
+
+def test_answer():
+ t = IoTest(verbose=True)
+ ok = t.run()
+ assert(ok)
+
+test_answer()
--- /dev/null
+#!/usr/bin/env python3
+
+from TraceTest import AnalyzesTest
+import sys
+
+
+class IrqTest(AnalyzesTest):
+ def __init__(self, delete_trace=True, verbose=False):
+ super().__init__(delete_trace=delete_trace,
+ verbose=verbose)
+ self.test_list = [('irqstats', self.run_irqstats),
+ ('irqlog', self.run_irqlog)]
+
+ def write_trace(self):
+ self.t.write_softirq_raise(1000 , 1, 1)
+ self.t.write_softirq_raise(1001 , 3, 1)
+ self.t.write_softirq_raise(1002 , 1, 9)
+ self.t.write_softirq_exit(1003 , 0, 4)
+ self.t.write_softirq_raise(1004 , 3, 9)
+ self.t.write_softirq_raise(1005 , 3, 7)
+ self.t.write_softirq_entry(1006 , 3, 1)
+ self.t.write_softirq_entry(1007 , 1, 1)
+ self.t.write_softirq_exit(1008 , 1, 1)
+ self.t.write_softirq_exit(1009 , 3, 1)
+ self.t.write_softirq_entry(1010 , 1, 9)
+ self.t.write_softirq_entry(1011 , 3, 7)
+ self.t.write_softirq_exit(1012 , 1, 9)
+ self.t.write_softirq_exit(1013 , 3, 7)
+ self.t.write_softirq_entry(1014 , 3, 9)
+ self.t.write_softirq_exit(1015 , 3, 9)
+ self.t.write_irq_handler_entry(1016 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1017 , 0, 4)
+ self.t.write_irq_handler_exit(1018 , 0, 41, 1)
+ self.t.write_softirq_entry(1019 , 0, 4)
+ self.t.write_softirq_exit(1020 , 0, 4)
+ self.t.write_irq_handler_entry(1021 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1022 , 0, 4)
+ self.t.write_irq_handler_exit(1023 , 0, 41, 1)
+ self.t.write_softirq_entry(1024 , 0, 4)
+ self.t.write_softirq_exit(1025 , 0, 4)
+ self.t.write_irq_handler_entry(1026 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1027 , 0, 4)
+ self.t.write_irq_handler_exit(1028 , 0, 41, 1)
+ self.t.write_softirq_entry(1029 , 0, 4)
+ self.t.write_softirq_exit(1030 , 0, 4)
+ self.t.write_irq_handler_entry(1031 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1032 , 0, 4)
+ self.t.write_irq_handler_exit(1033 , 0, 41, 1)
+ self.t.write_softirq_entry(1034 , 0, 4)
+ self.t.write_softirq_exit(1035 , 0, 4)
+ self.t.write_irq_handler_entry(1036 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1037 , 0, 4)
+ self.t.write_irq_handler_exit(1038 , 0, 41, 1)
+ self.t.write_softirq_entry(1039 , 0, 4)
+ self.t.write_softirq_exit(1040 , 0, 4)
+ self.t.write_irq_handler_entry(1041 , 0, 41, "ahci")
+ self.t.write_softirq_raise(1042 , 0, 4)
+ self.t.write_irq_handler_exit(1043 , 0, 41, 1)
+ self.t.write_softirq_entry(1044 , 0, 4)
+ self.t.write_softirq_exit(1045 , 0, 4)
+ self.t.flush()
+
+ def run_irqstats(self):
+ expected = """Timerange: [1969-12-31 19:00:01.000000000, 1969-12-31 19:00:01.045000000]
+Hard IRQ Duration (us)
+ count min avg max stdev
+----------------------------------------------------------------------------------|
+41: <ahci> 6 2000.000 2000.000 2000.000 0.000 |
+
+Soft IRQ Duration (us) Raise latency (us)
+ count min avg max stdev | count min avg max stdev
+----------------------------------------------------------------------------------|------------------------------------------------------------
+1: <TIMER_SOFTIRQ> 2 1000.000 2000.000 3000.000 1414.214 | 2 5000.000 6000.000 7000.000 1414.214
+4: <BLOCK_SOFTIRQ> 6 1000.000 1000.000 1000.000 0.000 | 6 2000.000 2000.000 2000.000 0.000
+7: <SCHED_SOFTIRQ> 1 2000.000 2000.000 2000.000 ? | 1 6000.000 6000.000 6000.000 ?
+9: <RCU_SOFTIRQ> 2 1000.000 1500.000 2000.000 707.107 | 2 8000.000 9000.000 10000.000 1414.214"""
+
+ return self.compare_output('%slttng-irqstats %s "%s"' % (
+ self.cmd_root, self.common_options, self.t.get_trace_root()),
+ expected)
+
+ def run_irqlog(self):
+ expected = """Timerange: [1969-12-31 19:00:01.000000000, 1969-12-31 19:00:01.045000000]
+Begin End Duration (us) CPU Type # Name
+[19:00:01.007000000, 19:00:01.008000000] 1000.000 1 SoftIRQ 1 TIMER_SOFTIRQ (raised at 19:00:01.000000000)
+[19:00:01.006000000, 19:00:01.009000000] 3000.000 3 SoftIRQ 1 TIMER_SOFTIRQ (raised at 19:00:01.001000000)
+[19:00:01.010000000, 19:00:01.012000000] 2000.000 1 SoftIRQ 9 RCU_SOFTIRQ (raised at 19:00:01.002000000)
+[19:00:01.011000000, 19:00:01.013000000] 2000.000 3 SoftIRQ 7 SCHED_SOFTIRQ (raised at 19:00:01.005000000)
+[19:00:01.014000000, 19:00:01.015000000] 1000.000 3 SoftIRQ 9 RCU_SOFTIRQ (raised at 19:00:01.004000000)
+[19:00:01.016000000, 19:00:01.018000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.019000000, 19:00:01.020000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.017000000)
+[19:00:01.021000000, 19:00:01.023000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.024000000, 19:00:01.025000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.022000000)
+[19:00:01.026000000, 19:00:01.028000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.029000000, 19:00:01.030000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.027000000)
+[19:00:01.031000000, 19:00:01.033000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.034000000, 19:00:01.035000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.032000000)
+[19:00:01.036000000, 19:00:01.038000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.039000000, 19:00:01.040000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.037000000)
+[19:00:01.041000000, 19:00:01.043000000] 2000.000 0 IRQ 41 ahci
+[19:00:01.044000000, 19:00:01.045000000] 1000.000 0 SoftIRQ 4 BLOCK_SOFTIRQ (raised at 19:00:01.042000000)"""
+
+ return self.compare_output('%slttng-irqlog %s "%s"' % (
+ self.cmd_root, self.common_options, self.t.get_trace_root()),
+ expected)
+
+
+def test_answer():
+ t = IrqTest(verbose=True)
+ ok = t.run()
+ assert(ok)