mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
- Root package unit tests: Targets, TargetNames, ApplyOptions, error sentinels - Every provider integration test now covers: - All Manager interface methods (positive + negative cases) - GetCapabilities verification (assert expected interfaces) - VersionQuerier: LatestVersion, ListUpgrades, UpgradeAvailable, VersionCmp - Holder: Hold, ListHeld, Unhold (apt, dnf) - Cleaner: Autoremove, Clean - FileOwner: FileList, Owner (+ not-found cases) - RepoManager: ListRepos (apt, dnf, flatpak) - KeyManager: ListKeys (apt, dnf) - Grouper: GroupList, GroupInfo (pacman, dnf) - NameNormalizer: NormalizeName, ParseArch table tests (apt, dpkg, dnf, rpm) - Containertest matrix: 5 distros (debian, alpine, arch, fedora39, fedora-latest) - CI: coverage profiles uploaded per-job, merged in codecov job - Added .gitignore for coverage files
177 lines
4.3 KiB
Go
177 lines
4.3 KiB
Go
//go:build integration
|
|
|
|
package dpkg_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/gogrlx/snack"
|
|
"github.com/gogrlx/snack/dpkg"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestIntegration_Dpkg(t *testing.T) {
|
|
mgr := dpkg.New()
|
|
if !mgr.Available() {
|
|
t.Skip("dpkg not available")
|
|
}
|
|
ctx := context.Background()
|
|
|
|
assert.Equal(t, "dpkg", mgr.Name())
|
|
|
|
caps := snack.GetCapabilities(mgr)
|
|
assert.True(t, caps.FileOwnership, "dpkg should support FileOwnership")
|
|
assert.True(t, caps.NameNormalize, "dpkg should support NameNormalize")
|
|
assert.False(t, caps.VersionQuery)
|
|
assert.False(t, caps.Hold)
|
|
assert.False(t, caps.Clean)
|
|
assert.False(t, caps.RepoManagement)
|
|
assert.False(t, caps.KeyManagement)
|
|
assert.False(t, caps.Groups)
|
|
|
|
t.Run("List", func(t *testing.T) {
|
|
pkgs, err := mgr.List(ctx)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, pkgs)
|
|
|
|
found := false
|
|
for _, p := range pkgs {
|
|
if p.Name == "bash" {
|
|
found = true
|
|
assert.NotEmpty(t, p.Version)
|
|
assert.True(t, p.Installed)
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "bash should be in list")
|
|
})
|
|
|
|
t.Run("IsInstalled_True", func(t *testing.T) {
|
|
installed, err := mgr.IsInstalled(ctx, "bash")
|
|
require.NoError(t, err)
|
|
assert.True(t, installed)
|
|
})
|
|
|
|
t.Run("IsInstalled_False", func(t *testing.T) {
|
|
installed, err := mgr.IsInstalled(ctx, "xyznonexistentpackage999")
|
|
require.NoError(t, err)
|
|
assert.False(t, installed)
|
|
})
|
|
|
|
t.Run("Version", func(t *testing.T) {
|
|
ver, err := mgr.Version(ctx, "bash")
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, ver)
|
|
t.Logf("bash version: %s", ver)
|
|
})
|
|
|
|
t.Run("Version_NotInstalled", func(t *testing.T) {
|
|
_, err := mgr.Version(ctx, "xyznonexistentpackage999")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Info", func(t *testing.T) {
|
|
pkg, err := mgr.Info(ctx, "bash")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, pkg)
|
|
assert.Equal(t, "bash", pkg.Name)
|
|
assert.NotEmpty(t, pkg.Version)
|
|
})
|
|
|
|
t.Run("Info_NotFound", func(t *testing.T) {
|
|
_, err := mgr.Info(ctx, "xyznonexistentpackage999")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Search", func(t *testing.T) {
|
|
pkgs, err := mgr.Search(ctx, "bash")
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, pkgs)
|
|
})
|
|
|
|
t.Run("Search_NoResults", func(t *testing.T) {
|
|
pkgs, err := mgr.Search(ctx, "xyznonexistentpackage999")
|
|
require.NoError(t, err)
|
|
assert.Empty(t, pkgs)
|
|
})
|
|
|
|
// --- FileOwner ---
|
|
t.Run("FileOwner", func(t *testing.T) {
|
|
fo, ok := mgr.(snack.FileOwner)
|
|
require.True(t, ok)
|
|
|
|
t.Run("FileList", func(t *testing.T) {
|
|
files, err := fo.FileList(ctx, "bash")
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, files)
|
|
|
|
found := false
|
|
for _, f := range files {
|
|
if f == "/usr/bin/bash" || f == "/bin/bash" {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "bash binary should be in file list")
|
|
})
|
|
|
|
t.Run("FileList_NotInstalled", func(t *testing.T) {
|
|
_, err := fo.FileList(ctx, "xyznonexistentpackage999")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Owner", func(t *testing.T) {
|
|
owner, err := fo.Owner(ctx, "/usr/bin/dpkg")
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, owner)
|
|
assert.Contains(t, owner, "dpkg")
|
|
})
|
|
|
|
t.Run("Owner_NotFound", func(t *testing.T) {
|
|
_, err := fo.Owner(ctx, "/nonexistent/path/xyz")
|
|
assert.Error(t, err)
|
|
})
|
|
})
|
|
|
|
// --- NameNormalizer ---
|
|
t.Run("NameNormalizer", func(t *testing.T) {
|
|
nn, ok := mgr.(snack.NameNormalizer)
|
|
require.True(t, ok)
|
|
|
|
tests := []struct {
|
|
input, wantName, wantArch string
|
|
}{
|
|
{"curl:amd64", "curl", "amd64"},
|
|
{"bash:arm64", "bash", "arm64"},
|
|
{"python3", "python3", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run("NormalizeName_"+tt.input, func(t *testing.T) {
|
|
got := nn.NormalizeName(tt.input)
|
|
assert.Equal(t, tt.wantName, got)
|
|
})
|
|
t.Run("ParseArch_"+tt.input, func(t *testing.T) {
|
|
name, arch := nn.ParseArch(tt.input)
|
|
assert.Equal(t, tt.wantName, name)
|
|
assert.Equal(t, tt.wantArch, arch)
|
|
})
|
|
}
|
|
})
|
|
|
|
// --- Operations that dpkg doesn't really support (exercise error paths) ---
|
|
t.Run("Install_Unsupported", func(t *testing.T) {
|
|
// dpkg install requires a .deb file path, not a package name
|
|
// This should fail gracefully
|
|
err := mgr.Install(ctx, snack.Targets("tree"))
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("Update", func(t *testing.T) {
|
|
// dpkg doesn't have update, should be a no-op or error
|
|
err := mgr.Update(ctx)
|
|
_ = err // exercise path
|
|
})
|
|
}
|