package acme import ( "context" "encoding/json" "testing" "time" ) func TestCreateEAB(t *testing.T) { h := testHandler(t) ctx := context.Background() cred, err := h.CreateEAB(ctx, "alice") if err != nil { t.Fatalf("CreateEAB() error: %v", err) } if cred.KID == "" { t.Fatalf("expected non-empty KID") } if len(cred.HMACKey) != 32 { t.Fatalf("expected 32-byte HMAC key, got %d bytes", len(cred.HMACKey)) } if cred.Used { t.Fatalf("expected Used=false for new credential") } if cred.CreatedBy != "alice" { t.Fatalf("expected CreatedBy=alice, got %s", cred.CreatedBy) } if cred.CreatedAt.IsZero() { t.Fatalf("expected non-zero CreatedAt") } } func TestGetEAB(t *testing.T) { h := testHandler(t) ctx := context.Background() created, err := h.CreateEAB(ctx, "bob") if err != nil { t.Fatalf("CreateEAB() error: %v", err) } got, err := h.GetEAB(ctx, created.KID) if err != nil { t.Fatalf("GetEAB() error: %v", err) } if got.KID != created.KID { t.Fatalf("KID mismatch: got %s, want %s", got.KID, created.KID) } if got.CreatedBy != "bob" { t.Fatalf("CreatedBy mismatch: got %s, want bob", got.CreatedBy) } if len(got.HMACKey) != 32 { t.Fatalf("expected 32-byte HMAC key, got %d bytes", len(got.HMACKey)) } if got.Used != false { t.Fatalf("expected Used=false, got true") } } func TestGetEABNotFound(t *testing.T) { h := testHandler(t) ctx := context.Background() _, err := h.GetEAB(ctx, "nonexistent-kid") if err == nil { t.Fatalf("expected error for non-existent KID, got nil") } } func TestMarkEABUsed(t *testing.T) { h := testHandler(t) ctx := context.Background() cred, err := h.CreateEAB(ctx, "carol") if err != nil { t.Fatalf("CreateEAB() error: %v", err) } if cred.Used { t.Fatalf("expected Used=false before marking") } if err := h.MarkEABUsed(ctx, cred.KID); err != nil { t.Fatalf("MarkEABUsed() error: %v", err) } got, err := h.GetEAB(ctx, cred.KID) if err != nil { t.Fatalf("GetEAB() after mark error: %v", err) } if !got.Used { t.Fatalf("expected Used=true after marking, got false") } } func TestListAccountsEmpty(t *testing.T) { h := testHandler(t) ctx := context.Background() accounts, err := h.ListAccounts(ctx) if err != nil { t.Fatalf("ListAccounts() error: %v", err) } if len(accounts) != 0 { t.Fatalf("expected 0 accounts, got %d", len(accounts)) } } func TestListAccounts(t *testing.T) { h := testHandler(t) ctx := context.Background() // Store two accounts directly in the barrier. for i, name := range []string{"user-a", "user-b"} { acc := &Account{ ID: name, Status: StatusValid, Contact: []string{"mailto:" + name + "@example.com"}, JWK: []byte(`{"kty":"EC"}`), CreatedAt: time.Now(), MCIASUsername: name, } data, err := json.Marshal(acc) if err != nil { t.Fatalf("marshal account %d: %v", i, err) } path := h.barrierPrefix() + "accounts/" + name + ".json" if err := h.barrier.Put(ctx, path, data); err != nil { t.Fatalf("store account %d: %v", i, err) } } accounts, err := h.ListAccounts(ctx) if err != nil { t.Fatalf("ListAccounts() error: %v", err) } if len(accounts) != 2 { t.Fatalf("expected 2 accounts, got %d", len(accounts)) } } func TestListOrders(t *testing.T) { h := testHandler(t) ctx := context.Background() // Store two orders directly in the barrier. for i, id := range []string{"order-1", "order-2"} { order := &Order{ ID: id, AccountID: "test-account", Status: StatusPending, Identifiers: []Identifier{{Type: IdentifierDNS, Value: "example.com"}}, AuthzIDs: []string{"authz-1"}, ExpiresAt: time.Now().Add(24 * time.Hour), CreatedAt: time.Now(), IssuerName: "test-issuer", } data, err := json.Marshal(order) if err != nil { t.Fatalf("marshal order %d: %v", i, err) } path := h.barrierPrefix() + "orders/" + id + ".json" if err := h.barrier.Put(ctx, path, data); err != nil { t.Fatalf("store order %d: %v", i, err) } } orders, err := h.ListOrders(ctx) if err != nil { t.Fatalf("ListOrders() error: %v", err) } if len(orders) != 2 { t.Fatalf("expected 2 orders, got %d", len(orders)) } }