diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 0000000..ca3d749 --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,118 @@ +name: Integration Tests +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + unit-tests: + name: Unit Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - run: go build ./... + - run: go vet ./... + - run: go test -race ./... + + debian: + name: Debian (apt) + runs-on: ubuntu-latest + container: debian:bookworm + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Setup + run: | + apt-get update + apt-get install -y sudo tree curl + - name: Integration tests + run: go test -v -tags integration -count=1 ./apt/ ./dpkg/ ./detect/ + + ubuntu: + name: Ubuntu (apt + snap) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Setup + run: | + sudo apt-get update + sudo apt-get install -y tree + sudo snap install hello-world 2>/dev/null; sudo snap remove hello-world 2>/dev/null + - name: Integration tests (apt) + run: sudo -E go test -v -tags integration -count=1 ./apt/ ./dpkg/ ./detect/ + - name: Integration tests (snap) + run: sudo -E go test -v -tags integration -count=1 ./snap/ + + fedora: + name: Fedora (dnf) + runs-on: ubuntu-latest + container: fedora:latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Setup + run: | + dnf install -y tree sudo + - name: Integration tests + run: go test -v -tags integration -count=1 ./dnf/ ./rpm/ ./detect/ + + alpine: + name: Alpine (apk) + runs-on: ubuntu-latest + container: alpine:latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Setup + run: | + apk add --no-cache sudo tree bash + - name: Integration tests + run: go test -v -tags integration -count=1 ./apk/ ./detect/ + + arch: + name: Arch Linux (pacman) + runs-on: ubuntu-latest + container: archlinux:latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Setup + run: | + pacman -Syu --noconfirm + pacman -S --noconfirm sudo tree + - name: Integration tests + run: go test -v -tags integration -count=1 ./pacman/ ./detect/ + + flatpak: + name: Ubuntu + Flatpak + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Verify flatpak not installed + run: | + if command -v flatpak &>/dev/null; then echo "already installed"; else echo "not installed — good"; fi + - name: Install flatpak + run: | + sudo apt-get update + sudo apt-get install -y flatpak + sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + - name: Integration tests + run: sudo -E go test -v -tags integration -count=1 ./flatpak/ diff --git a/apk/apk_integration_test.go b/apk/apk_integration_test.go new file mode 100644 index 0000000..f80fc4f --- /dev/null +++ b/apk/apk_integration_test.go @@ -0,0 +1,104 @@ +//go:build integration + +package apk_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/apk" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Apk(t *testing.T) { + mgr := apk.New() + if !mgr.Available() { + t.Skip("apk not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "curl") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + pkg, err := mgr.Info(ctx, "curl") + require.NoError(t, err) + require.NotNil(t, pkg) + assert.Equal(t, "curl", pkg.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "tree") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "tree" { + found = true + break + } + } + assert.True(t, found, "tree should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.False(t, installed) + }) + + t.Run("Capabilities", func(t *testing.T) { + if vq, ok := mgr.(snack.VersionQuerier); ok { + ver, err := vq.LatestVersion(ctx, "curl") + require.NoError(t, err) + assert.NotEmpty(t, ver) + + upgrades, err := vq.ListUpgrades(ctx) + require.NoError(t, err) + _ = upgrades + } + + if cl, ok := mgr.(snack.Cleaner); ok { + err := cl.Clean(ctx) + require.NoError(t, err) + } + + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/usr/bin/apk") + if err == nil { + assert.NotEmpty(t, owner) + } + } + }) +} diff --git a/apt/apt_integration_test.go b/apt/apt_integration_test.go new file mode 100644 index 0000000..b123a68 --- /dev/null +++ b/apt/apt_integration_test.go @@ -0,0 +1,104 @@ +//go:build integration + +package apt_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/apt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Apt(t *testing.T) { + mgr := apt.New() + if !mgr.Available() { + t.Skip("apt not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "curl") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + pkg, err := mgr.Info(ctx, "curl") + require.NoError(t, err) + require.NotNil(t, pkg) + assert.Equal(t, "curl", pkg.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "tree") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "tree" { + found = true + break + } + } + assert.True(t, found, "tree should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.False(t, installed) + }) + + t.Run("Capabilities", func(t *testing.T) { + if vq, ok := mgr.(snack.VersionQuerier); ok { + ver, err := vq.LatestVersion(ctx, "curl") + require.NoError(t, err) + assert.NotEmpty(t, ver) + + upgrades, err := vq.ListUpgrades(ctx) + require.NoError(t, err) + _ = upgrades + } + + if cl, ok := mgr.(snack.Cleaner); ok { + err := cl.Clean(ctx) + require.NoError(t, err) + } + + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/usr/bin/apt") + if err == nil { + assert.NotEmpty(t, owner) + } + } + }) +} diff --git a/detect/detect_integration_test.go b/detect/detect_integration_test.go new file mode 100644 index 0000000..6bc9e55 --- /dev/null +++ b/detect/detect_integration_test.go @@ -0,0 +1,29 @@ +//go:build integration + +package detect_test + +import ( + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/detect" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Detect(t *testing.T) { + mgr, err := detect.Default() + require.NoError(t, err) + require.NotNil(t, mgr) + t.Logf("Detected: %s", mgr.Name()) + + all := detect.All() + require.NotEmpty(t, all) + for _, m := range all { + t.Logf("Available: %s", m.Name()) + } + + caps := snack.GetCapabilities(mgr) + t.Logf("Capabilities: %+v", caps) + assert.NotEmpty(t, mgr.Name()) +} diff --git a/dnf/dnf_integration_test.go b/dnf/dnf_integration_test.go new file mode 100644 index 0000000..8c60429 --- /dev/null +++ b/dnf/dnf_integration_test.go @@ -0,0 +1,110 @@ +//go:build integration + +package dnf_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/dnf" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_DNF(t *testing.T) { + mgr := dnf.New() + if !mgr.Available() { + t.Skip("dnf not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "curl") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + pkg, err := mgr.Info(ctx, "curl") + require.NoError(t, err) + require.NotNil(t, pkg) + assert.Equal(t, "curl", pkg.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "tree") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "tree" { + found = true + break + } + } + assert.True(t, found, "tree should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.False(t, installed) + }) + + t.Run("Capabilities", func(t *testing.T) { + if vq, ok := mgr.(snack.VersionQuerier); ok { + ver, err := vq.LatestVersion(ctx, "curl") + require.NoError(t, err) + assert.NotEmpty(t, ver) + + upgrades, err := vq.ListUpgrades(ctx) + require.NoError(t, err) + _ = upgrades + } + + if cl, ok := mgr.(snack.Cleaner); ok { + err := cl.Clean(ctx) + require.NoError(t, err) + } + + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/usr/bin/dnf") + if err == nil { + assert.NotEmpty(t, owner) + } + } + + if g, ok := mgr.(snack.Grouper); ok { + groups, err := g.GroupList(ctx) + require.NoError(t, err) + _ = groups + } + }) +} diff --git a/dpkg/dpkg_integration_test.go b/dpkg/dpkg_integration_test.go new file mode 100644 index 0000000..9308734 --- /dev/null +++ b/dpkg/dpkg_integration_test.go @@ -0,0 +1,65 @@ +//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() + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("IsInstalled", func(t *testing.T) { + // bash should always be installed + installed, err := mgr.IsInstalled(ctx, "bash") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "bash") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + 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) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "bash") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("FileOwner", func(t *testing.T) { + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/bin/bash") + require.NoError(t, err) + assert.NotEmpty(t, owner) + + files, err := fo.FileList(ctx, "bash") + require.NoError(t, err) + assert.NotEmpty(t, files) + } + }) +} diff --git a/flatpak/flatpak_integration_test.go b/flatpak/flatpak_integration_test.go new file mode 100644 index 0000000..c92d4d3 --- /dev/null +++ b/flatpak/flatpak_integration_test.go @@ -0,0 +1,84 @@ +//go:build integration + +package flatpak_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/flatpak" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Flatpak(t *testing.T) { + mgr := flatpak.New() + if !mgr.Available() { + t.Skip("flatpak not available — install it first") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("RepoManager", func(t *testing.T) { + rm, ok := mgr.(snack.RepoManager) + if !ok { + t.Skip("RepoManager not implemented") + } + repos, err := rm.ListRepos(ctx) + require.NoError(t, err) + found := false + for _, r := range repos { + if r.Name == "flathub" || r.ID == "flathub" { + found = true + break + } + } + assert.True(t, found, "flathub repo should be configured") + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "Flatseal") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("com.github.tchx84.Flatseal"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "com.github.tchx84.Flatseal") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "com.github.tchx84.Flatseal" { + found = true + break + } + } + assert.True(t, found, "Flatseal should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("com.github.tchx84.Flatseal"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "com.github.tchx84.Flatseal") + require.NoError(t, err) + assert.False(t, installed) + }) +} diff --git a/go.mod b/go.mod index 61f7b23..3faa4ae 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/muesli/roff v0.1.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/pflag v1.0.9 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.37.0 // indirect diff --git a/go.sum b/go.sum index e9588ab..c577f67 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= diff --git a/pacman/pacman_integration_test.go b/pacman/pacman_integration_test.go new file mode 100644 index 0000000..7f968df --- /dev/null +++ b/pacman/pacman_integration_test.go @@ -0,0 +1,110 @@ +//go:build integration + +package pacman_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/pacman" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Pacman(t *testing.T) { + mgr := pacman.New() + if !mgr.Available() { + t.Skip("pacman not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "curl") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + pkg, err := mgr.Info(ctx, "curl") + require.NoError(t, err) + require.NotNil(t, pkg) + assert.Equal(t, "curl", pkg.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "tree") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "tree" { + found = true + break + } + } + assert.True(t, found, "tree should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.False(t, installed) + }) + + t.Run("Capabilities", func(t *testing.T) { + if vq, ok := mgr.(snack.VersionQuerier); ok { + ver, err := vq.LatestVersion(ctx, "curl") + require.NoError(t, err) + assert.NotEmpty(t, ver) + + upgrades, err := vq.ListUpgrades(ctx) + require.NoError(t, err) + _ = upgrades + } + + if cl, ok := mgr.(snack.Cleaner); ok { + err := cl.Clean(ctx) + require.NoError(t, err) + } + + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/usr/bin/pacman") + if err == nil { + assert.NotEmpty(t, owner) + } + } + + if g, ok := mgr.(snack.Grouper); ok { + groups, err := g.GroupList(ctx) + require.NoError(t, err) + assert.NotEmpty(t, groups) + } + }) +} diff --git a/pkg/pkg_integration_test.go b/pkg/pkg_integration_test.go new file mode 100644 index 0000000..7eb8c53 --- /dev/null +++ b/pkg/pkg_integration_test.go @@ -0,0 +1,80 @@ +//go:build integration + +package pkg_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/pkg" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Pkg(t *testing.T) { + mgr := pkg.New() + if !mgr.Available() { + t.Skip("pkg not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "curl") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + p, err := mgr.Info(ctx, "curl") + require.NoError(t, err) + require.NotNil(t, p) + assert.Equal(t, "curl", p.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "tree") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "tree" { + found = true + break + } + } + assert.True(t, found, "tree should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("tree"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "tree") + require.NoError(t, err) + assert.False(t, installed) + }) +} diff --git a/rpm/rpm_integration_test.go b/rpm/rpm_integration_test.go new file mode 100644 index 0000000..7853afa --- /dev/null +++ b/rpm/rpm_integration_test.go @@ -0,0 +1,58 @@ +//go:build integration + +package rpm_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/rpm" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_RPM(t *testing.T) { + mgr := rpm.New() + if !mgr.Available() { + t.Skip("rpm not available") + } + ctx := context.Background() + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "bash") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "bash") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + 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) + }) + + t.Run("FileOwner", func(t *testing.T) { + if fo, ok := mgr.(snack.FileOwner); ok { + owner, err := fo.Owner(ctx, "/bin/bash") + require.NoError(t, err) + assert.NotEmpty(t, owner) + + files, err := fo.FileList(ctx, "bash") + require.NoError(t, err) + assert.NotEmpty(t, files) + } + }) +} diff --git a/snap/snap_integration_test.go b/snap/snap_integration_test.go new file mode 100644 index 0000000..23ae4b8 --- /dev/null +++ b/snap/snap_integration_test.go @@ -0,0 +1,80 @@ +//go:build integration + +package snap_test + +import ( + "context" + "testing" + + "github.com/gogrlx/snack" + "github.com/gogrlx/snack/snap" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntegration_Snap(t *testing.T) { + mgr := snap.New() + if !mgr.Available() { + t.Skip("snap not available") + } + ctx := context.Background() + + t.Run("Update", func(t *testing.T) { + err := mgr.Update(ctx) + require.NoError(t, err) + }) + + t.Run("Search", func(t *testing.T) { + pkgs, err := mgr.Search(ctx, "hello-world") + require.NoError(t, err) + require.NotEmpty(t, pkgs) + }) + + t.Run("Info", func(t *testing.T) { + pkg, err := mgr.Info(ctx, "hello-world") + require.NoError(t, err) + require.NotNil(t, pkg) + assert.Equal(t, "hello-world", pkg.Name) + }) + + t.Run("Install", func(t *testing.T) { + err := mgr.Install(ctx, snack.Targets("hello-world"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "hello-world") + require.NoError(t, err) + assert.True(t, installed) + }) + + t.Run("Version", func(t *testing.T) { + ver, err := mgr.Version(ctx, "hello-world") + require.NoError(t, err) + assert.NotEmpty(t, ver) + }) + + t.Run("List", func(t *testing.T) { + pkgs, err := mgr.List(ctx) + require.NoError(t, err) + found := false + for _, p := range pkgs { + if p.Name == "hello-world" { + found = true + break + } + } + assert.True(t, found, "hello-world should be in installed list") + }) + + t.Run("Remove", func(t *testing.T) { + err := mgr.Remove(ctx, snack.Targets("hello-world"), snack.WithSudo(), snack.WithAssumeYes()) + require.NoError(t, err) + }) + + t.Run("IsInstalled_After_Remove", func(t *testing.T) { + installed, err := mgr.IsInstalled(ctx, "hello-world") + require.NoError(t, err) + assert.False(t, installed) + }) +}