1# SPDX-License-Identifier: MIT
2import os
3import subprocess
4import time
5from oeqa.core.decorator import OETestTag
6from oeqa.core.case import OEPTestResultTestCase
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu, Command
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    def test_rust(self, *args, **kwargs):
42        # Disable Rust Oe-selftest
43        #self.skipTest("The Rust Oe-selftest is disabled.")
44
45        # Skip mips32 target since it is unstable with rust tests
46        machine = get_bb_var('MACHINE')
47        if machine == "qemumips":
48            self.skipTest("The mips32 target is skipped for Rust Oe-selftest.")
49
50        # build remote-test-server before image build
51        recipe = "rust"
52        start_time = time.time()
53        bitbake("{} -c test_compile".format(recipe))
54        builddir = get_bb_var("RUSTSRC", "rust")
55        # build core-image-minimal with required packages
56        default_installed_packages = ["libgcc", "libstdc++", "libatomic", "libgomp"]
57        features = []
58        features.append('IMAGE_FEATURES += "ssh-server-dropbear"')
59        features.append('CORE_IMAGE_EXTRA_INSTALL += "{0}"'.format(" ".join(default_installed_packages)))
60        self.write_config("\n".join(features))
61        bitbake("core-image-minimal")
62
63        # Exclude the test folders that error out while building
64        # TODO: Fix the errors and include them for testing
65        # no-fail-fast: Run all tests regardless of failure.
66        # bless: First runs rustfmt to format the codebase,
67        # then runs tidy checks.
68        exclude_list =  [
69                            'compiler/rustc',
70                            'compiler/rustc_interface/src/tests.rs',
71                            'library/panic_abort',
72                            'library/panic_unwind',
73                            'library/test/src/stats/tests.rs',
74                            'src/bootstrap/builder/tests.rs',
75                            'src/doc/rustc',
76                            'src/doc/rustdoc',
77                            'src/doc/unstable-book',
78                            'src/librustdoc',
79                            'src/rustdoc-json-types',
80                            'src/tools/compiletest/src/common.rs',
81                            'src/tools/lint-docs',
82                            'src/tools/rust-analyzer',
83                            'src/tools/rustdoc-themes',
84                            'src/tools/tidy',
85                            'tests/assembly/asm/aarch64-outline-atomics.rs',
86                            'tests/codegen/abi-main-signature-32bit-c-int.rs',
87                            'tests/codegen/abi-repr-ext.rs',
88                            'tests/codegen/abi-x86-interrupt.rs',
89                            'tests/codegen/branch-protection.rs',
90                            'tests/codegen/catch-unwind.rs',
91                            'tests/codegen/cf-protection.rs',
92                            'tests/codegen/enum-bounds-check-derived-idx.rs',
93                            'tests/codegen/force-unwind-tables.rs',
94                            'tests/codegen/intrinsic-no-unnamed-attr.rs',
95                            'tests/codegen/issues/issue-103840.rs',
96                            'tests/codegen/issues/issue-47278.rs',
97                            'tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs',
98                            'tests/codegen/lifetime_start_end.rs',
99                            'tests/codegen/local-generics-in-exe-internalized.rs',
100                            'tests/codegen/match-unoptimized.rs',
101                            'tests/codegen/noalias-rwlockreadguard.rs',
102                            'tests/codegen/non-terminate/nonempty-infinite-loop.rs',
103                            'tests/codegen/noreturn-uninhabited.rs',
104                            'tests/codegen/repr-transparent-aggregates-3.rs',
105                            'tests/codegen/riscv-abi/call-llvm-intrinsics.rs',
106                            'tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs',
107                            'tests/codegen/riscv-abi/riscv64-lp64d-abi.rs',
108                            'tests/codegen/sse42-implies-crc32.rs',
109                            'tests/codegen/thread-local.rs',
110                            'tests/codegen/uninit-consts.rs',
111                            'tests/pretty/raw-str-nonexpr.rs',
112                            'tests/run-make',
113                            'tests/run-make-fulldeps',
114                            'tests/rustdoc',
115                            'tests/rustdoc-json',
116                            'tests/rustdoc-js-std',
117                            'tests/rustdoc-ui/cfg-test.rs',
118                            'tests/rustdoc-ui/check-cfg-test.rs',
119                            'tests/rustdoc-ui/display-output.rs',
120                            'tests/rustdoc-ui/doc-comment-multi-line-attr.rs',
121                            'tests/rustdoc-ui/doc-comment-multi-line-cfg-attr.rs',
122                            'tests/rustdoc-ui/doc-test-doctest-feature.rs',
123                            'tests/rustdoc-ui/doctest-multiline-crate-attribute.rs',
124                            'tests/rustdoc-ui/doctest-output.rs',
125                            'tests/rustdoc-ui/doc-test-rustdoc-feature.rs',
126                            'tests/rustdoc-ui/failed-doctest-compile-fail.rs',
127                            'tests/rustdoc-ui/issue-80992.rs',
128                            'tests/rustdoc-ui/issue-91134.rs',
129                            'tests/rustdoc-ui/nocapture-fail.rs',
130                            'tests/rustdoc-ui/nocapture.rs',
131                            'tests/rustdoc-ui/no-run-flag.rs',
132                            'tests/rustdoc-ui/run-directory.rs',
133                            'tests/rustdoc-ui/test-no_std.rs',
134                            'tests/rustdoc-ui/test-type.rs',
135                            'tests/rustdoc/unit-return.rs',
136                            'tests/ui/abi/stack-probes-lto.rs',
137                            'tests/ui/abi/stack-probes.rs',
138                            'tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs',
139                            'tests/ui/asm/x86_64/sym.rs',
140                            'tests/ui/associated-type-bounds/fn-apit.rs',
141                            'tests/ui/associated-type-bounds/fn-dyn-apit.rs',
142                            'tests/ui/associated-type-bounds/fn-wrap-apit.rs',
143                            'tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs',
144                            'tests/ui/drop/dynamic-drop.rs',
145                            'tests/ui/empty_global_asm.rs',
146                            'tests/ui/functions-closures/fn-help-with-err.rs',
147                            'tests/ui/linkage-attr/issue-10755.rs',
148                            'tests/ui/macros/restricted-shadowing-legacy.rs',
149                            'tests/ui/process/nofile-limit.rs',
150                            'tests/ui/process/process-panic-after-fork.rs',
151                            'tests/ui/process/process-sigpipe.rs',
152                            'tests/ui/simd/target-feature-mixup.rs',
153                            'tests/ui/structs-enums/multiple-reprs.rs',
154                            'src/tools/jsondoclint',
155                            'src/tools/replace-version-placeholder',
156                            'tests/codegen/abi-efiapi.rs',
157                            'tests/codegen/abi-sysv64.rs',
158                            'tests/codegen/align-byval.rs',
159                            'tests/codegen/align-fn.rs',
160                            'tests/codegen/asm-powerpc-clobbers.rs',
161                            'tests/codegen/async-fn-debug-awaitee-field.rs',
162                            'tests/codegen/binary-search-index-no-bound-check.rs',
163                            'tests/codegen/call-metadata.rs',
164                            'tests/codegen/debug-column.rs',
165                            'tests/codegen/debug-limited.rs',
166                            'tests/codegen/debuginfo-generic-closure-env-names.rs',
167                            'tests/codegen/drop.rs',
168                            'tests/codegen/dst-vtable-align-nonzero.rs',
169                            'tests/codegen/enable-lto-unit-splitting.rs',
170                            'tests/codegen/enum/enum-u128.rs',
171                            'tests/codegen/fn-impl-trait-self.rs',
172                            'tests/codegen/inherit_overflow.rs',
173                            'tests/codegen/inline-function-args-debug-info.rs',
174                            'tests/codegen/intrinsics/mask.rs',
175                            'tests/codegen/intrinsics/transmute-niched.rs',
176                            'tests/codegen/issues/issue-73258.rs',
177                            'tests/codegen/issues/issue-75546.rs',
178                            'tests/codegen/issues/issue-77812.rs',
179                            'tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs',
180                            'tests/codegen/llvm-ident.rs',
181                            'tests/codegen/mainsubprogram.rs',
182                            'tests/codegen/move-operands.rs',
183                            'tests/codegen/repr/transparent-mips64.rs',
184                            'tests/mir-opt/',
185                            'tests/rustdoc-json',
186                            'tests/rustdoc-ui/doc-test-rustdoc-feature.rs',
187                            'tests/rustdoc-ui/no-run-flag.rs',
188                            'tests/ui-fulldeps/',
189                            'tests/ui/numbers-arithmetic/u128.rs'
190                        ]
191
192        exclude_fail_tests = " ".join([" --exclude " + item for item in exclude_list])
193        # Add exclude_fail_tests with other test arguments
194        testargs =  exclude_fail_tests + " --doc --no-fail-fast --bless"
195
196        # wrap the execution with a qemu instance.
197        # Tests are run with 512 tasks in parallel to execute all tests very quickly
198        with runqemu("core-image-minimal", runqemuparams = "nographic", qemuparams = "-m 512") as qemu:
199            # Copy remote-test-server to image through scp
200            host_sys = get_bb_var("RUST_BUILD_SYS", "rust")
201            ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user="root")
202            ssh.copy_to(builddir + "/build/" + host_sys + "/stage1-tools-bin/remote-test-server","~/")
203            # Execute remote-test-server on image through background ssh
204            command = '~/remote-test-server --bind 0.0.0.0:12345 -v'
205            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)
206            # Get the values of variables.
207            tcpath = get_bb_var("TARGET_SYS", "rust")
208            targetsys = get_bb_var("RUST_TARGET_SYS", "rust")
209            rustlibpath = get_bb_var("WORKDIR", "rust")
210            tmpdir = get_bb_var("TMPDIR", "rust")
211
212            # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools.
213            cmd = " export PATH=%s/recipe-sysroot-native/usr/bin:$PATH;" % rustlibpath
214            cmd = cmd + " export TARGET_VENDOR=\"-poky\";"
215            cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, tcpath, tmpdir)
216            cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath
217            # Trigger testing.
218            cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip
219            cmd = cmd + " cd %s; python3 src/bootstrap/bootstrap.py test %s --target %s" % (builddir, testargs, targetsys)
220            retval = runCmd(cmd)
221            end_time = time.time()
222
223            resultlog = rustlibpath + "/results-log.txt"
224            with open(resultlog, "w") as f:
225                f.write(retval.output)
226
227            ptestsuite = "rust"
228            self.ptest_section(ptestsuite, duration = int(end_time - start_time), logfile=resultlog)
229            test_results = parse_results(resultlog)
230            for test in test_results:
231                self.ptest_result(ptestsuite, test, test_results[test])
232