Files
BrowserOS/packages/browseros-agent/apps/cli/update/state_test.go
Nikhil ace9307878 feat: add browseros-cli self-updater (#605)
* feat: add browseros-cli self-updater

* fix: address review comments for 0327-cli_self_updater

* fix: address PR review comments for 0327-cli_self_updater

* fix: replace goreleaser with Makefile-based release build

Remove .goreleaser.yml (required Pro license for monorepo field) and
consolidate cross-compilation into `make release`. CI now uses the same
Makefile target, fixing a bug where POSTHOG_API_KEY was missing from
release ldflags.

* fix: address critical self-updater bugs from code review

- Fix SHA256 checksum mismatch: verify archive checksum before extraction
  instead of verifying extracted binary against archive hash (was always
  failing). Add VerifyChecksum() and integration test.
- Fix JSON field name mismatch: TypeScript was emitting camelCase
  (publishedAt, archiveFormat) but Go expected snake_case
  (published_at, archive_format). Manifest parsing was silently broken.
- Add decompression size limit (256 MB) to prevent zip/gzip bombs.
- Don't update LastCheckedAt on transient errors so retry happens on
  next CLI invocation instead of waiting 24h.
2026-03-27 14:52:54 -07:00

55 lines
1.3 KiB
Go

package update
import (
"path/filepath"
"testing"
"time"
)
func TestLoadStateMissing(t *testing.T) {
configRoot := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", configRoot)
state, err := LoadState()
if err != nil {
t.Fatalf("LoadState() error = %v", err)
}
if state == nil {
t.Fatal("LoadState() returned nil state")
}
}
func TestSaveStateRoundTrip(t *testing.T) {
configRoot := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", configRoot)
want := &State{
LastCheckedAt: time.Unix(100, 0).UTC(),
LatestVersion: "1.2.3",
LatestPublishedAt: "2026-03-27T19:00:00Z",
AssetURL: "https://cdn.example.com/cli/v1.2.3/browseros-cli.tar.gz",
}
if err := SaveState(want); err != nil {
t.Fatalf("SaveState() error = %v", err)
}
got, err := LoadState()
if err != nil {
t.Fatalf("LoadState() error = %v", err)
}
if got.LatestVersion != want.LatestVersion {
t.Fatalf("LatestVersion = %q, want %q", got.LatestVersion, want.LatestVersion)
}
if StatePath() != filepath.Join(configRoot, "browseros-cli", "update-state.json") {
t.Fatalf("StatePath() = %q", StatePath())
}
}
func TestStateIsStale(t *testing.T) {
now := time.Unix(200, 0).UTC()
state := &State{LastCheckedAt: time.Unix(0, 0).UTC()}
if !state.IsStale(now, time.Minute) {
t.Fatal("IsStale() = false, want true")
}
}