remove version in all files
[dpdk.git] / app / test / autotest.py
1 #!/usr/bin/python
2
3 #   BSD LICENSE
4
5 #   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
6 #   All rights reserved.
7
8 #   Redistribution and use in source and binary forms, with or without 
9 #   modification, are permitted provided that the following conditions 
10 #   are met:
11
12 #     * Redistributions of source code must retain the above copyright 
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above copyright 
15 #       notice, this list of conditions and the following disclaimer in 
16 #       the documentation and/or other materials provided with the 
17 #       distribution.
18 #     * Neither the name of Intel Corporation nor the names of its 
19 #       contributors may be used to endorse or promote products derived 
20 #       from this software without specific prior written permission.
21
22 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
25 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
29 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
30 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34
35 # Script that uses qemu controlled by python-pexpect to check that
36 # all autotests are working in the baremetal environment.
37
38 import sys, pexpect, time, os, re
39
40 directory = sys.argv[2]
41 target = sys.argv[3]
42 log_file = "%s.txt"%(target)
43
44 if "baremetal" in target:
45     cmdline  = "qemu-system-x86_64 -cdrom %s.iso -boot d "%(sys.argv[1])
46     cmdline     += "-m 2000 -smp 4 -nographic -net nic,model=e1000"
47     platform = "QEMU x86_64"
48 else:
49     cmdline  = "%s -c f -n 4"%(sys.argv[1])
50     try:
51         platform = open("/root/rte_platform_model.txt").read()
52     except:
53         platform = "unknown"
54
55 print cmdline
56
57 report_hdr=""".. <COPYRIGHT_TAG>
58
59 """
60
61 test_whitelist=None
62 test_blacklist=None
63
64 class SubTest:
65     "Defines a subtest"
66     def __init__(self, title, function, command=None, timeout=10, genreport=None):
67         self.title = title
68         self.function = function
69         self.command = command
70         self.timeout = timeout
71         self.genreport = genreport
72
73 class AutoTest:
74     """This class contains all methods needed to launch several
75     automatic tests, archive test results, log, and generate a nice
76     test report in restructured text"""
77
78     title = "new"
79     mainlog = None
80     logbuf = None
81     literal = 0
82     test_list = []
83     report_list = []
84     child = None
85
86     def __init__(self, pexpectchild, filename, mode):
87         "Init the Autotest class"
88         self.mainlog = file(filename, mode)
89         self.child = pexpectchild
90         pexpectchild.logfile = self
91     def register(self, filename, title, subtest_list):
92         "Register a test with a list of subtests"
93         test = {}
94         test["filename"] = filename
95         test["title"] = title
96         test["subtest_list"] = subtest_list
97         self.test_list.append(test)
98
99     def start(self):
100         "start the tests, and fill the internal report_list field"
101         for t in self.test_list:
102             report = {}
103             report["date"] = time.asctime()
104             report["title"] = t["title"]
105             report["filename"] = t["filename"]
106             report["subreport_list"] = []
107             report["fails"] = 0
108             report["success"] = 0
109             report["subreport_list"] = []
110             for st in t["subtest_list"]:
111                 if test_whitelist is not None and st.title not in test_whitelist:
112                     continue
113                 if test_blacklist is not None and st.title in test_blacklist:
114                     continue
115                 subreport = {}
116                 self.reportbuf = ""
117                 subreport["title"] = st.title
118                 subreport["func"] = st.function
119                 subreport["command"] = st.command
120                 subreport["timeout"] = st.timeout
121                 subreport["genreport"] = st.genreport
122
123                 # launch subtest
124                 print "%s (%s): "%(subreport["title"], subreport["command"]),
125                 sys.stdout.flush()
126                 start = time.time()
127                 res = subreport["func"](self.child,
128                                         command = subreport["command"],
129                                         timeout = subreport["timeout"])
130                 t = int(time.time() - start)
131
132                 subreport["time"] = "%dmn%d"%(t/60, t%60)
133                 subreport["result"] = res[0] # 0 or -1
134                 subreport["result_str"] = res[1] # cause of fail
135                 subreport["logs"] = self.reportbuf
136                 print "%s [%s]"%(subreport["result_str"], subreport["time"])
137                 if subreport["result"] == 0:
138                     report["success"] += 1
139                 else:
140                     report["fails"] += 1
141                 report["subreport_list"].append(subreport)
142             self.report_list.append(report)
143
144     def gen_report(self):
145         for report in self.report_list:
146             # main report header and stats
147             self.literal = 0
148             reportlog = file(report["filename"], "w")
149             reportlog.write(report_hdr)
150             reportlog.write(report["title"] + "\n")
151             reportlog.write(re.sub(".", "=", report["title"]) + "\n\n")
152             reportlog.write("Autogenerated test report:\n\n" )
153             reportlog.write("- date: **%s**\n"%(report["date"]))
154             reportlog.write("- target: **%s**\n"%(target))
155             reportlog.write("- success: **%d**\n"%(report["success"]))
156             reportlog.write("- fails: **%d**\n"%(report["fails"]))
157             reportlog.write("- platform: **%s**\n\n"%(platform))
158
159             # summary
160             reportlog.write(".. csv-table:: Test results summary\n")
161             reportlog.write('   :header: "Name", "Result"\n\n')
162             for subreport in report["subreport_list"]:
163                 if subreport["result"] == 0:
164                     res_str = "Success"
165                 else:
166                     res_str = "Failure"
167                 reportlog.write('   "%s", "%s"\n'%(subreport["title"], res_str))
168             reportlog.write('\n')
169
170             # subreports
171             for subreport in report["subreport_list"]:
172                 # print subtitle
173                 reportlog.write(subreport["title"] + "\n")
174                 reportlog.write(re.sub(".", "-", subreport["title"]) + "\n\n")
175                 # print logs
176                 reportlog.write("::\n  \n  ")
177                 s = subreport["logs"].replace("\n", "\n  ")
178                 reportlog.write(s)
179                 # print result
180                 reportlog.write("\n\n")
181                 reportlog.write("**" + subreport["result_str"] + "**\n\n")
182                 # custom genreport
183                 if subreport["genreport"] != None:
184                     s = subreport["genreport"]()
185                     reportlog.write(s)
186
187             reportlog.close()
188
189         # displayed on console
190         print
191         print "-------------------------"
192         print
193         if report["fails"] == 0:
194             print "All test OK"
195         else:
196             print "%s test(s) failed"%(report["fails"])
197
198     # file API, to store logs from pexpect
199     def write(self, buf):
200         s = buf[:]
201         s = s.replace("\r", "")
202         self.mainlog.write(s)
203         self.reportbuf += s
204     def flush(self):
205         self.mainlog.flush()
206     def close(self):
207         self.mainlog.close()
208
209
210 # Try to match prompt: return 0 on success, else return -1
211 def wait_prompt(child):
212     for i in range(3):
213         index = child.expect(["RTE>>", pexpect.TIMEOUT], timeout = 1)
214         child.sendline("")
215         if index == 0:
216             return 0
217     print "Cannot find prompt"
218     return -1
219
220 # Try to match prompt after boot: return 0 on success, else return -1
221 def wait_boot(child):
222     index = child.expect(["RTE>>", pexpect.TIMEOUT],
223                          timeout = 120)
224     if index == 0:
225         return 0
226     if (wait_prompt(child) == -1):
227         print "Target did not boot, failed"
228         return -1
229     return 0
230
231 # quit RTE
232 def quit(child):
233     if wait_boot(child) != 0:
234         return -1, "Cannot find prompt"
235     child.sendline("quit")
236     return 0, "Success"
237
238 # Default function to launch an autotest that does not need to
239 # interact with the user. Basically, this function calls the autotest
240 # function through command line interface, then check that it displays
241 # "Test OK" or "Test Failed".
242 def default_autotest(child, command, timeout=10):
243     if wait_prompt(child) != 0:
244         return -1, "Failed: cannot find prompt"
245     child.sendline(command)
246     index = child.expect(["Test OK", "Test Failed",
247                           pexpect.TIMEOUT], timeout = timeout)
248     if index == 1:
249         return -1, "Failed"
250     elif index == 2:
251         return -1, "Failed [Timeout]"
252     return 0, "Success"
253
254 # wait boot
255 def boot_autotest(child, **kargs):
256     if wait_boot(child) != 0:
257         return -1, "Cannot find prompt"
258     return 0, "Success"
259
260 # Test memory dump. We need to check that at least one memory zone is
261 # displayed.
262 def memory_autotest(child, command, **kargs):
263     if wait_prompt(child) != 0:
264         return -1, "Failed: cannot find prompt"
265     child.sendline(command)
266     regexp = "phys:0x[0-9a-f]*, len:0x([0-9a-f]*), virt:0x[0-9a-f]*, socket_id:[0-9]*"
267     index = child.expect([regexp, pexpect.TIMEOUT], timeout = 180)
268     if index != 0:
269         return -1, "Failed: timeout"
270     size = int(child.match.groups()[0], 16)
271     if size <= 0:
272         return -1, "Failed: bad size"
273     index = child.expect(["Test OK", "Test Failed",
274                           pexpect.TIMEOUT], timeout = 10)
275     if index == 1:
276         return -1, "Failed: C code returned an error"
277     elif index == 2:
278         return -1, "Failed: timeout"
279     return 0, "Success"
280
281 # Test some libc functions including scanf. This requires a
282 # interaction with the user (simulated in expect), so we cannot use
283 # default_autotest() here.
284 def string_autotest(child, command, **kargs):
285     if wait_prompt(child) != 0:
286         return -1, "Failed: cannot find prompt"
287     child.sendline(command)
288     index = child.expect(["Now, test scanf, enter this number",
289                           pexpect.TIMEOUT], timeout = 10)
290     if index != 0:
291         return -1, "Failed: timeout"
292     child.sendline("123456")
293     index = child.expect(["number=123456", pexpect.TIMEOUT], timeout = 10)
294     if index != 0:
295         return -1, "Failed: timeout (2)"
296     index = child.expect(["Test OK", "Test Failed",
297                           pexpect.TIMEOUT], timeout = 10)
298     if index != 0:
299         return -1, "Failed: C code returned an error"
300     return 0, "Success"
301
302 # Test spinlock. This requires to check the order of displayed lines:
303 # we cannot use default_autotest() here.
304 def spinlock_autotest(child, command, **kargs):
305     i = 0
306     ir = 0
307     if wait_prompt(child) != 0:
308         return -1, "Failed: cannot find prompt"
309     child.sendline(command)
310     while True:
311         index = child.expect(["Test OK",
312                               "Test Failed",
313                               "Hello from core ([0-9]*) !",
314                               "Hello from within recursive locks from ([0-9]*) !",
315                               pexpect.TIMEOUT], timeout = 20)
316         # ok
317         if index == 0:
318             break
319
320         # message, check ordering
321         elif index == 2:
322             if int(child.match.groups()[0]) < i:
323                 return -1, "Failed: bad order"
324             i = int(child.match.groups()[0])
325         elif index == 3:
326             if int(child.match.groups()[0]) < ir:
327                 return -1, "Failed: bad order"
328             ir = int(child.match.groups()[0])
329
330         # fail
331         else:
332             return -1, "Failed: timeout or error"
333
334     return 0, "Success"
335
336
337 # Test rwlock. This requires to check the order of displayed lines:
338 # we cannot use default_autotest() here.
339 def rwlock_autotest(child, command, **kargs):
340     i = 0
341     if wait_prompt(child) != 0:
342         return -1, "Failed: cannot find prompt"
343     child.sendline(command)
344     while True:
345         index = child.expect(["Test OK",
346                               "Test Failed",
347                               "Hello from core ([0-9]*) !",
348                               "Global write lock taken on master core ([0-9]*)",
349                               pexpect.TIMEOUT], timeout = 10)
350         # ok
351         if index == 0:
352             if i != 0xffff:
353                 return -1, "Failed: a message is missing"
354             break
355
356         # message, check ordering
357         elif index == 2:
358             if int(child.match.groups()[0]) < i:
359                 return -1, "Failed: bad order"
360             i = int(child.match.groups()[0])
361
362         # must be the last message, check ordering
363         elif index == 3:
364             i = 0xffff
365
366         # fail
367         else:
368             return -1, "Failed: timeout or error"
369
370     return 0, "Success"
371
372 # Test logs. This requires to check the order of displayed lines:
373 # we cannot use default_autotest() here.
374 def logs_autotest(child, command, **kargs):
375     i = 0
376     if wait_prompt(child) != 0:
377         return -1, "Failed: cannot find prompt"
378     child.sendline(command)
379
380     log_list = [
381         "TESTAPP1: this is a debug level message",
382         "TESTAPP1: this is a info level message",
383         "TESTAPP1: this is a warning level message",
384         "TESTAPP2: this is a info level message",
385         "TESTAPP2: this is a warning level message",
386         "TESTAPP1: this is a debug level message",
387         "TESTAPP1: this is a debug level message",
388         "TESTAPP1: this is a info level message",
389         "TESTAPP1: this is a warning level message",
390         "TESTAPP2: this is a info level message",
391         "TESTAPP2: this is a warning level message",
392         "TESTAPP1: this is a debug level message",
393         ]
394
395     for log_msg in log_list:
396         index = child.expect([log_msg,
397                               "Test OK",
398                               "Test Failed",
399                               pexpect.TIMEOUT], timeout = 10)
400
401         # not ok
402         if index != 0:
403             return -1, "Failed: timeout or error"
404
405     index = child.expect(["Test OK",
406                           "Test Failed",
407                           pexpect.TIMEOUT], timeout = 10)
408
409     return 0, "Success"
410
411 # Test timers. This requires to check the order of displayed lines:
412 # we cannot use default_autotest() here.
413 def timer_autotest(child, command, **kargs):
414     i = 0
415     if wait_prompt(child) != 0:
416         return -1, "Failed: cannot find prompt"
417     child.sendline(command)
418
419     index = child.expect(["Start timer stress tests \(30 seconds\)",
420                           "Test Failed",
421                           pexpect.TIMEOUT], timeout = 10)
422
423     # not ok
424     if index != 0:
425         return -1, "Failed: timeout or error"
426
427     index = child.expect(["Start timer basic tests \(30 seconds\)",
428                           "Test Failed",
429                           pexpect.TIMEOUT], timeout = 40)
430
431     # not ok
432     if index != 0:
433         return -1, "Failed: timeout or error (2)"
434
435     prev_lcore_timer1 = -1
436
437     lcore_tim0 = -1
438     lcore_tim1 = -1
439     lcore_tim2 = -1
440     lcore_tim3 = -1
441
442     while True:
443         index = child.expect(["TESTTIMER: ([0-9]*): callback id=([0-9]*) count=([0-9]*) on core ([0-9]*)",
444                               "Test OK",
445                               "Test Failed",
446                               pexpect.TIMEOUT], timeout = 10)
447
448         if index == 1:
449             break
450
451         if index != 0:
452             return -1, "Failed: timeout or error (3)"
453
454         try:
455             t = int(child.match.groups()[0])
456             id = int(child.match.groups()[1])
457             cnt = int(child.match.groups()[2])
458             lcore = int(child.match.groups()[3])
459         except:
460             return -1, "Failed: cannot parse output"
461
462         # timer0 always expires on the same core when cnt < 20
463         if id == 0:
464             if lcore_tim0 == -1:
465                 lcore_tim0 = lcore
466             elif lcore != lcore_tim0 and cnt < 20:
467                 return -1, "Failed: lcore != lcore_tim0 (%d, %d)"%(lcore, lcore_tim0)
468             if cnt > 21:
469                 return -1, "Failed: tim0 cnt > 21"
470
471         # timer1 each time expires on a different core
472         if id == 1:
473             if lcore == lcore_tim1:
474                 return -1, "Failed: lcore == lcore_tim1 (%d, %d)"%(lcore, lcore_tim1)
475             lcore_tim1 = lcore
476             if cnt > 10:
477                 return -1, "Failed: tim1 cnt > 30"
478
479         # timer0 always expires on the same core
480         if id == 2:
481             if lcore_tim2 == -1:
482                 lcore_tim2 = lcore
483             elif lcore != lcore_tim2:
484                 return -1, "Failed: lcore != lcore_tim2 (%d, %d)"%(lcore, lcore_tim2)
485             if cnt > 30:
486                 return -1, "Failed: tim2 cnt > 30"
487
488         # timer0 always expires on the same core
489         if id == 3:
490             if lcore_tim3 == -1:
491                 lcore_tim3 = lcore
492             elif lcore != lcore_tim3:
493                 return -1, "Failed: lcore_tim3 changed (%d -> %d)"%(lcore, lcore_tim3)
494             if cnt > 30:
495                 return -1, "Failed: tim3 cnt > 30"
496
497     # must be 2 different cores
498     if lcore_tim0 == lcore_tim3:
499         return -1, "Failed: lcore_tim0 (%d) == lcore_tim3 (%d)"%(lcore_tim0, lcore_tim3)
500
501     return 0, "Success"
502
503 # Ring autotest
504 def ring_autotest(child, command, timeout=10):
505     if wait_prompt(child) != 0:
506         return -1, "Failed: cannot find prompt"
507     child.sendline(command)
508     index = child.expect(["Test OK", "Test Failed",
509                           pexpect.TIMEOUT], timeout = timeout)
510     if index != 0:
511         return -1, "Failed"
512
513     child.sendline("set_watermark test 100")
514     child.sendline("set_quota test 16")
515     child.sendline("dump_ring test")
516     index = child.expect(["  watermark=100",
517                           pexpect.TIMEOUT], timeout = 1)
518     if index != 0:
519         return -1, "Failed: bad watermark"
520
521     index = child.expect(["  bulk_default=16",
522                           pexpect.TIMEOUT], timeout = 1)
523     if index != 0:
524         return -1, "Failed: bad quota"
525
526     return 0, "Success"
527
528 def ring_genreport():
529     s  = "Performance curves\n"
530     s += "------------------\n\n"
531     sdk = os.getenv("RTE_SDK")
532     script = os.path.join(sdk, "app/test/graph_ring.py")
533     title ='"Autotest %s %s"'%(target, time.asctime())
534     filename = target + ".txt"
535     os.system("/usr/bin/python %s %s %s"%(script, filename, title))
536     for f in os.listdir("."):
537         if not f.startswith("ring"):
538             continue
539         if not f.endswith(".svg"):
540             continue
541         # skip single producer/consumer
542         if "_sc" in f:
543             continue
544         if "_sp" in f:
545             continue
546         f = f[:-4] + ".png"
547         s += ".. figure:: ../../images/autotests/%s/%s\n"%(target, f)
548         s += "   :width: 50%\n\n"
549         s += "   %s\n\n"%(f)
550     return s
551
552 def mempool_genreport():
553     s  = "Performance curves\n"
554     s += "------------------\n\n"
555     sdk = os.getenv("RTE_SDK")
556     script = os.path.join(sdk, "app/test/graph_mempool.py")
557     title ='"Autotest %s %s"'%(target, time.asctime())
558     filename = target + ".txt"
559     os.system("/usr/bin/python %s %s %s"%(script, filename, title))
560     for f in os.listdir("."):
561         if not f.startswith("mempool"):
562             continue
563         if not f.endswith(".svg"):
564             continue
565         # skip when n_keep = 128
566         if "_128." in f:
567             continue
568         f = f[:-4] + ".png"
569         s += ".. figure:: ../../images/autotests/%s/%s\n"%(target, f)
570         s += "   :width: 50%\n\n"
571         s += "   %s\n\n"%(f)
572     return s
573
574 #
575 # main
576 #
577
578 if len(sys.argv) > 4:
579     testlist=sys.argv[4].split(',')
580     if testlist[0].startswith('-'):
581         testlist[0]=testlist[0].lstrip('-')
582         test_blacklist=testlist
583     else:
584         test_whitelist=testlist
585
586 child = pexpect.spawn(cmdline)
587 autotest = AutoTest(child, log_file,'w')
588
589 # timeout for memcpy and hash test
590 if "baremetal" in target:
591     timeout = 60*180
592 else:
593     timeout = 180
594
595 autotest.register("eal_report.rst", "EAL-%s"%(target),
596                   [ SubTest("Boot", boot_autotest, "boot_autotest"),
597                     SubTest("EAL Flags", default_autotest, "eal_flags_autotest"),
598                     SubTest("Version", default_autotest, "version_autotest"),
599                     SubTest("PCI", default_autotest, "pci_autotest"),
600                     SubTest("Memory", memory_autotest, "memory_autotest"),
601                     SubTest("Lcore launch", default_autotest, "per_lcore_autotest"),
602                     SubTest("Spinlock", spinlock_autotest, "spinlock_autotest"),
603                     SubTest("Rwlock", rwlock_autotest, "rwlock_autotest"),
604                     SubTest("Atomic", default_autotest, "atomic_autotest"),
605                     SubTest("Byte order", default_autotest, "byteorder_autotest"),
606                     SubTest("Prefetch", default_autotest, "prefetch_autotest"),
607                     SubTest("Debug", default_autotest, "debug_autotest"),
608                     SubTest("Cycles", default_autotest, "cycles_autotest"),
609                     SubTest("Logs", logs_autotest, "logs_autotest"),
610                     SubTest("Memzone", default_autotest, "memzone_autotest"),
611                     SubTest("Cpu flags", default_autotest, "cpuflags_autotest"),
612                     SubTest("Memcpy", default_autotest, "memcpy_autotest", timeout),
613                     SubTest("String Functions", default_autotest, "string_autotest"),
614                     SubTest("Alarm", default_autotest, "alarm_autotest", 30),
615                     SubTest("Interrupt", default_autotest, "interrupt_autotest"),
616                     ])
617
618 autotest.register("ring_report.rst", "Ring-%s"%(target),
619                   [ SubTest("Ring", ring_autotest, "ring_autotest", 30*60,
620                             ring_genreport)
621                     ])
622
623 if "baremetal" in target:
624     timeout = 60*60*3
625 else:
626     timeout = 60*30
627
628 autotest.register("mempool_report.rst", "Mempool-%s"%(target),
629                   [ SubTest("Mempool", default_autotest, "mempool_autotest",
630                             timeout, mempool_genreport)
631                     ])
632 autotest.register("mbuf_report.rst", "Mbuf-%s"%(target),
633                   [ SubTest("Mbuf", default_autotest, "mbuf_autotest", timeout=120)
634                     ])
635 autotest.register("timer_report.rst", "Timer-%s"%(target),
636                   [ SubTest("Timer", timer_autotest, "timer_autotest")
637                     ])
638 autotest.register("malloc_report.rst", "Malloc-%s"%(target),
639                   [ SubTest("Malloc", default_autotest, "malloc_autotest")
640                     ])
641
642 # only do the hash autotest if supported by the platform
643 if not (platform.startswith("Intel(R) Core(TM)2 Quad CPU") or
644         platform.startswith("QEMU")):
645     autotest.register("hash_report.rst", "Hash-%s"%(target),
646                       [ SubTest("Hash", default_autotest, "hash_autotest", timeout)
647                         ])
648
649 autotest.register("lpm_report.rst", "LPM-%s"%(target),
650                   [ SubTest("Lpm", default_autotest, "lpm_autotest", timeout)
651                     ])
652 autotest.register("eal2_report.rst", "EAL2-%s"%(target),
653                   [ SubTest("TailQ", default_autotest, "tailq_autotest"),
654                    SubTest("Errno", default_autotest, "errno_autotest"),
655                    SubTest("Multiprocess", default_autotest, "multiprocess_autotest")
656                     ])
657
658 autotest.start()
659 autotest.gen_report()
660
661 quit(child)
662 child.terminate()
663 sys.exit(0)