package workload import ( "errors" "testing" "time" ) func TestSignedWorkloadTokenRoundTrips(t *testing.T) { secret := []byte("test-secret") now := time.Unix(1_700_000_000, 0).UTC() token, err := IssueSignedWorkloadToken(secret, "alloc-1", now, time.Minute) if err != nil { t.Fatalf("issue: %v", err) } claims, err := ParseSignedWorkloadToken(secret, token, now.Add(30*time.Second)) if err != nil { t.Fatalf("parse: %v", err) } if claims.AllocationID != "alloc-1" { t.Fatalf("unexpected claims: %+v", claims) } } func TestSignedWorkloadTokenRejectsExpiry(t *testing.T) { secret := []byte("test-secret") now := time.Unix(1_700_000_000, 0).UTC() token, err := IssueSignedWorkloadToken(secret, "alloc-1", now, time.Minute) if err != nil { t.Fatalf("issue: %v", err) } if _, err := ParseSignedWorkloadToken(secret, token, now.Add(61*time.Second)); !errors.Is(err, ErrTokenExpired) { t.Fatalf("expected ErrTokenExpired, got %v", err) } // Boundary: exactly at expiry must also be rejected (Before, not // Before-or-equal), matching the proposal-expiry read boundary // convention used elsewhere in this codebase. if _, err := ParseSignedWorkloadToken(secret, token, now.Add(time.Minute)); !errors.Is(err, ErrTokenExpired) { t.Fatalf("expected ErrTokenExpired at the boundary, got %v", err) } } func TestSignedWorkloadTokenRejectsTamperedPayload(t *testing.T) { secret := []byte("test-secret") now := time.Unix(1_700_000_000, 0).UTC() token, err := IssueSignedWorkloadToken(secret, "alloc-1", now, time.Minute) if err != nil { t.Fatalf("issue: %v", err) } tampered := token[:len(token)-4] + "AAAA" if _, err := ParseSignedWorkloadToken(secret, tampered, now); !errors.Is(err, ErrTokenSignature) && !errors.Is(err, ErrMalformedToken) { t.Fatalf("expected signature/malformed rejection, got %v", err) } } func TestSignedWorkloadTokenRejectsWrongSecret(t *testing.T) { now := time.Unix(1_700_000_000, 0).UTC() token, err := IssueSignedWorkloadToken([]byte("secret-a"), "alloc-1", now, time.Minute) if err != nil { t.Fatalf("issue: %v", err) } if _, err := ParseSignedWorkloadToken([]byte("secret-b"), token, now); !errors.Is(err, ErrTokenSignature) { t.Fatalf("expected ErrTokenSignature, got %v", err) } } func TestSignedWorkloadTokenRejectsMalformedInput(t *testing.T) { secret := []byte("test-secret") now := time.Unix(1_700_000_000, 0).UTC() for _, token := range []string{"", "no-dot-here", ".missing-payload", "missing-signature.", "!!!.!!!"} { if _, err := ParseSignedWorkloadToken(secret, token, now); err == nil { t.Fatalf("token %q: expected an error, got nil", token) } } } func TestIssueSignedWorkloadTokenRejectsInvalidInput(t *testing.T) { now := time.Unix(1_700_000_000, 0).UTC() cases := []struct { name string secret []byte allocationID string now time.Time ttl time.Duration }{ {"empty secret", nil, "a", now, time.Minute}, {"empty allocation id", []byte("k"), "", now, time.Minute}, {"zero now", []byte("k"), "a", time.Time{}, time.Minute}, {"non-positive ttl", []byte("k"), "a", now, 0}, } for _, c := range cases { if _, err := IssueSignedWorkloadToken(c.secret, c.allocationID, c.now, c.ttl); err == nil { t.Fatalf("%s: expected an error, got nil", c.name) } } }