xref: /openbmc/openbmc/poky/meta/lib/oeqa/selftest/cases/rust.py (revision c9537f57ab488bf5d90132917b0184e2527970a5)
1# SPDX-License-Identifier: MIT
2import subprocess
3import time
4from oeqa.core.decorator import OETestTag
5from oeqa.core.decorator.data import skipIfArch
6from oeqa.core.case import OEPTestResultTestCase
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
9from oeqa.utils.sshcontrol import SSHControl
10
11def parse_results(filename):
12    tests = {}
13    with open(filename, "r") as f:
14        lines = f.readlines()
15        for line in lines:
16            if "..." in line and "test [" in line:
17                test = line.split("test ")[1].split(" ... ")[0]
18                if "] " in test:
19                    test = test.split("] ", 1)[1]
20                result = line.split(" ... ")[1].strip()
21                if result == "ok":
22                    result = "PASS"
23                elif result == "failed":
24                    result = "FAIL"
25                elif "ignored" in result:
26                    result = "SKIPPED"
27                if test in tests:
28                    if tests[test] != result:
29                        print("Duplicate and mismatching result %s for %s" % (result, test))
30                    else:
31                        print("Duplicate result %s for %s" % (result, test))
32                else:
33                    tests[test] = result
34    return tests
35
36# Total time taken for testing is of about 2hr 20min, with PARALLEL_MAKE set to 40 number of jobs.
37@OETestTag("toolchain-system")
38@OETestTag("toolchain-user")
39@OETestTag("runqemu")
40class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
41
42    @skipIfArch(['mips', 'mips64'])
43    def test_rust(self, *args, **kwargs):
44        # build remote-test-server before image build
45        recipe = "rust"
46        start_time = time.time()
47        bitbake("{} -c test_compile".format(recipe))
48        builddir = get_bb_var("RUSTSRC", "rust")
49        # build core-image-minimal with required packages
50        default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp"]
51        features = []
52        features.append('IMAGE_FEATURES += "ssh-server-dropbear"')
53        features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages)))
54        self.write_config("\n".join(features))
55        bitbake("core-image-minimal")
56
57        # Exclude the test folders that error out while building
58        # TODO: Fix the errors and include them for testing
59        # no-fail-fast: Run all tests regardless of failure.
60        # bless: First runs rustfmt to format the codebase,
61        # then runs tidy checks.
62        exclude_list =  [
63                            'src/bootstrap',
64                            'src/doc/rustc',
65                            'src/doc/rustdoc',
66                            'src/doc/unstable-book',
67                            'src/etc/test-float-parse',
68                            'src/librustdoc',
69                            'src/rustdoc-json-types',
70                            'src/tools/jsondoclint',
71                            'src/tools/lint-docs',
72                            'src/tools/replace-version-placeholder',
73                            'src/tools/rust-analyzer',
74                            'src/tools/rustdoc-themes',
75                            'src/tools/rust-installer',
76                            'src/tools/suggest-tests',
77                            'tests/assembly/asm/aarch64-outline-atomics.rs',
78                            'tests/codegen/issues/issue-122805.rs',
79                            'tests/codegen/thread-local.rs',
80                            'tests/mir-opt/',
81                            'tests/run-make',
82                            'tests/run-make-fulldeps',
83                            'tests/rustdoc',
84                            'tests/rustdoc-json',
85                            'tests/rustdoc-js-std',
86                            'tests/ui/abi/stack-probes-lto.rs',
87                            'tests/ui/abi/stack-probes.rs',
88                            'tests/ui/codegen/mismatched-data-layouts.rs',
89                            'tests/codegen/rust-abi-arch-specific-adjustment.rs',
90                            'tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs',
91                            'tests/ui/feature-gates/version_check.rs',
92                            'tests/ui-fulldeps/',
93                            'tests/ui/process/nofile-limit.rs',
94                            'tidyselftest'
95                        ]
96
97        exclude_fail_tests = " ".join([" --exclude " + item for item in exclude_list])
98        # Add exclude_fail_tests with other test arguments
99        testargs =  exclude_fail_tests + " --no-fail-fast --bless"
100
101        # wrap the execution with a qemu instance.
102        # Tests are run with 512 tasks in parallel to execute all tests very quickly
103        with runqemu("core-image-minimal", runqemuparams = "nographic", qemuparams = "-m 512") as qemu:
104            # Copy remote-test-server to image through scp
105            host_sys = get_bb_var("RUST_BUILD_SYS", "rust")
106            ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user="root")
107            ssh.copy_to(builddir + "/build/" + host_sys + "/stage1-tools-bin/remote-test-server","~/")
108            # Execute remote-test-server on image through background ssh
109            command = '~/remote-test-server --bind 0.0.0.0:12345 -v'
110            sshrun=subprocess.Popen(("ssh", '-o',  'UserKnownHostsFile=/dev/null', '-o',  'StrictHostKeyChecking=no', '-f', "root@%s" % qemu.ip, command), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
111            # Get the values of variables.
112            tcpath = get_bb_var("TARGET_SYS", "rust")
113            targetsys = get_bb_var("RUST_TARGET_SYS", "rust")
114            rustlibpath = get_bb_var("WORKDIR", "rust")
115            tmpdir = get_bb_var("TMPDIR", "rust")
116
117            # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools.
118            cmd = "export TARGET_VENDOR=\"-poky\";"
119            cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/python3-native:%s/recipe-sysroot-native/usr/bin:%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, rustlibpath, rustlibpath, tcpath, tmpdir)
120            cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath
121            # Trigger testing.
122            cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip
123            cmd = cmd + " cd %s; python3 src/bootstrap/bootstrap.py test %s --target %s" % (builddir, testargs, targetsys)
124            retval = runCmd(cmd)
125            end_time = time.time()
126
127            resultlog = rustlibpath + "/results-log.txt"
128            with open(resultlog, "w") as f:
129                f.write(retval.output)
130
131            ptestsuite = "rust"
132            self.ptest_section(ptestsuite, duration = int(end_time - start_time), logfile=resultlog)
133            test_results = parse_results(resultlog)
134            for test in test_results:
135                self.ptest_result(ptestsuite, test, test_results[test])
136