[KVM-autotest] virtio_console test v3.0

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

 



New version of virtio_console test is more similar to upstream C virtio_console test so it will be easier to maintain. Also we moved the scripts/console_switch.py to more sensible scripts/virtio_guest.py

There are still some virtio_console bugs which restricts some usage (mostly with console). We have created workarounds which enables us to run the tests. They are marked as FIXME comments.

It tests more virtio_console features:
[preparation]:
* Prepare for testing
* test parameters '$console_type:$data;...'
1) creates GUEST machine with virtio_ports (serialport/consoles)
2) Initiate connection; defines and verifies the virtio_ports on GUEST side.

[test_smoke]:
* Tests the basic capabilities of virtio_consoles.
* test parameters, multiple recievers allowe. '$source_console_type@$buffer_length:$destination_console_type1@buffer_length:...:$loopback_buffer_length;...'

1) POLL test (IN,OUT,HUP)
2) Read/write without connected host
3) Read in nonblocking and blocking mode
4) Basic loopback test (different from test_loopback test)

[test_loopback]:
*Creates a loopback between sender port and receiving port, send data through this connection, verify data correctness.
* test parameters '$console_type@$buffer_length:$test_duration;...'
* link checking mode is configurable by virtio_check_mode = {none, poll, select}
1) GUEST: creates loopback between specified ports
2) HOST: creates thread for sending data and storing them into verification buffer
3) HOST: creates threads for receiving data and comparing them with verification buffer
4) let it work for 60 seconds
5) Exit threads and loopback

[test_perf]:
* Measure performance for the virtio console tunnel
---< Host->Guest >---
1) GUEST: creates loopback between the port and nothing (read and forget)
2) HOST: prepare for data send (sending thread, stats, cpu loads)
3) HOST: starts sending the data in loop for specified period of time
4) HOST: stop the sending and process stats/cpu loads
5) Exit threads and loopback

---< Guest->Host >---
1) GUEST: inits sender thread
2) HOST: prepare for receiving data (recv thread, stats, cpu loads)
3) GUEST: starts sending the data
4) HOST: stop logging stats
5) GUEST: exit sending thread
6) HOST: finish receiving

Signed-off-by: Lukas Doktor <ldoktor@xxxxxxxxxx>
Signed-off-by: Jiri Zupka <jzupka@xxxxxxxxxx>
---
 client/tests/kvm/scripts/console_switch.py |  219 ---------
 client/tests/kvm/scripts/virtio_guest.py   |  571 ++++++++++++++++++++++
 client/tests/kvm/tests/virtio_console.py   |  730 +++++++++++++++++-----------
 client/tests/kvm/tests_base.cfg.sample     |    8 +-
 4 files changed, 1022 insertions(+), 506 deletions(-)
 delete mode 100644 client/tests/kvm/scripts/console_switch.py
 create mode 100644 client/tests/kvm/scripts/virtio_guest.py

diff --git a/client/tests/kvm/scripts/console_switch.py b/client/tests/kvm/scripts/console_switch.py
deleted file mode 100644
index 3df4094..0000000
--- a/client/tests/kvm/scripts/console_switch.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-"""
-Auxiliary script used to send data between ports on guests.
-
-@copyright: 2008-2009 Red Hat Inc.
-@author: Jiri Zupka (jzupka@xxxxxxxxxx)
-@author: Lukas Doktor (ldoktor@xxxxxxxxxx)
-"""
-import threading
-from threading import Thread
-import os,time,select,re,random,sys,array
-
-files = {}
-ev = threading.Event()
-threads = []
-
-DEBUGPATH="/sys/kernel/debug"
-
-
-class Switch(Thread):
-    """
-    Create a thread which sends data between ports.
-    """
-    def __init__(self, exitevent, in_files, out_files, cachesize=1):
-        """
-        @param exitevent: Event to end switch.
-        @param in_files: Array of input files.
-        @param out_files: Array of output files.
-        @param cachesize: Block to receive and send.
-        """
-        Thread.__init__(self)
-
-        self.in_files = in_files
-        self.out_files = out_files
-
-        self.cachesize = cachesize
-        self.exitevent = exitevent
-
-
-    def run(self):
-        while not self.exitevent.isSet():
-            #TODO: Why select causes trouble? :-(
-            #ret = select.select(self.in_files,[],[],1.0)
-            data = ""
-            #if not ret[0] == []:
-            for desc in self.in_files:
-                data += os.read(desc, self.cachesize)
-            for desc in self.out_files:
-                os.write(desc, data)
-
-
-class Sender(Thread):
-    """
-    Creates thread which sends random blocks of data to the destination port.
-    """
-    def __init__(self, port, length):
-        """
-        @param port: Destination port.
-        @param length: Length of the random data block.
-        """
-        Thread.__init__(self)
-        self.port = port
-        self.data = array.array('L')
-        for i in range(max(length/self.data.itemsize, 1)):
-            self.data.append(random.randrange(sys.maxint))
-
-
-    def run(self):
-        while True:
-            os.write(self.port, self.data)
-        del threads[:]
-
-
-def get_port_status():
-    """
-    Get info about ports from kernel debugfs.
-
-    @return: ports dictionary of port properties
-    """
-    ports = {}
-
-    not_present_msg = "FAIL: There's no virtio-ports dir in debugfs"
-    if not os.path.ismount(DEBUGPATH):
-        os.system('mount -t debugfs none %s' % DEBUGPATH)
-    try:
-        if not os.path.isdir('%s/virtio-ports' % DEBUGPATH):
-            print not_present_msg
-    except:
-        print not_present_msg
-    else:
-        viop_names = os.listdir('%s/virtio-ports' % DEBUGPATH)
-        for name in viop_names:
-            f = open("%s/virtio-ports/%s" % (DEBUGPATH, name), 'r')
-            port = {}
-            for line in iter(f):
-                m = re.match("(\S+): (\S+)",line)
-                port[m.group(1)] = m.group(2)
-
-            if (port['is_console'] == "yes"):
-                port["path"] = "/dev/hvc%s" % port["console_vtermno"]
-                # Console works like a serialport
-            else:
-                port["path"] = "/dev/%s" % name
-            ports[port['name']] = port
-            f.close()
-
-    return ports
-
-
-def open_device(in_files, ports):
-    """
-    Open devices and return an array of descriptors.
-
-    @param in_files: files array
-    @return: array of descriptors
-    """
-    f = []
-
-    for item in in_files:
-        name = ports[item[0]]["path"]
-        if (not item[1] == ports[item[0]]["is_console"]):
-            print ports
-            print "FAIL: Host console is not like console on guest side\n"
-
-        if (name in files):
-            f.append(files[name])
-        else:
-            try:
-                files[name] = os.open(name, os.O_RDWR)
-                if (ports[item[0]]["is_console"] == "yes"):
-                    print os.system("stty -F %s raw -echo" %
-                                    (ports[item[0]]["path"]))
-                    print os.system("stty -F %s -a" % ports[item[0]]["path"])
-                f.append(files[name])
-            except Exception as inst:
-                print "FAIL: Failed to open file %s" % name
-                raise inst
-    return f
-
-
-def start_switch(in_files,out_files,cachesize=1):
-    """
-    Start a switch thread
-    (because there is a problem with opening one file multiple times).
-
-    @param in_files: array of input files
-    @param out_files: array of output files
-    @param cachesize: cachesize
-    """
-    ports = get_port_status()
-
-    in_f = open_device(in_files, ports)
-    out_f = open_device(out_files, ports)
-
-    s = Switch(ev, in_f, out_f, cachesize)
-    s.start()
-    threads.append(s)
-
-    print "PASS: Start switch"
-
-
-def end_switches():
-    """
-    End all running data switches.
-    """
-    ev.set()
-    for th in threads:
-        print "join"
-        th.join(3.0)
-    ev.clear()
-
-    del threads[:]
-    print "PASS: End switch"
-
-
-def die():
-    """
-    Quit consoleswitch.
-    """
-    for desc in files.itervalues():
-        os.close(desc)
-    current_pid = os.getpid()
-    os.kill(current_pid, 15)
-
-
-def sender_prepare(port, length):
-    """
-    Prepares the sender thread. Requires a clean thread structure.
-    """
-    del threads[:]
-    ports = get_port_status()
-    in_f = open_device([port], ports)
-
-    threads.append(Sender(in_f[0], length))
-    print "PASS: Sender prepare"
-
-
-def sender_start():
-    """
-    Start sender data transfer. Requires sender_prepare to run first.
-    """
-    threads[0].start()
-    print "PASS: Sender start"
-
-
-def main():
-    """
-    Main (infinite) loop of console_switch.
-    """
-    print "PASS: Start"
-    end = False
-    while not end:
-        str = raw_input()
-        exec str
-
-
-if __name__ == "__main__":
-    main()
diff --git a/client/tests/kvm/scripts/virtio_guest.py b/client/tests/kvm/scripts/virtio_guest.py
new file mode 100644
index 0000000..a0f9df8
--- /dev/null
+++ b/client/tests/kvm/scripts/virtio_guest.py
@@ -0,0 +1,571 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Auxiliary script used to send data between ports on guests.
+
+@copyright: 2008-2009 Red Hat Inc.
+@author: Jiri Zupka (jzupka@xxxxxxxxxx)
+@author: Lukas Doktor (ldoktor@xxxxxxxxxx)
+"""
+#from _pydev_SimpleXMLRPCServer import fcntl
+
+"""
+TODO:
+virt.init([consoles])   # sysfs, udev, OK
+virt.open(name)
+virt.close(name)
+virt.poll(name, eventmask, timeout) # poll.register(), poll.poll(),
+return event
+virt.send(name, length) # host disconnected
+virt.recv(name, length) # host disconnected
+virt.blocking(name, true)   # true = blocking, false = nonblocking
+virt.loopback(in_names, out_names, type="None")  # use select/poll
+"""
+
+import threading
+from threading import Thread
+import os, time, select, re, random, sys, array, fcntl, array, subprocess
+
+DEBUGPATH = "/sys/kernel/debug"
+SYSFSPATH = "/sys/class/virtio-ports/"
+
+
+class virtio_guest():
+
+    LOOP_NONE = 0
+    LOOP_POLL = 1
+    LOOP_SELECT = 2
+
+    def __init__(self):
+        self.files = {}
+        self.exit_thread = threading.Event()
+        self.threads = []
+        self.ports = {}
+
+    def _readfile(self, name):
+        """
+        Read file and return content as string
+
+        @param name: Name of file
+        @return: Content of file as string
+        """
+        out = ""
+        try:
+            f = open(name, "r")
+            out = f.read()
+            f.close()
+        except:
+            print "FAIL: Cannot open file %s" % (name)
+
+        return out
+
+    def _get_port_status(self):
+        """
+        Get info about ports from kernel debugfs.
+
+        @return: Ports dictionary of port properties
+        """
+        ports = {}
+        not_present_msg = "FAIL: There's no virtio-ports dir in debugfs"
+        if (not os.path.ismount(DEBUGPATH)):
+            os.system('mount -t debugfs none %s' % (DEBUGPATH))
+        try:
+            if not os.path.isdir('%s/virtio-ports' % (DEBUGPATH)):
+                print not_present_msg
+        except:
+            print not_present_msg
+        else:
+            viop_names = os.listdir('%s/virtio-ports' % (DEBUGPATH))
+            for name in viop_names:
+                f = open("%s/virtio-ports/%s" % (DEBUGPATH, name), 'r')
+                port = {}
+                for line in iter(f):
+                    m = re.match("(\S+): (\S+)", line)
+                    port[m.group(1)] = m.group(2)
+
+                if (port['is_console'] == "yes"):
+                    port["path"] = "/dev/hvc%s" % (port["console_vtermno"])
+                    # Console works like a serialport
+                else:
+                    port["path"] = "/dev/%s" % name
+
+                if (not os.path.exists(port['path'])):
+                    print "FAIL: %s not exist" % port['path']
+
+                sysfspath = SYSFSPATH + name
+                if (not os.path.isdir(sysfspath)):
+                    print "FAIL: %s not exist" % (sysfspath)
+
+                info_name = sysfspath + "/name"
+                port_name = self._readfile(info_name).strip()
+                if (port_name != port["name"]):
+                    print "FAIL: Port info not match \n%s - %s\n%s - %s" \
+                    % (info_name , port_name, \
+                       "%s/virtio-ports/%s" % (DEBUGPATH, name), port["name"])
+
+                ports[port['name']] = port
+                f.close()
+
+        return ports
+
+    def init(self, in_files):
+        """
+        Init and check port properties
+        """
+        self.ports = self._get_port_status()
+
+        for item in in_files:
+            if (item[1] != self.ports[item[0]]["is_console"]):
+                print self.ports
+                print "FAIL: Host console is not like console on guest side\n"
+        print "PASS: Init and check virtioconsole files in system."
+
+    class switch(Thread):
+        """
+        Create a thread which sends data between ports.
+        """
+        def __init__ (self, in_files, out_files, event, \
+                      cachesize=1024, method=0):
+            """
+            @param in_files: Array of input files
+            @param out_files: Array of output files
+            @param method: Method of read/write access
+            @param cachesize: Block to receive and send
+            """
+            Thread.__init__(self)
+
+            self.in_files = in_files
+            self.out_files = out_files
+            self.exit_thread = event
+            self.method = method
+
+            self.cachesize = cachesize
+
+        def _none_mode(self):
+            """
+            Read and write to device in blocking mode
+            """
+            data = ""
+            while not self.exit_thread.isSet():
+                data = ""
+                for desc in self.in_files:
+                    data += os.read(desc, self.cachesize)
+                if data != "":
+                    for desc in self.out_files:
+                        os.write(desc, data)
+
+        def _poll_mode(self):
+            """
+            Read and write to device in polling mode
+            """
+
+            pi = select.poll()
+            po = select.poll()
+
+            for fd in self.in_files:
+                pi.register(fd, select.POLLIN)
+
+            for fd in self.out_files:
+                po.register(fd, select.POLLOUT)
+            readyf = []
+            data = ""#array.array('B')
+            while not self.exit_thread.isSet():
+                data = ""
+                t_out = self.out_files
+
+                readyf = pi.poll(1.0)
+                for i in readyf:
+                    try:
+                        data += os.read(desc, self.cachesize)
+                    except EOFError:
+                        pass
+
+                if data.count(x):
+                    readyf = []
+                    while (len(t_out) != len(readyf)) and \
+                            not self.exit_thread.isSet():
+                        readyf = po.poll(1.0)
+                    for desc in t_out:
+                        os.write(desc, data)
+
+
+
+        def _select_mode(self):
+            """
+            Read and write to device in selecting mode
+            """
+            data = ""
+            ret = []
+            while not self.exit_thread.isSet():
+                #TODO: Why select causes trouble? :-(
+                ret = select.select(self.in_files, [], [], 1.0)
+                data = ""
+                if ret[0] != []:
+                    for desc in ret[0]:
+                        data += os.read(desc, self.cachesize)
+                if data != "":
+                    ret = select.select([], self.out_files, [], 1.0)
+                    while (len(self.out_files) != len(ret[1])) and \
+                            not self.exit_thread.isSet():
+                        ret = select.select([], self.out_files, [], 1.0)
+                    for desc in ret[1]:
+                        os.write(desc, data)
+
+        def run(self):
+            if (self.method == virtio_guest.LOOP_POLL):
+                self._poll_mode()
+            elif (self.method == virtio_guest.LOOP_SELECT):
+                self._select_mode()
+            else:
+                self._none_mode()
+
+        def _poll_mode(self):
+            """
+            Read and write to device in polling mode
+            """
+
+            pi = select.poll()
+            po = select.poll()
+
+            for fd in self.in_files:
+                pi.register(fd, select.POLLIN)
+
+            for fd in self.out_files:
+                po.register(fd, select.POLLOUT)
+
+            while not self.exit_thread.isSet():
+                data = ""
+                t_out = self.out_files
+
+                readyf = pi.poll(1.0)
+                for i in readyf:
+                    data += os.read(i[0], self.cachesize)
+
+                if data != "":
+                    while (len(t_out) != len(readyf)) and \
+                            not self.exit_thread.isSet():
+                        readyf = po.poll(1.0)
+                    for desc in t_out:
+                        os.write(desc, data)
+
+
+
+        def _select_mode(self):
+            """
+            Read and write to device in selecting mode
+            """
+            while not self.exit_thread.isSet():
+                #TODO: Why select causes trouble? :-(
+                ret = select.select(self.in_files, [], [], 1.0)
+                data = ""
+                if ret[0] != []:
+                    for desc in ret[0]:
+                        data += os.read(desc, self.cachesize)
+                if data != "":
+                    ret = select.select([], self.out_files, [], 1.0)
+                    while (len(self.out_files) != len(ret[1])) and \
+                            not self.exit_thread.isSet():
+                        ret = select.select([], self.out_files, [], 1.0)
+                    for desc in ret[1]:
+                        os.write(desc, data)
+
+        def run(self):
+            if (self.method == virtio_guest.LOOP_POLL):
+                self._poll_mode()
+            elif (self.method == virtio_guest.LOOP_SELECT):
+                self._select_mode()
+            else:
+                self._none_mode()
+
+    class sender(Thread):
+        """
+        Creates thread which sends random blocks of data to the destination
+        port.
+        """
+        def __init__(self, port, event, length):
+            """
+            @param port: Destination port
+            @param length: Length of the random data block
+            """
+            Thread.__init__(self)
+            self.port = port
+            self.exit_thread = event
+            self.data = array.array('L')
+            for i in range(max(length / self.data.itemsize, 1)):
+                self.data.append(random.randrange(sys.maxint))
+
+        def run(self):
+            while not self.exit_thread.isSet():
+                os.write(self.port, self.data)
+
+
+    def _open(self, in_files):
+        """
+        Open devices and return array of descriptors
+
+        @param in_files: Files array
+        @return: Array of descriptor
+        """
+
+        f = []
+
+        for item in in_files:
+            name = self.ports[item]["path"]
+            if (name in self.files):
+                f.append(self.files[name])
+            else:
+                try:
+                    self.files[name] = os.open(name, os.O_RDWR)
+                    if (self.ports[item]["is_console"] == "yes"):
+                        print os.system("stty -F %s raw -echo" % (name))
+                        print os.system("stty -F %s -a" % (name))
+                    f.append(self.files[name])
+                except Exception as inst:
+                    print "FAIL: Failed to open file %s" % (name)
+                    raise inst
+        return f
+
+
+    def poll(self, port, expected, timeout=500):
+        """
+        Pool event from device and print event like text
+
+        @param file: Device
+        """
+
+        in_f = self._open([port])
+
+        p = select.poll()
+        p.register(in_f[0])
+
+        mask = p.poll(timeout)
+
+        str = ""
+        if (mask[0][1] & select.POLLIN):
+            str += "IN "
+        if (mask[0][1] & select.POLLPRI):
+            str += "PRI IN "
+        if (mask[0][1] & select.POLLOUT):
+            str += "OUT "
+        if (mask[0][1] & select.POLLERR):
+            str += "ERR "
+        if (mask[0][1] & select.POLLHUP):
+            str += "HUP "
+        if (mask[0][1] & select.POLLMSG):
+            str += "MSG "
+
+        if (mask[0][1] & expected) == expected:
+            print "PASS: Events: " + str
+        else:
+            print "FAIL: Events: " + str
+
+
+    def blocking(self, port, mode=False):
+        """
+        Set port function mode blocking/nonblocking
+
+        @param port: port to set mode
+        @param mode: False to set nonblock mode, True for block mode
+        """
+        path = self.ports[port]["path"]
+        fd = self.files[path]
+
+        try:
+            fl = fcntl.fcntl(fd, fcntl.F_GETFL)
+            if not mode:
+                fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
+            else:
+                fcntl.fcntl(fd, fcntl.F_SETFL, fl & ~os.O_NONBLOCK)
+
+        except Exception as inst:
+            print "FAIL: Setting (non)blocking mode: " + str(inst)
+            return
+
+        print "PASS: set blocking mode to %s mode" % \
+                ("blocking" if mode else "nonblocking")
+
+
+    def close(self, file):
+        """
+        Close open port
+
+        @param file: file to close
+        """
+        descriptor = None
+        path = self.ports[file]["path"]
+        if path != None:
+            if path in self.files.keys():
+                descriptor = self.files[path]
+                del self.files[path]
+        try:
+            os.close(descriptor)
+        except Exception as inst:
+            print "FAIL: Closing the file: " + str(inst)
+            return
+        print "PASS: Close"
+
+    def open(self, in_files):
+        """
+        Direct open devices.
+
+        @param in_files: Files array
+        @return: Array of descriptor
+        """
+
+        name = self.ports[in_files]["path"]
+        try:
+            self.files[name] = os.open(name, os.O_RDWR)
+            print "PASS: Open all filles correctly."
+        except Exception as inst:
+            print "%s\nFAIL: Failed open file %s" % (str(inst), name)
+
+
+    def loopback(self, in_files, out_files, cachesize=1024, mode=LOOP_NONE):
+        """
+        Function starts switch thread (because there is problem with multiple
+        open of one files).
+
+        @param in_files: Array of input files
+        @param out_files: Array of output files
+        @param cachesize: Cachesize
+        """
+
+
+        self.ports = self._get_port_status()
+
+        in_f = self._open(in_files)
+        out_f = self._open(out_files)
+
+        s = self.switch(in_f, out_f, self.exit_thread, cachesize, mode)
+        s.start()
+        self.threads.append(s)
+        print "PASS: Start switch"
+
+    def exit_threads(self):
+        """
+        Function end all running data switch.
+        """
+        self.exit_thread.set()
+        for th in self.threads:
+            print "join"
+            th.join()
+        self.exit_thread.clear()
+
+        del self.threads[:]
+        for desc in self.files.itervalues():
+            os.close(desc)
+        self.files.clear()
+        print "PASS: All threads finished."
+
+    def die(self):
+        """
+        Quit consoleswitch.
+        """
+        self.exit_threads()
+        exit()
+
+
+    def send_loop_init(self, port, length):
+        """
+        Prepares the sender thread. Requires clean thread structure.
+        """
+        self.ports = self._get_port_status()
+        in_f = self._open([port])
+
+        self.threads.append(self.sender(in_f[0], self.exit_thread, length))
+        print "PASS: Sender prepare"
+
+
+    def send_loop(self):
+        """
+        Start sender data transfer. Requires senderprepare run firs.
+        """
+        self.threads[0].start()
+        print "PASS: Sender start"
+
+
+    def send(self, port, length=1, mode=True):
+        """
+        Send a data of some length
+
+        @param port: Port to write data
+        @param length: Length of data
+        @param mode: True = loop mode, False = one shoot mode
+        """
+        in_f = self._open([port])
+
+        data = ""
+        while len(data) < length:
+            data += "%c" % random.randrange(255)
+        try:
+            writes = os.write(in_f[0], data)
+        except Exception as inst:
+            print inst
+        if not writes:
+            writes = 0
+        if mode:
+            while (writes < length):
+                try:
+                    writes += os.write(in_f[0], data)
+                except Exception as inst:
+                    print inst
+        if writes >= length:
+            print "PASS: Send data length %d" % writes
+        else:
+            print "FAIL: Partial send: desired %d, transfered %d" \
+                    % (length, writes)
+
+
+    def recv(self, port, length=1, buffer=1024, mode=True):
+        """
+        Recv a data of some length
+
+        @param port: Port to write data
+        @param length: Length of data
+        @param mode: True = loop mode, False = one shoot mode
+        """
+        in_f = self._open([port])
+
+        recvs = ""
+        try:
+            recvs = os.read(in_f[0], buffer)
+        except Exception as inst:
+            print inst
+        if mode:
+            while (len(recvs) < length):
+                try:
+                    recvs += os.read(in_f[0], buffer)
+                except Exception as inst:
+                    print inst
+        if len(recvs) >= length:
+            print "PASS: Recv data length %d" % len(recvs)
+        else:
+            print "FAIL: Partial recv: desired %d, transfered %d" \
+                    % (length, len(recvs))
+
+def compile():
+    """
+    Compile virtio_guest.py to speed up.
+    """
+    import py_compile
+    py_compile.compile(sys.path[0] + "/virtio_guest.py")
+    print "PASS: compile"
+    exit(0)
+
+def main():
+    """
+    Main (infinite) loop of virtio_guest.
+    """
+    if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
+        compile()
+
+    virt = virtio_guest()
+    print "PASS: Start"
+
+    while True:
+        str = raw_input()
+        exec str
+
+
+if __name__ == "__main__":
+    main()
diff --git a/client/tests/kvm/tests/virtio_console.py b/client/tests/kvm/tests/virtio_console.py
index 2e22f2f..058bb94 100644
--- a/client/tests/kvm/tests/virtio_console.py
+++ b/client/tests/kvm/tests/virtio_console.py
@@ -1,10 +1,10 @@
-import socket, random, array, sys, os, tempfile, shutil, threading, select, re
-import logging, time
-from threading import Thread
+import array, logging, os, random, re, select, shutil, socket, sys, tempfile
+import threading, time
 from collections import deque
-from autotest_lib.client.common_lib import error
-import kvm_subprocess, kvm_test_utils, kvm_utils, kvm_preprocessing
+from threading import Thread
 
+import kvm_subprocess, kvm_test_utils, kvm_utils, kvm_preprocessing
+from autotest_lib.client.common_lib import error
 
 def run_virtio_console(test, params, env):
     """
@@ -28,139 +28,162 @@ def run_virtio_console(test, params, env):
         """
         Random data sender thread.
         """
-        def __init__(self, port, length, buffers, blocklen=32):
-            """
-            @param port: Destination port.
-            @param length: Amount of data we want to send.
-            @param buffers: Buffers for the control data (FIFOs).
-            @param blocklen: Block length.
-            """
-            Thread.__init__(self)
-            self.ExitState = True
-            self.port = port[0]
-            self.length = length
-            self.buffers = buffers
-            self.blocklen = blocklen
-
-
-        def run(self):
-            logging.debug("th_send %s: run", self.getName())
-            idx = 0
-            while idx < self.length:
-                ret = select.select([], [self.port], [], 1.0)
-                if ret:
-                    # Generate blocklen of random data add them to the FIFO
-                    # and send tham over virtio_console
-                    buf = ""
-                    for i in range(min(self.blocklen, self.length-idx)):
-                        ch = "%c" % random.randrange(255)
-                        buf += ch
-                        for buffer in self.buffers:
-                            buffer.append(ch)
-                    idx += len(buf)
-                    self.port.sendall(buf)
-            logging.debug("th_send %s: exit(%d)", self.getName(), idx)
-            if idx >= self.length:
-                self.ExitState = False
-
-
-    class th_send_loop(Thread):
-        """
-        Send data in the loop until the exit event is set
-        """
         def __init__(self, port, data, event):
             """
-            @param port: destination port
-            @param data: the data intend to be send in a loop
-            @param event: exit event
+            @param port: Destination port.
+            @param data: The data intend to be send in a loop.
+            @param event: Exit event.
             """
             Thread.__init__(self)
             self.port = port
+            # FIXME: socket.send(data>>127998) without read blocks thread
+            if len(data) > 102400:
+                data = data[0:102400]
+                logging.error("Data are too long, using only first %d bytes",
+                              len(data))
             self.data = data
             self.exitevent = event
             self.idx = 0
-
-
         def run(self):
-            logging.debug("th_send_loop %s: run", self.getName())
+            logging.debug("th_send %s: run", self.getName())
             while not self.exitevent.isSet():
                 self.idx += self.port.send(self.data)
-            logging.debug("th_send_loop %s: exit(%d)", self.getName(),
+            logging.debug("th_send %s: exit(%d)", self.getName(),
                           self.idx)
 
-
-    class th_recv(Thread):
+    class th_send_check(Thread):
         """
-        Random data reciever/checker thread
+        Random data sender thread
         """
-        def __init__(self, port, buffer, length, blocklen=32):
+        def __init__(self, port, event, queues, blocklen=1024):
             """
-            @param port: source port
-            @param buffer: control data buffer (FIFO)
-            @param length: amount of data we want to receive
-            @param blocklen: block length
+            @param port: Destination port
+            @param event: Exit event
+            @param queues: Queues for the control data (FIFOs)
+            @param blocklen: Block length
             """
             Thread.__init__(self)
-            self.ExitState = True
-            self.port = port[0]
-            self.buffer = buffer
-            self.length = length
+            self.port = port
+            self.queues = queues
+            # FIXME: socket.send(data>>127998) without read blocks thread
+            if blocklen > 102400:
+                blocklen = 102400
+                logging.error("Data are too long, using blocklen = %d",
+                              blocklen)
             self.blocklen = blocklen
-
+            self.exitevent = event
+            self.idx = 0
 
         def run(self):
-            logging.debug("th_recv %s: run", self.getName())
-            idx = 0
-            while idx < self.length:
-                ret = select.select([self.port], [], [], 1.0)
-                if ret:
-                    buf = self.port.recv(self.blocklen)
-                    if buf:
-                        # Compare the recvd data with the control data
-                        for ch in buf:
-                            if not ch == self.buffer.popleft():
-                                error.TestFail("th_recv: incorrect data")
-                    idx += len(buf)
-            logging.debug("th_recv %s: exit(%d)", self.getName(), idx)
-            if (idx >= self.length) and (len(self.buffer) == 0):
-                self.ExitState = False
+            logging.debug("th_send_check %s: run", self.getName())
+            too_much_data = False
+            while not self.exitevent.isSet():
+                # FIXME: workaround the problem with qemu-kvm stall when too
+                # much data send without receiving
+                for queue in self.queues:
+                    while not self.exitevent.isSet() and len(queue) > 1048576:
+                        too_much_data = True
+                        time.sleep(0.1)
+                ret = select.select([], [self.port], [], 1.0)
+                if ret[1]:
+                    # Generate blocklen of random data add them to the FIFO
+                    # and send them over virtio_console
+                    buf = ""
+                    for i in range(self.blocklen):
+                        ch = "%c" % random.randrange(255)
+                        buf += ch
+                        for queue in self.queues:
+                            queue.append(ch)
+                    target = self.idx + self.blocklen
+                    while not self.exitevent.isSet() and self.idx < target:
+                        idx = self.port.send(buf)
+                        buf = buf[idx:]
+                        self.idx += idx
+            logging.debug("th_send_check %s: exit(%d)", self.getName(),
+                          self.idx)
+            if too_much_data:
+                logging.error("th_send_check: workaround the 'too_much_data'"
+                              "bug")
 
 
-    class th_recv_null(Thread):
+    class th_recv(Thread):
         """
-        Receives data and throws it away.
+        Recieves data and throw them away
         """
-        def __init__(self, port, event, blocklen=32):
+        def __init__(self, port, event, blocklen=1024):
             """
             @param port: Data source port.
             @param event: Exit event.
             @param blocklen: Block length.
             """
             Thread.__init__(self)
-            self.port = port[0]
+            self.port = port
             self._port_timeout = self.port.gettimeout()
             self.port.settimeout(0.1)
             self.exitevent = event
             self.blocklen = blocklen
             self.idx = 0
-
-
         def run(self):
-            logging.debug("th_recv_null %s: run", self.getName())
+            logging.debug("th_recv %s: run", self.getName())
             while not self.exitevent.isSet():
-                # Workaround, it didn't work with select :-/
+                # TODO: Workaround, it didn't work with select :-/
                 try:
                     self.idx += len(self.port.recv(self.blocklen))
                 except socket.timeout:
                     pass
             self.port.settimeout(self._port_timeout)
-            logging.debug("th_recv_null %s: exit(%d)", self.getName(),
+            logging.debug("th_recv %s: exit(%d)", self.getName(), self.idx)
+
+
+    class th_recv_check(Thread):
+        """
+        Random data reciever/checker thread
+        """
+        def __init__(self, port, buffer, event, blocklen=1024):
+            """
+            @param port: Source port.
+            @param buffer: Control data buffer (FIFO).
+            @param length: Amount of data we want to receive.
+            @param blocklen: Block length.
+            """
+            Thread.__init__(self)
+            self.port = port
+            self.buffer = buffer
+            self.exitevent = event
+            self.blocklen = blocklen
+            self.idx = 0
+        def run(self):
+            logging.debug("th_recv_check %s: run", self.getName())
+            while not self.exitevent.isSet():
+                ret = select.select([self.port], [], [], 1.0)
+                if ret and (not self.exitevent.isSet()):
+                    buf = self.port.recv(self.blocklen)
+                    if buf:
+                        # Compare the recvd data with the control data
+                        for ch in buf:
+                            ch_ = self.buffer.popleft()
+                            if not ch == ch_:
+                                self.exitevent.set()
+                                logging.error("Failed to recv %dth character",
+                                              self.idx)
+                                logging.error("%s != %s", repr(ch), repr(ch_))
+                                logging.error("Recv = %s", repr(buf))
+                                # sender might change the buffer :-(
+                                time.sleep(1)
+                                ch_ = ""
+                                for buf in self.buffer:
+                                    ch_ += buf
+                                logging.error("Queue = %s", repr(ch_))
+                                raise error.TestFail("th_recv_check: incorrect "
+                                                     "data")
+                        self.idx += len(buf)
+            logging.debug("th_recv_check %s: exit(%d)", self.getName(),
                           self.idx)
 
     seqTest = threading.Lock();
 
 
-    class average_cpu_load():
+    class cpu_load():
         """
         Get average cpu load between start and get_load
         """
@@ -198,10 +221,11 @@ def run_virtio_console(test, params, env):
                     return load
 
 
-        def start ( self ):
+        def start (self):
             """
             Start CPU usage measurement
             """
+            self.old_load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
             self.startTime = time.time();
             self._get_cpu_load()
 
@@ -209,10 +233,11 @@ def run_virtio_console(test, params, env):
         def get_load(self):
             """
             Get and reset CPU usage
+
             @return: return group cpu (user[%], system[%], sum[%], testTime[s])
             """
             self.endTime = time.time()
-            testTime =  self.endTime-self.startTime
+            testTime = self.endTime - self.startTime
             load = self._get_cpu_load()
 
             user = load[0] / testTime
@@ -222,7 +247,7 @@ def run_virtio_console(test, params, env):
             return (user, system, sum, testTime)
 
 
-    class average_process_cpu_load():
+    class pid_load():
         """
         Get average process cpu load between start and get_load
         """
@@ -234,7 +259,7 @@ def run_virtio_console(test, params, env):
             self.name = name
 
 
-        def _get_cpu_load(self,pid):
+        def _get_cpu_load(self, pid):
             # Let's see if we can calc system load.
             try:
                 f = open("/proc/%d/stat" % (pid), "r")
@@ -249,19 +274,19 @@ def run_virtio_console(test, params, env):
                 load_values = reg.findall(line)
                 del load_values[0:11]
                 # extract values from /proc/stat
-                load = [0,0]
+                load = [0, 0]
                 for i in range(2):
-                    load[i] = int(load_values[i])-self.old_load[i]
+                    load[i] = int(load_values[i]) - self.old_load[i]
 
                 for i in range(2):
                     self.old_load[i] = int(load_values[i])
                 return load
 
-
-        def start ( self ):
+        def start (self):
             """
             Start CPU usage measurement
             """
+            self.old_load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
             self.startTime = time.time();
             self._get_cpu_load(self.pid)
 
@@ -274,7 +299,7 @@ def run_virtio_console(test, params, env):
                     (pid, user[%], system[%], sum[%], testTime[s])
             """
             self.endTime = time.time()
-            testTime =  self.endTime - self.startTime
+            testTime = self.endTime - self.startTime
             load = self._get_cpu_load(self.pid)
 
             user = load[0] / testTime
@@ -288,12 +313,12 @@ def run_virtio_console(test, params, env):
         """
         Print load in tabular mode.
 
-        @param process: list of process statistic tuples
-        @param system: tuple of system cpu usage
+        @param process: List of process statistic tuples.
+        @param system: Tuple of system cpu usage.
         """
 
         logging.info("%-10s %6s %5s %5s %5s %11s",
-                     "NAME", "PID","USER","SYS","SUM","TIME")
+                     "NAME", "PID", "USER", "SYS", "SUM", "TIME")
         for pr in process:
             logging.info("%-10s %6d %4.0f%% %4.0f%% %4.0f%% %10.3fs" % pr)
         logging.info("TOTAL:     ------ %4.0f%% %4.0f%% %4.0f%% %10.3fs" %
@@ -302,64 +327,96 @@ def run_virtio_console(test, params, env):
 
     def process_stats(stats, scale=1.0):
         """
-        Process and print the stats.
+        Process and print the statistic.
 
         @param stats: List of measured data.
         """
         if not stats:
             return None
-        for i in range((len(stats)-1),0,-1):
-            stats[i] = stats[i] - stats[i-1]
+        for i in range((len(stats) - 1), 0, -1):
+            stats[i] = stats[i] - stats[i - 1]
             stats[i] /= scale
         stats[0] /= scale
         stats = sorted(stats)
         return stats
 
 
-    def _start_console_switch(vm, timeout=2):
+    def init_guest(vm, timeout=2):
         """
-        Execute console_switch.py on guest, wait until it is initialized.
+        Execute virtio_guest.py on guest, wait until it is initialized.
 
         @param vm: Informations about the guest.
         @param timeout: Timeout that will be used to verify if the script
                 started properly.
         """
-        logging.debug("Starting console_switch.py on guest %s", vm[0].name)
-        vm[1].sendline("python /tmp/console_switch.py")
+        logging.debug("compile virtio_guest.py on guest %s", vm[0].name)
+        vm[1].sendline("python -OO /tmp/virtio_guest.py -c &&"
+                       "echo -n 'PASS: Compile virtio_guest finished' ||"
+                       "echo -n 'FAIL: Compile virtio_guest failed'")
         (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
                                                            timeout)
         if match == 1 or match is None:
             raise error.TestFail("Command console_switch.py on guest %s failed."
                                  "\nreturn code: %s\n output:\n%s" %
                                  (vm[0].name, match, data))
+        logging.debug("Starting virtio_guest.py on guest %s", vm[0].name)
+        vm[1].sendline("python /tmp/virtio_guest.pyo &&"
+                       "echo -n 'PASS: virtio_guest finished' ||"
+                       "echo -n 'FAIL: virtio_guest failed'")
+        (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
+                                                           timeout)
+        if match == 1 or match is None:
+            raise error.TestFail("Command console_switch.py on guest %s failed."
+                                 "\nreturn code: %s\n output:\n%s" %
+                                 (vm[0].name, match, data))
+        # Let the system rest
+        time.sleep(2)
 
 
-    def _execute_console_switch(command, vm, timeout=2):
+    def _on_guest(command, vm, timeout=2):
         """
         Execute given command inside the script's main loop, indicating the vm
         the command was executed on.
 
         @param command: Command that will be executed.
-        @param vm: Informations about the guest
+        @param vm: Informations about the guest.
         @param timeout: Timeout used to verify expected output.
 
         @return: Tuple (match index, data)
         """
-        logging.debug("Executing '%s' on console_switch.py loop, vm: %s,"
+        logging.debug("Executing '%s' on virtio_guest.py loop, vm: %s," +
                       "timeout: %s", command, vm[0].name, timeout)
         vm[1].sendline(command)
-        (match, data) = vm[1].read_until_last_line_matches(["PASS:","FAIL:"],
-                                                             timeout)
+        (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:" \
+                                                         "[Failed to execute]"], \
+                                                          timeout)
+        return (match, data)
+
+
+    def on_guest(command, vm, timeout=2):
+        """
+        Wrapper around the _on_guest command which executes the command on
+        guest. Unlike _on_guest command when the command fails it raises the
+        test error.
+
+        @param command: Command that will be executed.
+        @param vm: Informations about the guest.
+        @param timeout: Timeout used to verify expected output.
+
+        @return: Tuple (match index, data)
+        """
+        match, data = _on_guest(command, vm, timeout)
         if match == 1 or match is None:
-            raise error.TestFail("Failed to execute '%s' on console_switch.py, "
+            raise error.TestFail("Failed to execute '%s' on virtio_guest.py, "
                                  "vm: %s, output:\n%s" %
                                  (command, vm[0].name, data))
+
         return (match, data)
 
 
     def socket_readall(sock, read_timeout, mesagesize):
         """
-       Read everything from the socket.
+        Read everything from the socket
 
         @param sock: socket
         @param read_timeout: read timeout
@@ -380,14 +437,44 @@ def run_virtio_console(test, params, env):
         return message
 
 
+    def _guest_exit_threads(vm, send_pts, recv_pts):
+        """
+        Safely executes on_guest("virt.exit_threads()") using workaround of
+        the stucked thread in loopback in mode=virt.LOOP_NONE .
+
+        @param vm: Informations about the guest.
+        @param send_pts: list of possible send sockets we need to work around
+        @param recv_pts: list of possible recv sockets we need to read-out
+        """
+        # in LOOP_NONE mode it might stuck in read/write
+        match, tmp = _on_guest("virt.exit_threads()", vm, 10)
+        if match == None:
+            logging.debug("Workaround the stucked thread on Guest")
+            # Thread is stucked in read/write
+            for send_pt in send_pts:
+                send_pt[0].sendall(".")
+        elif match != 0:
+            # Something else
+            raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n"
+                                 % (match, tmp))
+
+        # Read-out all remaining data
+        for recv_pt in recv_pts:
+            while select.select([recv_pt[0]], [], [], 0.1)[0]:
+                recv_pt[0].recv(1024)
+
+        # This will cause fail in case anything went wrong.
+        on_guest("print 'PASS: nothing'", vm, 10)
+
+
     def _vm_create(no_console=3, no_serialport=3):
         """
         Creates the VM and connects the specified number of consoles and serial
         ports.
 
-        @param no_console: number of desired virtconsoles
-        @param no_serialport: number of desired virtserialports
-        @return tuple with (guest information, consoles information)
+        @param no_console: Number of desired virtconsoles.
+        @param no_serialport: Number of desired virtserialports.
+        @return tupple with (guest information, consoles information)
             guest informations = [vm, session, tmp_dir]
             consoles informations = [consoles[], serialports[]]
         """
@@ -398,24 +485,24 @@ def run_virtio_console(test, params, env):
             params['extra_params'] = ''
         params['extra_params'] += " -device virtio-serial"
 
-        for i in range(0, no_console):
-            params['extra_params'] += (" -chardev socket,path=%s/%d,id=c%d,"
+        for i in  range(0, no_console):
+            params['extra_params'] += (" -chardev socket,path=%s/%d,id=%d,"
                                        "server,nowait" % (tmp_dir, i, i))
-            params['extra_params'] += (" -device virtconsole,chardev=c%d,"
-                                       "name=org.fedoraproject.console.%d,"
-                                       "id=c%d" % (i, i, i))
+            params['extra_params'] += (" -device virtconsole,chardev=%d,"
+                                      "name=console-%d,id=c%d" % (i, i, i))
 
         for i in  range(no_console, no_console + no_serialport):
-            params['extra_params'] += (" -chardev socket,path=%s/%d,id=p%d,"
+            params['extra_params'] += (" -chardev socket,path=%s/%d,id=%d,"
                                        "server,nowait" % (tmp_dir, i, i))
-            params['extra_params'] += (" -device virtserialport,chardev=p%d,"
-                                       "name=org.fedoraproject.data.%d,id=p%d" %
-                                       (i, i, i))
+            params['extra_params'] += (" -device virtserialport,chardev=%d,"
+                                       "name=serialport-%d,id=p%d" % (i, i, i))
+
 
         logging.debug("Booting first guest %s", params.get("main_vm"))
         kvm_preprocessing.preprocess_vm(test, params, env,
                                         params.get("main_vm"))
 
+
         vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
 
         session = kvm_test_utils.wait_for_login(vm, 0,
@@ -426,12 +513,11 @@ def run_virtio_console(test, params, env):
         for i in range(0, no_console):
             sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             sock.connect("%s/%d" % (tmp_dir, i))
-            consoles.append([sock, "org.fedoraproject.console.%d" % i, "yes"])
-
+            consoles.append([sock, "console-%d" % i, "yes"])
         for i in range(no_console, no_console + no_serialport):
             sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             sock.connect("%s/%d" % (tmp_dir, i))
-            serialports.append([sock, "org.fedoraproject.data.%d" % i, "no"])
+            serialports.append([sock, "serialport-%d" % i, "no"])
 
         return [vm, session, tmp_dir], [consoles, serialports]
 
@@ -440,15 +526,15 @@ def run_virtio_console(test, params, env):
         """
         Virtio console smoke test.
 
-        Creates loopback on the vm machine between the ports[>=2] provided and
-        sends the data
+        Tests the basic functionalities (poll, read/write with and without
+        connected host, etc.
 
         @param vm: target virtual machine [vm, session, tmp_dir]
         @param consoles: a field of virtio ports with the minimum of 2 items
         @param params: test parameters '$console_type:$data;...'
         """
-        logging.info("Smoke test: Send data on the sender port, "
-                     "verify data integrity on the receiving port")
+        logging.info("Smoke test: Tests the basic capabilities of "
+                     "virtio_consoles.")
         # PREPARE
         for param in params.split(';'):
             if not param:
@@ -462,23 +548,118 @@ def run_virtio_console(test, params, env):
             param = (param[0] == 'serialport')
             send_pt = consoles[param][0]
             recv_pt = consoles[param][1]
-            _start_console_switch(vm, 10.0)
 
             # TEST
-            _execute_console_switch('start_switch([%s], [%s])' %
-                                   (str(send_pt[1:3]), str(recv_pt[1:3])),
-                                   vm, 2.0)
-
+            # Poll (OUT)
+            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLOUT), vm,
+                     2)
+
+            # Poll (IN, OUT)
+            send_pt[0].sendall("test")
+            for test in [select.POLLIN, select.POLLOUT]:
+                on_guest("virt.poll('%s', %s)" % (send_pt[1], test), vm, 2)
+
+            # Poll (IN HUP)
+            # I store the socket informations and close the socket
+            sock = send_pt[0]
+            send_pt[0] = sock.getpeername()
+            sock.shutdown(2)
+            sock.close()
+            del sock
+            for test in [select.POLLIN, select.POLLHUP]:
+                on_guest("virt.poll('%s', %s)" % (send_pt[1], test), vm, 2)
+
+            # Poll (HUP)
+            on_guest("virt.recv('%s', 4, 1024, False)" % (send_pt[1]), vm, 2)
+            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLHUP), vm,
+                     2)
+
+            # Reconnect the socket
+            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            sock.connect(send_pt[0])
+            send_pt[0] = sock
+            # Redefine socket in consoles
+            consoles[param][0] = send_pt
+            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLOUT), vm,
+                     2)
+
+            # Read/write without host connected
+            # I store the socket informations and close the socket
+            sock = send_pt[0]
+            send_pt[0] = sock.getpeername()
+            sock.shutdown(2)
+            sock.close()
+            del sock
+            # Read should pass
+            on_guest("virt.recv('%s', 0, 1024, False)" % send_pt[1], vm, 2)
+            # Write should timed-out
+            match, tmp = _on_guest("virt.send('%s', 10, False)"
+                                    % send_pt[1], vm, 2)
+            if match != None:
+                raise error.TestFail("Read on guest while host disconnected "
+                                     "didn't timed out.\nOutput:\n%s"
+                                     % tmp)
+            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            sock.connect(send_pt[0])
+            send_pt[0] = sock
+            # Redefine socket in consoles
+            consoles[param][0] = send_pt
+            if (send_pt[0].recv(1024) < 10):
+                raise error.TestFail("Didn't received data from guest")
+            # Now the _on_guest("virt.send('%s'... command should be finished
+            on_guest("print 'PASS: nothing'", vm, 2)
+
+            # Non-blocking mode
+            on_guest("virt.blocking('%s', False)" % send_pt[1], vm, 2)
+            # Recv should return FAIL with 0 received data
+            match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)"
+                                    % send_pt[1], vm, 2)
+            if match == 0:
+                raise error.TestFail("Received data even when non were sent\n"
+                                     "Data:\n%s" % tmp)
+            elif match == None:
+                raise error.TestFail("Timed out, probably in blocking mode\n"
+                                     "Data:\n%s" % tmp)
+            elif match != 1:
+                raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n"
+                                     % (match, tmp))
+            send_pt[0].sendall("1234567890")
+            on_guest("virt.recv('%s', 10, 1024, False)" % send_pt[1], vm, 2)
+
+            # Blocking mode
+            on_guest("virt.blocking('%s', True)" % send_pt[1], vm, 2)
+            # Recv should timed out
+            match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)"
+                                    % send_pt[1], vm, 2)
+            if match == 0:
+                raise error.TestFail("Received data even when non were sent\n"
+                                     "Data:\n%s" % tmp)
+            elif match != None:
+                raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n"
+                                     % (match, tmp))
+            send_pt[0].sendall("1234567890")
+            # Now guest received the data end escaped from the recv()
+            on_guest("print 'PASS: nothing'", vm, 2)
+
+            # Basic loopback test
+            on_guest("virt.loopback(['%s'], ['%s'], 1024, virt.LOOP_NONE)"
+                     % (send_pt[1], recv_pt[1]), vm, 2)
             send_pt[0].sendall(data)
-            d = socket_readall(recv_pt[0], 1.0, len(data))
-            if data != d:
-                raise error.TestFail("test_smoke: received data on port %s "
-                                     "does not match data sent through "
-                                     "port %s" % (recv_pt, send_pt))
-
-            vm[1].sendline('die()')
+            tmp = ""
+            i = 0
+            while i <= 10:
+                i += 1
+                ret = select.select([recv_pt[0]], [], [], 1.0)
+                if ret:
+                    tmp += recv_pt[0].recv(1024)
+                if len(tmp) >= len(data):
+                    break
+            if tmp != data:
+                raise error.TestFail("Incorrect data: '%s' != '%s'",
+                                     data, tmp)
+            _guest_exit_threads(vm, [send_pt], [recv_pt])
 
-        logging.info("test_smoke: PASS")
+        return consoles
 
 
     def test_loopback(vm, consoles, params):
@@ -492,9 +673,9 @@ def run_virtio_console(test, params, env):
         @param vm: target virtual machine [vm, session, tmp_dir]
         @param consoles: a field of virtio ports with the minimum of 2 items
         @param params: test parameters, multiple recievers allowed.
-                '$source_console_type@buffer_length:
-                 $destination_console_type1@buffer_length:...:
-                 $loopback_buffer_length;...'
+            '$source_console_type@buffer_length:
+             $destination_console_type1@$buffer_length:...:
+             $loopback_buffer_length;...'
         """
         logging.info("Loopback test: Creates a loopback between sender port "
                      "and receiving port, send data through this connection, "
@@ -517,7 +698,7 @@ def run_virtio_console(test, params, env):
             if (len(param[0].split('@')) == 2):
                 buf_len.append(int(param[0].split('@')[1]))
             else:
-                buf_len.append(32)
+                buf_len.append(1024)
             recv_pts = []
             for parm in param[1:]:
                 if (parm.isdigit()):
@@ -532,201 +713,170 @@ def run_virtio_console(test, params, env):
                 if (len(parm[0].split('@')) == 2):
                     buf_len.append(int(parm[0].split('@')[1]))
                 else:
-                    buf_len.append(32)
+                    buf_len.append(1024)
             # There must be sum(idx_*) consoles + last item as loopback buf_len
             if len(buf_len) == (idx_console + idx_serialport):
-                buf_len.append(32)
+                buf_len.append(1024)
 
             if len(recv_pts) == 0:
                 raise error.TestFail("test_loopback: incorrect recv consoles"
                                      "definition")
+
             threads = []
-            buffers = []
+            queues = []
             for i in range(0, len(recv_pts)):
-                buffers.append(deque())
+                queues.append(deque())
 
-            _start_console_switch(vm, 10.0)
-            tmp = str(recv_pts[0][1:3])
+            tmp = "'%s'" % recv_pts[0][1]
             for recv_pt in recv_pts[1:]:
-                tmp += ", " + str(recv_pt[1:3])
-            _execute_console_switch('start_switch([%s], [%s], %d)' %
-                                    (str(send_pt[1:3]), tmp, buf_len[-1]),
-                                    vm, 2.0)
+                tmp += ", '%s'" % (recv_pt[1])
+            on_guest("virt.loopback(['%s'], [%s], %d, virt.LOOP_POLL)"
+                     % (send_pt[1], tmp, buf_len[-1]), vm, 2)
+
+            exit_event = threading.Event()
 
             # TEST
-            thread = th_send(send_pt, 1048576, buffers, buf_len[0])
+            thread = th_send_check(send_pt[0], exit_event, queues, buf_len[0])
             thread.start()
             threads.append(thread)
 
             for i in range(len(recv_pts)):
-                thread = th_recv(recv_pts[i], buffers[i], 1048576,
-                                 buf_len[i+1])
+                thread = th_recv_check(recv_pts[i][0], queues[i], exit_event,
+                                       buf_len[i + 1])
                 thread.start()
                 threads.append(thread)
 
-            dead_threads = False
-            # Send + recv threads, DL 60s
-            for i in range(60):
-                for t in threads:
-                    if not t.is_alive():
-                        if t.ExitState:
-                            error.TestFail("test_loopback: send/recv thread "
-                                           "failed")
-                        dead_threads = True
-                if dead_threads:
-                    break
-                tmp = ""
-                for buf in buffers:
-                    tmp += str(len(buf)) + ", "
-                logging.debug("test_loopback: buffer length (%s)", tmp[:-2])
-                time.sleep(1)
-
-            if not dead_threads:
-                raise error.TestFail("test_loopback: send/recv timeout")
-            # at this point at least one thread died. It should be the send one.
-
-            # Wait for recv threads to finish their's work
-            for i in range(60):
-                dead_threads = True
-                for t in threads:
-                    if t.is_alive():
-                        dead_threads = False
-                # There are no living threads
-                if dead_threads:
-                    break
-                tmp = ""
-                for buf in buffers:
-                    tmp += str(len(buf)) + ", "
-                logging.debug("test_loopback: buffer length (%s)", tmp[:-2])
-                time.sleep(1)
+            time.sleep(60)
+            exit_event.set()
+            threads[0].join()
+            tmp = "%d data sent; " % threads[0].idx
+            for thread in threads[1:]:
+                thread.join()
+                tmp += "%d, " % thread.idx
+            logging.info("test_loopback: %s data received and verified",
+                         tmp[:-2])
 
-            for t in threads:
-                if t.ExitState:
-                    raise error.TestFail("test_loopback: recv thread failed")
+            # Read-out all remaining data
+            for recv_pt in recv_pts:
+                while select.select([recv_pt[0]], [], [], 0.1)[0]:
+                    recv_pt[0].recv(1024)
 
-            # At least one thread is still alive
-            if not dead_threads:
-                raise error.TestFail("test_loopback: recv timeout")
+            _guest_exit_threads(vm, [send_pt], recv_pts)
 
-            vm[1].sendline("die()")
-
-        logging.info("test_loopback: PASS")
+            del exit_event
+            del threads[:]
 
 
     def test_perf(vm, consoles, params):
         """
-        Virtio console performance test.
-
         Tests performance of the virtio_console tunel. First it sends the data
-        from host to guest and then back. It provides informations about
-        computer utilization and statistic information about the throughput.
+        from host to guest and than back. It provides informations about
+        computer utilisation and statistic informations about the troughput.
 
         @param vm: target virtual machine [vm, session, tmp_dir]
         @param consoles: a field of virtio ports with the minimum of 2 items
         @param params: test parameters:
-                '$console_type@buffer_length:$test_duration;...'
+                '$console_type@$buffer_length:$test_duration;...'
         """
         logging.info("Performance test: Measure performance for the "
-                     "virtio console tunnel")
-        # PREPARE
+                             "virtio console tunnel")
         for param in params.split(';'):
             if not param:
                 continue
-            logging.info("test_perf: params: %s", param)
+            print "test_perf: params: %s" % param
             param = param.split(':')
-            if len(param) > 1 and param[1].isdigit():
-                duration = float(param[1])
-            else:
-                duration = 30.0
+            duration = 60.0
+            if len(param) > 1:
+                try:
+                    duration = float(param[1])
+                except:
+                    pass
             param = param[0].split('@')
             if len(param) > 1 and param[1].isdigit():
                 buf_len = int(param[1])
             else:
-                buf_len = 32
-            if param[0] == "serialport":
-                port = consoles[1][0]
-            else:
-                port = consoles[0][0]
-            data = array.array("L")
-            for i in range(max((buf_len / data.itemsize), 1)):
-                data.append(random.randrange(sys.maxint))
-
-            ev = threading.Event()
-            thread = th_send_loop(port[0], data.tostring(), ev)
+                buf_len = 1024
+            param = (param[0] == 'serialport')
+            port = consoles[param][0]
 
-            _start_console_switch(vm, 10.0)
+            data = ""
+            for i in range(buf_len):
+                data += "%c" % random.randrange(255)
 
-            _execute_console_switch('start_switch([%s], [], %d)' %
-                                    (str(port[1:3]), buf_len), vm, 2.0)
+            exit_event = threading.Event()
+            slice = float(duration)/100
 
-            # TEST
-            # Host -> Guest
-            load = []
+            # HOST->GUEST
+            on_guest('virt.loopback(["%s"], [], %d, virt.LOOP_NONE)' % (
+                        port[1], buf_len), vm, 2)
+            thread = th_send(port[0], data, exit_event)
             stats = array.array('f', [])
-            slice = float(duration)/100
-            load.append(average_cpu_load())
-            load.append(average_process_cpu_load(os.getpid(), 'autotest'))
-            load.append(average_process_cpu_load(vm[0].get_pid(), 'VM'))
-            for ld in load:
-                ld.start()
+            loads = []
+            loads.append(cpu_load())
+            loads.append(pid_load(os.getpid(), 'autotest'))
+            loads.append(pid_load(vm[0].get_pid(), 'VM'))
+
+            for load in loads:
+                load.start()
             _time = time.time()
             thread.start()
             for i in range(100):
                 stats.append(thread.idx)
                 time.sleep(slice)
             _time = time.time() - _time - duration
-            print_load([load[1].get_load(), load[2].get_load()],
-                       load[0].get_load())
-            ev.set()
+            print_load([loads[1].get_load(), loads[2].get_load()],
+                       loads[0].get_load())
+            exit_event.set()
             thread.join()
+
+            _guest_exit_threads(vm, [port], [])
+
             if (_time > slice):
-                logging.error("test_perf: test ran %fs longer "
-                              "(more than 1 slice)", _time)
+                logging.error(
+                "Test ran %fs longer which is more than one slice", _time)
             else:
-                logging.debug("test_perf: test ran %fs longer "
-                              "(less than 1 slice)", _time)
-            stats = process_stats(stats[1:], slice*1024*1024)
-            logging.info("Host -> Guest [MB/s] min/med/max = %.3f/%.3f/%.3f",
+                logging.debug("Test ran %fs longer", _time)
+            stats = process_stats(stats[1:], slice*1048576)
+            logging.debug("Stats = %s", stats)
+            logging.info("Host->Guest [mb/s] min/med/max = %.3f/%.3f/%.3f",
                          stats[0], stats[len(stats)/2], stats[-1])
-            time.sleep(5)
-            vm[1].sendline("die()")
 
-            # Guest -> Host
-            _start_console_switch(vm, 10.0)
-            _execute_console_switch('sender_prepare(%s, %d)' %
-                                    (str(port[1:3]), buf_len), vm, 10)
+            del thread
+
+            # GUEST->HOST
+            exit_event.clear()
             stats = array.array('f', [])
-            ev.clear()
-            thread = th_recv_null(port, ev, buf_len)
+            on_guest("virt.send_loop_init('%s', %d)" % (port[1], buf_len),
+                     vm, 30)
+            thread = th_recv(port[0], exit_event, buf_len)
             thread.start()
-            # reset load measures
-            for ld in load:
-                ld.get_load()
-            _execute_console_switch('sender_start()', vm, 2)
+            for load in loads:
+                load.start()
+            on_guest("virt.send_loop()", vm, 2)
             _time = time.time()
             for i in range(100):
                 stats.append(thread.idx)
                 time.sleep(slice)
             _time = time.time() - _time - duration
-            print_load([load[1].get_load(), load[2].get_load()],
-                       load[0].get_load())
-            vm[1].sendline("die()")
-            time.sleep(5)
-            ev.set()
+            print_load([loads[1].get_load(), loads[2].get_load()],
+                       loads[0].get_load())
+            on_guest("virt.exit_threads()", vm, 2)
+            exit_event.set()
             thread.join()
             if (_time > slice): # Deviation is higher than 1 slice
-                logging.error("test_perf: test ran %fs longer "
-                              "(more than 1 slice)", _time)
+                logging.error(
+                "Test ran %fs longer which is more than one slice", _time)
             else:
-                logging.debug("test_perf: test ran %fs longer "
-                              "(less than 1 slice)", _time)
-            stats = process_stats(stats[1:], slice*1024*1024)
-            logging.info("Guest -> Host [MB/s] min/med/max = %.3f/%.3f/%.3f",
+                logging.debug("Test ran %fs longer" % _time)
+            stats = process_stats(stats[1:], slice*1048576)
+            logging.debug("Stats = %s", stats)
+            logging.info("Guest->Host [mb/s] min/med/max = %.3f/%.3f/%.3f",
                          stats[0], stats[len(stats)/2], stats[-1])
-            for ld in load:
-                del(ld)
 
-        logging.info("test_perf: PASS")
+            del thread
+
+            del exit_event
+            del loads[:]
 
 
     # INITIALIZE
@@ -736,35 +886,44 @@ def run_virtio_console(test, params, env):
 
     no_serialports = 0
     no_consoles = 0
-
     # consoles required for Smoke test
     if (test_smoke_params.count('serialport')):
         no_serialports = max(2, no_serialports)
     if (test_smoke_params.count('console')):
         no_consoles = max(2, no_consoles)
-
     # consoles required for Loopback test
     for param in test_loopback_params.split(';'):
         no_serialports = max(no_serialports, param.count('serialport'))
         no_consoles = max(no_consoles, param.count('console'))
-
     # consoles required for Performance test
     if (test_perf_params.count('serialport')):
         no_serialports = max(1, no_serialports)
     if (test_perf_params.count('console')):
         no_consoles = max(1, no_consoles)
 
+    if (no_serialports + no_consoles) == 0:
+        raise error.TestFail("No tests defined, probably incorrect "
+                             "configuration in tests_base.cfg")
+
     vm, consoles = _vm_create(no_consoles, no_serialports)
 
-    # Copy console_switch.py into guests
+    # Copy allocator.py into guests
     pwd = os.path.join(os.environ['AUTODIR'], 'tests/kvm')
-    vksmd_src = os.path.join(pwd, "scripts/console_switch.py")
+    vksmd_src = os.path.join(pwd, "scripts/virtio_guest.py")
     dst_dir = "/tmp"
     if not vm[0].copy_files_to(vksmd_src, dst_dir):
         raise error.TestFail("copy_files_to failed %s" % vm[0].name)
 
     # ACTUAL TESTING
-    test_smoke(vm, consoles, test_smoke_params)
+    # Defines all available consoles; tests udev and sysfs
+    conss = []
+    for mode in consoles:
+        for cons in mode:
+            conss.append(cons[1:3])
+    init_guest(vm, 10)
+    on_guest("virt.init(%s)" % (conss), vm, 10)
+
+    consoles = test_smoke(vm, consoles, test_smoke_params)
     test_loopback(vm, consoles, test_loopback_params)
     test_perf(vm, consoles, test_perf_params)
 
@@ -772,3 +931,4 @@ def run_virtio_console(test, params, env):
     vm[1].close()
     vm[0].destroy(gracefully=False)
     shutil.rmtree(vm[2])
+
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index bef0f1c..ff0a760 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -502,11 +502,15 @@ variants:
         vms = ''
         type = virtio_console
         # smoke params - $console_type:data_string
-        virtio_console_smoke = "serialport;console:Custom data"
+        # FIXME: test_smoke doesn't work with console yet (virtio_console bug)
+        # "serialport;console:Custom data"
+        virtio_console_smoke = "serialport"
         # loopback params - '$source_console_type@buffer_length:$destination_console_type1@buffer_length:...:$loopback_buffer_length;...'
         virtio_console_loopback = "serialport:serialport;serialport@1024:serialport@32:console@1024:console@8:16"
         # perf params - $console_type@buffer_length:$test_duration
-        virtio_console_perf = "serialport;serialport@1000000:120;console@1024:60"
+        # FIXME: test_perf doesn't work with console yet (virtio_console bug)
+        # virtio_console_perf = "serialport;serialport@1000000:120;console@1024:60"
+        virtio_console_perf = "serialport;serialport@1000000:120"
 
     # This unit test module is for older branches of KVM that use the
     # kvmctl test harness (such as the code shipped with RHEL 5.x)
-- 
1.7.2.2

--
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