]> git.lizzy.rs Git - rust.git/blob - test-cargo-miri/run-test.py
test for unnecessary rebuilds in 'cargo miri run'
[rust.git] / test-cargo-miri / run-test.py
1 #!/usr/bin/env python3
2 '''
3 Test whether cargo-miri works properly.
4 Assumes the `MIRI_SYSROOT` env var to be set appropriately,
5 and the working directory to contain the cargo-miri-test project.
6 '''
7
8 import sys, subprocess, os
9
10 CGREEN  = '\33[32m'
11 CBOLD   = '\33[1m'
12 CEND    = '\33[0m'
13
14 def fail(msg):
15     print("\nTEST FAIL: {}".format(msg))
16     sys.exit(1)
17
18 def cargo_miri(cmd, quiet = True):
19     args = ["cargo", "miri", cmd]
20     if quiet:
21         args += ["-q"]
22     if 'MIRI_TEST_TARGET' in os.environ:
23         args += ["--target", os.environ['MIRI_TEST_TARGET']]
24     return args
25
26 def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env={}):
27     print("Testing {}...".format(name))
28     ## Call `cargo miri`, capture all output
29     p_env = os.environ.copy()
30     p_env.update(env)
31     p = subprocess.Popen(
32         cmd,
33         stdin=subprocess.PIPE,
34         stdout=subprocess.PIPE,
35         stderr=subprocess.PIPE,
36         env=p_env,
37     )
38     (stdout, stderr) = p.communicate(input=stdin)
39     stdout = stdout.decode("UTF-8")
40     stderr = stderr.decode("UTF-8")
41     if p.returncode == 0 and stdout == open(stdout_ref).read() and stderr == open(stderr_ref).read():
42         # All good!
43         return
44     # Show output
45     print("--- BEGIN stdout ---")
46     print(stdout, end="")
47     print("--- END stdout ---")
48     print("--- BEGIN stderr ---")
49     print(stderr, end="")
50     print("--- END stderr ---")
51     fail("exit code was {}".format(p.returncode))
52
53 def test_rebuild(name, cmd, rebuild_count_expected):
54     print("Testing {}...".format(name))
55     p = subprocess.Popen(
56         cmd,
57         stdout=subprocess.PIPE,
58         stderr=subprocess.PIPE,
59     )
60     (stdout, stderr) = p.communicate()
61     stdout = stdout.decode("UTF-8")
62     stderr = stderr.decode("UTF-8")
63     if p.returncode != 0:
64         fail("rebuild failed");
65     rebuild_count =  stderr.count(" Compiling ");
66     if rebuild_count != rebuild_count_expected:
67         print("--- BEGIN stderr ---")
68         print(stderr, end="")
69         print("--- END stderr ---")
70         fail("Expected {} rebuild(s), but got {}".format(rebuild_count_expected, rebuild_count));
71
72 def test_cargo_miri_run():
73     test("`cargo miri run` (no isolation)",
74         cargo_miri("run"),
75         "run.default.stdout.ref", "run.default.stderr.ref",
76         stdin=b'12\n21\n',
77         env={
78             'MIRIFLAGS': "-Zmiri-disable-isolation",
79             'MIRITESTVAR': "wrongval", # make sure the build.rs value takes precedence
80         },
81     )
82     test("`cargo miri run` (with arguments and target)",
83         cargo_miri("run") + ["--bin", "cargo-miri-test", "--", "hello world", '"hello world"'],
84         "run.args.stdout.ref", "run.args.stderr.ref",
85     )
86     test("`cargo miri run` (subcrate, no ioslation)",
87         cargo_miri("run") + ["-p", "subcrate"],
88         "run.subcrate.stdout.ref", "run.subcrate.stderr.ref",
89         env={'MIRIFLAGS': "-Zmiri-disable-isolation"},
90     )
91     # Special test: run it again *without* `-q` to make sure nothing is being rebuilt (Miri issue #1722)
92     test_rebuild("`cargo miri run` (clean rebuild)",
93         cargo_miri("run", quiet=False) + ["--", ""],
94         rebuild_count_expected=1,
95     )
96
97 def test_cargo_miri_test():
98     # rustdoc is not run on foreign targets
99     is_foreign = 'MIRI_TEST_TARGET' in os.environ
100     rustdoc_ref = "test.stderr-empty.ref" if is_foreign else "test.stderr-rustdoc.ref"
101
102     test("`cargo miri test`",
103         cargo_miri("test"),
104         "test.default.stdout.ref", rustdoc_ref,
105         env={'MIRIFLAGS': "-Zmiri-seed=feed"},
106     )
107     test("`cargo miri test` (no isolation)",
108         cargo_miri("test"),
109         "test.default.stdout.ref", rustdoc_ref,
110         env={'MIRIFLAGS': "-Zmiri-disable-isolation"},
111     )
112     test("`cargo miri test` (raw-ptr tracking)",
113         cargo_miri("test"),
114         "test.default.stdout.ref", rustdoc_ref,
115         env={'MIRIFLAGS': "-Zmiri-track-raw-pointers"},
116     )
117     test("`cargo miri test` (with filter)",
118         cargo_miri("test") + ["--", "--format=pretty", "le1"],
119         "test.filter.stdout.ref", rustdoc_ref,
120     )
121     test("`cargo miri test` (test target)",
122         cargo_miri("test") + ["--test", "test", "--", "--format=pretty"],
123         "test.test-target.stdout.ref", "test.stderr-empty.ref",
124     )
125     test("`cargo miri test` (bin target)",
126         cargo_miri("test") + ["--bin", "cargo-miri-test", "--", "--format=pretty"],
127         "test.bin-target.stdout.ref", "test.stderr-empty.ref",
128     )
129     test("`cargo miri test` (subcrate, no isolation)",
130         cargo_miri("test") + ["-p", "subcrate"],
131         "test.subcrate.stdout.ref", "test.stderr-proc-macro.ref",
132         env={'MIRIFLAGS': "-Zmiri-disable-isolation"},
133     )
134
135 os.chdir(os.path.dirname(os.path.realpath(__file__)))
136 os.environ["RUST_TEST_NOCAPTURE"] = "0" # this affects test output, so make sure it is not set
137
138 target_str = " for target {}".format(os.environ['MIRI_TEST_TARGET']) if 'MIRI_TEST_TARGET' in os.environ else ""
139 print(CGREEN + CBOLD + "## Running `cargo miri` tests{}".format(target_str) + CEND)
140
141 if not 'MIRI_SYSROOT' in os.environ:
142     # Make sure we got a working sysroot.
143     # (If the sysroot gets built later when output is compared, that leads to test failures.)
144     subprocess.run(cargo_miri("setup"), check=True)
145 test_cargo_miri_run()
146 test_cargo_miri_test()
147
148 print("\nTEST SUCCESSFUL!")
149 sys.exit(0)