From 74d51c8c3e18a8b6738aff0c6f7ff706fd70eaa6 Mon Sep 17 00:00:00 2001 From: Adrian Dudau Date: Thu, 26 Jun 2014 13:57:02 +0200 Subject: initial commit for Enea Linux 4.0 Migrated from the internal git server on the daisy-enea branch Signed-off-by: Adrian Dudau --- .../virt-test/files/qemu-tests-cyclictest.patch | 217 +++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 recipes-test/virt-test/files/qemu-tests-cyclictest.patch (limited to 'recipes-test/virt-test/files/qemu-tests-cyclictest.patch') diff --git a/recipes-test/virt-test/files/qemu-tests-cyclictest.patch b/recipes-test/virt-test/files/qemu-tests-cyclictest.patch new file mode 100644 index 0000000..f9ee831 --- /dev/null +++ b/recipes-test/virt-test/files/qemu-tests-cyclictest.patch @@ -0,0 +1,217 @@ +commit 61c087a0386ad04fd5579ad170b9d7933ed90c8c +Author: Jonas Eriksson +Date: Fri Apr 25 16:00:12 2014 +0200 + + Add cyclictest test case + + Cyclictest is a part of rt-tests used to test the responsiveness of a + system. While not developed for non-realtime systems, it can be used to + detect unexpected spikes in latencies within virtual machines. + + Signed-off-by: Jonas Eriksson + Upstream-Status: Pending + +diff --git a/qemu/tests/cfg/cyclictest.cfg b/qemu/tests/cfg/cyclictest.cfg +new file mode 100644 +index 0000000..d142b7d +--- /dev/null ++++ b/qemu/tests/cfg/cyclictest.cfg +@@ -0,0 +1,25 @@ ++- cyclictest: ++ virt_test_type = qemu ++ only Linux ++ type = cyclictest ++ kill_vm = yes ++ kill_vm_gracefully = no ++ backup_image_before_testing = yes ++ ++ # It is possible to tune the arguments to cyclictest using the ++ # cyclictest_args variable. ++ #cyclictest_args = "-D 30m --smp" ++ # It is formatted using a dictionary where a number of properties of the ++ # target is available, for example 'num_cpus' which is the number of cpus, ++ # and 'mask_all_cpus', which is the string "0-[num_cpus - 1]". See ++ # cyclictest.py for all available values. The following is for example ++ # equivalent to "-D 30m --smp": ++ #cyclictest_args = "-D 30m -t %(num_cpus)s -a %(mask_all_cpus)s" ++ # Default timeout is 35 min ++ #cyclictest_timeout_s = 2100 ++ ++ # After the run, the test case will check all values against the below ++ # allowed maximum values of each result. ++ #allowed_max = 50 ++ #allowed_avg = 30 ++ #allowed_act = +diff --git a/qemu/tests/cyclictest.py b/qemu/tests/cyclictest.py +new file mode 100644 +index 0000000..0ad447f +--- /dev/null ++++ b/qemu/tests/cyclictest.py +@@ -0,0 +1,167 @@ ++import logging ++import re ++from autotest.client import utils ++from autotest.client.shared import error ++from virttest import remote, utils_misc, utils_test ++ ++ ++# Information about cyclictest is available here: ++# https://rt.wiki.kernel.org/index.php/Cyclictest ++@error.context_aware ++def run(test, params, env): ++ """ ++ Test Steps: ++ ++ 1. Check availability of cyclictest ++ 2. Get information about the target ++ 3. Run cyclictest ++ 4. Parse and check result ++ ++ Params: ++ :param test: QEMU test object. ++ :param params: Dictionary with the test parameters. ++ :param env: Dictionary with test environment. ++ """ ++ ++ def parse_cyclictest(output_string): ++ """ ++ Parses the output from a cyclictest run into a nested dictionary. ++ ++ Example input: ++ # /dev/cpu_dma_latency set to 0us ++ T: 0 ( 7064) P: 0 I:1000 C: 2000 Min: 1 Act: 2 Avg: 3 Max: 751 ++ T: 1 ( 7065) P: 0 I:1500 C: 1334 Min: 1 Act: 3 Avg: 2 Max: 167 ++ Example output: ++ { '0': { 'Act': '2', ++ 'Avg': '3', ++ 'C': '2000', ++ 'I': '1000', ++ 'Max': '751', ++ 'Min': '1', ++ 'P': '0', ++ 'T': '0 ( 7064)'}, ++ '1': { 'Act': '3', ++ 'Avg': '2', ++ 'C': '1334', ++ 'I': '1500', ++ 'Max': '167', ++ 'Min': '1', ++ 'P': '0', ++ 'T': '1 ( 7065)'} ++ } ++ ++ Params: ++ :param output_string: Output data from cyclictest ++ :returns: Nested dict of parsed output ++ """ ++ output = output_string.split("\n") ++ result = {} ++ for row_string in output: ++ # Only process lines beginning with "T:" ++ if re.match("^T:", row_string): ++ # Since the different segments of a line are not comma ++ # separated (or similar), it is tricky to split them right ++ # away. Instead, match the "header" of an entry (e.g. "P:"), ++ # and add a line break before them. Then split the string using ++ # the added line breaks. ++ row_list = re.sub("\S+:", "\n\g<0>", row_string).split("\n") ++ sub_result = {} ++ for part in row_list: ++ part = re.sub("\s+$", "", part) ++ if not part == "": ++ # The strings are now on the form "P: 0" (for example) ++ kv = re.split(":\s*", part) ++ sub_result[kv[0]] = kv[1] ++ # Use the thread as an index in the outer result dict. Avoid ++ # using an array to be able to process results in any order and ++ # with gaps. ++ thread = (sub_result['T'].split(" "))[0] ++ result[thread] = sub_result ++ return result ++ ++ def check_val_ceiling(allowed_ceil, val, name, cpu): ++ """ ++ Check that the value :val: is not larger than :allowed_ceil:, and if so ++ log the error using :name: as the name of the value. ++ ++ Params: ++ :allowed_ceil: Maximum allowed vaule of :val:. If None, "" or 0, ++ just return 0. ++ :val: The value to be tested ++ :name: The name of the value, for logging ++ :cpu: CPU number for error reporting ++ :returns: Number of errors; 0 if successful. ++ """ ++ if allowed_ceil > 0 and val > allowed_ceil: ++ logging.error("%s value too large: %d for CPU %d" % (name, ++ val, ++ cpu)) ++ return 1 ++ return 0 ++ ++ # Get/setup VM and session ++ vm_name = params.get("vm_name", "main_vm") ++ vm = env.get_vm(params[vm_name]) ++ vm.verify_alive() ++ timeout = int(params.get("timeout", 2400)) ++ session = vm.wait_for_login(timeout=timeout) ++ ++ try: ++ error.context("Check availability of cyclictest") ++ if session.cmd_status("which cyclictest"): ++ raise error.TestFail("Test application not available") ++ ++ error.context("Get information about the target") ++ # Get the number of CPUs on target ++ cmd = "grep -c '^processor[[:space:]]*:' /proc/cpuinfo" ++ output = session.cmd_output(cmd) ++ num_cpus = int(output) ++ if num_cpus == 0: ++ raise error.TestFail("Unable to get number of CPUs on target") ++ ++ # Get arguments from the configuration ++ default_args = "-D 30m --smp" ++ cyclictest_args = params.get("cyclictest_args", default_args) ++ fmt_dict = { ++ 'num_cpus': num_cpus, ++ 'last_cpu': num_cpus - 1, ++ 'mask_all_cpus': "0-%d" % (num_cpus - 1), ++ } ++ formatted_args = cyclictest_args % fmt_dict ++ ++ error.context("Run cyclictest") ++ timeout_s = params.get("cyclictest_timeout_s", 60*35) ++ cmd = "cyclictest -q %s" % formatted_args ++ status, ct_output = session.cmd_status_output(cmd, ++ timeout=timeout_s) ++ if status: ++ logging.error("Cyclic test output: %s" % ct_output) ++ raise error.TestFail("Cyclictest returned %d" % status) ++ ++ error.context("Parse and check result") ++ results = parse_cyclictest(ct_output) ++ if not results: ++ logging.error("Cyclic test output: %s" % ct_output) ++ raise error.TestFail("Parsing of cyclictest output failed") ++ ++ # Get check values. By default, don't check Act. ++ allowed_max = int(params.get("allowed_max", 50)) ++ allowed_avg = int(params.get("allowed_avg", 30)) ++ allowed_act = int(params.get("allowed_act", 0)) ++ ++ fails = 0 ++ for key, result in results.iteritems(): ++ cpu = int(key) ++ max_val = int(result['Max']) ++ avg_val = int(result['Avg']) ++ act_val = int(result['Act']) ++ fails += check_val_ceiling(allowed_max, max_val, "Max", cpu) ++ fails += check_val_ceiling(allowed_avg, avg_val, "Avg", cpu) ++ fails += check_val_ceiling(allowed_act, act_val, "Act", cpu) ++ ++ if fails > 0: ++ logging.error("Cyclic test output: %s" % ct_output) ++ raise error.TestFail("Values out of bounds, see log") ++ ++ finally: ++ session.close() -- cgit v1.2.3-54-g00ecf