From e804299c3f62e1739c16385193620810e0259f00 Mon Sep 17 00:00:00 2001 From: Tomasz Grabiec <tgrabiec@cloudius-systems.com> Date: Mon, 28 Apr 2014 18:34:10 +0200 Subject: [PATCH] tests: introduce tracing smoke test The test verifies basic tracing functionallity: * that samples are collected by OSv * extraction via `trace extract` succeeds * `trace summary` shows expected tracepoint names * listing via `trace list` shows tracepoints with arguments * network packet parsing works This test is run as part of standard 'make check'. Note: this single test can be executed as easily as: $ scripts/test.py --test tracing_smoke_test Signed-off-by: Tomasz Grabiec <tgrabiec@cloudius-systems.com> Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com> --- scripts/test.py | 1 + scripts/tests/test_net.py | 3 ++- scripts/tests/test_tracing.py | 35 ++++++++++++++++++++++++++ scripts/tests/testing.py | 46 ++++++++++++++++++++++++----------- 4 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 scripts/tests/test_tracing.py diff --git a/scripts/test.py b/scripts/test.py index 0215b2082..89740dc3f 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -8,6 +8,7 @@ import os import re import tests.test_net +import tests.test_tracing from operator import attrgetter from tests.testing import * diff --git a/scripts/tests/test_net.py b/scripts/tests/test_net.py index 0c7481faf..d0ddd22b9 100644 --- a/scripts/tests/test_net.py +++ b/scripts/tests/test_net.py @@ -8,7 +8,8 @@ def is_broken_pipe_error(e): @test def tcp_close_without_reading(): host_port = 7777 - server = run_guest('/tests/misc-tcp-close-without-reading.so', forward=[(host_port, 7777)]) + server = run_command_in_guest('/tests/misc-tcp-close-without-reading.so', + forward=[(host_port, 7777)]) wait_for_line(server, 'listening...') diff --git a/scripts/tests/test_tracing.py b/scripts/tests/test_tracing.py new file mode 100644 index 000000000..14eef46c7 --- /dev/null +++ b/scripts/tests/test_tracing.py @@ -0,0 +1,35 @@ +from testing import * +import os +import subprocess + +@test +def tracing_smoke_test(): + path = '/this/path/does/not/exist' + guest = Guest(['--trace=vfs_*,net_packet*', '-e', path], hold_with_poweroff=True, show_output_on_error=False) + try: + wait_for_line(guest, 'run_main(): cannot execute %s. Powering off.' % path) + + trace_script = os.path.join(osv_base, 'scripts', 'trace.py') + + if os.path.exists('tracefile'): + os.remove('tracefile') + + assert(subprocess.call([trace_script, 'extract']) == 0) + + summary = subprocess.check_output([trace_script, 'summary']) + assert('vfs_open' in summary) + assert('vfs_open_err' in summary) + + samples = subprocess.check_output([trace_script, 'list']) + assert('vfs_open "%s" 0x0 00' % path in samples) + assert('vfs_open_err 2' in samples) + + tcpdump = subprocess.check_output([trace_script, 'tcpdump']) + assert('0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from' in tcpdump) + assert('192.168.122.1.67 > 255.255.255.255.68: BOOTP/DHCP, Reply' in tcpdump) + + tcpdump = subprocess.check_output([trace_script, 'list', '--tcpdump']) + assert('0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from' in tcpdump) + assert('192.168.122.1.67 > 255.255.255.255.68: BOOTP/DHCP, Reply' in tcpdump) + finally: + guest.kill() diff --git a/scripts/tests/testing.py b/scripts/tests/testing.py index e4a09548d..bbf9bdd08 100644 --- a/scripts/tests/testing.py +++ b/scripts/tests/testing.py @@ -4,10 +4,13 @@ import sys import subprocess import threading import traceback +import socket tests = [] _verbose_output = False +osv_base = '.' + class TestFailed(Exception): pass @@ -24,7 +27,7 @@ class SingleCommandTest(Test): self.command = command def run(self): - run_guest_sync(self.command) + run_command_in_guest(self.command).join() class test(Test): """ @@ -72,13 +75,14 @@ def scan_errors(s): return False class SupervisedProcess: - def __init__(self, args, show_output=False): + def __init__(self, args, show_output=False, show_output_on_error=True): self.process = subprocess.Popen(args, stdout=subprocess.PIPE) self.cv = threading.Condition() self.lines = [] self.output_collector_done = False self.has_errors = False self.show_output = show_output + self.show_output_on_error = show_output_on_error self.output_collector_thread = threading.Thread(target=self._output_collector) self.output_collector_thread.start() @@ -89,7 +93,7 @@ class SupervisedProcess: if not self.has_errors and scan_errors(line): self.has_errors = True - if not self.show_output: + if self.show_output_on_error and not self.show_output: sys.stdout.write(self.output) sys.stdout.flush() self.show_output = True @@ -162,21 +166,35 @@ class SupervisedProcess: assert not self.output_collector_thread.isAlive() return self.has_errors or self.process.returncode +def run_command_in_guest(command, **kwargs): + return Guest(["-s", "-e", command], **kwargs) + +class Guest(SupervisedProcess): + def __init__(self, args, forward=[], hold_with_poweroff=False, show_output_on_error=True): + run_script = os.path.join(osv_base, "scripts/run.py") + + if hold_with_poweroff: + args.append('-H') + + self.monitor_socket = 'qemu-monitor' + args.extend(['--pass-args=-monitor unix:%s,server,nowait' % self.monitor_socket]) -def run_guest(command, forward=[]): - osv_base = '.' - run_script = os.path.join(osv_base, "scripts/run.py") - args = ["-s", "-e", command] + for rule in forward: + args.extend(['--forward', 'tcp:%s::%s' % rule]) - for rule in forward: - args.extend(['--forward', 'tcp:%s::%s' % rule]) + SupervisedProcess.__init__(self, [run_script] + args, + show_output=_verbose_output, + show_output_on_error=show_output_on_error) - return SupervisedProcess([run_script] + args, show_output=_verbose_output) + def send_command(self, command): + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(self.monitor_socket) + s.send(command) + s.send('\n') + s.close() -def run_guest_sync(*args, **kwargs): - guest = run_guest(*args, **kwargs) - guest.join() - return guest + def kill(self): + self.send_command('quit') def wait_for_line(guest, text): for line in guest.read_lines(): -- GitLab