"""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'{lic}' if lic else 'LICENSE'
(d / f"{pid.lower()}.nuspec").write_text(
f''
f"{pid}{ver}{licel}{copy}")
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''
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("")
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('')
self.assertEqual(self.run_main("--write")[0], 1)
if __name__ == "__main__":
unittest.main()