[elbe-devel] [RFC PATCH 2/3] commands check-build: Add CheckImage test
Olivier Dion
dion at linutronix.de
Mon May 18 03:35:33 CEST 2020
The CheckImage build test can be used to boot images from a build into
an interpreter and make communication with it using a serial line.
This test can be skipped by using the '--skip-img' flag on the CLI.
The test failed if any image emulation failed. An image emulation can
failed if there's a timeout during an expectation from the guest on
the serial line or if the guest breaks the serial line unexpectedly.
A transcript of the communications between the host and the guest is
printed at the end of each image emulation.
Signed-off-by: Olivier Dion <dion at linutronix.de>
---
elbepack/commands/check-build.py | 100 +++++++++++++++++++++++++++++--
1 file changed, 96 insertions(+), 4 deletions(-)
diff --git a/elbepack/commands/check-build.py b/elbepack/commands/check-build.py
index 408c7b62..2027f8c2 100644
--- a/elbepack/commands/check-build.py
+++ b/elbepack/commands/check-build.py
@@ -6,11 +6,12 @@
import multiprocessing
import optparse
import os
-import subprocess
import sys
import tempfile
import traceback
+import pexpect
+
from elbepack.treeutils import etree
from elbepack.shellhelper import command_out, system_out
@@ -32,7 +33,6 @@ class TempDirectory(object):
shutil.rmtree(self._dir)
return False
-
def get_files_with_prefix(prefix, _dir="."):
# TODO - Change os.listdir for os.scandir in Python3
return [path
@@ -46,6 +46,17 @@ def dpkg_get_infos(path, fmt):
cmd = 'grep -E "^(%s):" %s' % ("|".join(fmt), path)
return system_out(cmd)
+def open_tgz(path):
+ tmp = tempfile.NamedTemporaryFile(prefix='elbe')
+ command_out("tar --to-stdout --extract --gunzip --file %s" % path,
+ output=tmp)
+ return tmp
+
+def open_img(path):
+ if path.endswith(".tar.gz"):
+ return open_tgz(path)
+ return open(path)
+
class CheckBase(object):
_tests = []
@@ -279,10 +290,10 @@ def run_command(argv):
oparser = optparse.OptionParser(usage="usage: %prog check-build [options] <build-dir>")
# pylint: disable=protected-access
- for _, skip_if in CheckBase._tests:
+ for cls, skip_if in CheckBase._tests:
oparser.add_option("--%s" % skip_if, action="store_true",
dest=skip_if, default=False,
- help="Skip test cdroms integrity")
+ help=cls.__doc__)
(opt, args) = oparser.parse_args(argv)
@@ -332,4 +343,84 @@ def run_command(argv):
print("Passed %d tests ouf of %d" % (total_cnt - fail_cnt, total_cnt))
sys.exit(0 if fail_cnt == 0 else 1)
+
+
+ at CheckBase.register("skip-img")
+class CheckImage(CheckBase):
+
+ """Check if image can boot"""
+
+ def run(self):
+
+ xml = etree("source.xml")
+
+ # For all image
+ for tag in xml.all("./check-img"):
+
+ img_name = tag.text("./name")
+
+ # Open it
+ with open_img(img_name) as img:
+
+ # ELBE_IMG always point to the opened image
+ os.environ["ELBE_IMG"] = img.name
+
+ qemu = tag.text("./interpreter-name")
+ opts = os.path.expandvars(tag.text("./interpreter-opts").strip(' \t\n')).split(' ')
+ serial = tag.all("./serial/*")
+
+ transcript = []
+ child = pexpect.spawn(qemu, opts)
+
+ try:
+ for action in serial:
+
+ if "expect" == action.tag:
+
+ # Try to expect something from the guest
+ # If there's a timeout; the test fail
+ # Otherwise; Add to the transcript what we
+ # received
+ try:
+ child.expect(action.et.text)
+ except pexpect.exceptions.TIMEOUT:
+ print('Was expecting "%s" but got timeout (%ds)' %
+ (action.et.text, child.timeout))
+ self.ret = 1
+ break
+ else:
+ transcript.append(child.before.decode('utf-8'))
+ transcript.append(child.after.decode('utf-8'))
+
+ elif "sendline" == action.tag:
+ child.sendline(action.et.text)
+
+ # We're expecting the line to be closed by the
+ # guest. If there's a timeout, this means
+ # that the guest has not closed the line and
+ # the test failed. In every case the test
+ # ends here.
+ elif "EOF" == action.tag:
+ try:
+ child.expect(pexpect.EOF)
+ except pexpect.exceptions.TIMEOUT:
+ print('Was expecting EOF but got timeout (%d)' %
+ child.timeout)
+ self.ret = 1
+ else:
+ transcript.append(child.before.decode('utf-8'))
+ break
+
+ # Woops. The guest has die and we didn't expect that!
+ except pexpect.exceptions.EOF:
+ print("Communication was interrupted unexpectedly")
+ self.ret = 1
+
+ child.close()
+
+ print("Transcript for image %s:" % img_name)
+ print("----------------------------------------------------------------------")
+ print(''.join(transcript))
+ print("----------------------------------------------------------------------")
+
+ self.ret = self.ret or child.exitstatus
--
2.26.2
More information about the elbe-devel
mailing list