]> rtime.felk.cvut.cz Git - coffee/buildroot.git/blob - support/testing/infra/emulator.py
support/testing: use pexpect.expect directly
[coffee/buildroot.git] / support / testing / infra / emulator.py
1 import pexpect
2
3 import infra
4 import infra.basetest
5
6 class Emulator(object):
7
8     def __init__(self, builddir, downloaddir, logtofile):
9         self.qemu = None
10         self.downloaddir = downloaddir
11         self.logfile = infra.open_log_file(builddir, "run", logtofile)
12
13     # Start Qemu to boot the system
14     #
15     # arch: Qemu architecture to use
16     #
17     # kernel: path to the kernel image, or the special string
18     # 'builtin'. 'builtin' means a pre-built kernel image will be
19     # downloaded from ARTEFACTS_URL and suitable options are
20     # automatically passed to qemu and added to the kernel cmdline. So
21     # far only armv5, armv7 and i386 builtin kernels are available.
22     # If None, then no kernel is used, and we assume a bootable device
23     # will be specified.
24     #
25     # kernel_cmdline: array of kernel arguments to pass to Qemu -append option
26     #
27     # options: array of command line options to pass to Qemu
28     #
29     def boot(self, arch, kernel=None, kernel_cmdline=None, options=None):
30         if arch in ["armv7", "armv5"]:
31             qemu_arch = "arm"
32         else:
33             qemu_arch = arch
34
35         qemu_cmd = ["qemu-system-{}".format(qemu_arch),
36                     "-serial", "stdio",
37                     "-display", "none"]
38
39         if options:
40             qemu_cmd += options
41
42         if kernel_cmdline is None:
43             kernel_cmdline = []
44
45         if kernel:
46             if kernel == "builtin":
47                 if arch in ["armv7", "armv5"]:
48                     kernel_cmdline.append("console=ttyAMA0")
49
50                 if arch == "armv7":
51                     kernel = infra.download(self.downloaddir,
52                                             "kernel-vexpress")
53                     dtb = infra.download(self.downloaddir,
54                                          "vexpress-v2p-ca9.dtb")
55                     qemu_cmd += ["-dtb", dtb]
56                     qemu_cmd += ["-M", "vexpress-a9"]
57                 elif arch == "armv5":
58                     kernel = infra.download(self.downloaddir,
59                                             "kernel-versatile")
60                     qemu_cmd += ["-M", "versatilepb"]
61
62             qemu_cmd += ["-kernel", kernel]
63
64         if kernel_cmdline:
65             qemu_cmd += ["-append", " ".join(kernel_cmdline)]
66
67         self.logfile.write("> starting qemu with '%s'\n" % " ".join(qemu_cmd))
68         self.qemu = pexpect.spawn(qemu_cmd[0], qemu_cmd[1:], timeout=5)
69         # We want only stdout into the log to avoid double echo
70         self.qemu.logfile_read = self.logfile
71
72     # Wait for the login prompt to appear, and then login as root with
73     # the provided password, or no password if not specified.
74     def login(self, password=None):
75         index = self.qemu.expect(["buildroot login:", pexpect.TIMEOUT],
76                                  timeout=10)
77         if index != 0:
78             self.logfile.write("==> System does not boot")
79             raise SystemError("System does not boot")
80
81         self.qemu.sendline("root")
82         if password:
83             self.qemu.expect("Password:")
84             self.qemu.sendline(password)
85         index = self.qemu.expect(["# ", pexpect.TIMEOUT])
86         if index != 0:
87             raise SystemError("Cannot login")
88         self.run("dmesg -n 1")
89
90     # Run the given 'cmd' on the target
91     # return a tuple (output, exit_code)
92     def run(self, cmd):
93         self.qemu.sendline(cmd)
94         self.qemu.expect("# ")
95         # Remove double carriage return from qemu stdout so str.splitlines()
96         # works as expected.
97         output = self.qemu.before.replace("\r\r", "\r").splitlines()[1:]
98
99         self.qemu.sendline("echo $?")
100         self.qemu.expect("# ")
101         exit_code = self.qemu.before.splitlines()[2]
102         exit_code = int(exit_code)
103
104         return output, exit_code
105
106     def stop(self):
107         if self.qemu is None:
108             return
109         self.qemu.terminate(force=True)