package packages import ( "strings" "testing" ) func TestParsePackages(t *testing.T) { input := `{ "firefox": { "name": "firefox-120.0", "pname": "firefox", "version": "120.0", "system": "x86_64-linux", "meta": { "description": "A web browser built from Firefox source tree", "homepage": "https://www.mozilla.org/firefox/", "license": {"spdxId": "MPL-2.0", "fullName": "Mozilla Public License 2.0"}, "maintainers": [ {"name": "John Doe", "github": "johndoe", "githubId": 12345} ], "platforms": ["x86_64-linux", "aarch64-linux"] } }, "python312Packages.requests": { "name": "python3.12-requests-2.31.0", "pname": "requests", "version": "2.31.0", "system": "x86_64-linux", "meta": { "description": "HTTP library for Python", "homepage": ["https://requests.readthedocs.io/"], "license": [{"spdxId": "Apache-2.0"}], "unfree": false } } }` packages, err := ParsePackages(strings.NewReader(input)) if err != nil { t.Fatalf("ParsePackages failed: %v", err) } if len(packages) != 2 { t.Errorf("Expected 2 packages, got %d", len(packages)) } // Check firefox firefox, ok := packages["firefox"] if !ok { t.Fatal("firefox package not found") } if firefox.Pname != "firefox" { t.Errorf("Expected pname 'firefox', got %q", firefox.Pname) } if firefox.Version != "120.0" { t.Errorf("Expected version '120.0', got %q", firefox.Version) } if firefox.Homepage != "https://www.mozilla.org/firefox/" { t.Errorf("Expected homepage 'https://www.mozilla.org/firefox/', got %q", firefox.Homepage) } if firefox.License != `["MPL-2.0"]` { t.Errorf("Expected license '[\"MPL-2.0\"]', got %q", firefox.License) } // Check python requests requests, ok := packages["python312Packages.requests"] if !ok { t.Fatal("python312Packages.requests package not found") } if requests.Pname != "requests" { t.Errorf("Expected pname 'requests', got %q", requests.Pname) } // Homepage is array, should extract first element if requests.Homepage != "https://requests.readthedocs.io/" { t.Errorf("Expected homepage 'https://requests.readthedocs.io/', got %q", requests.Homepage) } } func TestParsePackagesStream(t *testing.T) { input := `{ "hello": { "name": "hello-2.12", "pname": "hello", "version": "2.12", "system": "x86_64-linux", "meta": { "description": "A program that produces a familiar, friendly greeting" } }, "world": { "name": "world-1.0", "pname": "world", "version": "1.0", "system": "x86_64-linux", "meta": {} } }` var packages []*ParsedPackage count, err := ParsePackagesStream(strings.NewReader(input), func(pkg *ParsedPackage) error { packages = append(packages, pkg) return nil }) if err != nil { t.Fatalf("ParsePackagesStream failed: %v", err) } if count != 2 { t.Errorf("Expected count 2, got %d", count) } if len(packages) != 2 { t.Errorf("Expected 2 packages, got %d", len(packages)) } } func TestNormalizeLicense(t *testing.T) { tests := []struct { name string input interface{} expected string }{ {"nil", nil, "[]"}, {"string", "MIT", `["MIT"]`}, {"object with spdxId", map[string]interface{}{"spdxId": "MIT"}, `["MIT"]`}, {"object with fullName", map[string]interface{}{"fullName": "MIT License"}, `["MIT License"]`}, {"array of strings", []interface{}{"MIT", "Apache-2.0"}, `["MIT","Apache-2.0"]`}, {"array of objects", []interface{}{ map[string]interface{}{"spdxId": "MIT"}, map[string]interface{}{"spdxId": "Apache-2.0"}, }, `["MIT","Apache-2.0"]`}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := normalizeLicense(tc.input) if result != tc.expected { t.Errorf("Expected %q, got %q", tc.expected, result) } }) } } func TestNormalizeHomepage(t *testing.T) { tests := []struct { name string input interface{} expected string }{ {"nil", nil, ""}, {"string", "https://example.com", "https://example.com"}, {"array", []interface{}{"https://example.com", "https://docs.example.com"}, "https://example.com"}, {"empty array", []interface{}{}, ""}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := normalizeHomepage(tc.input) if result != tc.expected { t.Errorf("Expected %q, got %q", tc.expected, result) } }) } } func TestNormalizeMaintainers(t *testing.T) { tests := []struct { name string maintainers []Maintainer expected string }{ {"empty", nil, "[]"}, {"with name", []Maintainer{{Name: "John Doe"}}, `["John Doe"]`}, {"with github only", []Maintainer{{Github: "johndoe"}}, `["@johndoe"]`}, {"multiple", []Maintainer{{Name: "Alice"}, {Name: "Bob"}}, `["Alice","Bob"]`}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := normalizeMaintainers(tc.maintainers) if result != tc.expected { t.Errorf("Expected %q, got %q", tc.expected, result) } }) } } func TestSplitAttrPath(t *testing.T) { tests := []struct { input string expected []string }{ {"firefox", []string{"firefox"}}, {"python312Packages.requests", []string{"python312Packages", "requests"}}, {"haskellPackages.aeson.components.library", []string{"haskellPackages", "aeson", "components", "library"}}, } for _, tc := range tests { t.Run(tc.input, func(t *testing.T) { result := SplitAttrPath(tc.input) if len(result) != len(tc.expected) { t.Errorf("Expected %v, got %v", tc.expected, result) return } for i := range result { if result[i] != tc.expected[i] { t.Errorf("Expected %v, got %v", tc.expected, result) return } } }) } }