raw · 5605 bytes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | """python3 -m unittest discover -s scripts -p 'test_*.py'""" import contextlib import io import json import tempfile import unittest from pathlib import Path import godosa_licenses as gl def nuspec(cache: Path, pid: str, ver: str, lic: str | None, copy: str = "© Someone"): d = cache / pid.lower() / ver d.mkdir(parents=True) licel = f'<license type="expression">{lic}</license>' if lic else '<license type="file">LICENSE</license>' (d / f"{pid.lower()}.nuspec").write_text( f'<?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">' f"<metadata><id>{pid}</id><version>{ver}</version>{licel}<copyright>{copy}</copyright></metadata></package>") def project(repo: Path, sln: str, rel: str, pkgs: dict[str, str]): """pkgs: "Id/ver" -> "runtime" | "build" (analyzer, nothing in the output).""" p = repo / rel f = repo / sln line = f'<Project Path="{rel}/{p.name}.csproj" />' old = f.read_text() if f.exists() else "" if line not in old: f.write_text(old + line + "\n") (p / "obj").mkdir(parents=True, exist_ok=True) (p / f"{p.name}.csproj").write_text("<Project/>") targets = {k: ({"type": "package", "runtime": {"lib/net10.0/X.dll": {}}} if kind == "runtime" else {"type": "package", "runtime": {"lib/netstandard2.0/_._": {}}}) for k, kind in pkgs.items()} (p / "obj" / "project.assets.json").write_text(json.dumps({ "targets": {"net10.0": targets}, "libraries": {k: {"type": "package"} for k in pkgs}})) class LicensesTest(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.repo = Path(self.tmp.name) / "repo" self.cache = Path(self.tmp.name) / "cache" self.repo.mkdir() self.cache.mkdir() self.cfg = gl.Config("Game.slnx", ("src/Game/",), "# Licences\n", extra=[("runtime", "10", "MIT", "© R", "all")], planned=[("Later", "2.0", "BSD|0", "managed", "nuspec")], command="tool") (self.repo / "Game.slnx").write_text("") def tearDown(self): self.tmp.cleanup() def run_main(self, *argv) -> tuple[int, str]: err = io.StringIO() with contextlib.redirect_stderr(err): code = gl.main(list(argv), self.cfg, self.repo, self.cache) return code, err.getvalue() def test_write_then_check_is_clean_and_splits_shipped_from_test(self): nuspec(self.cache, "Pack", "1.0.0", "MIT", "© P") nuspec(self.cache, "xunit", "2.9.2", "Apache-2.0") project(self.repo, "Game.slnx", "src/Game", {"Pack/1.0.0": "runtime"}) project(self.repo, "Game.slnx", "src/Game.Tests", {"xunit/2.9.2": "runtime", "Pack/1.0.0": "runtime"}) self.assertEqual(self.run_main("--write")[0], 0) self.assertEqual(self.run_main(), (0, "")) md = (self.repo / "licenses.md").read_text() self.assertTrue(md.startswith("# Licences\n")) shipped, rest = md.split("## Not a package") self.assertIn("| Pack | 1.0.0 | MIT | © P | Game | |", shipped) self.assertNotIn("xunit", shipped) self.assertIn("| runtime | 10 | MIT | © R | all |", rest) self.assertIn("| Later | 2.0 | BSD\\|0 | managed | nuspec |", rest) self.assertIn("| xunit | 2.9.2 | Apache-2.0 | Game.Tests |", rest) def test_stale_names_the_command(self): self.assertEqual(self.run_main(), (1, "licenses.md is stale: run tool --write\n")) def test_copyleft_ships_only_when_allowed(self): nuspec(self.cache, "OpenAL.Native", "1.0.0", "LGPL-2.0-or-later") project(self.repo, "Game.slnx", "src/Game.Tests", {"OpenAL.Native/1.0.0": "runtime"}) self.assertEqual(self.run_main("--write")[0], 0) # test project: not shipped project(self.repo, "Game.slnx", "src/Game", {"OpenAL.Native/1.0.0": "runtime"}) self.assertEqual(self.run_main("--write"), (1, "NuGet OpenAL.Native 1.0.0: copyleft licence LGPL-2.0-or-later ships\n")) self.cfg.allow_shipped["OpenAL.Native"] = "shared library" self.assertEqual(self.run_main("--write")[0], 0) self.assertIn("| shared library |", (self.repo / "licenses.md").read_text()) def test_build_only_package_is_not_shipped(self): nuspec(self.cache, "Analyzer", "1.0.0", "GPL-3.0-only") project(self.repo, "Game.slnx", "src/Game", {"Analyzer/1.0.0": "build"}) self.assertEqual(self.run_main("--write")[0], 0) def test_unknown_licence_fails_until_overridden(self): nuspec(self.cache, "FileLicensed", "1.0.0", None) project(self.repo, "Game.slnx", "src/Game.Tests", {"FileLicensed/1.0.0": "runtime"}) self.assertEqual(self.run_main("--write")[0], 1) self.cfg.overrides["FileLicensed"] = "MIT" self.assertEqual(self.run_main("--write")[0], 0) def test_projects_come_from_the_configured_solution(self): nuspec(self.cache, "GplLib", "1.0.0", "GPL-3.0-only") project(self.repo, "Other.slnx", "src/Game", {"GplLib/1.0.0": "runtime"}) self.assertEqual(self.run_main("--write")[0], 0) self.cfg.solution = "Other.slnx" self.assertEqual(self.run_main("--write")[0], 1) def test_missing_assets_fails(self): (self.repo / "src/Game").mkdir(parents=True) (self.repo / "Game.slnx").write_text('<Project Path="src/Game/Game.csproj" />') self.assertEqual(self.run_main("--write")[0], 1) if __name__ == "__main__": unittest.main() |