Pulse/internal/updates/manager_applyupdate_test.go
rcourtman a6a8efaa65 test: Add comprehensive test coverage across packages
New test files with expanded coverage:

API tests:
- ai_handler_test.go: AI handler unit tests with mocking
- agent_profiles_tools_test.go: Profile management tests
- alerts_endpoints_test.go: Alert API endpoint tests
- alerts_test.go: Updated for interface changes
- audit_handlers_test.go: Audit handler tests
- frontend_embed_test.go: Frontend embedding tests
- metadata_handlers_test.go, metadata_provider_test.go: Metadata tests
- notifications_test.go: Updated for interface changes
- profile_suggestions_test.go: Profile suggestion tests
- saml_service_test.go: SAML authentication tests
- sensor_proxy_gate_test.go: Sensor proxy tests
- updates_test.go: Updated for interface changes

Agent tests:
- dockeragent/signature_test.go: Docker agent signature tests
- hostagent/agent_metrics_test.go: Host agent metrics tests
- hostagent/commands_test.go: Command execution tests
- hostagent/network_helpers_test.go: Network helper tests
- hostagent/proxmox_setup_test.go: Updated setup tests
- kubernetesagent/*_test.go: Kubernetes agent tests

Core package tests:
- monitoring/kubernetes_agents_test.go, reload_test.go
- remoteconfig/client_test.go, signature_test.go
- sensors/collector_test.go
- updates/adapter_installsh_*_test.go: Install adapter tests
- updates/manager_*_test.go: Update manager tests
- websocket/hub_*_test.go: WebSocket hub tests

Library tests:
- pkg/audit/export_test.go: Audit export tests
- pkg/metrics/store_test.go: Metrics store tests
- pkg/proxmox/*_test.go: Proxmox client tests
- pkg/reporting/reporting_test.go: Reporting tests
- pkg/server/*_test.go: Server tests
- pkg/tlsutil/extra_test.go: TLS utility tests

Total: ~8000 lines of new test code
2026-01-19 19:26:18 +00:00

122 lines
3 KiB
Go

package updates
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"testing"
)
func writeStub(t *testing.T, dir, name, script string) {
t.Helper()
path := filepath.Join(dir, name)
if err := os.WriteFile(path, []byte(script), 0755); err != nil {
t.Fatalf("write stub %s: %v", name, err)
}
}
func copyFile(src, dest string, mode os.FileMode) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dest)
if err != nil {
return err
}
_, copyErr := io.Copy(out, in)
closeErr := out.Close()
if copyErr != nil {
return copyErr
}
if closeErr != nil {
return closeErr
}
if mode != 0 {
return os.Chmod(dest, mode)
}
return nil
}
func TestManagerApplyUpdateFilesMissingBinary(t *testing.T) {
manager := &Manager{}
if err := manager.applyUpdateFiles(t.TempDir()); err == nil {
t.Fatal("expected error for missing pulse binary")
}
}
func TestManagerApplyUpdateFilesCopiesPulseBinary(t *testing.T) {
manager := &Manager{}
cpPath, err := exec.LookPath("cp")
if err != nil {
t.Fatalf("find cp: %v", err)
}
mvPath, err := exec.LookPath("mv")
if err != nil {
t.Fatalf("find mv: %v", err)
}
stubDir := t.TempDir()
writeStub(t, stubDir, "cp", fmt.Sprintf("#!/bin/sh\nexec %s \"$@\"\n", cpPath))
writeStub(t, stubDir, "mv", fmt.Sprintf("#!/bin/sh\nexec %s \"$@\"\n", mvPath))
writeStub(t, stubDir, "chown", "#!/bin/sh\nexit 0\n")
t.Setenv("PATH", stubDir+string(os.PathListSeparator)+os.Getenv("PATH"))
binaryPath, err := os.Executable()
if err != nil {
t.Fatalf("executable path: %v", err)
}
info, err := os.Stat(binaryPath)
if err != nil {
t.Fatalf("stat executable: %v", err)
}
backup := filepath.Join(t.TempDir(), "orig-binary")
if err := copyFile(binaryPath, backup, info.Mode()); err != nil {
t.Fatalf("backup binary: %v", err)
}
t.Cleanup(func() {
if err := copyFile(backup, binaryPath, info.Mode()); err != nil {
t.Fatalf("restore binary: %v", err)
}
})
extractDir := t.TempDir()
if err := os.WriteFile(filepath.Join(extractDir, "pulse"), []byte("newbinary"), 0755); err != nil {
t.Fatalf("write pulse: %v", err)
}
if err := manager.applyUpdateFiles(extractDir); err != nil {
t.Fatalf("applyUpdateFiles root pulse: %v", err)
}
data, err := os.ReadFile(binaryPath)
if err != nil {
t.Fatalf("read replaced binary: %v", err)
}
if string(data) != "newbinary" {
t.Fatalf("unexpected root binary contents: %q", string(data))
}
extractDir = t.TempDir()
if err := os.MkdirAll(filepath.Join(extractDir, "bin"), 0755); err != nil {
t.Fatalf("mkdir bin: %v", err)
}
if err := os.WriteFile(filepath.Join(extractDir, "bin", "pulse"), []byte("newbinary2"), 0755); err != nil {
t.Fatalf("write pulse bin: %v", err)
}
if err := manager.applyUpdateFiles(extractDir); err != nil {
t.Fatalf("applyUpdateFiles bin pulse: %v", err)
}
data, err = os.ReadFile(binaryPath)
if err != nil {
t.Fatalf("read replaced binary (bin): %v", err)
}
if string(data) != "newbinary2" {
t.Fatalf("unexpected bin binary contents: %q", string(data))
}
}