103 lines
5.1 KiB
Go
103 lines
5.1 KiB
Go
package main
|
|
|
|
import (
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
// novox/hq issue 611: mesh-controller #293 changed one test file. Its delivery plan, made while another walk built
|
|
// build-agent and route-proxy (issue 606), read them whole and named them; at the cut their recorded build sources
|
|
// held none of its files, so its walk moved nothing and its record named no module. mesh-delivery could not tell
|
|
// "matched what runs" from "never built" and stopped the delivery, asking the operator about a change already on
|
|
// every machine. The walk now says, per module, that its build matched what runs (delivery.unchanged, ADR 0267 §5).
|
|
|
|
// The shape of #293: a test file of the controller's repository. The controller, built from the root, and the two
|
|
// modules packaging the repository each recorded a build source holding none of it: each is said unchanged, with
|
|
// why; a module of another repository is not named.
|
|
func TestAMergeSaysTheModulesWhoseBuildSourceItLeftUnchanged(t *testing.T) {
|
|
const catalogueRepo = "http://forge.internal:20000/novox/mesh-catalog.git"
|
|
const controllerRepo = "http://forge.internal:20000/novox/mesh-controller.git"
|
|
entries := []inventory.Entry{
|
|
fromRepo("mesh-controller", controllerRepo, ""),
|
|
fromRepo("build-agent", catalogueRepo, "modules/build-agent"),
|
|
fromRepo("route-proxy", catalogueRepo, "modules/route-proxy"),
|
|
fromRepo("gitea", catalogueRepo, "modules/gitea"),
|
|
}
|
|
read := map[string][]inventory.ReadRepository{
|
|
"mesh-controller": {{Own: true, Paths: []string{"go.mod", "module.json", "cmd/mesh-controller/", "internal/builder/"}}},
|
|
"build-agent": {
|
|
{Repository: "novox/mesh-controller", Ref: "main", Paths: []string{"go.mod", "cmd/mesh-builder/", "internal/builder/"}},
|
|
{Own: true, Paths: []string{"modules/build-agent/Dockerfile", "modules/build-agent/module.json"}},
|
|
},
|
|
"route-proxy": {
|
|
{Repository: "novox/mesh-controller", Ref: "main", Paths: []string{"go.mod", "examples/route-proxy/"}},
|
|
{Own: true, Paths: []string{"modules/route-proxy/Dockerfile", "modules/route-proxy/module.json"}},
|
|
},
|
|
}
|
|
m := link.SourceMoved{Owner: "novox", Repo: "mesh-controller", Base: "main", Commit: "8f1aec0",
|
|
Paths: []string{"internal/builder/replay363_test.go"}}
|
|
if moved := reachOfMerge(m, entries, read, sharedRepositoryEdges).Moved(); len(moved) != 0 {
|
|
t.Fatalf("the fixture moves %v: a test file is in no build source", moved)
|
|
}
|
|
got := unchangedOfMerge(m, entries, read)
|
|
var names []string
|
|
for n, why := range got {
|
|
names = append(names, n)
|
|
if !strings.Contains(why, "holds none of") || !strings.Contains(why, "internal/builder/replay363_test.go") ||
|
|
!strings.Contains(why, "the build the mesh holds is its build") {
|
|
t.Errorf("%s is said unchanged as %q", n, why)
|
|
}
|
|
}
|
|
if want := []string{"build-agent", "mesh-controller", "route-proxy"}; !reflect.DeepEqual(sortedOf(names), want) {
|
|
t.Fatalf("said unchanged: %v; want %v", sortedOf(names), want)
|
|
}
|
|
|
|
// A module whose build source holds a changed file is moved, never said unchanged.
|
|
touched := m
|
|
touched.Paths = []string{"internal/builder/builder.go"}
|
|
if got := unchangedOfMerge(touched, entries, read); got["mesh-controller"] != "" || got["build-agent"] != "" {
|
|
t.Errorf("a module the merge moves is said unchanged: %v", got)
|
|
}
|
|
if got := unchangedOfMerge(touched, entries, read); got["route-proxy"] == "" {
|
|
t.Errorf("the route proxy, whose build source holds none of it, is not said unchanged: %v", got)
|
|
}
|
|
// With no build source recorded, the module is read whole and moved: nothing says it unchanged.
|
|
unsaid := map[string][]inventory.ReadRepository{"build-agent": {{Repository: "novox/mesh-controller", Ref: "main"}}}
|
|
if got := unchangedOfMerge(m, entries, unsaid); len(got) != 0 {
|
|
t.Errorf("modules with no recorded build source are said unchanged: %v", got)
|
|
}
|
|
// Files not all said: every module is moved, none said unchanged.
|
|
truncated := m
|
|
truncated.PathsTruncated = true
|
|
if got := unchangedOfMerge(truncated, entries, read); len(got) != 0 {
|
|
t.Errorf("a merge whose files were not all said says %v unchanged", got)
|
|
}
|
|
}
|
|
|
|
// A module the walk builds anyway — another merge's, or a dependent — is not said unchanged: the modules map keeps
|
|
// meaning what the walk builds, and the two never name one module.
|
|
func TestAWalkSaysUnchangedOnlyWhatItDoesNotBuild(t *testing.T) {
|
|
unchanged := map[string]string{"build-agent": "why a", "route-proxy": "why b"}
|
|
got := unchangedLeft(unchanged, map[string]*inventory.PlanModule{"build-agent": {}})
|
|
if !reflect.DeepEqual(got, map[string]string{"route-proxy": "why b"}) {
|
|
t.Fatalf("left %v", got)
|
|
}
|
|
if got := unchangedLeft(map[string]string{"x": "y"}, map[string]*inventory.PlanModule{"x": {}}); got != nil {
|
|
t.Fatalf("left %v; want none", got)
|
|
}
|
|
}
|
|
|
|
// Against the store, the path a real merge takes: a merge whose module recorded a build source that holds none
|
|
// of its files is cut into a walk done with nothing to walk, whose record names the module unchanged and why.
|
|
|
|
func sortedOf(names []string) []string {
|
|
out := append([]string{}, names...)
|
|
sort.Strings(out)
|
|
return out
|
|
}
|