199 lines
5.3 KiB
Go
199 lines
5.3 KiB
Go
package debian
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type roundTripFunc func(*http.Request) (*http.Response, error)
|
|
|
|
func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
return f(req)
|
|
}
|
|
|
|
func TestResolveSourceHTTPFallbackToGzip(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sources := strings.TrimSpace(`
|
|
Package: neofetch
|
|
Binary: neofetch
|
|
Version: 7.1.0-4
|
|
Directory: pool/main/n/neofetch
|
|
Checksums-Sha256:
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1978 neofetch_7.1.0-4.dsc
|
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 73791 neofetch_7.1.0.orig.tar.gz
|
|
`) + "\n"
|
|
|
|
var gz bytes.Buffer
|
|
zw := gzip.NewWriter(&gz)
|
|
if _, err := zw.Write([]byte(sources)); err != nil {
|
|
t.Fatalf("failed to write gzip sources: %v", err)
|
|
}
|
|
if err := zw.Close(); err != nil {
|
|
t.Fatalf("failed to close gzip writer: %v", err)
|
|
}
|
|
|
|
client := &http.Client{
|
|
Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
|
|
switch req.URL.Path {
|
|
case "/debian/dists/stable/main/source/Sources.xz":
|
|
return httpResponse(req, http.StatusNotFound, []byte("not found")), nil
|
|
case "/debian/dists/stable/main/source/Sources.gz":
|
|
return httpResponse(req, http.StatusOK, gz.Bytes()), nil
|
|
default:
|
|
return httpResponse(req, http.StatusNotFound, []byte("missing")), nil
|
|
}
|
|
}),
|
|
}
|
|
|
|
r := NewResolver(
|
|
WithHTTPClient(client),
|
|
WithMirrors([]string{"https://mirror.example/debian"}),
|
|
WithSuites([]string{"stable"}),
|
|
WithComponents([]string{"main"}),
|
|
)
|
|
|
|
info, err := r.ResolveSource("neofetch")
|
|
if err != nil {
|
|
t.Fatalf("ResolveSource() error = %v", err)
|
|
}
|
|
|
|
if info.SourcePackage != "neofetch" {
|
|
t.Fatalf("unexpected source package: %s", info.SourcePackage)
|
|
}
|
|
if info.DebianVersion != "7.1.0-4" {
|
|
t.Fatalf("unexpected debian version: %s", info.DebianVersion)
|
|
}
|
|
if info.UpstreamVersion != "7.1.0" {
|
|
t.Fatalf("unexpected upstream version: %s", info.UpstreamVersion)
|
|
}
|
|
wantURL := "https://mirror.example/debian/pool/main/n/neofetch/neofetch_7.1.0-4.dsc"
|
|
if info.DSCURL != wantURL {
|
|
t.Fatalf("unexpected dsc url:\nwant: %s\ngot: %s", wantURL, info.DSCURL)
|
|
}
|
|
}
|
|
|
|
func TestResolveSourceByBinaryName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sources := strings.TrimSpace(`
|
|
Package: pkgconf
|
|
Binary: pkgconf, pkg-config
|
|
Version: 2.0.3-1
|
|
Directory: pool/main/p/pkgconf
|
|
Checksums-Sha256:
|
|
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc 1800 pkgconf_2.0.3-1.dsc
|
|
`) + "\n"
|
|
|
|
client := &http.Client{
|
|
Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
|
|
if strings.HasSuffix(req.URL.Path, "/Sources") {
|
|
return httpResponse(req, http.StatusOK, []byte(sources)), nil
|
|
}
|
|
return httpResponse(req, http.StatusNotFound, []byte("missing")), nil
|
|
}),
|
|
}
|
|
|
|
r := NewResolver(
|
|
WithHTTPClient(client),
|
|
WithMirrors([]string{"https://mirror.example/debian"}),
|
|
WithSuites([]string{"stable"}),
|
|
WithComponents([]string{"main"}),
|
|
)
|
|
|
|
info, err := r.ResolveSource("pkg-config")
|
|
if err != nil {
|
|
t.Fatalf("ResolveSource() error = %v", err)
|
|
}
|
|
|
|
if info.SourcePackage != "pkgconf" {
|
|
t.Fatalf("unexpected source package: %s", info.SourcePackage)
|
|
}
|
|
wantURL := "https://mirror.example/debian/pool/main/p/pkgconf/pkgconf_2.0.3-1.dsc"
|
|
if info.DSCURL != wantURL {
|
|
t.Fatalf("unexpected dsc url:\nwant: %s\ngot: %s", wantURL, info.DSCURL)
|
|
}
|
|
}
|
|
|
|
func TestResolveSourceHTTPNotFound(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
client := &http.Client{
|
|
Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
|
|
return httpResponse(req, http.StatusNotFound, []byte("not found")), nil
|
|
}),
|
|
}
|
|
|
|
r := NewResolver(
|
|
WithHTTPClient(client),
|
|
WithMirrors([]string{"https://mirror.example/debian"}),
|
|
WithSuites([]string{"stable"}),
|
|
WithComponents([]string{"main"}),
|
|
)
|
|
|
|
_, err := r.ResolveSource("no-such-package")
|
|
if err == nil {
|
|
t.Fatalf("expected not found error")
|
|
}
|
|
if !strings.Contains(err.Error(), "not found") {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseSourcesParagraph(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
paragraph := []string{
|
|
"Package: foo",
|
|
"Version: 1:2.3.4-5",
|
|
"Directory: pool/main/f/foo",
|
|
"Checksums-Sha256:",
|
|
" aaaa 10 foo_1:2.3.4-5.dsc",
|
|
" bbbb 20 foo_2.3.4.orig.tar.gz",
|
|
}
|
|
|
|
rec, err := parseSourcesParagraph(paragraph)
|
|
if err != nil {
|
|
t.Fatalf("parseSourcesParagraph() error = %v", err)
|
|
}
|
|
if rec.Package != "foo" || rec.Version != "1:2.3.4-5" {
|
|
t.Fatalf("unexpected record identity: %s %s", rec.Package, rec.Version)
|
|
}
|
|
if rec.Directory != "pool/main/f/foo" {
|
|
t.Fatalf("unexpected directory: %s", rec.Directory)
|
|
}
|
|
if rec.DSCName != "foo_1:2.3.4-5.dsc" {
|
|
t.Fatalf("unexpected dsc name: %s", rec.DSCName)
|
|
}
|
|
if rec.DSCSHA256 != "aaaa" {
|
|
t.Fatalf("unexpected dsc hash: %s", rec.DSCSHA256)
|
|
}
|
|
if got := normalizeUpstreamVersion(rec.Version); got != "2.3.4" {
|
|
t.Fatalf("unexpected normalized version: %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveSourceInvalidPackageName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
r := NewResolver()
|
|
_, err := r.ResolveSource("bad/name")
|
|
if err == nil {
|
|
t.Fatalf("expected package name validation error")
|
|
}
|
|
}
|
|
|
|
func httpResponse(req *http.Request, status int, body []byte) *http.Response {
|
|
return &http.Response{
|
|
StatusCode: status,
|
|
Body: io.NopCloser(bytes.NewReader(body)),
|
|
Header: make(http.Header),
|
|
Request: req,
|
|
Status: fmt.Sprintf("%d %s", status, http.StatusText(status)),
|
|
}
|
|
}
|