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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190package bulk
import ( "context" "fmt" "net/http" "net/http/httptest" "testing"
"tangled.org/odd.computer/isomorph/internal/distro/opensuse" "tangled.org/odd.computer/isomorph/internal/fetch" "tangled.org/odd.computer/isomorph/internal/model")
func TestRescoreMergesAliases(t *testing.T) { // DEP-12 names the pre-transfer repository, the homepage and watch URL the new one; without // the alias the stale key wins on weight, with it all three agree. p := Package{ UpstreamKey: "github.com/spacetelescope/asdf-standard", Status: StatusResolved, Basis: BasisMetadata, Evidence: []model.Evidence{ {Source: "debian/upstream/metadata:Repository", Key: "github.com/spacetelescope/asdf-standard", Weight: 0.95}, {Source: "debian/watch:upstream_url", Key: "github.com/asdf-format/asdf-standard", Weight: 0.36}, {Source: "debian/control:Homepage", Key: "github.com/asdf-format/asdf-standard", Weight: 0.4}, }, } alias := map[string]string{"github.com/spacetelescope/asdf-standard": "github.com/asdf-format/asdf-standard"} pkgs := []Package{p} if n := ApplyAliases(pkgs, alias); n != 1 { t.Fatalf("changed %d", n) } got := pkgs[0] if got.UpstreamKey != "github.com/asdf-format/asdf-standard" || got.Repo != "https://github.com/asdf-format/asdf-standard" || got.Basis != BasisMetadata { t.Fatalf("rescored: %+v", got) }}
func TestMirrorAliases(t *testing.T) { got := MirrorAliases([]string{ "gitbox.apache.org/repos/asf/activemq", "gitbox.apache.org/zookeeper", "github.com/gnome/glib", "github.com/golang/text", "github.com/openstack/nova", "github.com/kde/heaptrack", "github.com/other/x", "invent.kde.org/heaptrack", }) want := map[string]string{ "gitbox.apache.org/repos/asf/activemq": "github.com/apache/activemq", "gitbox.apache.org/zookeeper": "github.com/apache/zookeeper", "github.com/gnome/glib": "gitlab.gnome.org/gnome/glib", "github.com/golang/text": "go.googlesource.com/text", "github.com/openstack/nova": "opendev.org/openstack/nova", } if len(got) != len(want) { t.Fatalf("got %+v", got) } for _, a := range got { if want[a.From] != a.To || a.Source != AliasMirrorRule { t.Errorf("alias %+v", a) } } kde := kdeAliases([]string{"sdk/heaptrack", "a/dup", "b/dup", "accessibility/KMouseTool"}, []string{ "github.com/kde/heaptrack", "github.com/kde/dup", "github.com/kde/unknown", "invent.kde.org/kmousetool", "invent.kde.org/sdk/heaptrack", }) wantKDE := map[string]string{ "github.com/kde/heaptrack": "invent.kde.org/sdk/heaptrack", "invent.kde.org/kmousetool": "invent.kde.org/accessibility/kmousetool", } if len(kde) != len(wantKDE) { t.Fatalf("kde aliases %+v", kde) } for _, a := range kde { if wantKDE[a.From] != a.To || a.Source != AliasKDEProjects { t.Errorf("kde alias %+v", a) } } if Resolve(map[string]string{"a": "b", "b": "c", "c": "c"}, "a") != "c" { t.Error("alias chains must be followed") }}
func TestGitLabProjectAliases(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v4/projects/20183" { fmt.Fprint(w, `{"id":20183,"path_with_namespace":"World/amberol"}`) return } http.NotFound(w, r) })) defer srv.Close() c := fetch.New(t.TempDir()) c.MinInterval, c.Retries = 0, 0 got, failed := GitLabProjectAliases(context.Background(), c, []string{"gitlab.gnome.org/-/project/20183", "gitlab.gnome.org/-/project/404", "github.com/x/y"}, func(string) string { return srv.URL }) if failed != 1 || len(got) != 1 || got[0].From != "gitlab.gnome.org/-/project/20183" || got[0].To != "gitlab.gnome.org/world/amberol" || got[0].Source != AliasGitLabProject { t.Fatalf("aliases %+v failed %d", got, failed) }}
func TestRegistryAliases(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/pypi/acme-tiny/json": fmt.Fprint(w, `{"info":{"home_page":"","project_urls":{"Documentation":"https://docs.example.org","Source":"https://github.com/diafygi/acme-tiny"}}}`) case "/pypi/docs-only/json": fmt.Fprint(w, `{"info":{"home_page":"https://docs-only.example.org","project_urls":{}}}`) case "/api/v1/crates/ripgrep": fmt.Fprint(w, `{"crate":{"repository":"https://github.com/BurntSushi/ripgrep","homepage":""}}`) default: http.NotFound(w, r) } })) defer srv.Close() c := fetch.New(t.TempDir()) c.MinInterval, c.Retries = 0, 0 got, failed := RegistryAliases(context.Background(), c, []string{"pypi.org/acme-tiny", "pypi.org/docs-only", "pypi.org/gone", "crates.io/ripgrep", "github.com/x/y"}, func(string) string { return srv.URL }) want := map[string]string{"pypi.org/acme-tiny": "github.com/diafygi/acme-tiny", "crates.io/ripgrep": "github.com/burntsushi/ripgrep"} if failed != 1 || len(got) != len(want) { t.Fatalf("got %+v failed %d", got, failed) } for _, a := range got { if want[a.From] != a.To || a.Source != AliasRegistry { t.Errorf("alias %+v", a) } }}
func TestRegistryHintIsNotARepository(t *testing.T) { // A PyPI sdist outweighs the homepage, but a registry entry is not a repository: the // homepage's repository is chosen, and rescoring without an alias keeps it. pkgs := FromOpenSUSE([]opensuse.RPM{{Name: "acme-tiny", Arch: "src", Version: "5-1", URL: "https://github.com/diafygi/acme-tiny"}}, nil, nil, nil) p := pkgs[0] p.Evidence = append(p.Evidence, model.Evidence{Source: "APKBUILD:source", Key: "pypi.org/acme-tiny", Weight: 0.9}) Rescore(&p, nil) if p.UpstreamKey != "github.com/diafygi/acme-tiny" { t.Fatalf("registry key chosen: %+v", p) } Rescore(&p, map[string]string{"pypi.org/acme-tiny": "github.com/diafygi/acme-tiny"}) if p.UpstreamKey != "github.com/diafygi/acme-tiny" || p.Basis != BasisReleaseURL { t.Fatalf("aliased registry evidence should support the repository: %+v", p) }}
// TestRescoreGone: a repository aliased away as gone drops out; the package falls back to its// next candidate, or is left unresolved when there is none.func TestRescoreGone(t *testing.T) { ev := func(src, key string, w float64) model.Evidence { return model.Evidence{Source: src, Value: "https://" + key, Key: key, Weight: w} } alias := map[string]string{"github.com/freedesktop/libqmi": ""} p := Package{Name: "libqmi", UpstreamKey: "github.com/freedesktop/libqmi", Status: StatusResolved, Evidence: []model.Evidence{ ev("zq1:giturls", "github.com/freedesktop/libqmi", 0.7), ev("spec:URL", "gitlab.freedesktop.org/mobile-broadband/libqmi", 0.5), }} Rescore(&p, alias) if p.UpstreamKey != "gitlab.freedesktop.org/mobile-broadband/libqmi" || p.Basis != BasisHomepage { t.Errorf("fallback: %+v", p) } q := Package{Name: "x", UpstreamKey: "github.com/freedesktop/libqmi", Status: StatusResolved, Evidence: []model.Evidence{ ev("zq1:giturls", "github.com/freedesktop/libqmi", 0.7), }} Rescore(&q, alias) if q.UpstreamKey != "" || q.Status != StatusUnresolved { t.Errorf("no fallback: %+v", q) }}
// TestSecondarySource: a secondary spec source (a config file from another repository)// corroborates but never decides, even when it outscores the primary evidence.func TestSecondarySource(t *testing.T) { ev := func(src, key string, w float64) model.Evidence { return model.Evidence{Source: src, Value: "https://" + key, Key: key, Weight: w} } p := Package{Name: "caddy", Evidence: []model.Evidence{ ev("spec:Source2", "github.com/caddyserver/dist", 0.7), ev("spec:URL", "github.com/caddyserver/caddy", 0.5), }} Rescore(&p, nil) if p.UpstreamKey != "github.com/caddyserver/caddy" || p.Basis != BasisHomepage { t.Errorf("caddy: %+v", p) } q := Package{Name: "cmocka", Evidence: []model.Evidence{ev("spec:Source4", "github.com/jothepro/doxygen-awesome-css", 0.7)}} Rescore(&q, nil) if q.UpstreamKey != "" || q.Status != StatusUnresolved { t.Errorf("secondary only: %+v", q) } if BasisOf("spec:Source") != BasisReleaseURL || BasisOf("spec:Source0") != BasisReleaseURL || BasisOf("spec:Source12") != BasisSecondary { t.Error("spec source bases") }}