mirror of
https://github.com/awalsh128/cache-apt-pkgs-action.git
synced 2026-01-22 11:09:16 +00:00
288 lines
7.7 KiB
Go
288 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"awalsh128.com/cache-apt-pkgs-action/internal/logging"
|
|
atesting "awalsh128.com/cache-apt-pkgs-action/internal/testing"
|
|
"github.com/awalsh128/syspkg"
|
|
"github.com/awalsh128/syspkg/manager"
|
|
)
|
|
|
|
func installAptFastIfMissing(t *testing.T) error {
|
|
t.Helper()
|
|
registry, err := syspkg.New(syspkg.IncludeOptions{Apt: true})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to initialize syspkg: %v", err)
|
|
}
|
|
|
|
// Get APT package manager (if available)
|
|
aptManager, err := registry.GetPackageManager("apt-fast")
|
|
if err != nil {
|
|
return fmt.Errorf("APT package manager not available: %v", err)
|
|
}
|
|
|
|
_, err = aptManager.ListInstalledFiles("apt-fast")
|
|
if err != nil {
|
|
logging.Info("apt-fast not installed, attempting installation.")
|
|
_, err := aptManager.Install(
|
|
[]string{"apt-fast"}, &manager.Options{AssumeYes: true, Verbose: true},
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to install apt-fast: %v", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetupTest performs per-test initialization and registers cleanup hooks.
|
|
func SetupTest(t *testing.T) {
|
|
logging.Init(true)
|
|
err := installAptFastIfMissing(t)
|
|
if err != nil {
|
|
t.Fatalf("Aborting testt: %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
logging.InitDefault()
|
|
})
|
|
}
|
|
|
|
// Integration test for main processing actual and non-existent commands.
|
|
//
|
|
// NOTE: No args are tested, just help as an example of a valid command.
|
|
func TestIntegration_MainCommands(t *testing.T) {
|
|
// Build the binary first
|
|
binaryPath := filepath.Join(t.TempDir(), "cache-apt-pkgs")
|
|
cmd := exec.Command("go", "build", "-o", binaryPath, ".")
|
|
cmd.Dir = "."
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to build binary: %v", err)
|
|
}
|
|
|
|
// Test cases for different subcommands
|
|
testCases := []struct {
|
|
name string
|
|
args []string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "help",
|
|
args: []string{"--help"},
|
|
expectError: false, // --help exits with 0
|
|
},
|
|
{
|
|
name: "no_args",
|
|
args: []string{},
|
|
expectError: true, // no command specified
|
|
},
|
|
{
|
|
name: "unknown_command",
|
|
args: []string{"unknown"},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "createkey_help",
|
|
args: []string{"createkey", "--help"},
|
|
expectError: false, // command help exits with 0
|
|
},
|
|
{
|
|
name: "install_help",
|
|
args: []string{"install", "--help"},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "restore_help",
|
|
args: []string{"restore", "--help"},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "validate_help",
|
|
args: []string{"validate", "--help"},
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cmd := exec.Command(binaryPath, tc.args...)
|
|
err := cmd.Run()
|
|
|
|
if tc.expectError && err == nil {
|
|
t.Errorf("Expected error for %s but got none", tc.name)
|
|
}
|
|
if !tc.expectError && err != nil {
|
|
t.Errorf("Expected no error for %s but got: %v", tc.name, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Test that commands can be executed (they may fail due to missing dependencies, but shouldn't crash)
|
|
func TestIntegration_CommandExecution(t *testing.T) {
|
|
// Create temp directory for testing
|
|
tmpDir := t.TempDir()
|
|
|
|
// Build the binary
|
|
binaryPath := filepath.Join(tmpDir, "cache-apt-pkgs")
|
|
cmd := exec.Command("go", "build", "-o", binaryPath, ".")
|
|
cmd.Dir = "."
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to build binary: %v", err)
|
|
}
|
|
|
|
// Test createkey with minimal args (should work without APT)
|
|
t.Run("createkey_execution", func(t *testing.T) {
|
|
cacheDir := filepath.Join(tmpDir, "cache")
|
|
if err := os.MkdirAll(cacheDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create cache dir: %v", err)
|
|
}
|
|
|
|
cmd := exec.Command(binaryPath, "createkey",
|
|
"--cache-dir", cacheDir,
|
|
"--version", "1.0",
|
|
"--global-version", "1.0",
|
|
"test-package")
|
|
|
|
// This should succeed since createkey doesn't require APT
|
|
if err := cmd.Run(); err != nil {
|
|
t.Logf("createkey execution failed (may be expected in test environment): %v", err)
|
|
} else {
|
|
// Check if cache key files were created
|
|
keyFile := filepath.Join(cacheDir, "cache_key.txt")
|
|
md5File := filepath.Join(cacheDir, "cache_key.md5")
|
|
|
|
if _, err := os.Stat(keyFile); err != nil {
|
|
t.Errorf("cache_key.txt was not created: %v", err)
|
|
}
|
|
|
|
if _, err := os.Stat(md5File); err != nil {
|
|
t.Errorf("cache_key.md5 was not created: %v", err)
|
|
}
|
|
}
|
|
})
|
|
|
|
// Test other commands (expected to fail without APT but shouldn't crash)
|
|
testCommands := []struct {
|
|
name string
|
|
args []string
|
|
}{
|
|
{"validate", []string{"validate", "test-package"}},
|
|
{
|
|
"install",
|
|
[]string{
|
|
"install",
|
|
"--cache-dir",
|
|
tmpDir,
|
|
"--version",
|
|
"1.0",
|
|
"--global-version",
|
|
"1.0",
|
|
"test-package",
|
|
},
|
|
},
|
|
{"restore", []string{"restore", "--cache-dir", tmpDir, "test-package"}},
|
|
}
|
|
|
|
for _, tc := range testCommands {
|
|
t.Run(tc.name+"_no_crash", func(t *testing.T) {
|
|
cmd := exec.Command(binaryPath, tc.args...)
|
|
err := cmd.Run()
|
|
// We expect these to fail in test environment, but they shouldn't crash
|
|
if err != nil {
|
|
t.Logf("%s command failed as expected in test environment: %v", tc.name, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
type execRunResponse struct {
|
|
stdout string
|
|
stderr string
|
|
err error
|
|
ghVars map[string]string
|
|
}
|
|
|
|
func execBinaryAndReturnResponse(t *testing.T, binaryPath string, args []string) (response execRunResponse) {
|
|
t.Helper()
|
|
var err error
|
|
stdout, stderr := atesting.CaptureStd(func() {
|
|
cmd := exec.Command(binaryPath, args...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
err = cmd.Run()
|
|
})
|
|
return execRunResponse{
|
|
stdout: stdout,
|
|
stderr: stderr,
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
// Simulate a pseudo GitHub Actions workflow using the commands
|
|
|
|
func TestIntegration_PseudoActionWorkflow(t *testing.T) {
|
|
const cacheDirName = "cache-apt-pkgs-action-cache"
|
|
const pkgs = "xdot rolldice"
|
|
|
|
// This test simulates a pseudo GitHub Actions workflow using the commands
|
|
tmpDir := t.TempDir()
|
|
cacheDir := filepath.Join(tmpDir, cacheDirName)
|
|
if err := os.MkdirAll(cacheDir, 0755); err != nil {
|
|
t.Fatalf("Failed to create cache dir: %v", err)
|
|
}
|
|
|
|
// Build the binary
|
|
binaryPath := filepath.Join(tmpDir, "cache-apt-pkgs")
|
|
cmd := exec.Command("go", "build", "-o", binaryPath, ".")
|
|
cmd.Dir = "."
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to build binary: %v", err)
|
|
}
|
|
|
|
// Step 1: Validate packages
|
|
response := execBinaryAndReturnResponse(t, binaryPath, []string{"validate", pkgs})
|
|
if response.err != nil {
|
|
t.Fatalf("validate failed: %v", response.err)
|
|
}
|
|
|
|
// Step 2: Create cache key
|
|
response = execBinaryAndReturnResponse(t, binaryPath, []string{"createkey",
|
|
"--cache-dir", cacheDir,
|
|
"--version", "1.0",
|
|
"--global-version", "1.0",
|
|
"--ciphertext-path", filepath.Join(cacheDir, "cache_key.sha256"),
|
|
"--plaintext-path", filepath.Join(cacheDir, "cache_key.txt"),
|
|
pkgs})
|
|
if response.err != nil {
|
|
t.Fatalf("createkey command failed: %v", response.err)
|
|
}
|
|
|
|
// if response.ghVars["cache-hit"] == "true" {
|
|
// t.Log("Cache hit detected, executing restore.")
|
|
// // Step 4b: Restore packages
|
|
// response = execBinaryAndReturnResponse(t, binaryPath, []string{"restore",
|
|
// "--cache-dir", cacheDir,
|
|
// pkgs})
|
|
// if response.err != nil {
|
|
// t.Logf("restore failed: %v", response.err)
|
|
// }
|
|
// } else {
|
|
// t.Log("No cache hit, executing install.")
|
|
// // Step 4a: Install packages
|
|
// response = execBinaryAndReturnResponse(t, binaryPath, []string{"install",
|
|
// "--cache-dir", cacheDir,
|
|
// "--version", "1.0",
|
|
// "--global-version", "1.0",
|
|
// pkgs})
|
|
// if response.err != nil {
|
|
// t.Logf("install command failed: %v", response.err)
|
|
// }
|
|
// }
|
|
|
|
// t.Log("Pseudo GitHub Actions workflow simulation completed.")
|
|
}
|