mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
fix(parity): keep saved probe selections compatible with the library split
Co-Authored-By: Codex <[email protected]>
This commit is contained in:
1 parent
42a5981e94
commit
452910ffce
6 files changed
+64
No files matched your search
@@ -0,0 +1,22 @@
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from tools import interaction_lab
|
||||
|
||||
|
||||
class CargoExampleTests(unittest.TestCase):
|
||||
def test_client_probe_uses_the_reusable_library_package(self):
|
||||
with mock.patch.object(interaction_lab.subprocess, 'run') as run:
|
||||
interaction_lab.cargo_example('horizon-client', 'menu_fixture', Path('cases.txt'), profile='fast')
|
||||
run.assert_called_once_with(
|
||||
['cargo', 'run', '-q', '-j3', '--profile', 'fast', '-p', 'horizon-client-lib',
|
||||
'--example', 'client_probe', '--', 'menu_fixture', 'cases.txt'],
|
||||
check=True, cwd=interaction_lab.lab.ROOT)
|
||||
|
||||
def test_other_probe_packages_are_unchanged(self):
|
||||
with mock.patch.object(interaction_lab.subprocess, 'run') as run:
|
||||
interaction_lab.cargo_example('horizon-world', 'loot_probe', 42)
|
||||
run.assert_called_once_with(
|
||||
['cargo', 'run', '-q', '-j3', '-p', 'horizon-world', '--example', 'world_probe', '--', 'loot_probe', '42'],
|
||||
check=True, cwd=interaction_lab.lab.ROOT)
|
||||
@@ -138,6 +138,7 @@ class ReachTests(unittest.TestCase):
|
||||
'[[example]]\nname = "client_probe"\npath = "../a/examples/probe/main.rs"\n',
|
||||
"crates/a/src/shared.rs": "pub mod used;\n",
|
||||
"crates/a/src/lib.rs": "pub fn game_only() {}\n",
|
||||
"crates/a/Cargo.toml": '[package]\nname = "a"\nautobins = false\nautoexamples = false\n',
|
||||
"crates/a/examples/probe/main.rs": "extern crate b as legacy;\nfn main() { legacy::used::helper(); }\n",
|
||||
"crates/b/src/main.rs": "compile_error!(\"disabled auto-bin\");\n",
|
||||
"crates/b/examples/ignored.rs": "compile_error!(\"disabled auto-example\");\n",
|
||||
@@ -148,6 +149,8 @@ class ReachTests(unittest.TestCase):
|
||||
self.assertIn((self.root / "crates/a/examples/probe/main.rs").resolve(), roots)
|
||||
self.assertNotIn((self.root / "crates/b/src/main.rs").resolve(), roots)
|
||||
self.assertTrue(graph.is_library("crates/a/src/shared.rs"))
|
||||
self.assertEqual(graph.entries([["example", "client_probe", "dev", ["-p", "a"], True]],
|
||||
{"crates/a/examples/probe/main.rs"}), {"crates/a/examples/probe/main.rs"})
|
||||
reached = graph.reachable({"crates/a/examples/probe/main.rs"},
|
||||
{"crates/a/examples/probe/main.rs", "crates/a/src/shared.rs", "crates/a/src/used.rs"})
|
||||
self.assertIn("crates/a/src/used.rs", reached)
|
||||
|
||||
@@ -30,6 +30,19 @@ class ParityRunnerTests(unittest.TestCase):
|
||||
self.assertEqual(parity.artifacts_of(["cargo", "build", "--release", "-p", "horizon-world", "--bin=horizon-world"]),
|
||||
[["bin", "horizon-world", "release", ["-p", "horizon-world"], False]])
|
||||
|
||||
def test_prebuild_follows_a_moved_target_without_losing_features(self):
|
||||
selection = ["-p", "horizon-client", "--no-default-features", "--features", "horizon-client/rng-trace"]
|
||||
artifacts = [["example", "client_probe", "fast", selection, True],
|
||||
["bin", "horizon-ctl", "fast", selection, False]]
|
||||
packages = {("example", "client_probe"): "horizon-client-lib", ("bin", "horizon-ctl"): "horizon-client-lib"}
|
||||
commands = parity.prebuild_commands(artifacts, packages)
|
||||
self.assertEqual(len(commands), 2)
|
||||
for command in commands:
|
||||
self.assertEqual(command[:5], ["cargo", "build", "--locked", "--profile", "fast"])
|
||||
self.assertEqual(command[5:5 + len(selection)], selection)
|
||||
self.assertEqual(command[5 + len(selection):7 + len(selection)], ["-p", "horizon-client-lib"])
|
||||
self.assertEqual(artifacts[0][3], selection)
|
||||
|
||||
def test_prebuild_repeats_each_harness_selection(self):
|
||||
artifacts = [
|
||||
*parity.artifacts_of(["cargo", "build", "--release", "-p", "horizon-world", "--example", "a"]),
|
||||
@@ -578,5 +591,16 @@ class WorkspaceManifestTests(unittest.TestCase):
|
||||
optional = {"crates/horizon-client/Cargo.toml": self.CLIENT + '\n[features]\nfast = ["wgpu/x"]\n'}
|
||||
self.assertEqual(self.verdict({"crates/horizon-client/Cargo.toml": self.CLIENT}, optional), set())
|
||||
|
||||
def test_external_feature_sources_are_not_discarded(self):
|
||||
with tempfile.TemporaryDirectory() as temp, mock.patch.object(parity, "ROOT", Path(temp)):
|
||||
root = Path(temp)
|
||||
(root / "crates/core").mkdir(parents=True)
|
||||
(root / "shared").mkdir()
|
||||
(root / "crates/core/Cargo.toml").write_text(
|
||||
'[package]\nname = "core"\n[lib]\npath = "../../shared/lib.rs"\n'
|
||||
'[features]\nextra = []\n')
|
||||
(root / "shared/lib.rs").write_text('#[cfg(feature = "extra")]\nfn extra() {}\n')
|
||||
self.assertFalse(parity.feature_sources_changed("core", "extra", {"crates/core/Cargo.toml"}))
|
||||
|
||||
def test_without_a_base_everything_counts(self):
|
||||
self.assertEqual(parity.workspace_only_manifests({"Cargo.lock"}, None), set())
|
||||
@@ -51,6 +51,8 @@ def cargo_example(package, example, *args, profile=None):
|
||||
if profile:
|
||||
command += ['--profile', profile]
|
||||
probe = package.removeprefix('horizon-') + '_probe' # each crate's probe example: client_probe, world_probe
|
||||
if package == 'horizon-client':
|
||||
package = 'horizon-client-lib'
|
||||
command += ['-p', package, '--example', probe, '--', example, *map(str, args)]
|
||||
subprocess.run(command, check=True, cwd=lab.ROOT)
|
||||
|
||||
|
||||
@@ -644,6 +644,11 @@ def prebuild_commands(artifacts, packages=None):
|
||||
if len(artifact) < 5:
|
||||
continue
|
||||
kind, name, profile, selection, examples = artifact
|
||||
owner = (packages or {}).get((kind, name))
|
||||
selected = [value for flag, value in zip(selection, selection[1:]) if flag == "-p"]
|
||||
if owner and selected and owner not in selected:
|
||||
# A recorded target may have moved packages; retain its feature flags and old selections.
|
||||
selection = [*selection, "-p", owner]
|
||||
targets = groups.setdefault((profile, tuple(selection), examples), [])
|
||||
target = [f"--{kind}", name] if name else [f"--{kind}"]
|
||||
if target not in targets:
|
||||
@@ -1351,6 +1356,9 @@ def feature_sources_changed(crate, feature, changed):
|
||||
break
|
||||
else:
|
||||
return False
|
||||
if any(not root.is_relative_to(manifest.parent.resolve()) for root in parity_reach.crate_roots(manifest.parent)):
|
||||
# A directory-only scan cannot prove that shared external sources changed too.
|
||||
return False
|
||||
table = re.search(r"^\[features\]\n(.*?)(?=^\[|\Z)", text, re.M | re.S)
|
||||
implies = {name: re.findall(r'"([^"]+)"', value) for name, value in
|
||||
re.findall(r'^([\w-]+)\s*=\s*\[([^\]]*)\]', table.group(1) if table else "", re.M)}
|
||||
|
||||
@@ -260,6 +260,11 @@ class SourceGraph:
|
||||
packages = [value for flag, value in zip(selection, selection[1:]) if flag == "-p"] or \
|
||||
[manifest.parent.name for manifest in sorted((self.root / "crates").glob("*/Cargo.toml"))]
|
||||
roots = set()
|
||||
if name and not any(name in self.targets(self.root / "crates" / package) for package in packages):
|
||||
owners = [manifest.parent.name for manifest in (self.root / "crates").glob("*/Cargo.toml")
|
||||
if self.targets(manifest.parent).get(name, (None,))[0] == kind.rstrip("s")]
|
||||
if len(owners) == 1:
|
||||
packages = [*packages, owners[0]]
|
||||
for package in packages:
|
||||
crate = self.root / "crates" / package
|
||||
targets = self.targets(crate)
|
||||
|
||||
Reference in new issue
Block a user