f9718e6077
CI / Test (rest) (pull_request) Successful in 40s
CI / Test (store) (pull_request) Successful in 42s
CI / Lint (pull_request) Successful in 11s
CI / Build (windows/amd64) (pull_request) Successful in 8s
CI / Build (linux/arm64) (pull_request) Successful in 7s
CI / Build (linux/amd64) (pull_request) Successful in 8s
CI / Test (server-http) (pull_request) Successful in 1m32s
e2e / Playwright vs docker-compose (pull_request) Successful in 1m26s
84 lines
2.7 KiB
Go
84 lines
2.7 KiB
Go
package http
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
stdhttp "net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dcglab.co.uk/steve/restic-manager/internal/api"
|
|
"gitea.dcglab.co.uk/steve/restic-manager/internal/store"
|
|
)
|
|
|
|
func TestSnapshotsFreshnessAndExplicitRefresh(t *testing.T) {
|
|
t.Parallel()
|
|
srv, ts, st := rawTestServerWithUI(t)
|
|
hostID, token := enrolHostForUI(t, srv, st, "snapshot-refresh-host")
|
|
c := agentDial(t, srv, ts, hostID, token)
|
|
sendHello(t, c, "snapshot-refresh-host")
|
|
_ = drainUntil(t, c, api.MsgScheduleSet)
|
|
cookie := loginAsAdmin(t, st)
|
|
|
|
mutationAt := time.Now().UTC().Add(-time.Minute).Truncate(time.Millisecond)
|
|
if err := st.CreateJob(context.Background(), store.Job{
|
|
ID: "mutation-job", HostID: hostID, Kind: "forget", ActorKind: "user", CreatedAt: mutationAt.Add(-time.Minute),
|
|
}); err != nil {
|
|
t.Fatalf("create mutation: %v", err)
|
|
}
|
|
if err := st.MarkJobFinished(context.Background(), "mutation-job", "succeeded", 0, nil, "", mutationAt); err != nil {
|
|
t.Fatalf("finish mutation: %v", err)
|
|
}
|
|
|
|
get := func() listSnapshotsResponse {
|
|
req, _ := stdhttp.NewRequest(stdhttp.MethodGet, ts.URL+"/api/hosts/"+hostID+"/snapshots", nil)
|
|
req.AddCookie(cookie)
|
|
res, err := stdhttp.DefaultClient.Do(req)
|
|
if err != nil {
|
|
t.Fatalf("get snapshots: %v", err)
|
|
}
|
|
defer res.Body.Close()
|
|
var body listSnapshotsResponse
|
|
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
|
|
t.Fatalf("decode snapshots: %v", err)
|
|
}
|
|
return body
|
|
}
|
|
if body := get(); !body.Stale || body.RefreshedAt != nil {
|
|
t.Fatalf("unrefreshed projection should be stale: %+v", body)
|
|
}
|
|
|
|
refreshedAt := mutationAt.Add(time.Second)
|
|
if err := st.ReplaceHostSnapshots(context.Background(), hostID, nil, refreshedAt); err != nil {
|
|
t.Fatalf("replace empty: %v", err)
|
|
}
|
|
if body := get(); body.Stale || body.RefreshedAt == nil || !body.RefreshedAt.Equal(refreshedAt) {
|
|
t.Fatalf("fresh empty projection reported incorrectly: %+v", body)
|
|
}
|
|
|
|
req, _ := stdhttp.NewRequest(stdhttp.MethodPost, ts.URL+"/api/hosts/"+hostID+"/snapshots/refresh", nil)
|
|
req.AddCookie(cookie)
|
|
res, err := stdhttp.DefaultClient.Do(req)
|
|
if err != nil {
|
|
t.Fatalf("request refresh: %v", err)
|
|
}
|
|
defer res.Body.Close()
|
|
if res.StatusCode != stdhttp.StatusAccepted {
|
|
t.Fatalf("refresh status = %d, want 202", res.StatusCode)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
_, raw, err := c.Read(ctx)
|
|
if err != nil {
|
|
t.Fatalf("read refresh command: %v", err)
|
|
}
|
|
var env api.Envelope
|
|
if err := json.Unmarshal(raw, &env); err != nil {
|
|
t.Fatalf("decode envelope: %v", err)
|
|
}
|
|
if env.Type != api.MsgSnapshotsRefresh {
|
|
t.Fatalf("message type = %q, want %q", env.Type, api.MsgSnapshotsRefresh)
|
|
}
|
|
}
|