Files
mesh-delivery/modules/mesh-delivery-indexer/internal/index/catalog_graph_test.go
T

113 lines
5.8 KiB
Go

package index
import (
"context"
"reflect"
"testing"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/clients/meshcatalogclient"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/graph"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// Design 47 G §506, §443: an entry carries the manifest whole and the digest of the bytes the forge answered, set at take-in
// and never computed again from the manifest whole; the module's value read back from the entry holds that digest.
func TestAnEntryCarriesItsManifestWholeAndTheDigestOfItsBytes(t *testing.T) {
raw := `{ "module":"avahi", "version":"1" }` // its encoding is not the one a map gives back
digest := meshcatalogclient.ManifestDigest([]byte(raw))
cur := meshcatalog.ModulesByModuleValue{Repository: "novox/mesh-catalog", Path: "modules/avahi", Commit: "c", Manifest: digest}
e := CatalogEntryOf("avahi", cur, catalogue.Manifest{}, raw, graph.Node{})
if e.ManifestDigest != "sha256:"+digest || e.Manifest["module"] != "avahi" {
t.Fatalf("entry digest %q manifest %v, want sha256: and the digits %s of the bytes (§578) and the manifest whole", e.ManifestDigest, e.Manifest, digest)
}
if back := ModuleValueOf(e); back.Manifest != digest {
t.Errorf("the module's value read back holds %q, want the bare digits %s (§578)", back.Manifest, digest)
}
// §609: an entry taken in before G carries the digits its module value held; reading it back gives the same digits.
before := e
before.ManifestDigest = digest
if back := ModuleValueOf(before); back.Manifest != digest {
t.Errorf("an entry of before G read back holds %q, want %s (§609)", back.Manifest, digest)
}
}
// Design 47 G §676: at take-in the entry's artifacts carry the package name read from the revision's own files at the
// artifact's path: the module of a go.mod, the name of a package.json.
func TestAnEntryCarriesItsArtifactsPackageNames(t *testing.T) {
ix := &Indexer{ReadFile: func(_ context.Context, repository, sha, path string) ([]byte, error) {
files := map[string]string{
"mods/m/go/go.mod": "module git.example/m/go\n\ngo 1.26\n",
"mods/m/js/package.json": `{"name":"@example/m"}`,
}
if repository != "r" || sha != "c1" {
t.Errorf("read %s %s %s, want the entry's repository and commit", repository, sha, path)
}
if f, ok := files[path]; ok {
return []byte(f), nil
}
return nil, nil
}}
m := catalogue.Manifest{Module: "m", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{
{Name: "gopkg", Kind: catalogue.ArtifactPackage, Language: "go", Paths: []string{"go"}},
{Name: "jspkg", Kind: catalogue.ArtifactPackage, Language: "typescript", Paths: []string{"js"}},
{Name: "img", Kind: catalogue.ArtifactImage},
{Name: "prog", Kind: "bundle", Language: "go"},
}}}
e := ix.withArtifacts(context.Background(), meshcatalog.CatalogEntry{Module: "m", Repository: "r", Path: "mods/m", Commit: "c1"}, m)
got := map[string]string{}
for _, a := range e.Artifacts {
name := "none"
if a.Package != nil {
name = a.Package.Ecosystem + " " + a.Package.Name
}
got[a.Ref] = name
}
want := map[string]string{"m:gopkg": "go git.example/m/go", "m:jspkg": "npm @example/m", "m:img": "image m/img", "m:prog": "none"}
if !reflect.DeepEqual(got, want) {
t.Errorf("artifacts' packages %v, want %v (§676)", got, want)
}
}
// Design 47 G §694: an image artifact's package is {image, <module>/<artifact>}, read from no file, so two modules
// with an image artifact of one name carry two package names.
func TestAnImageArtifactsPackageNameIsItsModulesAndItsOwn(t *testing.T) {
ix := &Indexer{}
names := map[string]bool{}
for _, module := range []string{"a", "b"} {
m := catalogue.Manifest{Module: module, Build: &catalogue.Build{Artifacts: []catalogue.Artifact{{Name: "server", Kind: catalogue.ArtifactImage}}}}
e := ix.withArtifacts(context.Background(), meshcatalog.CatalogEntry{Module: module}, m)
if len(e.Artifacts) != 1 || e.Artifacts[0].Package == nil || e.Artifacts[0].Package.Ecosystem != "image" || e.Artifacts[0].Package.Name != module+"/server" {
t.Fatalf("module %s: artifacts %+v, want the package {image, %s/server} (§694)", module, e.Artifacts, module)
}
names[e.Artifacts[0].Package.Name] = true
}
if len(names) != 2 {
t.Errorf("two modules' image artifacts of one name carry %v, want two package names", names)
}
}
// Design 47 G §709 and A-229: a manifest whose contributes names route gives an entry whose contributes and requires both
// name it; requires names an optional requirement too, as catalogue.Manifest.Wants lists them, beside the node's own.
func TestAnEntryNamesWhatItContributesToAndEveryRequirement(t *testing.T) {
raw := `{"module":"web","version":"1","requires":["database",{"name":"cache","optional":true}],"contributes":{"route":{"host":"web"}}}`
m, err := catalogue.Decode([]byte(raw))
if err != nil {
t.Fatal(err)
}
e := CatalogEntryOf("web", meshcatalog.ModulesByModuleValue{}, m, raw, graph.Node{Requires: []string{"database", graph.BusState}})
if !reflect.DeepEqual(e.Contributes, []string{"route"}) {
t.Errorf("contributes = %v, want [route]", e.Contributes)
}
if want := []string{"database", graph.BusState, "cache", "route"}; !reflect.DeepEqual(e.Requires, want) {
t.Errorf("requires = %v, want %v", e.Requires, want)
}
// Read back as the module graph's node, the optional requirement is told apart by the entry's manifest (A-229).
if n := graph.NodeOf(e); !reflect.DeepEqual(n.Requires, []string{"database", graph.BusState, "route"}) {
t.Errorf("the node's requires = %v, want the optional cache left out", n.Requires)
}
if e := CatalogEntryOf("kv", meshcatalog.ModulesByModuleValue{}, catalogue.Manifest{}, "", graph.Node{}); e.Contributes != nil {
t.Errorf("an entry of a manifest contributing nothing carries contributes %v", e.Contributes)
}
}