A test verdict's digest takes a mesh package by its reached files' content, so a package merge that leaves them alone keeps every verdict (ADR 0593 §5)

The digest counted a module outside the tree by its version and checksum, so every mesh-sdk merge invalidated each kept
verdict of each repository. A package of the mesh's forge is now hashed by the files the tests reach, as a replacement to a
directory already was; any other outside module still counts by version and checksum. Every kept verdict is invalidated
once, by the form change.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 18:29:32 +01:00
parent 6f781abb57
commit 6118c790e6
2 changed files with 54 additions and 3 deletions
@@ -398,7 +398,10 @@ func packageDigest(root, testMain *goPackage, pkgs map[string]*goPackage, tree s
if mod.Replace != nil {
mod = mod.Replace
}
if !mod.Main && mod.Version != "" {
// A module outside the tree counts by its version and checksum; a package of the mesh's own forge by the content of
// its files, as a local replacement does, so a new version of a mesh package whose reached files are the same keeps
// every verdict kept for them (ADR 0593 §5, ADR 0444 §3).
if !mod.Main && mod.Version != "" && !strings.HasPrefix(mod.Path, delivery.ForgeModulePrefix) {
lines = append(lines, "module "+mod.Path+"@"+mod.Version+" "+mod.Sum)
continue
}
@@ -152,8 +152,9 @@ func TestTheDigestIsTheSameInAnotherWorkspace(t *testing.T) {
}
}
// A module outside the tree counts by its version and checksum, not by its files: the package of mesh-sdk, as go list
// gave it for this module's own dependency (testdata/captured/golist-external.json, which README describes).
// A module outside the tree counts by its version and checksum, not by its files: a package of a module that is not the
// mesh's, as go list gave it for this module's own dependency (testdata/captured/golist-external.json, which README
// describes). A package of the mesh's own forge counts by its files' content instead (ADR 0593 §5; the next test).
func TestAModuleOutsideTheTreeCountsByVersionAndChecksum(t *testing.T) {
raw, err := os.ReadFile(filepath.Join("testdata", "captured", "golist-external.json"))
if err != nil {
@@ -167,6 +168,7 @@ func TestAModuleOutsideTheTreeCountsByVersionAndChecksum(t *testing.T) {
if ext == nil || ext.Module == nil || ext.Module.Sum == "" || ext.Module.Version == "" || ext.Module.Main {
t.Fatalf("the capture holds no external package with a version and a checksum: %+v", ext)
}
ext.Module.Path = "example.com/outside" // the capture's package, as a module that is not the mesh's
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "r.go"), []byte("package r\n"), 0o644)
root := &goPackage{ImportPath: "x/r", Dir: dir, Module: &goModule{Path: "x", Main: true}, GoFiles: []string{"r.go"}, TestGoFiles: []string{"r.go"}}
@@ -205,6 +207,52 @@ func TestAModuleOutsideTheTreeCountsByVersionAndChecksum(t *testing.T) {
}
}
// ADR 0593 §5 (C5): a package of the mesh's forge counts by the content of the files the tests reach, not by the version
// of its module. Two versions of mesh-sdk whose reached files are equal give one digest; a changed reached file changes it;
// a changed file of a package no test reaches does not.
func TestAMeshPackageCountsByTheContentOfTheFilesReached(t *testing.T) {
mesh := t.TempDir()
write := func(dir, name, text string) {
t.Helper()
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, name), []byte(text), 0o644); err != nil {
t.Fatal(err)
}
}
write(filepath.Join(mesh, "reached"), "a.go", "package reached\n")
write(filepath.Join(mesh, "unreached"), "b.go", "package unreached\n")
module := &goModule{Path: "git.novox.be/novox/mesh-sdk/go", Version: "v0.1.1", Sum: "h1:one="}
reached := &goPackage{ImportPath: module.Path + "/reached", Dir: filepath.Join(mesh, "reached"), Module: module, GoFiles: []string{"a.go"}}
unreached := &goPackage{ImportPath: module.Path + "/unreached", Dir: filepath.Join(mesh, "unreached"), Module: module, GoFiles: []string{"b.go"}}
own := t.TempDir()
write(own, "r.go", "package r\n")
root := &goPackage{ImportPath: "x/r", Dir: own, Module: &goModule{Path: "x", Main: true}, GoFiles: []string{"r.go"}, TestGoFiles: []string{"r.go"}}
pkgs := map[string]*goPackage{reached.ImportPath: reached, unreached.ImportPath: unreached, root.ImportPath: root}
testMain := &goPackage{ImportPath: "x/r.test", Deps: []string{reached.ImportPath}}
digest := func() string {
d, err := packageDigest(root, testMain, pkgs, own, []string{"digest 1"}, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
return d
}
d1 := digest()
module.Version, module.Sum = "v0.2.0", "h1:two=" // a new version of the module whose reached files are the same
if d2 := digest(); d2 != d1 {
t.Errorf("a new version of mesh-sdk with equal reached files changed the digest")
}
write(filepath.Join(mesh, "unreached"), "b.go", "package unreached\n\nconst B = 1\n")
if d3 := digest(); d3 != d1 {
t.Errorf("a changed package no test reaches changed the digest")
}
write(filepath.Join(mesh, "reached"), "a.go", "package reached\n\nconst A = 1\n")
if d4 := digest(); d4 == d1 {
t.Errorf("a changed reached file left the digest as it was")
}
}
// Issue 1935, 1936: a package whose reads-outside marker lists nothing it can trust is never kept: its digest is one no
// kept verdict can have (it differs on every call, though nothing changed), and the answer names it. A marker that lists
// what the tests read is kept: a change to a file it names changes the package's digest, a change elsewhere does not.