mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-01 20:58:42 -07:00
- Add brew package for Homebrew support on macOS and Linux - Implement NameNormalizer interface (NormalizeName, ParseArch) for all providers - Add darwin platform detection with Homebrew as default - Consolidate capabilities by removing separate *_linux.go/*_other.go files - Update tests for new capability expectations - Add comprehensive tests for AUR and brew providers - Update README with capability matrix and modern Target API usage 💘 Generated with Crush Assisted-by: AWS Claude Opus 4.5 via Crush <crush@charm.land>
809 lines
19 KiB
Go
809 lines
19 KiB
Go
package ports
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/gogrlx/snack"
|
|
)
|
|
|
|
func TestParseList(t *testing.T) {
|
|
input := `bash-5.2.21 GNU Bourne Again Shell
|
|
curl-8.5.0 command line tool for transferring data
|
|
python-3.11.7p0 interpreted object-oriented programming language
|
|
`
|
|
pkgs := parseList(input)
|
|
if len(pkgs) != 3 {
|
|
t.Fatalf("expected 3 packages, got %d", len(pkgs))
|
|
}
|
|
if pkgs[0].Name != "bash" || pkgs[0].Version != "5.2.21" {
|
|
t.Errorf("unexpected first package: %+v", pkgs[0])
|
|
}
|
|
if pkgs[0].Description != "GNU Bourne Again Shell" {
|
|
t.Errorf("unexpected description: %q", pkgs[0].Description)
|
|
}
|
|
if !pkgs[0].Installed {
|
|
t.Error("expected Installed=true")
|
|
}
|
|
if pkgs[2].Name != "python" || pkgs[2].Version != "3.11.7p0" {
|
|
t.Errorf("unexpected third package: %+v", pkgs[2])
|
|
}
|
|
}
|
|
|
|
func TestParseListEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLen int
|
|
wantPkgs []snack.Package
|
|
}{
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "whitespace only",
|
|
input: " \n \n\n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "single entry",
|
|
input: "vim-9.0.2100 Vi IMproved\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "vim", Version: "9.0.2100", Description: "Vi IMproved", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "no description",
|
|
input: "vim-9.0.2100\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "vim", Version: "9.0.2100", Description: "", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "empty lines between entries",
|
|
input: "bash-5.2 Shell\n\n\ncurl-8.5.0 Transfer tool\n",
|
|
wantLen: 2,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "bash", Version: "5.2", Description: "Shell", Installed: true},
|
|
{Name: "curl", Version: "8.5.0", Description: "Transfer tool", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "package with p-suffix version (OpenBSD style)",
|
|
input: "python-3.11.7p0 interpreted language\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "python", Version: "3.11.7p0", Description: "interpreted language", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "package name with multiple hyphens",
|
|
input: "py3-django-rest-3.14.0 REST framework\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "py3-django-rest", Version: "3.14.0", Description: "REST framework", Installed: true},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pkgs := parseList(tt.input)
|
|
if len(pkgs) != tt.wantLen {
|
|
t.Fatalf("expected %d packages, got %d", tt.wantLen, len(pkgs))
|
|
}
|
|
for i, want := range tt.wantPkgs {
|
|
if i >= len(pkgs) {
|
|
break
|
|
}
|
|
got := pkgs[i]
|
|
if got.Name != want.Name {
|
|
t.Errorf("[%d] Name = %q, want %q", i, got.Name, want.Name)
|
|
}
|
|
if got.Version != want.Version {
|
|
t.Errorf("[%d] Version = %q, want %q", i, got.Version, want.Version)
|
|
}
|
|
if got.Description != want.Description {
|
|
t.Errorf("[%d] Description = %q, want %q", i, got.Description, want.Description)
|
|
}
|
|
if got.Installed != want.Installed {
|
|
t.Errorf("[%d] Installed = %v, want %v", i, got.Installed, want.Installed)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseSearchResults(t *testing.T) {
|
|
input := `nginx-1.24.0
|
|
nginx-1.25.3
|
|
`
|
|
pkgs := parseSearchResults(input)
|
|
if len(pkgs) != 2 {
|
|
t.Fatalf("expected 2 packages, got %d", len(pkgs))
|
|
}
|
|
if pkgs[0].Name != "nginx" || pkgs[0].Version != "1.24.0" {
|
|
t.Errorf("unexpected first package: %+v", pkgs[0])
|
|
}
|
|
}
|
|
|
|
func TestParseSearchResultsEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLen int
|
|
wantPkgs []snack.Package
|
|
}{
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "whitespace only",
|
|
input: " \n\n \n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "single result",
|
|
input: "curl-8.5.0\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "curl", Version: "8.5.0"},
|
|
},
|
|
},
|
|
{
|
|
name: "name with many hyphens",
|
|
input: "py3-django-rest-framework-3.14.0\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "py3-django-rest-framework", Version: "3.14.0"},
|
|
},
|
|
},
|
|
{
|
|
name: "no version (no hyphen)",
|
|
input: "quirks\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "quirks", Version: ""},
|
|
},
|
|
},
|
|
{
|
|
name: "p-suffix version",
|
|
input: "python-3.11.7p0\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "python", Version: "3.11.7p0"},
|
|
},
|
|
},
|
|
{
|
|
name: "multiple results with blank lines",
|
|
input: "a-1.0\n\nb-2.0\n\nc-3.0\n",
|
|
wantLen: 3,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pkgs := parseSearchResults(tt.input)
|
|
if len(pkgs) != tt.wantLen {
|
|
t.Fatalf("expected %d packages, got %d", tt.wantLen, len(pkgs))
|
|
}
|
|
for i, want := range tt.wantPkgs {
|
|
if i >= len(pkgs) {
|
|
break
|
|
}
|
|
got := pkgs[i]
|
|
if got.Name != want.Name {
|
|
t.Errorf("[%d] Name = %q, want %q", i, got.Name, want.Name)
|
|
}
|
|
if got.Version != want.Version {
|
|
t.Errorf("[%d] Version = %q, want %q", i, got.Version, want.Version)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseInfoOutput(t *testing.T) {
|
|
input := `Information for nginx-1.24.0:
|
|
|
|
Comment:
|
|
robust and small WWW server
|
|
Description:
|
|
nginx is an HTTP and reverse proxy server, a mail proxy server,
|
|
and a generic TCP/UDP proxy server.
|
|
`
|
|
pkg := parseInfoOutput(input, "nginx-1.24.0")
|
|
if pkg == nil {
|
|
t.Fatal("expected non-nil package")
|
|
}
|
|
if pkg.Name != "nginx" {
|
|
t.Errorf("expected name 'nginx', got %q", pkg.Name)
|
|
}
|
|
if pkg.Version != "1.24.0" {
|
|
t.Errorf("unexpected version: %q", pkg.Version)
|
|
}
|
|
}
|
|
|
|
func TestParseInfoOutputWithComment(t *testing.T) {
|
|
input := `Information for curl-8.5.0:
|
|
|
|
Comment: command line tool for transferring data
|
|
Description:
|
|
curl is a tool to transfer data from or to a server.
|
|
`
|
|
pkg := parseInfoOutput(input, "curl-8.5.0")
|
|
if pkg == nil {
|
|
t.Fatal("expected non-nil package")
|
|
}
|
|
if pkg.Name != "curl" {
|
|
t.Errorf("expected name 'curl', got %q", pkg.Name)
|
|
}
|
|
if pkg.Description != "command line tool for transferring data" {
|
|
t.Errorf("unexpected description: %q", pkg.Description)
|
|
}
|
|
}
|
|
|
|
func TestParseInfoOutputEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
pkgArg string
|
|
wantNil bool
|
|
want *snack.Package
|
|
}{
|
|
{
|
|
name: "empty input and empty pkg arg",
|
|
input: "",
|
|
pkgArg: "",
|
|
wantNil: true,
|
|
},
|
|
{
|
|
name: "empty input with pkg arg fallback",
|
|
input: "",
|
|
pkgArg: "curl-8.5.0",
|
|
want: &snack.Package{Name: "curl", Version: "8.5.0", Installed: true},
|
|
},
|
|
{
|
|
name: "no header, falls back to pkg arg",
|
|
input: "Some random output\nwithout the expected header",
|
|
pkgArg: "vim-9.0",
|
|
want: &snack.Package{Name: "vim", Version: "9.0", Installed: true},
|
|
},
|
|
{
|
|
name: "comment on same line as Comment: label",
|
|
input: `Information for zsh-5.9:
|
|
|
|
Comment: Zsh shell
|
|
`,
|
|
pkgArg: "zsh-5.9",
|
|
want: &snack.Package{Name: "zsh", Version: "5.9", Description: "Zsh shell", Installed: true},
|
|
},
|
|
{
|
|
name: "comment on next line after Comment: label (not captured as description)",
|
|
input: `Information for bash-5.2:
|
|
|
|
Comment:
|
|
GNU Bourne Again Shell
|
|
`,
|
|
pkgArg: "bash-5.2",
|
|
// Comment: with nothing after the colon sets Description="",
|
|
// and the next line isn't in a Description: block so it's ignored.
|
|
want: &snack.Package{Name: "bash", Version: "5.2", Description: "", Installed: true},
|
|
},
|
|
{
|
|
name: "description spans multiple lines",
|
|
input: `Information for git-2.43.0:
|
|
|
|
Comment: distributed version control system
|
|
Description:
|
|
Git is a fast, scalable, distributed revision control system
|
|
with an unusually rich command set.
|
|
`,
|
|
pkgArg: "git-2.43.0",
|
|
want: &snack.Package{Name: "git", Version: "2.43.0", Description: "distributed version control system", Installed: true},
|
|
},
|
|
{
|
|
name: "extra fields are ignored",
|
|
input: `Information for tmux-3.3a:
|
|
|
|
Comment: terminal multiplexer
|
|
Maintainer: someone@openbsd.org
|
|
WWW: https://tmux.github.io
|
|
Description:
|
|
tmux is a terminal multiplexer.
|
|
`,
|
|
pkgArg: "tmux-3.3a",
|
|
want: &snack.Package{Name: "tmux", Version: "3.3a", Description: "terminal multiplexer", Installed: true},
|
|
},
|
|
{
|
|
name: "pkg arg with no version (no hyphen)",
|
|
input: "",
|
|
pkgArg: "quirks",
|
|
want: &snack.Package{Name: "quirks", Version: "", Installed: true},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := parseInfoOutput(tt.input, tt.pkgArg)
|
|
if tt.wantNil {
|
|
if got != nil {
|
|
t.Errorf("expected nil, got %+v", got)
|
|
}
|
|
return
|
|
}
|
|
if got == nil {
|
|
t.Fatal("expected non-nil package")
|
|
}
|
|
if got.Name != tt.want.Name {
|
|
t.Errorf("Name = %q, want %q", got.Name, tt.want.Name)
|
|
}
|
|
if got.Version != tt.want.Version {
|
|
t.Errorf("Version = %q, want %q", got.Version, tt.want.Version)
|
|
}
|
|
if tt.want.Description != "" && got.Description != tt.want.Description {
|
|
t.Errorf("Description = %q, want %q", got.Description, tt.want.Description)
|
|
}
|
|
if got.Installed != tt.want.Installed {
|
|
t.Errorf("Installed = %v, want %v", got.Installed, tt.want.Installed)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseInfoOutputEmpty(t *testing.T) {
|
|
pkg := parseInfoOutput("", "")
|
|
if pkg != nil {
|
|
t.Error("expected nil for empty input and empty pkg name")
|
|
}
|
|
}
|
|
|
|
func TestParseInfoOutputFallbackToPkgArg(t *testing.T) {
|
|
input := "Some random output\nwithout the expected header"
|
|
pkg := parseInfoOutput(input, "curl-8.5.0")
|
|
if pkg == nil {
|
|
t.Fatal("expected non-nil package from fallback")
|
|
}
|
|
if pkg.Name != "curl" || pkg.Version != "8.5.0" {
|
|
t.Errorf("unexpected fallback parse: %+v", pkg)
|
|
}
|
|
}
|
|
|
|
func TestSplitNameVersion(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
wantName string
|
|
wantVersion string
|
|
}{
|
|
{"nginx-1.24.0", "nginx", "1.24.0"},
|
|
{"py3-pip-23.1", "py3-pip", "23.1"},
|
|
{"bash", "bash", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
name, ver := splitNameVersion(tt.input)
|
|
if name != tt.wantName || ver != tt.wantVersion {
|
|
t.Errorf("splitNameVersion(%q) = (%q, %q), want (%q, %q)",
|
|
tt.input, name, ver, tt.wantName, tt.wantVersion)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSplitNameVersionEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantName string
|
|
wantVersion string
|
|
}{
|
|
{
|
|
name: "empty string",
|
|
input: "",
|
|
wantName: "",
|
|
wantVersion: "",
|
|
},
|
|
{
|
|
name: "no hyphen",
|
|
input: "singleword",
|
|
wantName: "singleword",
|
|
wantVersion: "",
|
|
},
|
|
{
|
|
name: "multiple hyphens",
|
|
input: "py3-django-rest-3.14.0",
|
|
wantName: "py3-django-rest",
|
|
wantVersion: "3.14.0",
|
|
},
|
|
{
|
|
name: "leading hyphen (idx=0, returns whole string)",
|
|
input: "-1.0",
|
|
wantName: "-1.0",
|
|
wantVersion: "",
|
|
},
|
|
{
|
|
name: "trailing hyphen",
|
|
input: "nginx-",
|
|
wantName: "nginx",
|
|
wantVersion: "",
|
|
},
|
|
{
|
|
name: "only hyphen",
|
|
input: "-",
|
|
wantName: "-",
|
|
wantVersion: "",
|
|
},
|
|
{
|
|
name: "hyphen at index 1",
|
|
input: "a-1.0",
|
|
wantName: "a",
|
|
wantVersion: "1.0",
|
|
},
|
|
{
|
|
name: "p-suffix version",
|
|
input: "python-3.11.7p0",
|
|
wantName: "python",
|
|
wantVersion: "3.11.7p0",
|
|
},
|
|
{
|
|
name: "version with v prefix",
|
|
input: "go-v1.21.5",
|
|
wantName: "go",
|
|
wantVersion: "v1.21.5",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
name, ver := splitNameVersion(tt.input)
|
|
if name != tt.wantName || ver != tt.wantVersion {
|
|
t.Errorf("splitNameVersion(%q) = (%q, %q), want (%q, %q)",
|
|
tt.input, name, ver, tt.wantName, tt.wantVersion)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSplitNameVersionNoHyphen(t *testing.T) {
|
|
name, ver := splitNameVersion("singleword")
|
|
if name != "singleword" || ver != "" {
|
|
t.Errorf("splitNameVersion(\"singleword\") = (%q, %q), want (\"singleword\", \"\")", name, ver)
|
|
}
|
|
}
|
|
|
|
func TestSplitNameVersionLeadingHyphen(t *testing.T) {
|
|
name, ver := splitNameVersion("-1.0")
|
|
if name != "-1.0" || ver != "" {
|
|
t.Errorf("splitNameVersion(\"-1.0\") = (%q, %q), want (\"-1.0\", \"\")", name, ver)
|
|
}
|
|
}
|
|
|
|
func TestParseUpgradeOutput(t *testing.T) {
|
|
input := `quirks-7.14 -> quirks-7.18
|
|
curl-8.5.0 -> curl-8.6.0
|
|
python-3.11.7p0 -> python-3.11.8p0
|
|
`
|
|
pkgs := parseUpgradeOutput(input)
|
|
if len(pkgs) != 3 {
|
|
t.Fatalf("expected 3 packages, got %d", len(pkgs))
|
|
}
|
|
if pkgs[0].Name != "quirks" || pkgs[0].Version != "7.18" {
|
|
t.Errorf("unexpected first package: %+v", pkgs[0])
|
|
}
|
|
if pkgs[1].Name != "curl" || pkgs[1].Version != "8.6.0" {
|
|
t.Errorf("unexpected second package: %+v", pkgs[1])
|
|
}
|
|
if pkgs[2].Name != "python" || pkgs[2].Version != "3.11.8p0" {
|
|
t.Errorf("unexpected third package: %+v", pkgs[2])
|
|
}
|
|
}
|
|
|
|
func TestParseUpgradeOutputEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLen int
|
|
wantPkgs []snack.Package
|
|
}{
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "whitespace only",
|
|
input: " \n\n \n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "single upgrade",
|
|
input: "bash-5.2 -> bash-5.3\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "bash", Version: "5.3", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "line without -> is skipped",
|
|
input: "Some info line\nbash-5.2 -> bash-5.3\nAnother line\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "bash", Version: "5.3", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "malformed line (-> but not enough fields)",
|
|
input: "-> bash-5.3\n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "wrong arrow (=> instead of ->)",
|
|
input: "bash-5.2 => bash-5.3\n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "package name with multiple hyphens",
|
|
input: "py3-django-rest-3.14.0 -> py3-django-rest-3.15.0\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "py3-django-rest", Version: "3.15.0", Installed: true},
|
|
},
|
|
},
|
|
{
|
|
name: "p-suffix versions",
|
|
input: "python-3.11.7p0 -> python-3.11.8p1\n",
|
|
wantLen: 1,
|
|
wantPkgs: []snack.Package{
|
|
{Name: "python", Version: "3.11.8p1", Installed: true},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pkgs := parseUpgradeOutput(tt.input)
|
|
if len(pkgs) != tt.wantLen {
|
|
t.Fatalf("expected %d packages, got %d", tt.wantLen, len(pkgs))
|
|
}
|
|
for i, want := range tt.wantPkgs {
|
|
if i >= len(pkgs) {
|
|
break
|
|
}
|
|
got := pkgs[i]
|
|
if got.Name != want.Name {
|
|
t.Errorf("[%d] Name = %q, want %q", i, got.Name, want.Name)
|
|
}
|
|
if got.Version != want.Version {
|
|
t.Errorf("[%d] Version = %q, want %q", i, got.Version, want.Version)
|
|
}
|
|
if got.Installed != want.Installed {
|
|
t.Errorf("[%d] Installed = %v, want %v", i, got.Installed, want.Installed)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseUpgradeOutputEmpty(t *testing.T) {
|
|
pkgs := parseUpgradeOutput("")
|
|
if len(pkgs) != 0 {
|
|
t.Fatalf("expected 0 packages, got %d", len(pkgs))
|
|
}
|
|
}
|
|
|
|
func TestParseFileListOutput(t *testing.T) {
|
|
input := `Information for curl-8.5.0:
|
|
|
|
Files:
|
|
/usr/local/bin/curl
|
|
/usr/local/include/curl/curl.h
|
|
/usr/local/lib/libcurl.so.26.0
|
|
/usr/local/man/man1/curl.1
|
|
`
|
|
files := parseFileListOutput(input)
|
|
if len(files) != 4 {
|
|
t.Fatalf("expected 4 files, got %d", len(files))
|
|
}
|
|
if files[0] != "/usr/local/bin/curl" {
|
|
t.Errorf("unexpected first file: %q", files[0])
|
|
}
|
|
}
|
|
|
|
func TestParseFileListOutputEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantLen int
|
|
want []string
|
|
}{
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "header only no files",
|
|
input: "Information for pkg-1.0:\n\nFiles:\n",
|
|
wantLen: 0,
|
|
},
|
|
{
|
|
name: "paths with spaces",
|
|
input: "Information for pkg-1.0:\n\nFiles:\n/usr/local/share/my dir/file name.txt\n/usr/local/share/another path/test\n",
|
|
wantLen: 2,
|
|
want: []string{
|
|
"/usr/local/share/my dir/file name.txt",
|
|
"/usr/local/share/another path/test",
|
|
},
|
|
},
|
|
{
|
|
name: "single file",
|
|
input: "Files:\n/usr/local/bin/bash\n",
|
|
wantLen: 1,
|
|
want: []string{"/usr/local/bin/bash"},
|
|
},
|
|
{
|
|
name: "no header just paths",
|
|
input: "/usr/local/bin/a\n/usr/local/bin/b\n",
|
|
wantLen: 2,
|
|
},
|
|
{
|
|
name: "blank lines between files",
|
|
input: "Files:\n/usr/local/bin/a\n\n/usr/local/bin/b\n",
|
|
wantLen: 2,
|
|
},
|
|
{
|
|
name: "non-path lines are skipped",
|
|
input: "Information for pkg-1.0:\n\nFiles:\nNot a path\n/usr/local/bin/real\n",
|
|
wantLen: 1,
|
|
want: []string{"/usr/local/bin/real"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
files := parseFileListOutput(tt.input)
|
|
if len(files) != tt.wantLen {
|
|
t.Fatalf("expected %d files, got %d", tt.wantLen, len(files))
|
|
}
|
|
for i, w := range tt.want {
|
|
if i >= len(files) {
|
|
break
|
|
}
|
|
if files[i] != w {
|
|
t.Errorf("[%d] got %q, want %q", i, files[i], w)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseFileListOutputEmpty(t *testing.T) {
|
|
files := parseFileListOutput("")
|
|
if len(files) != 0 {
|
|
t.Fatalf("expected 0 files, got %d", len(files))
|
|
}
|
|
}
|
|
|
|
func TestParseOwnerOutput(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
want string
|
|
}{
|
|
{"curl-8.5.0", "curl"},
|
|
{"python-3.11.7p0", "python"},
|
|
{"", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
got := parseOwnerOutput(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("parseOwnerOutput(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseOwnerOutputEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
}{
|
|
{
|
|
name: "empty input",
|
|
input: "",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "whitespace only",
|
|
input: " \n ",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "name with many hyphens",
|
|
input: "py3-django-rest-framework-3.14.0",
|
|
want: "py3-django-rest-framework",
|
|
},
|
|
{
|
|
name: "no version (no hyphen)",
|
|
input: "quirks",
|
|
want: "quirks",
|
|
},
|
|
{
|
|
name: "leading/trailing whitespace",
|
|
input: " curl-8.5.0 ",
|
|
want: "curl",
|
|
},
|
|
{
|
|
name: "p-suffix version",
|
|
input: "python-3.11.7p0",
|
|
want: "python",
|
|
},
|
|
{
|
|
name: "trailing newline",
|
|
input: "bash-5.2\n",
|
|
want: "bash",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := parseOwnerOutput(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("parseOwnerOutput(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInterfaceCompliance(t *testing.T) {
|
|
var _ snack.Manager = (*Ports)(nil)
|
|
var _ snack.VersionQuerier = (*Ports)(nil)
|
|
var _ snack.Cleaner = (*Ports)(nil)
|
|
var _ snack.FileOwner = (*Ports)(nil)
|
|
var _ snack.PackageUpgrader = (*Ports)(nil)
|
|
}
|
|
|
|
func TestPackageUpgraderInterface(t *testing.T) {
|
|
var _ snack.PackageUpgrader = (*Ports)(nil)
|
|
}
|
|
|
|
func TestName(t *testing.T) {
|
|
p := New()
|
|
if p.Name() != "ports" {
|
|
t.Errorf("Name() = %q, want %q", p.Name(), "ports")
|
|
}
|
|
}
|
|
|
|
func TestCapabilities(t *testing.T) {
|
|
caps := snack.GetCapabilities(New())
|
|
|
|
// Should be true
|
|
if !caps.VersionQuery {
|
|
t.Error("expected VersionQuery=true")
|
|
}
|
|
if !caps.Clean {
|
|
t.Error("expected Clean=true")
|
|
}
|
|
if !caps.FileOwnership {
|
|
t.Error("expected FileOwnership=true")
|
|
}
|
|
|
|
// Should be false
|
|
if caps.Hold {
|
|
t.Error("expected Hold=false")
|
|
}
|
|
if caps.RepoManagement {
|
|
t.Error("expected RepoManagement=false")
|
|
}
|
|
if caps.KeyManagement {
|
|
t.Error("expected KeyManagement=false")
|
|
}
|
|
if caps.Groups {
|
|
t.Error("expected Groups=false")
|
|
}
|
|
if !caps.NameNormalize {
|
|
t.Error("expected NameNormalize=true")
|
|
}
|
|
if caps.DryRun {
|
|
t.Error("expected DryRun=false")
|
|
}
|
|
if !caps.PackageUpgrade {
|
|
t.Error("expected PackageUpgrade=true")
|
|
}
|
|
}
|