package apt import ( "testing" ) const sampleStanza = `Package: curl Version: 7.88.1-10+deb12u5 Architecture: amd64 Filename: pool/main/c/curl/curl_7.88.1-10+deb12u5_amd64.deb SHA256: abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 Size: 314456` const sampleStanza2 = `Package: wget Version: 1.21.3-1+b1 Architecture: amd64 Filename: pool/main/w/wget/wget_1.21.3-1+b1_amd64.deb SHA256: 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff Size: 512000` func TestParsePackages_single(t *testing.T) { pkgs, err := ParsePackages([]byte(sampleStanza)) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(pkgs) != 1 { t.Fatalf("expected 1 package, got %d", len(pkgs)) } p := pkgs[0] if p.Package != "curl" { t.Errorf("Package: got %q, want %q", p.Package, "curl") } if p.Version != "7.88.1-10+deb12u5" { t.Errorf("Version: got %q, want %q", p.Version, "7.88.1-10+deb12u5") } if p.Architecture != "amd64" { t.Errorf("Architecture: got %q, want %q", p.Architecture, "amd64") } if p.Filename != "pool/main/c/curl/curl_7.88.1-10+deb12u5_amd64.deb" { t.Errorf("Filename: got %q", p.Filename) } if p.SHA256 != "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" { t.Errorf("SHA256: got %q", p.SHA256) } if p.Size != 314456 { t.Errorf("Size: got %d, want %d", p.Size, 314456) } } func TestParsePackages_multiple(t *testing.T) { input := sampleStanza + "\n\n" + sampleStanza2 pkgs, err := ParsePackages([]byte(input)) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(pkgs) != 2 { t.Fatalf("expected 2 packages, got %d", len(pkgs)) } if pkgs[0].Package != "curl" { t.Errorf("first package: got %q, want curl", pkgs[0].Package) } if pkgs[1].Package != "wget" { t.Errorf("second package: got %q, want wget", pkgs[1].Package) } } func TestParsePackages_empty(t *testing.T) { pkgs, err := ParsePackages([]byte("")) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(pkgs) != 0 { t.Errorf("expected 0 packages, got %d", len(pkgs)) } } func TestParsePackages_missingPackageField(t *testing.T) { bad := `Version: 1.0 Architecture: amd64 Filename: pool/main/x/x/x_1.0_amd64.deb SHA256: 0000000000000000000000000000000000000000000000000000000000000000 Size: 100` _, err := ParsePackages([]byte(bad)) if err == nil { t.Error("expected error for missing Package field, got nil") } } func TestFilterPackages(t *testing.T) { pkgs, _ := ParsePackages([]byte(sampleStanza + "\n\n" + sampleStanza2)) // Only curl is "on disk". onDisk := map[string]bool{ "pool/main/c/curl/curl_7.88.1-10+deb12u5_amd64.deb": true, } filtered := FilterPackages(pkgs, func(filename string) bool { return onDisk[filename] }) if len(filtered) != 1 { t.Fatalf("expected 1 filtered package, got %d", len(filtered)) } if filtered[0].Package != "curl" { t.Errorf("expected curl, got %q", filtered[0].Package) } } func TestParseEmitRoundTrip(t *testing.T) { input := []byte(sampleStanza + "\n\n" + sampleStanza2 + "\n") pkgs, err := ParsePackages(input) if err != nil { t.Fatalf("parse: %v", err) } emitted := emitPackages(pkgs) reparsed, err := ParsePackages(emitted) if err != nil { t.Fatalf("reparse: %v", err) } if len(reparsed) != len(pkgs) { t.Fatalf("round-trip length: got %d, want %d", len(reparsed), len(pkgs)) } for i := range pkgs { if reparsed[i].Package != pkgs[i].Package { t.Errorf("[%d] Package: got %q, want %q", i, reparsed[i].Package, pkgs[i].Package) } if reparsed[i].Filename != pkgs[i].Filename { t.Errorf("[%d] Filename: got %q, want %q", i, reparsed[i].Filename, pkgs[i].Filename) } if reparsed[i].SHA256 != pkgs[i].SHA256 { t.Errorf("[%d] SHA256: got %q, want %q", i, reparsed[i].SHA256, pkgs[i].SHA256) } if reparsed[i].Size != pkgs[i].Size { t.Errorf("[%d] Size: got %d, want %d", i, reparsed[i].Size, pkgs[i].Size) } } }