Something went wrong. Try again.
Maps Linux distribution source packages to their upstream repositories, and through them to each other
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131package schema_test
import ( "encoding/json" "io/fs" "sort" "testing" "time"
"tangled.org/odd.computer/isomorph/internal/bulk" "tangled.org/odd.computer/isomorph/internal/model" "tangled.org/odd.computer/isomorph/schema")
type node struct { Required []string `json:"required"` Properties map[string]*node `json:"properties"` Items *node `json:"items"` Enum []string `json:"enum"`}
func load(t *testing.T, name string) *node { t.Helper() b, err := fs.ReadFile(schema.FS, name) if err != nil { t.Fatal(err) } var n node if err := json.Unmarshal(b, &n); err != nil { t.Fatalf("%s: %v", name, err) } return &n}
// conforms checks that every key of v is declared in n and every required key is present,// recursing into objects and arrays of objects.func conforms(t *testing.T, path string, n *node, v any) { t.Helper() switch v := v.(type) { case map[string]any: for _, r := range n.Required { if _, ok := v[r]; !ok { t.Errorf("%s: required %q missing", path, r) } } for k, sub := range v { p, ok := n.Properties[k] if !ok { t.Errorf("%s: %q is not in the schema", path, k) continue } conforms(t, path+"."+k, p, sub) } case []any: if n.Items != nil { for _, sub := range v { conforms(t, path+"[]", n.Items, sub) } } }}
func roundTrip(t *testing.T, v any) any { b, err := json.Marshal(v) if err != nil { t.Fatal(err) } var out any json.Unmarshal(b, &out) return out}
func sorted(s []string) []string { s = append([]string(nil), s...) sort.Strings(s) return s}
func TestPackageSchema(t *testing.T) { n := load(t, "package.schema.json") full := bulk.Package{ Distro: model.Debian, Suite: "sid", Name: "json-c", Version: "0.18+ds-1", OSVEcosystem: "Debian:sid", PURL: "pkg:deb/debian/json-c?arch=source", Binaries: []string{"libjson-c5"}, Homepage: "https://github.com/json-c/json-c/wiki", UpstreamKey: "github.com/json-c/json-c", Repo: "https://github.com/json-c/json-c", Status: bulk.StatusResolved, Basis: bulk.BasisMetadata, Evidence: []model.Evidence{{Source: "debian/upstream/metadata:Repository", Value: "https://github.com/json-c/json-c.git", Key: "github.com/json-c/json-c", Weight: 0.95}}, SourceSHA256: []string{"0000000000000000000000000000000000000000000000000000000000000000"}, } conforms(t, "package", n, roundTrip(t, full)) conforms(t, "package", n, roundTrip(t, bulk.Package{Distro: model.Arch, Suite: "extra", Name: "x", Version: "1-1", Status: bulk.StatusUnresolved}))
var distros []string for _, d := range model.AllDistros { distros = append(distros, string(d)) } if got := sorted(n.Properties["distro"].Enum); !equal(got, sorted(distros)) { t.Errorf("distro enum %v, want %v", got, distros) } bases := []string{bulk.BasisMetadata, bulk.BasisVCSSource, bulk.BasisReleaseURL, bulk.BasisDerived, bulk.BasisBugTracker, bulk.BasisHomepage} if got := sorted(n.Properties["basis"].Enum); !equal(got, sorted(bases)) { t.Errorf("basis enum %v, want %v (a secondary source never decides a mapping)", got, bases) } if got := sorted(n.Properties["status"].Enum); !equal(got, sorted([]string{bulk.StatusResolved, bulk.StatusUnresolved})) { t.Errorf("status enum %v", got) }}
func TestManifestSchema(t *testing.T) { n := load(t, "manifest.schema.json") m := bulk.Manifest{ Format: bulk.ManifestFormat, Snapshot: "20260928-0123456789ab", Created: time.Now(), Slices: []bulk.SliceFile{{Distro: "debian", Suite: "sid", Origin: "udd", FetchedAt: time.Now(), Packages: 2, Resolved: 1, Path: "debian-sid.jsonl", SHA256: "00"}}, Database: bulk.DatabaseFile{Path: "packages.sqlite", SHA256: "00", SchemaVersion: 2}, Schemas: bulk.ManifestFiles{Package: "package.schema.json", Manifest: "manifest.schema.json"}, } conforms(t, "manifest", n, roundTrip(t, m))}
func equal(a, b []string) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true}