Skip to content
Snippets Groups Projects
Commit e804299c authored by Tomasz Grabiec's avatar Tomasz Grabiec Committed by Pekka Enberg
Browse files

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: default avatarTomasz Grabiec <tgrabiec@cloudius-systems.com>
Signed-off-by: default avatarPekka Enberg <penberg@cloudius-systems.com>
parent ee3bfb76
No related branches found
No related tags found
No related merge requests found
...@@ -8,6 +8,7 @@ import os ...@@ -8,6 +8,7 @@ import os
import re import re
import tests.test_net import tests.test_net
import tests.test_tracing
from operator import attrgetter from operator import attrgetter
from tests.testing import * from tests.testing import *
......
...@@ -8,7 +8,8 @@ def is_broken_pipe_error(e): ...@@ -8,7 +8,8 @@ def is_broken_pipe_error(e):
@test @test
def tcp_close_without_reading(): def tcp_close_without_reading():
host_port = 7777 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...') wait_for_line(server, 'listening...')
......
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()
...@@ -4,10 +4,13 @@ import sys ...@@ -4,10 +4,13 @@ import sys
import subprocess import subprocess
import threading import threading
import traceback import traceback
import socket
tests = [] tests = []
_verbose_output = False _verbose_output = False
osv_base = '.'
class TestFailed(Exception): class TestFailed(Exception):
pass pass
...@@ -24,7 +27,7 @@ class SingleCommandTest(Test): ...@@ -24,7 +27,7 @@ class SingleCommandTest(Test):
self.command = command self.command = command
def run(self): def run(self):
run_guest_sync(self.command) run_command_in_guest(self.command).join()
class test(Test): class test(Test):
""" """
...@@ -72,13 +75,14 @@ def scan_errors(s): ...@@ -72,13 +75,14 @@ def scan_errors(s):
return False return False
class SupervisedProcess: 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.process = subprocess.Popen(args, stdout=subprocess.PIPE)
self.cv = threading.Condition() self.cv = threading.Condition()
self.lines = [] self.lines = []
self.output_collector_done = False self.output_collector_done = False
self.has_errors = False self.has_errors = False
self.show_output = show_output 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 = threading.Thread(target=self._output_collector)
self.output_collector_thread.start() self.output_collector_thread.start()
...@@ -89,7 +93,7 @@ class SupervisedProcess: ...@@ -89,7 +93,7 @@ class SupervisedProcess:
if not self.has_errors and scan_errors(line): if not self.has_errors and scan_errors(line):
self.has_errors = True 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.write(self.output)
sys.stdout.flush() sys.stdout.flush()
self.show_output = True self.show_output = True
...@@ -162,21 +166,35 @@ class SupervisedProcess: ...@@ -162,21 +166,35 @@ class SupervisedProcess:
assert not self.output_collector_thread.isAlive() assert not self.output_collector_thread.isAlive()
return self.has_errors or self.process.returncode 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=[]): for rule in forward:
osv_base = '.' args.extend(['--forward', 'tcp:%s::%s' % rule])
run_script = os.path.join(osv_base, "scripts/run.py")
args = ["-s", "-e", command]
for rule in forward: SupervisedProcess.__init__(self, [run_script] + args,
args.extend(['--forward', 'tcp:%s::%s' % rule]) 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): def kill(self):
guest = run_guest(*args, **kwargs) self.send_command('quit')
guest.join()
return guest
def wait_for_line(guest, text): def wait_for_line(guest, text):
for line in guest.read_lines(): for line in guest.read_lines():
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment