rust/src/bootstrap/bootstrap_test.py

170 lines
6.5 KiB
Python

"""Bootstrap tests
Run these with `x test bootstrap`, or `python -m unittest src/bootstrap/bootstrap_test.py`."""
from __future__ import absolute_import, division, print_function
import os
import unittest
import tempfile
import hashlib
import sys
from shutil import rmtree
# Allow running this from the top-level directory.
bootstrap_dir = os.path.dirname(os.path.abspath(__file__))
# For the import below, have Python search in src/bootstrap first.
sys.path.insert(0, bootstrap_dir)
import bootstrap # noqa: E402
import configure # noqa: E402
def serialize_and_parse(configure_args, bootstrap_args=None):
from io import StringIO
if bootstrap_args is None:
bootstrap_args = bootstrap.FakeArgs()
section_order, sections, targets = configure.parse_args(configure_args)
buffer = StringIO()
configure.write_config_toml(buffer, section_order, targets, sections)
build = bootstrap.RustBuild(config_toml=buffer.getvalue(), args=bootstrap_args)
try:
import tomllib
# Verify this is actually valid TOML.
tomllib.loads(build.config_toml)
except ImportError:
print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr)
return build
class VerifyTestCase(unittest.TestCase):
"""Test Case for verify"""
def setUp(self):
self.container = tempfile.mkdtemp()
self.src = os.path.join(self.container, "src.txt")
self.bad_src = os.path.join(self.container, "bad.txt")
content = "Hello world"
self.expected = hashlib.sha256(content.encode("utf-8")).hexdigest()
with open(self.src, "w") as src:
src.write(content)
with open(self.bad_src, "w") as bad:
bad.write("Hello!")
def tearDown(self):
rmtree(self.container)
def test_valid_file(self):
"""Check if the sha256 sum of the given file is valid"""
self.assertTrue(bootstrap.verify(self.src, self.expected, False))
def test_invalid_file(self):
"""Should verify that the file is invalid"""
self.assertFalse(bootstrap.verify(self.bad_src, self.expected, False))
class ProgramOutOfDate(unittest.TestCase):
"""Test if a program is out of date"""
def setUp(self):
self.container = tempfile.mkdtemp()
os.mkdir(os.path.join(self.container, "stage0"))
self.build = bootstrap.RustBuild()
self.build.date = "2017-06-15"
self.build.build_dir = self.container
self.rustc_stamp_path = os.path.join(self.container, "stage0",
".rustc-stamp")
self.key = self.build.date + str(None)
def tearDown(self):
rmtree(self.container)
def test_stamp_path_does_not_exist(self):
"""Return True when the stamp file does not exist"""
if os.path.exists(self.rustc_stamp_path):
os.unlink(self.rustc_stamp_path)
self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
def test_dates_are_different(self):
"""Return True when the dates are different"""
with open(self.rustc_stamp_path, "w") as rustc_stamp:
rustc_stamp.write("2017-06-14None")
self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
def test_same_dates(self):
"""Return False both dates match"""
with open(self.rustc_stamp_path, "w") as rustc_stamp:
rustc_stamp.write("2017-06-15None")
self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
class GenerateAndParseConfig(unittest.TestCase):
"""Test that we can serialize and deserialize a config.toml file"""
def test_no_args(self):
build = serialize_and_parse([])
self.assertEqual(build.get_toml("profile"), 'dist')
self.assertIsNone(build.get_toml("llvm.download-ci-llvm"))
def test_set_section(self):
build = serialize_and_parse(["--set", "llvm.download-ci-llvm"])
self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true')
def test_set_target(self):
build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"])
self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc')
def test_set_top_level(self):
build = serialize_and_parse(["--set", "profile=compiler"])
self.assertEqual(build.get_toml("profile"), 'compiler')
def test_set_codegen_backends(self):
build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1)
build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1)
build = serialize_and_parse(["--enable-full-tools"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1)
class BuildBootstrap(unittest.TestCase):
"""Test that we generate the appropriate arguments when building bootstrap"""
def build_args(self, configure_args=None, args=None, env=None):
if configure_args is None:
configure_args = []
if args is None:
args = []
if env is None:
env = {}
env = env.copy()
env["PATH"] = os.environ["PATH"]
parsed = bootstrap.parse_args(args)
build = serialize_and_parse(configure_args, parsed)
# Make these optional so that `python -m unittest` works when run manually.
build_dir = os.environ.get("BUILD_DIR")
if build_dir is not None:
build.build_dir = build_dir
build_platform = os.environ.get("BUILD_PLATFORM")
if build_platform is not None:
build.build = build_platform
return build.build_bootstrap_cmd(env), env
def test_cargoflags(self):
args, _ = self.build_args(env={"CARGOFLAGS": "--timings"})
self.assertTrue("--timings" in args)
def test_warnings(self):
for toml_warnings in ['false', 'true', None]:
configure_args = []
if toml_warnings is not None:
configure_args = ["--set", "rust.deny-warnings=" + toml_warnings]
_, env = self.build_args(configure_args, args=["--warnings=warn"])
self.assertFalse("-Dwarnings" in env["RUSTFLAGS"])
_, env = self.build_args(configure_args, args=["--warnings=deny"])
self.assertTrue("-Dwarnings" in env["RUSTFLAGS"])