This repository has been archived on 2026-10-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
submarine/internal/update/update_test.go
T
simonfrankenandClaude Sonnet 5.5 633de5aab1 Add install script, release Makefile and self-update
Releases are built locally (no runner) and uploaded to the Gitea generic
package registry. install.sh installs submarine plus a sub symlink;
`submarine update` replaces the binary after verifying its checksum.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 20:01:04 +02:00

107 lines
2.9 KiB
Go

package update
import (
"context"
"crypto/sha256"
"encoding/hex"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
)
func TestNewer(t *testing.T) {
cases := []struct {
cur, latest string
want bool
}{
{"v0.1.0", "v0.2.0", true},
{"v0.2.0", "v0.2.0", false},
{"v0.10.0", "v0.9.0", false},
{"v1.0.0", "v0.9.9", false},
{"dev", "v0.1.0", true},
{"v0.1.0-3-gabc", "v0.1.0", true},
{"v0.1.0", "garbage", false},
}
for _, c := range cases {
if got := Newer(c.cur, c.latest); got != c.want {
t.Errorf("Newer(%q, %q) = %v, want %v", c.cur, c.latest, got, c.want)
}
}
}
func registry(t *testing.T, bin, sum string) *Client {
t.Helper()
mux := http.NewServeMux()
mux.HandleFunc("/submarine-latest/latest/VERSION", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("v0.2.0\n"))
})
mux.HandleFunc("/submarine/v0.2.0/checksums.txt", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte(sum + " submarine_linux_arm64\n"))
})
mux.HandleFunc("/submarine/v0.2.0/submarine_linux_arm64", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte(bin))
})
srv := httptest.NewServer(mux)
t.Cleanup(srv.Close)
return &Client{BaseURL: srv.URL, HTTP: srv.Client(), GOOS: "linux", GOARCH: "arm64"}
}
func sha(s string) string { h := sha256.Sum256([]byte(s)); return hex.EncodeToString(h[:]) }
func TestLatest(t *testing.T) {
c := registry(t, "x", sha("x"))
v, err := c.Latest(context.Background())
if err != nil || v != "v0.2.0" {
t.Fatalf("Latest = %q, %v", v, err)
}
}
func TestInstallReplaces(t *testing.T) {
dir := t.TempDir()
target := filepath.Join(dir, "submarine")
os.WriteFile(target, []byte("old"), 0o755)
c := registry(t, "new-binary", sha("new-binary"))
if err := c.InstallTo(context.Background(), "v0.2.0", target); err != nil {
t.Fatal(err)
}
got, _ := os.ReadFile(target)
if string(got) != "new-binary" {
t.Fatalf("target = %q", got)
}
if fi, _ := os.Stat(target); fi.Mode().Perm()&0o111 == 0 {
t.Error("target not executable")
}
if entries, _ := os.ReadDir(dir); len(entries) != 1 {
t.Errorf("leftover files: %v", entries)
}
}
func TestInstallChecksumMismatch(t *testing.T) {
dir := t.TempDir()
target := filepath.Join(dir, "submarine")
os.WriteFile(target, []byte("old"), 0o755)
c := registry(t, "tampered", sha("original"))
err := c.InstallTo(context.Background(), "v0.2.0", target)
if err == nil || !strings.Contains(err.Error(), "checksum mismatch") {
t.Fatalf("err = %v", err)
}
if got, _ := os.ReadFile(target); string(got) != "old" {
t.Errorf("target modified: %q", got)
}
if entries, _ := os.ReadDir(dir); len(entries) != 1 {
t.Errorf("temp file left behind: %v", entries)
}
}
func TestInstallMissingAsset(t *testing.T) {
c := registry(t, "x", sha("x"))
c.GOARCH = "riscv64"
err := c.InstallTo(context.Background(), "v0.2.0", filepath.Join(t.TempDir(), "submarine"))
if err == nil {
t.Fatal("expected error")
}
}