Files
felhom.eu/hub/internal/web/r292_artifact_flash_test.go
T

99 lines
3.7 KiB
Go

package web
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"sync/atomic"
"testing"
"gitea.dooplex.hu/admin/felhom-hub/internal/gitea"
)
// R-292: the artifact save names the cause of a checksum failure. One flash used to cover "version
// missing", "registry unreachable" and "bad typed sha" — and the operator acts differently on each.
//
// These drive resolveArtifactSHA through the real handler. The installability gate is passed by a
// registry that serves the tag and the download; ONLY the sha metadata route is varied.
func shaRegistry(t *testing.T, metaStatus int, metaBody string) *gitea.Client {
t.Helper()
var hits int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt32(&hits, 1)
p := strings.TrimPrefix(r.URL.Path, "/")
if strings.HasPrefix(p, "api/v1/packages/") && strings.HasSuffix(p, "/files") {
if metaStatus != http.StatusOK {
w.WriteHeader(metaStatus)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(metaBody))
return
}
w.WriteHeader(http.StatusOK) // tag probe + package download: installable
}))
t.Cleanup(srv.Close)
return gitea.New(srv.URL, "admin", "", "")
}
func TestArtifactSave_FlashNamesTheCause(t *testing.T) {
sha := strings.Repeat("c", 64)
for _, tc := range []struct {
name string
metaStatus int
metaBody string
want string
}{
{"version not found", http.StatusNotFound, "", "artifact_version_missing"},
{"registry failing", http.StatusBadGateway, "", "artifact_unverifiable"},
{"no sha listed", http.StatusOK, `[{"name":"x","sha256":""}]`, "artifact_sha_missing"},
{"healthy", http.StatusOK, `[{"name":"x","sha256":"` + sha + `"}]`, "artifacts_set"},
} {
t.Run(tc.name, func(t *testing.T) {
s, _ := newTestServer(t)
s.SetGiteaClient(shaRegistry(t, tc.metaStatus, tc.metaBody))
if got := flashOf(saveArtifacts(t, s)); got != tc.want {
t.Fatalf("flash = %q, want %q", got, tc.want)
}
})
}
}
// The manual path (no Gitea client): a malformed typed sha is the ONE case artifact_sha_invalid means.
func TestArtifactSave_BadTypedSHAIsShaInvalid(t *testing.T) {
s, st := newTestServer(t)
form := url.Values{"agent_version": {"0.128.0"}, "agent_sha256": {"not-a-sha"}}
r := httptest.NewRequest(http.MethodPost, "/configuration/artifacts", strings.NewReader(form.Encode()))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
s.handleSetArtifacts(w, r)
if got := flashOf(w); got != "artifact_sha_invalid" {
t.Fatalf("flash = %q, want artifact_sha_invalid", got)
}
assertUnchanged(t, st, "bad typed sha")
}
// Every flash the save can redirect to renders its own message (seam: a flash with no template branch
// shows the operator nothing). The sha_invalid text no longer claims a lookup failure.
func TestArtifactFlashes_EachRendersItsOwnText(t *testing.T) {
s, _ := newRenderServer(t)
for flash, want := range map[string]string{
"artifact_version_missing": "the registry has no such version",
"artifact_sha_missing": "no checksum for a chosen version",
"artifact_unverifiable": "could not verify",
"artifact_sha_invalid": "a checksum you typed is not valid",
} {
req := httptest.NewRequest(http.MethodGet, "/configuration?flash="+flash, nil)
rr := httptest.NewRecorder()
s.handleConfiguration(rr, req)
body := rr.Body.String()
if !strings.Contains(body, want) {
t.Errorf("flash %s: page does not render %q", flash, want)
}
if flash == "artifact_sha_invalid" && strings.Contains(body, "Gitea unreachable") {
t.Error("artifact_sha_invalid still conflates an unreachable registry with a bad sha")
}
}
}