+++ /dev/null
-#!/usr/bin/env python
-
-import os, sys
-import subprocess
-import threading
-import Queue
-import time
-import shlex
-
-from signal import signal, SIGTERM, SIGINT, SIGPIPE, SIG_DFL
-
-SESSIOND_BIN_NAME = "lttng-sessiond"
-SESSIOND_BIN_PATH = "src/bin/lttng-sessiond/"
-CONSUMERD_BIN_NAME = "lttng-consumerd"
-CONSUMERD_BIN_PATH = "src/bin/lttng-consumerd/"
-TESTDIR_PATH = ""
-
-PRINT_BRACKET = "\033[1;34m[\033[1;33m+\033[1;34m]\033[00m"
-PRINT_RED_BRACKET = "\033[1;31m[+]\033[00m"
-PRINT_GREEN_BRACKET = "\033[1;32m[+]\033[00m"
-PRINT_ARROW = "\033[1;32m-->\033[00m"
-
-is_root = 1
-no_stats = 0
-stop_sampling = 1
-
-top_cpu_legend = { 'us': "User CPU time", 'sy': "System CPU time",
- 'id': "Idle CPU time", 'ni': "Nice CPU time", 'wa': "iowait",
- 'hi': "Hardware IRQ", 'si': "Software Interrupts", 'st': "Steal Time", }
-
-cpu_ret_q = Queue.Queue()
-mem_ret_q = Queue.Queue()
-test_ret_q = Queue.Queue()
-
-global sdaemon_proc
-global worker_proc
-
-def cpu_create_usage_dict(top_line):
- """
- Return a dictionnary from a 'top' cpu line.
- Ex: Cpu(s): 2.1%us, 1.2%sy, 0.0%ni, 96.2%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
- """
- top_dict = {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
-
- # Split expression and remove first value which is "Cpu(s)"
- top_line = top_line.replace(",","")
- words = top_line.split()[1:]
-
-
- for key in top_dict:
- index = words.index(key)
- # Add the value to the dictionnary
- val = words[index-1]
- top_dict[key] = float(val)
-
- return top_dict
-
-def cpu_average_usage(top_lines):
- """
- Return a dictionnary of 'top' CPU stats but averaging all values.
- """
- avg_dict = {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
- # Average count
- count = 0.0
-
- for line in top_lines:
- tmp_dict = cpu_create_usage_dict(line)
- # Add value to avg dictionnary
- for key in tmp_dict:
- avg_dict[key] += tmp_dict[key]
-
- count += 1.0
-
- for key in avg_dict:
- avg_dict[key] = avg_dict[key] / count
-
- return (count, avg_dict)
-
-def cpu_sample_usage(pid=None):
- """
- Sample CPU usage for num iterations.
- If num is greater than 1, the average will be computed.
- """
- args = ["top", "-b", "-n", "1"]
- if pid:
- args.append("-p")
- args.append(str(pid))
-
- # Spawn top process
- top = subprocess.Popen(args, stdout = subprocess.PIPE)
-
- grep = subprocess.Popen(["grep", "Cpu"], stdin = top.stdout,
- stdout = subprocess.PIPE)
- top.stdout.close()
-
- return grep.communicate()[0].strip("\n")
-
-def mem_sample_usage(pid):
- """
- Sample memory usage using /proc and a pid
- """
- args = ["cat", "/proc/" + str(pid) + "/status"]
-
- if not os.path.isfile(args[1]):
- return -1
-
- mem_proc = subprocess.Popen(args, stdout = subprocess.PIPE)
-
- grep = subprocess.Popen(["grep", "^VmRSS"], stdin = mem_proc.stdout,
- stdout = subprocess.PIPE)
- mem_proc.stdout.close()
-
- # Return virtual memory size in kilobytes (kB)
- #ret = grep.communicate()[0].split()
- ret = grep.communicate()[0].split()
-
- if len(ret) > 1:
- ret = ret[1]
- else:
- ret = 0
-
- return int(ret)
-
-class SamplingWorker(threading.Thread):
- def __init__(self, s_type, worker = None, delay = 0.2, pid = 0):
- threading.Thread.__init__ (self)
- self.s_type = s_type
- self.delay = delay
- self.pid = pid
- self.worker = worker
-
- def run(self):
- count = 1
- lines = []
-
- if self.s_type == "cpu":
- while 1:
- if self.worker == None:
- cpu_line = cpu_sample_usage(self.pid)
- lines.append(cpu_line)
- break
- elif self.worker.is_alive():
- cpu_line = cpu_sample_usage(self.pid)
- lines.append(cpu_line)
- else:
- break
-
- # Delay sec per memory sampling
- time.sleep(self.delay)
-
- count, stats = cpu_average_usage(lines)
- cpu_ret_q.put((count, stats))
- # grep process has ended here
-
- elif self.s_type == "mem":
- count = 0
- mem_stat = 0
-
- while 1:
- if self.worker == None:
- cpu_line = cpu_sample_usage(self.pid)
- lines.append(cpu_line)
- break
- elif self.worker.is_alive():
- mem_stat += get_mem_usage(self.pid)
- count += 1
- else:
- break
-
- # Delay sec per memory sampling
- time.sleep(self.delay)
-
- mem_ret_q.put((count, mem_stat))
-
-class TestWorker(threading.Thread):
- def __init__(self, path, name, env):
- threading.Thread.__init__(self)
- self.path = path
- self.name = name
- self.env = env
-
- def run(self):
- bin_path_name = os.path.join(self.path, self.name)
-
- test = subprocess.Popen([bin_path_name], env=self.env, preexec_fn = lambda: signal(SIGPIPE, SIG_DFL))
- test.wait()
-
- # Send ret value to main thread
- test_ret_q.put(test.returncode)
-
-def get_pid(procname):
- """
- Return pid of process name using 'pidof' command
- """
- pidof = subprocess.Popen(["pidof", procname], stdout = subprocess.PIPE)
- pid = pidof.communicate()[0].split()
-
- if pid == []:
- return 0
-
- return int(pid[0])
-
-def spawn_session_daemon():
- """
- Exec the session daemon and return PID
- """
- global sdaemon_proc
-
- pid = get_pid(SESSIOND_BIN_NAME)
- if pid != 0:
- os.kill(pid, SIGTERM)
-
- bin_path = os.path.join(TESTDIR_PATH, "..", SESSIOND_BIN_PATH, SESSIOND_BIN_NAME)
- consumer_path = os.path.join(TESTDIR_PATH, "..", CONSUMERD_BIN_PATH, CONSUMERD_BIN_NAME)
-
- if not os.path.isfile(bin_path):
- print "Error: No session daemon binary found. Compiled?"
- return 0
-
- try:
- args = shlex.split("libtool execute " + bin_path
- + " --consumerd32-path=" + consumer_path
- + " --consumerd64-path=" + consumer_path)
-
- sdaemon_proc = subprocess.Popen(args, shell = False, stderr = subprocess.PIPE)
-
- except OSError, e:
- print e
- return 0
-
- time.sleep(1)
-
- return get_pid("lt-" + SESSIOND_BIN_NAME)
-
-def start_test(name):
- """
- Spawn test and return exit code
- """
- tw = TestWorker(".", name)
- tw.start()
-
- return test_ret_q.get(True)
-
-def print_cpu_stats(stats, count):
- """
- Pretty print on one line the CPU stats
- """
- sys.stdout.write(PRINT_ARROW + " Cpu [sampled %d time(s)]:\n " % (count))
- for stat in stats:
- sys.stdout.write(" %s: %.2f, " % (stat, stats[stat]))
- print ""
-
-def get_cpu_usage(delay=1, pid=0):
- """
- Spawn a worker thread to sample cpu usage.
- """
- sw = SamplingWorker("cpu", delay = delay, pid = pid)
- sw.start()
-
- return cpu_ret_q.get(True)
-
-def get_mem_usage(pid):
- """
- Get memory usage for PID
- """
- return mem_sample_usage(pid)
-
-def print_test_success(ret, expect):
- """
- Print if test has failed or pass according to the expected value.
- """
- if ret != expect:
- print "\n" + PRINT_RED_BRACKET + \
- " Failed: ret = %d (expected %d)" % (ret, expect)
- return 1
- else:
- print "\n" + PRINT_BRACKET + \
- " Passed: ret = %d (expected %d)" % (ret, expect)
- return 0
-
-def run_test(test):
- """
- Run test 'name' and output report of the test with stats.
- """
- global worker_proc
- global sdaemon_proc
- dem_pid = 0 # Session daemon pid
-
- print PRINT_BRACKET + " %s" % (test['name'])
- print PRINT_ARROW + " %s" % (test['desc'])
- if no_stats:
- print PRINT_ARROW + " Statistics will NOT be collected"
- else:
- print PRINT_ARROW + " Statistics of the session daemon will be collected"
-
- if test['kern'] and not is_root:
- print "Needs root for kernel tracing. Skipping"
- return 0
-
- if not os.path.isfile(test['bin']):
- print "Unable to find test file '%s'. Skipping" % (test['bin'])
- return 0
-
- # Session daemon is controlled by the test
- if test['daemon'] == "test":
- print PRINT_ARROW + " Session daemon is controlled by the test"
- env = os.environ
- env['TEST_NO_SESSIOND'] = '0'
- tw = TestWorker(".", test['bin'], env)
- tw.start()
- ret = test_ret_q.get(True)
- print_test_success(ret, test['success'])
- return 0
- elif test['daemon'] == False:
- print PRINT_ARROW + " No session daemon needed"
- env = os.environ
- env['TEST_NO_SESSIOND'] = '1'
- tw = TestWorker(".", test['bin'], env)
- tw.start()
- ret = test_ret_q.get(True)
- print_test_success(ret, test['success'])
- return 0
- else:
- print PRINT_ARROW + " Session daemon needed"
-
- dem_pid = spawn_session_daemon()
- if dem_pid <= 0:
- print "Unable to start %s. Stopping" % (SESSIOND_BIN_NAME)
- print sdaemon_proc.communicate()[1]
- return 0
-
- print PRINT_BRACKET + " Session daemon spawned (pid: %d)\n" % (dem_pid)
-
- if not no_stats:
- mem_before = get_mem_usage(dem_pid)
- print PRINT_BRACKET + " Stats *before* test:"
- print PRINT_ARROW + " Mem (kB): %d" % (mem_before)
- cpu_count, cpu_stats = get_cpu_usage(pid = dem_pid)
- print_cpu_stats(cpu_stats, cpu_count)
-
- # Sessiond was already spawned, do not let the test spawn
- # an additional sessiond
- env = os.environ
- env['TEST_NO_SESSIOND'] = '1'
-
- tw = TestWorker(".", test['bin'], env)
- tw.start()
-
- if not no_stats:
- # Start CPU sampling for test
- sw_cpu = SamplingWorker("cpu", worker = tw, pid = dem_pid)
- sw_cpu.start()
- sw_mem = SamplingWorker("mem", worker = tw, pid = dem_pid)
- sw_mem.start()
-
- ret = test_ret_q.get(True)
-
- if not no_stats:
- time.sleep(2)
- # Compute memory average
- mem_count, mem_during = mem_ret_q.get(True)
- mem_during = float(mem_during) / float(mem_count)
- cpu_count, cpu_stats = cpu_ret_q.get(True)
-
- print "\n" + PRINT_BRACKET + " Stats *during* test:"
- print PRINT_ARROW + " Mem (kB): %.0f [sampled %d time(s)]" % (mem_during, mem_count)
- print_cpu_stats(cpu_stats, cpu_count)
-
- mem_after = get_mem_usage(dem_pid)
- print "\n" + PRINT_BRACKET + " Stats *after* test:"
- print PRINT_ARROW + " Mem (kB): %d" % (mem_after)
- cpu_count, cpu_stats = get_cpu_usage(pid = dem_pid)
- print_cpu_stats(cpu_stats, cpu_count)
-
- print "\n" + PRINT_BRACKET + " Memory usage differences:"
- print PRINT_ARROW + " Diff during and before (kB): %d" % (mem_during - mem_before)
- print PRINT_ARROW + " Diff during and after (kB): %d" % (mem_during - mem_after)
- print PRINT_ARROW + " Diff before and after (kB): %d" % (mem_after - mem_before)
-
- # Return value of 0 means that is passed else it failed
- ret = print_test_success(ret, test['success'])
-
- # Stop session daemon
- if dem_pid > 0:
- print PRINT_BRACKET + " Stopping session daemon (pid: %d)..." % (dem_pid)
- try:
- os.kill(dem_pid, SIGTERM)
- # This call simply does not work... It seems python does not relay the signal
- # to the child processes of sdaemon_proc.
- # sdaemon_proc.terminate()
- if ret != 0:
- print sdaemon_proc.communicate()[1]
- elif sdaemon_proc.returncode == None:
- sdaemon_proc.communicate()
- except OSError, e:
- print e
-
- # Make sure all thread are released
- if not no_stats:
- tw.join()
- sw_cpu.join()
- sw_mem.join()
-
- return ret
-
-def main():
- for test in Tests:
- if not test['enabled']:
- continue
-
- ret = run_test(test)
- if ret != 0:
- # Stop all tests, the last one failed
- return
- print ""
-
-def cleanup(signo, stack):
- """ Cleanup function """
- sys.exit(0)
-
-if __name__ == "__main__":
- if not os.getuid() == 0:
- is_root = 0
- print "NOTICE: Not root. No kernel tracing will be tested\n"
-
- if os.path.isfile("test_list.py"):
- from test_list import Tests
- else:
- print "No test_list.py found. Stopping"
- cleanup(0, 0)
-
- TESTDIR_PATH = os.getcwd()
-
- if len(sys.argv) > 1:
- if sys.argv[1] == "--no-stats":
- no_stats = 1
-
- try:
- signal(SIGTERM, cleanup)
- signal(SIGINT, cleanup)
- main()
- cleanup(0, 0)
- except KeyboardInterrupt:
- cleanup(0, 0)
+++ /dev/null
-Tests = \
-[
- # lttng-tools unit tests
- {
- 'bin': "tools/test_sessions", 'daemon': False, 'kern': False, 'name': "Test sessions",
- 'desc': "Test tracing session data structures and methods.",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/test_kernel_data_trace", 'daemon': False, 'kern': False,
- 'name': "Kernel data structures",
- 'desc': "Test Kernel data structures and methods.",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/test_ust_data_trace", 'daemon': False, 'kern': False,
- 'name': "UST data structures",
- 'desc': "Test UST data structures and methods.",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/streaming/run-ust", 'daemon': True, 'kern': False,
- 'name': "UST network streaming",
- 'desc': "Test user space tracing network streaming support",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/streaming/run-kernel", 'daemon': True, 'kern': True,
- 'name': "Kernel network streaming",
- 'desc': "Test kernel tracing network streaming support",
- 'success': 0, 'enabled': True
- },
-
- # Kernel tests
- {
- 'bin': "kernel/run-kernel-tests.sh", 'daemon': True, 'kern': True,
- 'name': "Kernel tracer - lttng client",
- 'desc': "Test the Kernel tracer using the lttng client",
- 'success': 0, 'enabled': True
- },
-
- # UST tests
- {
- 'bin': "ust/run-ust-global-tests.sh", 'daemon': True, 'kern': False,
- 'name': "UST tracer - Global domain",
- 'desc': "Test the UST tracer functionnalities for domain LTTNG_DOMAIN_UST",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "ust/nprocesses/run", 'daemon': True, 'kern': False,
- 'name': "UST tracer - Multiple processes",
- 'desc': "Test multiple process registering and tracing",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "ust/high-throughput/run", 'daemon': True, 'kern': False,
- 'name': "UST tracer - Testing high events throughput",
- 'desc': "Test multiple large number of events with concurrent application",
- 'success': 0, 'enabled': True
- },
- # Deactivated. This test last 20 minutes...
- #{
- #'bin': "ust/low-throughput/run", 'daemon': True, 'kern': False,
- #'name': "UST tracer - Testing high events throughput",
- #'desc': "Test low throughput of events",
- #'success': 0, 'enabled': False
- #},
- {
- 'bin': "ust/before-after/run", 'daemon': True, 'kern': False,
- 'name': "UST tracer - Tracing before and after app execution",
- 'desc': "Test tracing before and after app execution",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "ust/multi-session/run", 'daemon': True, 'kern': False,
- 'name': "UST tracer - Multi-session",
- 'desc': "Test tracing with 4 sessions for one application",
- 'success': 0, 'enabled': True
- },
-
- # Tools filtering tests
- {
- 'bin': "tools/filtering/unsupported-ops", 'daemon': True, 'kern': False,
- 'name': "Filtering - Unsupported operators",
- 'desc': "Test the failure of filter with unsupported operators",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/filtering/invalid-filters", 'daemon': True, 'kern': False,
- 'name': "Filtering - Invalid filters",
- 'desc': "Test the failure of invalid filters",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/filtering/valid-filters", 'daemon': True, 'kern': False,
- 'name': "Filtering - Valid filters",
- 'desc': "Validate the expected trace output of valid filters",
- 'success': 0, 'enabled': True
- },
-
- # Tools health check tests
- {
- 'bin': "tools/health/health_thread_ok", 'daemon': "test", 'kern': True,
- 'name': "Health check - Threads OK",
- 'desc': "Verify that health check is OK when running lttng-sessiond, lttng-consumerd, and lttng-relayd",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/health/health_thread_exit", 'daemon': "test", 'kern': True,
- 'name': "Health check - Thread exit",
- 'desc': "Call exit in the various lttng-sessiond, lttng-consumerd, lttng-relayd threads and ensure that health failure is detected",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/health/health_thread_stall", 'daemon': "test", 'kern': True,
- 'name': "Health check - Thread stall",
- 'desc': "Stall the various lttng-sessiond, lttng-consumerd, lttng-relayd threads and ensure that health failure is detected",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/health/health_tp_fail", 'daemon': "test", 'kern': True,
- 'name': "Health check - Testpoint failure",
- 'desc': "Trigger a failure in the testpoint mechanism in each thread to provoke thread teardown",
- 'success': 0, 'enabled': True
- },
-
- # Tools streaming tests
- {
- 'bin': "tools/streaming/run-kernel", 'daemon': True, 'kern': True,
- 'name': "Streaming - Kernel tracing",
- 'desc': "Stream a kernel trace across the network",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/streaming/run-ust", 'daemon': True, 'kern': False,
- 'name': "Streaming - Userspace tracing",
- 'desc': "Stream a userspace trace across the network",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/streaming/uri_switch", 'daemon': True, 'kern': False,
- 'name': "Streaming - URI switching",
- 'desc': "Switch URI and verify that the trace result are in the proper location",
- 'success': 0, 'enabled': True
- },
- {
- 'bin': "tools/streaming/high_throughput_limits", 'daemon': True, 'kern': True,
- 'name': "Streaming - High throughput with bandwith limits",
- 'desc': "Trace streaming with bandwidth limits",
- 'success': 0, 'enabled': True
- },
-]