//go:build !windows package updater import ( "bytes" "io" "net/http" "net/http/httptest" "os" "path/filepath" "runtime" "testing" ) // TestUpdate_LinuxAtomicSwap stages a fake "running binary" file, runs // UpdateForTest against a fake /agent/binary server, and asserts that // the binary was swapped, .old preserves the previous bytes, and .new // was renamed away. func TestUpdate_LinuxAtomicSwap(t *testing.T) { tmp := t.TempDir() binPath := filepath.Join(tmp, "agent") if err := os.WriteFile(binPath, []byte("OLD"), 0o755); err != nil { t.Fatal(err) } newBytes := []byte("NEW BINARY CONTENTS") srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/agent/binary" { http.NotFound(w, r) return } gotOS, gotArch := r.URL.Query().Get("os"), r.URL.Query().Get("arch") if gotOS != runtime.GOOS || gotArch != runtime.GOARCH { t.Errorf("query mismatch: got os=%s arch=%s want %s/%s", gotOS, gotArch, runtime.GOOS, runtime.GOARCH) } _, _ = io.Copy(w, bytes.NewReader(newBytes)) })) defer srv.Close() if err := UpdateForTest(srv.URL, binPath); err != nil { t.Fatalf("update: %v", err) } got, err := os.ReadFile(binPath) if err != nil { t.Fatal(err) } if string(got) != string(newBytes) { t.Fatalf("binary contents: got %q want %q", got, newBytes) } old, err := os.ReadFile(binPath + ".old") if err != nil { t.Fatalf("agent.old missing: %v", err) } if string(old) != "OLD" { t.Fatalf("agent.old contents: got %q want %q", old, "OLD") } if _, err := os.Stat(binPath + ".new"); !os.IsNotExist(err) { t.Fatalf("agent.new should be absent after swap, got err=%v", err) } } // TestUpdate_FetchHTTPError surfaces the server's status when the // binary is not published for this os/arch. func TestUpdate_FetchHTTPError(t *testing.T) { tmp := t.TempDir() binPath := filepath.Join(tmp, "agent") if err := os.WriteFile(binPath, []byte("OLD"), 0o755); err != nil { t.Fatal(err) } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, `{"error":"binary_not_published"}`, http.StatusNotFound) })) defer srv.Close() err := UpdateForTest(srv.URL, binPath) if err == nil { t.Fatal("expected error, got nil") } got, _ := os.ReadFile(binPath) if string(got) != "OLD" { t.Fatalf("binary should not have changed, got %q", got) } }