[PATCH] [NEW] cgroup test * general smoke_test + module dependend subtests (memory test included) * library for future use in other tests (kvm)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: root <root@xxxxxxxxxxxxxxxxxxxxxxxxxx>

cgroup.py:
* structure for different cgroup subtests
* contains basic "cgroup-memory" test

cgroup_common.py:
* library for cgroup handling (intended to be used from kvm test in the future)
* universal smoke_test for every module

cgroup_client.py:
* application which is executed and controled using cgroups
* contains smoke, memory, cpu and devices tests which were manually tested to break cgroup rules and will be used in the cgroup.py subtests

Signed-off-by: Lukas Doktor <ldoktor@xxxxxxxxxx>
---
 client/tests/cgroup/cgroup.py        |  236 ++++++++++++++++++++++++++++++++++
 client/tests/cgroup/cgroup_client.py |  116 +++++++++++++++++
 client/tests/cgroup/control          |   12 ++
 3 files changed, 364 insertions(+), 0 deletions(-)
 create mode 100755 client/tests/cgroup/cgroup.py
 create mode 100755 client/tests/cgroup/cgroup_client.py
 create mode 100644 client/tests/cgroup/control

diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
new file mode 100755
index 0000000..d043d65
--- /dev/null
+++ b/client/tests/cgroup/cgroup.py
@@ -0,0 +1,236 @@
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+import os, logging
+import time
+from cgroup_common import Cgroup as CG
+from cgroup_common import CgroupModules
+
+class cgroup(test.test):
+    """
+    Tests the cgroup functionalities
+    """
+    version = 1
+    _client = ""
+    modules = CgroupModules()
+
+
+    def run_once(self):
+        """
+	    Try to access different resources which are restricted by cgroup.
+        """
+        logging.info('Start')
+
+        err = ""
+        # Run available tests
+        for i in ['memory']:
+            try:
+                if self.modules.get_pwd(i):
+                    if (eval ("self.test_%s()" % i)):
+                        err += "%s, " % i
+                else:
+                    logging.error("CGROUP: Skipping test_%s, module not "
+                                  "available/mounted", i)
+                    err += "%s, " % i
+            except Exception, inst:
+                logging.error("CGROUP: test_%s fatal failure: %s", i, inst)
+                err += "%s, " % i
+
+        if err:
+            raise error.TestFail('CGROUP: Some subtests failed (%s)' % err[:-2])
+
+
+    def setup(self):
+        """
+        Setup
+        """
+        logging.info('Setup')
+
+        self._client = os.path.join(self.bindir, "cgroup_client.py")
+
+        _modules = ['cpuset', 'ns', 'cpu', 'cpuacct', 'memory', 'devices',
+                    'freezer', 'net_cls', 'blkio']
+        if (self.modules.init(_modules) <= 0):
+            raise error.TestFail('Can\'t mount any cgroup modules')
+
+
+    def cleanup(self):
+        """
+        Unmount all cgroups and remove directories
+        """
+        logging.info('Cleanup')
+        self.modules.cleanup()
+
+
+    #############################
+    # TESTS
+    #############################
+    def test_memory(self):
+        """
+        Memory test
+        """
+        # Preparation
+        logging.info("Entering 'test_memory'")
+        item = CG('memory', self._client)
+        if item.initialize(self.modules):
+            logging.error("test_memory: cgroup init failed")
+            return -1
+
+        if item.smoke_test():
+            logging.error("test_memory: smoke_test failed")
+            return -1
+
+        pwd = item.mk_cgroup()
+        if pwd == None:
+            logging.error("test_memory: Can't create cgroup")
+            return -1
+
+        logging.debug("test_memory: Memory filling test")
+
+        f = open('/proc/meminfo','r')
+        mem = f.readline()
+        while not mem.startswith("MemFree"):
+            mem = f.readline()
+        # Use only 1G or max of the free memory
+        mem = min(int(mem.split()[1])/1024, 1024)
+        mem = max(mem, 100) # at least 100M
+        if (item.get_property("memory.memsw.limit_in_bytes", supress=True)
+                                                                    != None):
+            memsw = True
+            # Clear swap
+            os.system("swapoff -a")
+            os.system("swapon -a")
+            f.seek(0)
+            swap = f.readline()
+            while not swap.startswith("SwapTotal"):
+                swap = f.readline()
+            swap = int(swap.split()[1])/1024
+            if swap < mem / 2:
+                logging.error("Not enough swap memory to test 'memsw'")
+                memsw = False
+        else:
+            # Doesn't support swap+memory limitation, disable swap
+            logging.info("'memsw' not supported")
+            os.system("swapoff -a")
+            memsw = False
+        logging.debug("test_memory: Initializition passed")
+
+        ################################################
+        # Fill the memory without cgroup limitation
+        # Should pass
+        ################################################
+        ps = item.test("memfill %d" % mem)
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 60:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 60:
+            logging.error("test_memory: Memory filling failed (WO cgroup)")
+            ps.terminate()
+            return -1
+        if not ps.stdout.readlines()[-1].startswith("PASS"):
+            logging.error("test_memory: Unsuccessful memory filling "
+                          "(WO cgroup)")
+            return -1
+        logging.debug("test_memory: Memfill WO cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory limit
+        # memsw: should swap out part of the process and pass
+        # WO memsw: should fail (SIGKILL)
+        ################################################
+        ps = item.test("memfill %d" % mem)
+        if item.set_cgroup(ps.pid, pwd):
+            logging.error("test_memory: Could not set cgroup")
+            return -1
+        if item.set_property("memory.limit_in_bytes", (1024*1024*mem/2), pwd):
+            logging.error("test_memory: Could not set mem limit (mem)")
+            return -1
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 60:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 60:
+            logging.error("test_memory: Memory filling failed (mem)")
+            ps.terminate()
+            return -1
+        out = ps.stdout.readlines()
+        if len(out) < 2:
+            logging.error("test_memory: Process failed; output:\n%s", out)
+            return -1
+        if memsw:
+            if not out[-1].startswith("PASS"):
+                logging.error("test_memory: Unsuccessful memory filling (mem)")
+                logging.error("test_memory: cgroup_client.py returned %d; "
+                              "output:\n%s", ps.poll(), out)
+                return -1
+        else:
+            if out[-1].startswith("PASS"):
+                logging.error("test_memory: Unexpected memory filling (mem)")
+                return -1
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem/2 > 1.5*filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                               "python overhead upto 1/3 (mem)", mem/2, filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                               "python overhead upto 1/3 (mem)", mem/2, filled)
+        logging.debug("test_memory: Memfill mem only cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory+swap limit
+        # Should fail
+        ################################################
+        if memsw:
+            ps = item.test("memfill %d" % mem)
+            if item.set_cgroup(ps.pid, pwd):
+                logging.error("test_memory: Could not set cgroup (memsw)")
+                return -1
+            if item.set_property("memory.memsw.limit_in_bytes",
+                                 (1024*1024*mem/2), pwd):
+                logging.error("test_memory: Could not set mem limit (memsw)")
+                return -1
+            ps.stdin.write('\n')
+            i = 0
+            while ps.poll() == None:
+                if i > 60:
+                    break
+                i += 1
+                time.sleep(1)
+            if i > 60:
+                logging.error("test_memory: Memory filling failed (mem)")
+                ps.terminate()
+                return -1
+            out = ps.stdout.readlines()
+            if len(out) < 2:
+                logging.error("test_memory: Process failed; output:\n%s", out)
+                return -1
+            if out[-1].startswith("PASS"):
+                logging.error("test_memory: Unexpected memory filling (memsw)",
+                              mem)
+                return -1
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem/2 > 1.5*filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                              "python overhead upto 1/3 (memsw)", mem/2, filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                              "python overhead upto 1/3 (memsw)", mem/2, filled)
+            logging.debug("test_memory: Memfill mem+swap cgroup passed")
+
+        # cleanup
+        if item.rm_cgroup(pwd):
+            logging.error("test_memory: Can't remove cgroup directory")
+            return -1
+        os.system("swapon -a")
+        logging.debug("test_memory: Cleanup passed")
+
+        logging.info("Leaving 'test_memory': PASSED")
+        return 0
diff --git a/client/tests/cgroup/cgroup_client.py b/client/tests/cgroup/cgroup_client.py
new file mode 100755
index 0000000..ff098ef
--- /dev/null
+++ b/client/tests/cgroup/cgroup_client.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Interactive python script for testing cgroups
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@xxxxxxxxxx>
+"""
+import array, sys, time, math
+
+def test_smoke():
+    """
+    SIGSTOP the process and after SIGCONT exits.
+    """
+    print "TEST: smoke"
+    print "TEST: wait for input"
+    raw_input()
+    print "PASS: smoke"
+
+
+def test_memfill(size=1024):
+    """
+    SIGSTOP and after SIGCONT fills the memory up to size size.
+    """
+    print "TEST: memfill (%dM)" % size
+    print "TEST: wait for input"
+    raw_input()
+    mem = array.array('B')
+    buf = ""
+    for i in range(1024*1024):
+        buf += '\x00'
+    for i in range(size):
+        mem.fromstring(buf)
+        #for j in range(1024*1024):
+        #    mem.append(0)
+        print "TEST: %dM" % i
+    print "PASS: memfill (%dM)" % size
+
+
+def test_cpu():
+    """
+    Stress the CPU
+    """
+    print "TEST: cpu"
+    print "TEST: wait for input"
+    raw_input()
+    while True:
+        for i in range (1000, 10000):
+            math.factorial(i)
+
+
+def test_devices_read():
+    """
+    Inf read from /dev/zero
+    """
+    print "TEST: devices read"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/zero", 'r')
+    while True:
+        print "TEST: tick"
+        dev.flush()
+        dev.read(1024*1024)
+        time.sleep(1)
+
+
+def test_devices_write():
+    """
+    Inf write into /dev/null device
+    """
+    print "TEST: devices write"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/null", 'w')
+    buf = ""
+    for _ in range(1024*1024):
+        buf += '\x00'
+    while True:
+        print "TEST: tick"
+        dev.write(buf)
+        dev.flush()
+        time.sleep(1)
+
+
+def main():
+    """
+    Main (infinite) loop.
+    """
+    if len(sys.argv) < 2:
+        print "FAIL: Incorrect usage"
+        return -1
+    if sys.argv[1] == "smoke":
+        test_smoke()
+    elif sys.argv[1] == "memfill":
+        if len(sys.argv) > 2:
+            test_memfill(int(sys.argv[2]))
+        else:
+            test_memfill()
+    elif sys.argv[1] == "cpu":
+        test_cpu()
+    elif sys.argv[1] == "devices":
+        if len(sys.argv) > 2:
+            if (sys.argv[2] == "write"):
+                test_devices_write()
+            else:
+                test_devices_read()
+        else:
+            test_devices_read()
+    else:
+        print "FAIL: No test specified"
+
+if __name__ == "__main__":
+    main()
+
diff --git a/client/tests/cgroup/control b/client/tests/cgroup/control
new file mode 100644
index 0000000..86aec06
--- /dev/null
+++ b/client/tests/cgroup/control
@@ -0,0 +1,12 @@
+AUTHOR = "Lukas Doktor <ldoktor@xxxxxxxxxx>"
+NAME = "Cgroup"
+TIME = "SHORT"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "General"
+TEST_TYPE = "client"
+
+DOC = """
+This test checks basic functionality of cgroups
+"""
+
+job.run_test('cgroup')
-- 
1.7.6

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux