personal memory agent
0

Configure Feed

Select the types of activity you want to include in your feed.

solstone / tests / test_normalize_maturin_sdist.py
7.1 kB 196 lines
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4from __future__ import annotations 5 6import hashlib 7import tarfile 8import tomllib 9from io import BytesIO 10from pathlib import Path 11 12import pytest 13 14from scripts.normalize_maturin_sdist import ( 15 SdistLockError, 16 normalize_core_sdist_workspace_lock, 17) 18 19 20def _source_workspace(root: Path) -> None: 21 members = ( 22 "crates/solstone-core", 23 "crates/solstone-core-journal", 24 "crates/solstone-core-sol", 25 "crates/solstone-core-sol-client", 26 "crates/solstone-core-sol-client-cli", 27 "crates/solstone-core-unused", 28 ) 29 (root / "core").mkdir(parents=True) 30 (root / "core" / "Cargo.toml").write_text( 31 "[workspace]\nmembers = [\n" 32 + "".join(f' "{member}",\n' for member in members) 33 + ']\nresolver = "3"\n', 34 encoding="utf-8", 35 ) 36 for member in members: 37 path = root / "core" / member 38 path.mkdir(parents=True) 39 (path / "Cargo.toml").write_text( 40 f'[package]\nname = "{Path(member).name}"\nversion = "1.2.3"\n', 41 encoding="utf-8", 42 ) 43 main = root / "core" / "crates" / "solstone-core" / "src" / "main.rs" 44 main.parent.mkdir(parents=True) 45 main.write_text("fn main() {}\n", encoding="utf-8") 46 47 48def _archive(root: Path, *, pruned_source: bool = False) -> Path: 49 archive = root / "dist" / "solstone_core-1.2.3.tar.gz" 50 archive.parent.mkdir() 51 manifest = ( 52 "[workspace]\n" 53 'members = ["crates/solstone-core", "crates/solstone-core-journal", ' 54 '"crates/solstone-core-sol", "crates/solstone-core-sol-client", ' 55 '"crates/solstone-core-sol-client-cli"]\n' 56 'resolver = "3"\n' 57 ).encode() 58 source_line = ( 59 '\nsource = "registry+https://github.com/rust-lang/crates.io-index"' 60 if pruned_source 61 else "" 62 ) 63 lock = ( 64 "version = 4\n\n" 65 '[[package]]\nname = "serde"\nversion = "1.0.228"\n' 66 'source = "registry+https://github.com/rust-lang/crates.io-index"\n\n' 67 '[[package]]\nname = "ureq"\nversion = "3.1.4"\n' 68 'source = "registry+https://github.com/rust-lang/crates.io-index"\n\n' 69 '[[package]]\nname = "solstone-core"\nversion = "1.2.3"\n' 70 'dependencies = ["serde"]\n\n' 71 '[[package]]\nname = "solstone-core-journal"\nversion = "1.2.3"\n\n' 72 '[[package]]\nname = "solstone-core-sol"\nversion = "1.2.3"\n\n' 73 '[[package]]\nname = "solstone-core-sol-client"\nversion = "1.2.3"\n' 74 'dependencies = ["ureq"]\n\n' 75 '[[package]]\nname = "solstone-core-sol-client-cli"\nversion = "1.2.3"\n' 76 'dependencies = ["solstone-core-sol-client"]\n\n' 77 f'[[package]]\nname = "solstone-core-unused"\nversion = "1.2.3"{source_line}\n' 78 ).encode() 79 with tarfile.open(archive, mode="w:gz") as target: 80 for name, data in ( 81 ("solstone_core-1.2.3/PKG-INFO", b"metadata\n"), 82 ("solstone_core-1.2.3/core/Cargo.toml", manifest), 83 ("solstone_core-1.2.3/core/Cargo.lock", lock), 84 ): 85 member = tarfile.TarInfo(name) 86 member.mode = 0o644 87 member.mtime = 1_784_800_000 88 member.size = len(data) 89 target.addfile(member, BytesIO(data)) 90 return archive 91 92 93def _members(archive: Path) -> dict[str, bytes]: 94 with tarfile.open(archive, mode="r:gz") as source: 95 return { 96 member.name: source.extractfile(member).read() # type: ignore[union-attr] 97 for member in source.getmembers() 98 if member.isfile() 99 } 100 101 102def test_normalizer_retains_now_reachable_sol_workspace_records( 103 tmp_path: Path, 104) -> None: 105 _source_workspace(tmp_path) 106 archive = _archive(tmp_path) 107 before = _members(archive) 108 109 removed = normalize_core_sdist_workspace_lock(tmp_path, archive) 110 111 assert removed == ("solstone-core-unused",) 112 after = _members(archive) 113 assert after.keys() == before.keys() 114 assert ( 115 after["solstone_core-1.2.3/PKG-INFO"] == before["solstone_core-1.2.3/PKG-INFO"] 116 ) 117 assert ( 118 after["solstone_core-1.2.3/core/Cargo.toml"] 119 == before["solstone_core-1.2.3/core/Cargo.toml"] 120 ) 121 packages = tomllib.loads(after["solstone_core-1.2.3/core/Cargo.lock"].decode())[ 122 "package" 123 ] 124 assert [package["name"] for package in packages] == [ 125 "serde", 126 "ureq", 127 "solstone-core", 128 "solstone-core-journal", 129 "solstone-core-sol", 130 "solstone-core-sol-client", 131 "solstone-core-sol-client-cli", 132 ] 133 134 digest = hashlib.sha256(archive.read_bytes()).hexdigest() 135 assert normalize_core_sdist_workspace_lock(tmp_path, archive) == () 136 assert hashlib.sha256(archive.read_bytes()).hexdigest() == digest 137 138 139def test_normalizer_refuses_to_remove_registry_package_record(tmp_path: Path) -> None: 140 _source_workspace(tmp_path) 141 archive = _archive(tmp_path, pruned_source=True) 142 143 with pytest.raises(SdistLockError, match="is not a workspace package"): 144 normalize_core_sdist_workspace_lock(tmp_path, archive) 145 146 147def test_normalizer_injects_native_sol_sources(tmp_path: Path) -> None: 148 _source_workspace(tmp_path) 149 source = tmp_path / "solstone" / "apps" / "sample" / "native" / "command.rs" 150 source.parent.mkdir(parents=True) 151 source.write_text("// native source\n", encoding="utf-8") 152 authority = source.with_name("authority.toml") 153 authority.write_text("# native authority\n", encoding="utf-8") 154 archive = _archive(tmp_path) 155 156 normalize_core_sdist_workspace_lock(tmp_path, archive) 157 158 after = _members(archive) 159 assert ( 160 after["solstone_core-1.2.3/solstone/apps/sample/native/command.rs"] 161 == b"// native source\n" 162 ) 163 assert ( 164 after["solstone_core-1.2.3/solstone/apps/sample/native/authority.toml"] 165 == b"# native authority\n" 166 ) 167 168 digest = hashlib.sha256(archive.read_bytes()).hexdigest() 169 assert normalize_core_sdist_workspace_lock(tmp_path, archive) == () 170 assert hashlib.sha256(archive.read_bytes()).hexdigest() == digest 171 172 173def test_normalizer_injects_derived_compile_inputs(tmp_path: Path) -> None: 174 _source_workspace(tmp_path) 175 main = tmp_path / "core" / "crates" / "solstone-core" / "src" / "main.rs" 176 main.write_text( 177 'const CONTRACT: &str = include_str!("../../../fixtures/sample-contract.json");\n' 178 "fn main() {}\n", 179 encoding="utf-8", 180 ) 181 asset = tmp_path / "core" / "fixtures" / "sample-contract.json" 182 asset.parent.mkdir(parents=True) 183 asset.write_text('{"ok":true}\n', encoding="utf-8") 184 archive = _archive(tmp_path) 185 186 normalize_core_sdist_workspace_lock(tmp_path, archive) 187 188 after = _members(archive) 189 assert ( 190 after["solstone_core-1.2.3/core/fixtures/sample-contract.json"] 191 == b'{"ok":true}\n' 192 ) 193 194 digest = hashlib.sha256(archive.read_bytes()).hexdigest() 195 assert normalize_core_sdist_workspace_lock(tmp_path, archive) == () 196 assert hashlib.sha256(archive.read_bytes()).hexdigest() == digest