package main import ( "encoding/json" "net/http" "strconv" "strings" "testing" "time" ) func enrolStatus(t *testing.T, ts string, nonce string) bool { t.Helper() resp, err := http.Get(ts + "/api/enroll-status?nonce=" + nonce) if err != nil { t.Fatalf("status GET: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("status code = %d", resp.StatusCode) } if got := resp.Header.Get("Access-Control-Allow-Origin"); got != "*" { t.Fatalf("ACAO = %q, want *", got) } var body struct{ Done bool } if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { t.Fatalf("decode: %v", err) } return body.Done } func TestEnrolStatusRoundTrip(t *testing.T) { ts, _ := newTestServer(t) defer ts.Close() const nonce = "abcdefgh1234" if enrolStatus(t, ts.URL, nonce) { t.Fatal("unknown nonce reported done") } resp, err := http.Post(ts.URL+"/api/enroll-done", "application/json", strings.NewReader(`{"nonce":"`+nonce+`"}`)) if err != nil { t.Fatalf("done POST: %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusNoContent { t.Fatalf("done POST code = %d", resp.StatusCode) } if !enrolStatus(t, ts.URL, nonce) { t.Fatal("marked nonce not reported done") } if enrolStatus(t, ts.URL, "differentnonce") { t.Fatal("other nonce reported done") } } func TestEnrolDoneRejectsBadNonces(t *testing.T) { ts, _ := newTestServer(t) defer ts.Close() for _, body := range []string{`{}`, `{"nonce":"short"}`, `{"nonce":"` + strings.Repeat("x", 200) + `"}`, `not json`} { resp, err := http.Post(ts.URL+"/api/enroll-done", "application/json", strings.NewReader(body)) if err != nil { t.Fatalf("POST: %v", err) } resp.Body.Close() if resp.StatusCode != http.StatusBadRequest { t.Fatalf("body %q: code = %d, want 400", body, resp.StatusCode) } } } func TestEnrolMarksExpiry(t *testing.T) { m := newEnrolMarks() now := time.Now() m.now = func() time.Time { return now } m.mark("nonce-that-expires") if !m.check("nonce-that-expires") { t.Fatal("fresh mark not found") } now = now.Add(enrolMarkTTL + time.Minute) if m.check("nonce-that-expires") { t.Fatal("expired mark still reported done") } // And the next mark purges it from the map entirely. m.mark("another-nonce") m.mu.Lock() _, still := m.done["nonce-that-expires"] m.mu.Unlock() if still { t.Fatal("expired mark not purged") } } func TestEnrolMarksCap(t *testing.T) { m := newEnrolMarks() for i := 0; i < enrolMarkCap; i++ { m.mark("padpadpad" + strconv.Itoa(i)) } m.mark("overflow-nonce") if m.check("overflow-nonce") { t.Fatal("mark accepted past the cap") } }