84 lines
3.2 KiB
Go
84 lines
3.2 KiB
Go
package inventory
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"slices"
|
|
"testing"
|
|
)
|
|
|
|
// aNodesPackages is the resources of a node whose modules declare packages: one package two modules declare present, one
|
|
// declared absent, and a resource that is no package.
|
|
func aNodesPackages() ([]map[string]any, map[string]string) {
|
|
return []map[string]any{
|
|
{"id": "web.pkg-curl", "type": "package", "package": "curl"},
|
|
{"id": "backup.pkg-curl", "type": "package", "package": "curl"},
|
|
{"id": "web.pkg-nano", "type": "package", "package": "nano", "absent": true},
|
|
{"id": "web.conf", "type": "file", "path": "/etc/web.conf"},
|
|
},
|
|
map[string]string{"web.pkg-curl": "web", "backup.pkg-curl": "backup", "web.pkg-nano": "web", "web.conf": "web"}
|
|
}
|
|
|
|
// 1840/AC5: the declared-packages mirror's value for a node names each package with the modules that declare it and whether
|
|
// they declare it absent, and the same declaration is the same bytes however its resources are ordered, so a pass over an
|
|
// unchanged node writes nothing.
|
|
func TestTheDeclaredPackagesValueNamesEachPackageWithItsModules(t *testing.T) {
|
|
resources, owner := aNodesPackages()
|
|
got, err := DeclaredPackagesValue("one", resources, owner)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := `{"node":"one","packages":[{"package":"curl","modules":["backup","web"],"absent":false},` +
|
|
`{"package":"nano","modules":["web"],"absent":true}]}`
|
|
if string(got) != want {
|
|
t.Errorf("the value is\n%s\nwant\n%s", got, want)
|
|
}
|
|
reversed := slices.Clone(resources)
|
|
slices.Reverse(reversed)
|
|
again, err := DeclaredPackagesValue("one", reversed, owner)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(got, again) {
|
|
t.Errorf("the same declaration in another order is other bytes:\n%s\n%s", got, again)
|
|
}
|
|
if got := jsonFields(reflect.TypeOf(DeclaredPackagesMirrored{})); !slices.Equal(got, []string{"node", "packages"}) {
|
|
t.Errorf("the value carries %v", got)
|
|
}
|
|
}
|
|
|
|
// A node declaring no package has a value that says so, an empty list and not null.
|
|
func TestANodeDeclaringNoPackageHasAnEmptyList(t *testing.T) {
|
|
got, err := DeclaredPackagesValue("one", nil, nil)
|
|
if err != nil || string(got) != `{"node":"one","packages":[]}` {
|
|
t.Errorf("the value is %s (%v)", got, err)
|
|
}
|
|
}
|
|
|
|
// 1840/S3: a node's value stays under the 64 KiB a mirror's key holds at far more packages than a node declares: 600
|
|
// packages, each declared by four modules, is a few times what the largest node declares today.
|
|
func TestTheDeclaredPackagesValueOfABigNodeFitsAKey(t *testing.T) {
|
|
var resources []map[string]any
|
|
owner := map[string]string{}
|
|
for p := 0; p < 600; p++ {
|
|
for m := 0; m < 4; m++ {
|
|
id := fmt.Sprintf("module-%d.pkg-%d", m, p)
|
|
resources = append(resources, map[string]any{"id": id, "type": "package", "package": fmt.Sprintf("package-%d", p)})
|
|
owner[id] = fmt.Sprintf("module-%d", m)
|
|
}
|
|
}
|
|
got, err := DeclaredPackagesValue("one", resources, owner)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var v DeclaredPackagesMirrored
|
|
if err := json.Unmarshal(got, &v); err != nil || len(v.Packages) != 600 {
|
|
t.Fatalf("the value holds %d packages (%v)", len(v.Packages), err)
|
|
}
|
|
if len(got) >= 64<<10 {
|
|
t.Errorf("the value is %d bytes, over the 64 KiB a key holds", len(got))
|
|
}
|
|
}
|