package arch import ( "archive/tar" "bytes" "compress/gzip" "context" "fmt" "net/http" "net/http/httptest" "strings" "testing" "tangled.org/odd.computer/isomorph/internal/fetch" ) func stateArchive(t *testing.T, files map[string]string) []byte { t.Helper() var buf bytes.Buffer zw := gzip.NewWriter(&buf) tw := tar.NewWriter(zw) for name, body := range files { if err := tw.WriteHeader(&tar.Header{Name: name, Mode: 0o644, Size: int64(len(body)), Typeflag: tar.TypeReg}); err != nil { t.Fatal(err) } tw.Write([]byte(body)) } tw.Close() zw.Close() return buf.Bytes() } func TestParseState(t *testing.T) { b := stateArchive(t, map[string]string{ "state-main/extra-x86_64/json-c": "json-c 0.18-1 0.18-1 aaaa\n", "state-main/extra-any/json-c": "json-c 0.18-1 0.18-1 aaaa\n", // same pkgbase in -any: once "state-main/core-x86_64/glibc": "glibc 2.44-1 2.44-1 bbbb\n", "state-main/extra-testing-x86_64/x": "x 1-1 1-1 cccc\n", // not a stable repo "state-main/README.md": "readme", }) got, err := ParseState(b, StableRepos) if err != nil { t.Fatal(err) } want := []StateEntry{{Repo: "core", PkgBase: "glibc", Version: "2.44-1", Commit: "bbbb"}, {Repo: "extra", PkgBase: "json-c", Version: "0.18-1", Commit: "aaaa"}} if len(got) != len(want) || got[0] != want[0] || got[1] != want[1] { t.Fatalf("ParseState = %+v, want %+v", got, want) } } func TestSourceSHA256(t *testing.T) { si, err := ParseSRCINFO([]byte(`pkgbase = demo pkgver = 1.0 pkgrel = 1 url = https://example.org source = https://example.org/demo-1.0.tar.gz source = https://example.org/demo-1.0.tar.gz.sig source = git+https://github.com/o/demo.git#tag=v1.0 source = local.patch source_x86_64 = https://example.org/blob-x86_64.bin sha256sums = 1111 sha256sums = SKIP sha256sums = SKIP sha256sums = 4444 sha256sums_x86_64 = 5555 pkgname = demo `)) if err != nil { t.Fatal(err) } got := SourceSHA256(si) if len(got) != 1 || got[0] != "1111" { t.Fatalf("SourceSHA256 = %v, want only the release tarball's hash", got) } cands := Candidates(si) if len(cands) == 0 { t.Fatal("no candidates") } } func TestParseSyncDB(t *testing.T) { b := stateArchive(t, map[string]string{ "bash-5.3-1/desc": "%FILENAME%\nbash-5.3-1-x86_64.pkg.tar.zst\n\n%NAME%\nbash\n\n%BASE%\nbash\n\n%VERSION%\n5.3-1\n\n%URL%\nhttps://www.gnu.org/software/bash/\n\n%LICENSE%\nGPL\n", "libfoo-docs-1.0-2/desc": "%NAME%\nlibfoo-docs\n\n%BASE%\nlibfoo\n\n%VERSION%\n1.0-2\n", "nobase-1-1/desc": "%NAME%\nnobase\n\n%VERSION%\n1-1\n", "bash-5.3-1/files": "%FILES%\nusr/bin/bash\n", }) got, err := ParseSyncDB(b, "core") if err != nil { t.Fatal(err) } by := map[string]SyncPackage{} for _, p := range got { by[p.Name] = p } if len(got) != 3 || by["bash"] != (SyncPackage{Repo: "core", Name: "bash", Base: "bash", Version: "5.3-1", URL: "https://www.gnu.org/software/bash/"}) || by["libfoo-docs"].Base != "libfoo" || by["nobase"].Base != "nobase" { t.Fatalf("ParseSyncDB = %+v", got) } } func TestParsePKGBUILD(t *testing.T) { si, err := ParsePKGBUILD([]byte(`# Maintainer: someone pkgname=mkinitcpio-busybox pkgver=1.36.1 pkgrel=2 url="https://www.busybox.net/" arch=(x86_64) source=(https://busybox.net/downloads/busybox-$pkgver.tar.bz2{,.sig} "config" # local file "git+https://github.com/o/extra.git#tag=v${pkgver}") sha256sums=('aaaa' 'SKIP' 'cccc' 'SKIP') source_x86_64=(https://example.org/blob-x86_64.bin) sha256sums_x86_64=(eeee) build() { cd busybox-$pkgver source=(not-a-real-assignment) make } package() { install -Dm755 busybox "$pkgdir"/usr/lib/initcpio/busybox } `)) if err != nil { t.Fatal(err) } if si.PkgBase != "mkinitcpio-busybox" || si.PkgVer != "1.36.1" || si.URL != "https://www.busybox.net/" || si.Version() != "1.36.1-2" { t.Fatalf("fields: %+v", si) } var urls []string for _, s := range si.Sources { urls = append(urls, s.Arch+"|"+s.Remote()) } want := []string{"|https://busybox.net/downloads/busybox-1.36.1.tar.bz2", "|https://busybox.net/downloads/busybox-1.36.1.tar.bz2.sig", "|", "|https://github.com/o/extra.git", "x86_64|https://example.org/blob-x86_64.bin"} if len(urls) != len(want) { t.Fatalf("sources %q, want %q", urls, want) } if sums := SourceSHA256(si); len(sums) != 1 || sums[0] != "aaaa" { t.Fatalf("SourceSHA256 = %v", sums) } if c := Candidates(si); len(c) == 0 { t.Fatal("no candidates") } } func TestFetchSRCINFOFallsBackToPKGBUILD(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { case strings.Contains(r.URL.String(), "PKGBUILD"): fmt.Fprint(w, "pkgname=lzo\npkgver=2.10\npkgrel=1\nurl=\"https://www.oberhumer.com/opensource/lzo\"\nsource=(https://www.oberhumer.com/opensource/lzo/download/lzo-${pkgver}.tar.gz)\nsha256sums=('c0f8')\n") default: http.NotFound(w, r) } })) defer srv.Close() c := fetch.New(t.TempDir()) c.MinInterval, c.Retries = 0, 0 r := New(c) r.GitLabBase = srv.URL for _, web := range []bool{false, true} { si, err := r.FetchSRCINFO(context.Background(), "lzo", "bc2d", web) if err != nil || si.PkgBase != "lzo" || si.Sources[0].Remote() != "https://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz" { t.Fatalf("web=%v: %v %+v", web, err, si) } } if !r.HasSRCINFO("lzo", "bc2d") { t.Fatal("a cached PKGBUILD must count") } }