You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
14 KiB
406 lines
14 KiB
#!/usr/bin/env python
|
|
# Copyright (c) Sasha Goldshtein, 2017
|
|
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
|
|
import distutils.version
|
|
import subprocess
|
|
import os
|
|
import re
|
|
from unittest import main, skipUnless, TestCase
|
|
|
|
TOOLS_DIR = "../../tools/"
|
|
|
|
def kernel_version_ge(major, minor):
|
|
# True if running kernel is >= X.Y
|
|
version = distutils.version.LooseVersion(os.uname()[2]).version
|
|
if version[0] > major:
|
|
return True
|
|
if version[0] < major:
|
|
return False
|
|
if minor and version[1] < minor:
|
|
return False
|
|
return True
|
|
|
|
@skipUnless(kernel_version_ge(4,1), "requires kernel >= 4.1")
|
|
class SmokeTests(TestCase):
|
|
# Use this for commands that have a built-in timeout, so they only need
|
|
# to be killed in case of a hard hang.
|
|
def run_with_duration(self, command, timeout=10):
|
|
full_command = TOOLS_DIR + command
|
|
self.assertEqual(0, # clean exit
|
|
subprocess.call("timeout -s KILL %ds %s > /dev/null" %
|
|
(timeout, full_command), shell=True))
|
|
|
|
# Use this for commands that don't have a built-in timeout, so we have
|
|
# to Ctrl-C out of them by sending SIGINT. If that still doesn't stop
|
|
# them, send a kill signal 5 seconds later.
|
|
def run_with_int(self, command, timeout=5, kill_timeout=5,
|
|
allow_early=False, kill=False):
|
|
full_command = TOOLS_DIR + command
|
|
signal = "KILL" if kill else "INT"
|
|
rc = subprocess.call("timeout -s %s -k %ds %ds %s > /dev/null" %
|
|
(signal, kill_timeout, timeout, full_command), shell=True)
|
|
# timeout returns 124 if the program did not terminate prematurely,
|
|
# and returns 137 if we used KILL instead of INT. So there are three
|
|
# sensible scenarios:
|
|
# 1. The script is allowed to return early, and it did, with a
|
|
# success return code.
|
|
# 2. The script timed out and was killed by the SIGINT signal.
|
|
# 3. The script timed out and was killed by the SIGKILL signal, and
|
|
# this was what we asked for using kill=True.
|
|
self.assertTrue((rc == 0 and allow_early) or rc == 124
|
|
or (rc == 137 and kill), "rc was %d" % rc)
|
|
|
|
def kmod_loaded(self, mod):
|
|
with open("/proc/modules", "r") as mods:
|
|
reg = re.compile("^%s\s" % mod)
|
|
for line in mods:
|
|
if reg.match(line):
|
|
return 1
|
|
return 0
|
|
|
|
def setUp(self):
|
|
pass
|
|
|
|
def tearDown(self):
|
|
pass
|
|
|
|
def test_argdist(self):
|
|
self.run_with_duration("argdist.py -v -C 'p::do_sys_open()' -n 1 -i 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_bashreadline(self):
|
|
self.run_with_int("bashreadline.py")
|
|
|
|
def test_biolatency(self):
|
|
self.run_with_duration("biolatency.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_biosnoop(self):
|
|
self.run_with_int("biosnoop.py")
|
|
|
|
def test_biotop(self):
|
|
self.run_with_duration("biotop.py 1 1")
|
|
|
|
def test_bitesize(self):
|
|
self.run_with_int("biotop.py")
|
|
|
|
def test_bpflist(self):
|
|
self.run_with_duration("bpflist.py")
|
|
|
|
def test_btrfsdist(self):
|
|
# Will attempt to do anything meaningful only when btrfs is installed.
|
|
self.run_with_duration("btrfsdist.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_btrfsslower(self):
|
|
# Will attempt to do anything meaningful only when btrfs is installed.
|
|
self.run_with_int("btrfsslower.py", allow_early=True)
|
|
|
|
def test_cachestat(self):
|
|
self.run_with_duration("cachestat.py 1 1")
|
|
|
|
def test_cachetop(self):
|
|
# TODO cachetop doesn't like to run without a terminal, disabled
|
|
# for now.
|
|
# self.run_with_int("cachetop.py 1")
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_capable(self):
|
|
self.run_with_int("capable.py")
|
|
|
|
def test_cpudist(self):
|
|
self.run_with_duration("cpudist.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9")
|
|
def test_cpuunclaimed(self):
|
|
self.run_with_duration("cpuunclaimed.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_dbslower(self):
|
|
# Deliberately left empty -- dbslower requires an instance of either
|
|
# MySQL or PostgreSQL to be running, or it fails to attach.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,3), "requires kernel >= 4.3")
|
|
def test_dbstat(self):
|
|
# Deliberately left empty -- dbstat requires an instance of either
|
|
# MySQL or PostgreSQL to be running, or it fails to attach.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_dcsnoop(self):
|
|
self.run_with_int("dcsnoop.py")
|
|
|
|
def test_dcstat(self):
|
|
self.run_with_duration("dcstat.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_deadlock_detector(self):
|
|
# TODO This tool requires a massive BPF stack traces table allocation,
|
|
# which might fail the run or even trigger the oomkiller to kill some
|
|
# other processes. Disabling for now.
|
|
# self.run_with_int("deadlock_detector.py $(pgrep -n bash)", timeout=10)
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
|
|
def test_execsnoop(self):
|
|
self.run_with_int("execsnoop.py")
|
|
|
|
def test_ext4dist(self):
|
|
self.run_with_duration("ext4dist.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_ext4slower(self):
|
|
self.run_with_int("ext4slower.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_filelife(self):
|
|
self.run_with_int("filelife.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_fileslower(self):
|
|
self.run_with_int("fileslower.py")
|
|
|
|
def test_filetop(self):
|
|
self.run_with_duration("filetop.py 1 1")
|
|
|
|
def test_funccount(self):
|
|
self.run_with_int("funccount.py __kmalloc -i 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_funclatency(self):
|
|
self.run_with_int("funclatency.py __kmalloc -i 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_funcslower(self):
|
|
self.run_with_int("funcslower.py __kmalloc")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_gethostlatency(self):
|
|
self.run_with_int("gethostlatency.py")
|
|
|
|
def test_hardirqs(self):
|
|
self.run_with_duration("hardirqs.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_killsnoop(self):
|
|
# Because killsnoop intercepts signals, if we send it a SIGINT we we
|
|
# we likely catch it while it is handling the data packet from the
|
|
# BPF program, and the exception from the SIGINT will be swallowed by
|
|
# ctypes. Therefore, we use SIGKILL.
|
|
# To reproduce the above issue, run killsnoop and in another shell run
|
|
# `kill -s SIGINT $(pidof python)`. As a result, killsnoop will print
|
|
# a traceback but will not exit.
|
|
self.run_with_int("killsnoop.py", kill=True)
|
|
|
|
@skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9")
|
|
def test_llcstat(self):
|
|
# Requires PMU, which is not available in virtual machines.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_mdflush(self):
|
|
self.run_with_int("mdflush.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_memleak(self):
|
|
self.run_with_duration("memleak.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
|
|
def test_mountsnoop(self):
|
|
self.run_with_int("mountsnoop.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,3), "requires kernel >= 4.3")
|
|
def test_mysqld_qslower(self):
|
|
# Deliberately left empty -- mysqld_qslower requires an instance of
|
|
# MySQL to be running, or it fails to attach.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_nfsslower(self):
|
|
if(self.kmod_loaded("nfs")):
|
|
self.run_with_int("nfsslower.py")
|
|
else:
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_nfsdist(self):
|
|
if(self.kmod_loaded("nfs")):
|
|
self.run_with_duration("nfsdist.py 1 1")
|
|
else:
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_offcputime(self):
|
|
self.run_with_duration("offcputime.py 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_offwaketime(self):
|
|
self.run_with_duration("offwaketime.py 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9")
|
|
def test_oomkill(self):
|
|
self.run_with_int("oomkill.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_opensnoop(self):
|
|
self.run_with_int("opensnoop.py")
|
|
|
|
def test_pidpersec(self):
|
|
self.run_with_int("pidpersec.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9")
|
|
def test_profile(self):
|
|
self.run_with_duration("profile.py 1")
|
|
|
|
def test_runqlat(self):
|
|
self.run_with_duration("runqlat.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,9), "requires kernel >= 4.9")
|
|
def test_runqlen(self):
|
|
self.run_with_duration("runqlen.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
|
|
def test_shmsnoop(self):
|
|
self.run_with_int("shmsnoop.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
|
|
def test_sofdsnoop(self):
|
|
self.run_with_int("sofdsnoop.py")
|
|
|
|
def test_slabratetop(self):
|
|
self.run_with_duration("slabratetop.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,7), "requires kernel >= 4.7")
|
|
def test_softirqs(self):
|
|
self.run_with_duration("softirqs.py 1 1")
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_solisten(self):
|
|
self.run_with_int("solisten.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_sslsniff(self):
|
|
self.run_with_int("sslsniff.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_stackcount(self):
|
|
self.run_with_int("stackcount.py __kmalloc -i 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_statsnoop(self):
|
|
self.run_with_int("statsnoop.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_syncsnoop(self):
|
|
self.run_with_int("syncsnoop.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,7), "requires kernel >= 4.7")
|
|
def test_syscount(self):
|
|
self.run_with_int("syscount.py -i 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_tcpaccept(self):
|
|
self.run_with_int("tcpaccept.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_tcpconnect(self):
|
|
self.run_with_int("tcpconnect.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_tcpconnlat(self):
|
|
self.run_with_int("tcpconnlat.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_tcplife(self):
|
|
self.run_with_int("tcplife.py")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_tcpretrans(self):
|
|
self.run_with_int("tcpretrans.py")
|
|
|
|
@skipUnless(kernel_version_ge(4, 7), "requires kernel >= 4.7")
|
|
def test_tcpdrop(self):
|
|
self.run_with_int("tcpdrop.py")
|
|
|
|
def test_tcptop(self):
|
|
self.run_with_duration("tcptop.py 1 1")
|
|
|
|
def test_tplist(self):
|
|
self.run_with_duration("tplist.py -p %d" % os.getpid())
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_trace(self):
|
|
self.run_with_int("trace.py do_sys_open")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_ttysnoop(self):
|
|
self.run_with_int("ttysnoop.py /dev/console")
|
|
|
|
@skipUnless(kernel_version_ge(4,7), "requires kernel >= 4.7")
|
|
def test_ucalls(self):
|
|
self.run_with_int("lib/ucalls.py -l none -S %d" % os.getpid())
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_uflow(self):
|
|
# The Python installed on the Ubuntu buildbot doesn't have USDT
|
|
# probes, so we can't run uflow.
|
|
# self.run_with_int("pythonflow.py %d" % os.getpid())
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_ugc(self):
|
|
# This requires a runtime that has GC probes to be installed.
|
|
# Python has them, but only in very recent versions. Skip.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_uobjnew(self):
|
|
self.run_with_int("cobjnew.sh %d" % os.getpid())
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_ustat(self):
|
|
self.run_with_duration("lib/ustat.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_uthreads(self):
|
|
self.run_with_int("lib/uthreads.py %d" % os.getpid())
|
|
|
|
def test_vfscount(self):
|
|
self.run_with_int("vfscount.py", timeout=15, kill_timeout=15)
|
|
|
|
def test_vfsstat(self):
|
|
self.run_with_duration("vfsstat.py 1 1")
|
|
|
|
@skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6")
|
|
def test_wakeuptime(self):
|
|
self.run_with_duration("wakeuptime.py 1")
|
|
|
|
def test_xfsdist(self):
|
|
# Doesn't work on build bot because xfs functions not present in the
|
|
# kernel image.
|
|
# self.run_with_duration("xfsdist.py 1 1")
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_xfsslower(self):
|
|
# Doesn't work on build bot because xfs functions not present in the
|
|
# kernel image.
|
|
# self.run_with_int("xfsslower.py")
|
|
pass
|
|
|
|
def test_zfsdist(self):
|
|
# Fails to attach the probe if zfs is not installed.
|
|
pass
|
|
|
|
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4")
|
|
def test_zfsslower(self):
|
|
# Fails to attach the probe if zfs is not installed.
|
|
pass
|
|
|
|
if __name__ == "__main__":
|
|
main()
|