10bb1c928SMiguel Ojeda#!/usr/bin/env python3 20bb1c928SMiguel Ojeda# SPDX-License-Identifier: GPL-2.0 30bb1c928SMiguel Ojeda 40bb1c928SMiguel Ojeda"""Tests the `rust_is_available.sh` script. 50bb1c928SMiguel Ojeda 60bb1c928SMiguel OjedaSome of the tests require the real programs to be available in `$PATH` 70bb1c928SMiguel Ojedaunder their canonical name (and with the expected versions). 80bb1c928SMiguel Ojeda""" 90bb1c928SMiguel Ojeda 100bb1c928SMiguel Ojedaimport enum 110bb1c928SMiguel Ojedaimport os 120bb1c928SMiguel Ojedaimport pathlib 130bb1c928SMiguel Ojedaimport stat 140bb1c928SMiguel Ojedaimport subprocess 150bb1c928SMiguel Ojedaimport tempfile 160bb1c928SMiguel Ojedaimport unittest 170bb1c928SMiguel Ojeda 180bb1c928SMiguel Ojedaclass TestRustIsAvailable(unittest.TestCase): 190bb1c928SMiguel Ojeda @enum.unique 200bb1c928SMiguel Ojeda class Expected(enum.Enum): 210bb1c928SMiguel Ojeda SUCCESS = enum.auto() 220bb1c928SMiguel Ojeda SUCCESS_WITH_WARNINGS = enum.auto() 230bb1c928SMiguel Ojeda SUCCESS_WITH_EXTRA_OUTPUT = enum.auto() 240bb1c928SMiguel Ojeda FAILURE = enum.auto() 250bb1c928SMiguel Ojeda 260bb1c928SMiguel Ojeda @classmethod 270bb1c928SMiguel Ojeda def generate_executable(cls, content): 280bb1c928SMiguel Ojeda path = pathlib.Path(cls.tempdir.name) 290bb1c928SMiguel Ojeda name = str(len(tuple(path.iterdir()))) 300bb1c928SMiguel Ojeda path = path / name 310bb1c928SMiguel Ojeda with open(path, "w") as file_: 320bb1c928SMiguel Ojeda file_.write(content) 330bb1c928SMiguel Ojeda os.chmod(path, os.stat(path).st_mode | stat.S_IXUSR) 340bb1c928SMiguel Ojeda return path 350bb1c928SMiguel Ojeda 360bb1c928SMiguel Ojeda @classmethod 370bb1c928SMiguel Ojeda def generate_clang(cls, stdout): 380bb1c928SMiguel Ojeda return cls.generate_executable(f"""#!/usr/bin/env python3 390bb1c928SMiguel Ojedaimport sys 400bb1c928SMiguel Ojedaif "-E" in " ".join(sys.argv): 410bb1c928SMiguel Ojeda print({repr("Clang " + " ".join(cls.llvm_default_version.split(" ")))}) 420bb1c928SMiguel Ojedaelse: 430bb1c928SMiguel Ojeda print({repr(stdout)}) 440bb1c928SMiguel Ojeda""") 450bb1c928SMiguel Ojeda 460bb1c928SMiguel Ojeda @classmethod 470bb1c928SMiguel Ojeda def generate_rustc(cls, stdout): 480bb1c928SMiguel Ojeda return cls.generate_executable(f"""#!/usr/bin/env python3 490bb1c928SMiguel Ojedaimport sys 500bb1c928SMiguel Ojedaif "--print sysroot" in " ".join(sys.argv): 510bb1c928SMiguel Ojeda print({repr(cls.rust_default_sysroot)}) 520bb1c928SMiguel Ojedaelse: 530bb1c928SMiguel Ojeda print({repr(stdout)}) 540bb1c928SMiguel Ojeda""") 550bb1c928SMiguel Ojeda 560bb1c928SMiguel Ojeda @classmethod 57*b2603f8aSMiguel Ojeda def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False, libclang_concat_patched=False): 58d49082faSMiguel Ojeda if libclang_stderr is None: 59d49082faSMiguel Ojeda libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})" 60d49082faSMiguel Ojeda else: 61d49082faSMiguel Ojeda libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)" 62d49082faSMiguel Ojeda 63981ad93cSMiguel Ojeda if version_0_66_patched: 64981ad93cSMiguel Ojeda version_0_66_case = "pass" 65981ad93cSMiguel Ojeda else: 66981ad93cSMiguel Ojeda version_0_66_case = "raise SystemExit(1)" 67981ad93cSMiguel Ojeda 68*b2603f8aSMiguel Ojeda if libclang_concat_patched: 69*b2603f8aSMiguel Ojeda libclang_concat_case = "print('pub static mut foofoo: ::std::os::raw::c_int;')" 70*b2603f8aSMiguel Ojeda else: 71*b2603f8aSMiguel Ojeda libclang_concat_case = "pass" 72*b2603f8aSMiguel Ojeda 730bb1c928SMiguel Ojeda return cls.generate_executable(f"""#!/usr/bin/env python3 740bb1c928SMiguel Ojedaimport sys 750bb1c928SMiguel Ojedaif "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv): 76d49082faSMiguel Ojeda {libclang_case} 77981ad93cSMiguel Ojedaelif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv): 78981ad93cSMiguel Ojeda {version_0_66_case} 79*b2603f8aSMiguel Ojedaelif "rust_is_available_bindgen_libclang_concat.h" in " ".join(sys.argv): 80*b2603f8aSMiguel Ojeda {libclang_concat_case} 810bb1c928SMiguel Ojedaelse: 820bb1c928SMiguel Ojeda print({repr(version_stdout)}) 830bb1c928SMiguel Ojeda""") 840bb1c928SMiguel Ojeda 850bb1c928SMiguel Ojeda @classmethod 86981ad93cSMiguel Ojeda def generate_bindgen_version(cls, stdout, version_0_66_patched=False): 87981ad93cSMiguel Ojeda return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr, version_0_66_patched) 880bb1c928SMiguel Ojeda 890bb1c928SMiguel Ojeda @classmethod 90d49082faSMiguel Ojeda def generate_bindgen_libclang_failure(cls): 91d49082faSMiguel Ojeda return cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, None) 92d49082faSMiguel Ojeda 93d49082faSMiguel Ojeda @classmethod 940bb1c928SMiguel Ojeda def generate_bindgen_libclang(cls, stderr): 950bb1c928SMiguel Ojeda return cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, stderr) 960bb1c928SMiguel Ojeda 970bb1c928SMiguel Ojeda @classmethod 980bb1c928SMiguel Ojeda def setUpClass(cls): 990bb1c928SMiguel Ojeda cls.tempdir = tempfile.TemporaryDirectory() 1000bb1c928SMiguel Ojeda 1010bb1c928SMiguel Ojeda cls.missing = pathlib.Path(cls.tempdir.name) / "missing" 1020bb1c928SMiguel Ojeda 1030bb1c928SMiguel Ojeda cls.nonexecutable = pathlib.Path(cls.tempdir.name) / "nonexecutable" 1040bb1c928SMiguel Ojeda with open(cls.nonexecutable, "w") as file_: 1050bb1c928SMiguel Ojeda file_.write("nonexecutable") 1060bb1c928SMiguel Ojeda 1070bb1c928SMiguel Ojeda cls.unexpected_binary = "true" 1080bb1c928SMiguel Ojeda 1090bb1c928SMiguel Ojeda cls.rustc_default_version = subprocess.check_output(("scripts/min-tool-version.sh", "rustc")).decode().strip() 1100bb1c928SMiguel Ojeda cls.bindgen_default_version = subprocess.check_output(("scripts/min-tool-version.sh", "bindgen")).decode().strip() 1110bb1c928SMiguel Ojeda cls.llvm_default_version = subprocess.check_output(("scripts/min-tool-version.sh", "llvm")).decode().strip() 1120bb1c928SMiguel Ojeda cls.rust_default_sysroot = subprocess.check_output(("rustc", "--print", "sysroot")).decode().strip() 1130bb1c928SMiguel Ojeda 1140bb1c928SMiguel Ojeda cls.bindgen_default_bindgen_version_stdout = f"bindgen {cls.bindgen_default_version}" 115d49082faSMiguel Ojeda cls.bindgen_default_bindgen_libclang_failure_exit_code = 42 1160bb1c928SMiguel Ojeda cls.bindgen_default_bindgen_libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {cls.llvm_default_version} [-W#pragma-messages], err: false" 1170bb1c928SMiguel Ojeda 1180bb1c928SMiguel Ojeda cls.default_rustc = cls.generate_rustc(f"rustc {cls.rustc_default_version}") 1190bb1c928SMiguel Ojeda cls.default_bindgen = cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, cls.bindgen_default_bindgen_libclang_stderr) 1200bb1c928SMiguel Ojeda cls.default_cc = cls.generate_clang(f"clang version {cls.llvm_default_version}") 1210bb1c928SMiguel Ojeda 1220bb1c928SMiguel Ojeda def run_script(self, expected, override_env): 1230bb1c928SMiguel Ojeda env = { 1240bb1c928SMiguel Ojeda "RUSTC": self.default_rustc, 1250bb1c928SMiguel Ojeda "BINDGEN": self.default_bindgen, 1260bb1c928SMiguel Ojeda "CC": self.default_cc, 1270bb1c928SMiguel Ojeda } 1280bb1c928SMiguel Ojeda 1290bb1c928SMiguel Ojeda for key, value in override_env.items(): 1300bb1c928SMiguel Ojeda if value is None: 1310bb1c928SMiguel Ojeda del env[key] 1320bb1c928SMiguel Ojeda continue 1330bb1c928SMiguel Ojeda env[key] = value 1340bb1c928SMiguel Ojeda 1350bb1c928SMiguel Ojeda result = subprocess.run("scripts/rust_is_available.sh", env=env, capture_output=True) 1360bb1c928SMiguel Ojeda 1370bb1c928SMiguel Ojeda # The script should never output anything to `stdout`. 1380bb1c928SMiguel Ojeda self.assertEqual(result.stdout, b"") 1390bb1c928SMiguel Ojeda 1400bb1c928SMiguel Ojeda if expected == self.Expected.SUCCESS: 1410bb1c928SMiguel Ojeda # When expecting a success, the script should return 0 1420bb1c928SMiguel Ojeda # and it should not output anything to `stderr`. 1430bb1c928SMiguel Ojeda self.assertEqual(result.returncode, 0) 1440bb1c928SMiguel Ojeda self.assertEqual(result.stderr, b"") 1450bb1c928SMiguel Ojeda elif expected == self.Expected.SUCCESS_WITH_EXTRA_OUTPUT: 1460bb1c928SMiguel Ojeda # When expecting a success with extra output (that is not warnings, 1470bb1c928SMiguel Ojeda # which is the common case), the script should return 0 and it 1480bb1c928SMiguel Ojeda # should output at least something to `stderr` (the output should 1490bb1c928SMiguel Ojeda # be checked further by the test). 1500bb1c928SMiguel Ojeda self.assertEqual(result.returncode, 0) 1510bb1c928SMiguel Ojeda self.assertNotEqual(result.stderr, b"") 1520bb1c928SMiguel Ojeda elif expected == self.Expected.SUCCESS_WITH_WARNINGS: 1530bb1c928SMiguel Ojeda # When expecting a success with warnings, the script should return 0 1540bb1c928SMiguel Ojeda # and it should output at least the instructions to `stderr`. 1550bb1c928SMiguel Ojeda self.assertEqual(result.returncode, 0) 1560bb1c928SMiguel Ojeda self.assertIn(b"Please see Documentation/rust/quick-start.rst for details", result.stderr) 1570bb1c928SMiguel Ojeda else: 1580bb1c928SMiguel Ojeda # When expecting a failure, the script should return non-0 1590bb1c928SMiguel Ojeda # and it should output at least the instructions to `stderr`. 1600bb1c928SMiguel Ojeda self.assertNotEqual(result.returncode, 0) 1610bb1c928SMiguel Ojeda self.assertIn(b"Please see Documentation/rust/quick-start.rst for details", result.stderr) 1620bb1c928SMiguel Ojeda 1630bb1c928SMiguel Ojeda # The output will generally be UTF-8 (i.e. unless the user has 1640bb1c928SMiguel Ojeda # put strange values in the environment). 1650bb1c928SMiguel Ojeda result.stderr = result.stderr.decode() 1660bb1c928SMiguel Ojeda 1670bb1c928SMiguel Ojeda return result 1680bb1c928SMiguel Ojeda 1690bb1c928SMiguel Ojeda def test_rustc_unset(self): 1700bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": None }) 1710bb1c928SMiguel Ojeda self.assertIn("Environment variable 'RUSTC' is not set.", result.stderr) 1720bb1c928SMiguel Ojeda self.assertIn("This script is intended to be called from Kbuild.", result.stderr) 1730bb1c928SMiguel Ojeda 1740bb1c928SMiguel Ojeda def test_bindgen_unset(self): 1750bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": None }) 1760bb1c928SMiguel Ojeda self.assertIn("Environment variable 'BINDGEN' is not set.", result.stderr) 1770bb1c928SMiguel Ojeda self.assertIn("This script is intended to be called from Kbuild.", result.stderr) 1780bb1c928SMiguel Ojeda 1790bb1c928SMiguel Ojeda def test_cc_unset(self): 1800bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "CC": None }) 1810bb1c928SMiguel Ojeda self.assertIn("Environment variable 'CC' is not set.", result.stderr) 1820bb1c928SMiguel Ojeda self.assertIn("This script is intended to be called from Kbuild.", result.stderr) 1830bb1c928SMiguel Ojeda 1840bb1c928SMiguel Ojeda def test_rustc_missing(self): 1850bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.missing }) 1860bb1c928SMiguel Ojeda self.assertIn(f"Rust compiler '{self.missing}' could not be found.", result.stderr) 1870bb1c928SMiguel Ojeda 1880bb1c928SMiguel Ojeda def test_bindgen_missing(self): 1890bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.missing }) 1900bb1c928SMiguel Ojeda self.assertIn(f"Rust bindings generator '{self.missing}' could not be found.", result.stderr) 1910bb1c928SMiguel Ojeda 1920bb1c928SMiguel Ojeda def test_rustc_nonexecutable(self): 1930bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.nonexecutable }) 1940bb1c928SMiguel Ojeda self.assertIn(f"Running '{self.nonexecutable}' to check the Rust compiler version failed with", result.stderr) 1950bb1c928SMiguel Ojeda 1960bb1c928SMiguel Ojeda def test_rustc_unexpected_binary(self): 1970bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.unexpected_binary }) 1980bb1c928SMiguel Ojeda self.assertIn(f"Running '{self.unexpected_binary}' to check the Rust compiler version did not return", result.stderr) 1990bb1c928SMiguel Ojeda 2000bb1c928SMiguel Ojeda def test_rustc_unexpected_name(self): 2010bb1c928SMiguel Ojeda rustc = self.generate_rustc(f"unexpected {self.rustc_default_version} (a8314ef7d 2022-06-27)") 2020bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": rustc }) 2030bb1c928SMiguel Ojeda self.assertIn(f"Running '{rustc}' to check the Rust compiler version did not return", result.stderr) 2040bb1c928SMiguel Ojeda 2050bb1c928SMiguel Ojeda def test_rustc_unexpected_version(self): 2060bb1c928SMiguel Ojeda rustc = self.generate_rustc("rustc unexpected (a8314ef7d 2022-06-27)") 2070bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": rustc }) 2080bb1c928SMiguel Ojeda self.assertIn(f"Running '{rustc}' to check the Rust compiler version did not return", result.stderr) 2090bb1c928SMiguel Ojeda 2100bb1c928SMiguel Ojeda def test_rustc_no_minor(self): 2110bb1c928SMiguel Ojeda rustc = self.generate_rustc(f"rustc {'.'.join(self.rustc_default_version.split('.')[:2])} (a8314ef7d 2022-06-27)") 2120bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": rustc }) 2130bb1c928SMiguel Ojeda self.assertIn(f"Running '{rustc}' to check the Rust compiler version did not return", result.stderr) 2140bb1c928SMiguel Ojeda 2150bb1c928SMiguel Ojeda def test_rustc_old_version(self): 2160bb1c928SMiguel Ojeda rustc = self.generate_rustc("rustc 1.60.0 (a8314ef7d 2022-06-27)") 2170bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUSTC": rustc }) 2180bb1c928SMiguel Ojeda self.assertIn(f"Rust compiler '{rustc}' is too old.", result.stderr) 2190bb1c928SMiguel Ojeda 2200bb1c928SMiguel Ojeda def test_bindgen_nonexecutable(self): 2210bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.nonexecutable }) 2220bb1c928SMiguel Ojeda self.assertIn(f"Running '{self.nonexecutable}' to check the Rust bindings generator version failed with", result.stderr) 2230bb1c928SMiguel Ojeda 2240bb1c928SMiguel Ojeda def test_bindgen_unexpected_binary(self): 2250bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.unexpected_binary }) 2260bb1c928SMiguel Ojeda self.assertIn(f"Running '{self.unexpected_binary}' to check the bindings generator version did not return", result.stderr) 2270bb1c928SMiguel Ojeda 2280bb1c928SMiguel Ojeda def test_bindgen_unexpected_name(self): 2290bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_version(f"unexpected {self.bindgen_default_version}") 2300bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2310bb1c928SMiguel Ojeda self.assertIn(f"Running '{bindgen}' to check the bindings generator version did not return", result.stderr) 2320bb1c928SMiguel Ojeda 2330bb1c928SMiguel Ojeda def test_bindgen_unexpected_version(self): 2340bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_version("bindgen unexpected") 2350bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2360bb1c928SMiguel Ojeda self.assertIn(f"Running '{bindgen}' to check the bindings generator version did not return", result.stderr) 2370bb1c928SMiguel Ojeda 2380bb1c928SMiguel Ojeda def test_bindgen_no_minor(self): 2390bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_version(f"bindgen {'.'.join(self.bindgen_default_version.split('.')[:2])}") 2400bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2410bb1c928SMiguel Ojeda self.assertIn(f"Running '{bindgen}' to check the bindings generator version did not return", result.stderr) 2420bb1c928SMiguel Ojeda 2430bb1c928SMiguel Ojeda def test_bindgen_old_version(self): 2440bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_version("bindgen 0.50.0") 2450bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2460bb1c928SMiguel Ojeda self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr) 2470bb1c928SMiguel Ojeda 248981ad93cSMiguel Ojeda def test_bindgen_bad_version_0_66_0_and_0_66_1(self): 249981ad93cSMiguel Ojeda for version in ("0.66.0", "0.66.1"): 250981ad93cSMiguel Ojeda with self.subTest(version=version): 251981ad93cSMiguel Ojeda bindgen = self.generate_bindgen_version(f"bindgen {version}") 252981ad93cSMiguel Ojeda result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) 253981ad93cSMiguel Ojeda self.assertIn(f"Rust bindings generator '{bindgen}' versions 0.66.0 and 0.66.1 may not", result.stderr) 254981ad93cSMiguel Ojeda 255981ad93cSMiguel Ojeda def test_bindgen_bad_version_0_66_0_and_0_66_1_patched(self): 256981ad93cSMiguel Ojeda for version in ("0.66.0", "0.66.1"): 257981ad93cSMiguel Ojeda with self.subTest(version=version): 258981ad93cSMiguel Ojeda bindgen = self.generate_bindgen_version(f"bindgen {version}", True) 259981ad93cSMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen }) 260981ad93cSMiguel Ojeda 2610bb1c928SMiguel Ojeda def test_bindgen_libclang_failure(self): 262d49082faSMiguel Ojeda bindgen = self.generate_bindgen_libclang_failure() 263d49082faSMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 264d49082faSMiguel Ojeda self.assertIn(f"Running '{bindgen}' to check the libclang version (used by the Rust", result.stderr) 265d49082faSMiguel Ojeda self.assertIn(f"bindings generator) failed with code {self.bindgen_default_bindgen_libclang_failure_exit_code}. This may be caused by", result.stderr) 2660bb1c928SMiguel Ojeda 2670bb1c928SMiguel Ojeda def test_bindgen_libclang_unexpected_version(self): 2680bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version unexpected [-W#pragma-messages], err: false") 2690bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2700bb1c928SMiguel Ojeda self.assertIn(f"Running '{bindgen}' to check the libclang version (used by the Rust", result.stderr) 2710bb1c928SMiguel Ojeda self.assertIn("bindings generator) did not return an expected output. See output", result.stderr) 2720bb1c928SMiguel Ojeda 2730bb1c928SMiguel Ojeda def test_bindgen_libclang_old_version(self): 2740bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 10.0.0 [-W#pragma-messages], err: false") 2750bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 2760bb1c928SMiguel Ojeda self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr) 2770bb1c928SMiguel Ojeda 278*b2603f8aSMiguel Ojeda def test_bindgen_bad_libclang_concat(self): 279*b2603f8aSMiguel Ojeda for (bindgen_version, libclang_version, expected_not_patched) in ( 280*b2603f8aSMiguel Ojeda ("0.69.4", "18.0.0", self.Expected.SUCCESS), 281*b2603f8aSMiguel Ojeda ("0.69.4", "19.1.0", self.Expected.SUCCESS_WITH_WARNINGS), 282*b2603f8aSMiguel Ojeda ("0.69.4", "19.2.0", self.Expected.SUCCESS_WITH_WARNINGS), 283*b2603f8aSMiguel Ojeda 284*b2603f8aSMiguel Ojeda ("0.69.5", "18.0.0", self.Expected.SUCCESS), 285*b2603f8aSMiguel Ojeda ("0.69.5", "19.1.0", self.Expected.SUCCESS), 286*b2603f8aSMiguel Ojeda ("0.69.5", "19.2.0", self.Expected.SUCCESS), 287*b2603f8aSMiguel Ojeda 288*b2603f8aSMiguel Ojeda ("0.70.0", "18.0.0", self.Expected.SUCCESS), 289*b2603f8aSMiguel Ojeda ("0.70.0", "19.1.0", self.Expected.SUCCESS), 290*b2603f8aSMiguel Ojeda ("0.70.0", "19.2.0", self.Expected.SUCCESS), 291*b2603f8aSMiguel Ojeda ): 292*b2603f8aSMiguel Ojeda with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version): 293*b2603f8aSMiguel Ojeda cc = self.generate_clang(f"clang version {libclang_version}") 294*b2603f8aSMiguel Ojeda libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false" 295*b2603f8aSMiguel Ojeda bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr) 296*b2603f8aSMiguel Ojeda result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc }) 297*b2603f8aSMiguel Ojeda if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS: 298*b2603f8aSMiguel Ojeda self.assertIn(f"Rust bindings generator '{bindgen}' < 0.69.5 together with libclang >= 19.1", result.stderr) 299*b2603f8aSMiguel Ojeda 300*b2603f8aSMiguel Ojeda bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_concat_patched=True) 301*b2603f8aSMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc }) 302*b2603f8aSMiguel Ojeda 3030bb1c928SMiguel Ojeda def test_clang_matches_bindgen_libclang_different_bindgen(self): 3040bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false") 3050bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) 3060bb1c928SMiguel Ojeda self.assertIn("version does not match Clang's. This may be a problem.", result.stderr) 3070bb1c928SMiguel Ojeda 3080bb1c928SMiguel Ojeda def test_clang_matches_bindgen_libclang_different_clang(self): 3090bb1c928SMiguel Ojeda cc = self.generate_clang("clang version 999.0.0") 3100bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "CC": cc }) 3110bb1c928SMiguel Ojeda self.assertIn("version does not match Clang's. This may be a problem.", result.stderr) 3120bb1c928SMiguel Ojeda 3130bb1c928SMiguel Ojeda def test_rustc_src_core_krustflags(self): 3140bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "PATH": os.environ["PATH"], "RUSTC": "rustc", "KRUSTFLAGS": f"--sysroot={self.missing}" }) 3150bb1c928SMiguel Ojeda self.assertIn("Source code for the 'core' standard library could not be found", result.stderr) 3160bb1c928SMiguel Ojeda 3170bb1c928SMiguel Ojeda def test_rustc_src_core_rustlibsrc(self): 3180bb1c928SMiguel Ojeda result = self.run_script(self.Expected.FAILURE, { "RUST_LIB_SRC": self.missing }) 3190bb1c928SMiguel Ojeda self.assertIn("Source code for the 'core' standard library could not be found", result.stderr) 3200bb1c928SMiguel Ojeda 3210bb1c928SMiguel Ojeda def test_success_cc_unknown(self): 3220bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS_WITH_EXTRA_OUTPUT, { "CC": self.missing }) 3230bb1c928SMiguel Ojeda self.assertIn("unknown C compiler", result.stderr) 3240bb1c928SMiguel Ojeda 3250bb1c928SMiguel Ojeda def test_success_cc_multiple_arguments_ccache(self): 3260bb1c928SMiguel Ojeda clang = self.generate_clang(f"""Ubuntu clang version {self.llvm_default_version}-1ubuntu1 3270bb1c928SMiguel OjedaTarget: x86_64-pc-linux-gnu 3280bb1c928SMiguel OjedaThread model: posix 3290bb1c928SMiguel OjedaInstalledDir: /usr/bin 3300bb1c928SMiguel Ojeda""") 3310bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "CC": f"{clang} clang" }) 3320bb1c928SMiguel Ojeda 3330bb1c928SMiguel Ojeda def test_success_rustc_version(self): 3340bb1c928SMiguel Ojeda for rustc_stdout in ( 3350bb1c928SMiguel Ojeda f"rustc {self.rustc_default_version} (a8314ef7d 2022-06-27)", 3360bb1c928SMiguel Ojeda f"rustc {self.rustc_default_version}-dev (a8314ef7d 2022-06-27)", 3370bb1c928SMiguel Ojeda f"rustc {self.rustc_default_version}-1.60.0 (a8314ef7d 2022-06-27)", 3380bb1c928SMiguel Ojeda ): 3390bb1c928SMiguel Ojeda with self.subTest(rustc_stdout=rustc_stdout): 3400bb1c928SMiguel Ojeda rustc = self.generate_rustc(rustc_stdout) 3410bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "RUSTC": rustc }) 3420bb1c928SMiguel Ojeda 3430bb1c928SMiguel Ojeda def test_success_bindgen_version(self): 3440bb1c928SMiguel Ojeda for bindgen_stdout in ( 3450bb1c928SMiguel Ojeda f"bindgen {self.bindgen_default_version}", 3460bb1c928SMiguel Ojeda f"bindgen {self.bindgen_default_version}-dev", 3470bb1c928SMiguel Ojeda f"bindgen {self.bindgen_default_version}-0.999.0", 3480bb1c928SMiguel Ojeda ): 3490bb1c928SMiguel Ojeda with self.subTest(bindgen_stdout=bindgen_stdout): 3500bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_version(bindgen_stdout) 3510bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen }) 3520bb1c928SMiguel Ojeda 3530bb1c928SMiguel Ojeda def test_success_bindgen_libclang(self): 3540bb1c928SMiguel Ojeda for stderr in ( 3550bb1c928SMiguel Ojeda f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (https://github.com/llvm/llvm-project.git 4a2c05b05ed07f1f620e94f6524a8b4b2760a0b1) [-W#pragma-messages], err: false", 3560bb1c928SMiguel Ojeda f"/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false", 3570bb1c928SMiguel Ojeda f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false", 3580bb1c928SMiguel Ojeda f""" 3590bb1c928SMiguel Ojeda/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1-p16/bin/bash: warning: setlocale: LC_ALL: cannot change locale (c) 3600bb1c928SMiguel Ojedascripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} [-W#pragma-messages], err: false 3610bb1c928SMiguel Ojeda""", 3620bb1c928SMiguel Ojeda f""" 3630bb1c928SMiguel Ojeda/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1.0-p16/bin/bash: warning: setlocale: LC_ALL: cannot change locale (c) 3640bb1c928SMiguel Ojeda/home/jd/Documents/dev/kernel-module-flake/linux-6.1/outputs/dev/lib/modules/6.1.0-development/source/scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {self.llvm_default_version} (Fedora 13.0.0-3.fc35) [-W#pragma-messages], err: false 3650bb1c928SMiguel Ojeda""" 3660bb1c928SMiguel Ojeda ): 3670bb1c928SMiguel Ojeda with self.subTest(stderr=stderr): 3680bb1c928SMiguel Ojeda bindgen = self.generate_bindgen_libclang(stderr) 3690bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen }) 3700bb1c928SMiguel Ojeda 3710bb1c928SMiguel Ojeda def test_success_clang_version(self): 3720bb1c928SMiguel Ojeda for clang_stdout in ( 3730bb1c928SMiguel Ojeda f"clang version {self.llvm_default_version} (https://github.com/llvm/llvm-project.git 4a2c05b05ed07f1f620e94f6524a8b4b2760a0b1)", 3740bb1c928SMiguel Ojeda f"clang version {self.llvm_default_version}-dev", 3750bb1c928SMiguel Ojeda f"clang version {self.llvm_default_version}-2~ubuntu20.04.1", 3760bb1c928SMiguel Ojeda f"Ubuntu clang version {self.llvm_default_version}-2~ubuntu20.04.1", 3770bb1c928SMiguel Ojeda ): 3780bb1c928SMiguel Ojeda with self.subTest(clang_stdout=clang_stdout): 3790bb1c928SMiguel Ojeda clang = self.generate_clang(clang_stdout) 3800bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { "CC": clang }) 3810bb1c928SMiguel Ojeda 3820bb1c928SMiguel Ojeda def test_success_real_programs(self): 3830bb1c928SMiguel Ojeda for cc in ["gcc", "clang"]: 3840bb1c928SMiguel Ojeda with self.subTest(cc=cc): 3850bb1c928SMiguel Ojeda result = self.run_script(self.Expected.SUCCESS, { 3860bb1c928SMiguel Ojeda "PATH": os.environ["PATH"], 3870bb1c928SMiguel Ojeda "RUSTC": "rustc", 3880bb1c928SMiguel Ojeda "BINDGEN": "bindgen", 3890bb1c928SMiguel Ojeda "CC": cc, 3900bb1c928SMiguel Ojeda }) 3910bb1c928SMiguel Ojeda 3920bb1c928SMiguel Ojedaif __name__ == "__main__": 3930bb1c928SMiguel Ojeda unittest.main() 394