test: enforce AX exact test naming
Renames the remaining AX v0.8.0 test cases to the exact TestFile_Function_{Good,Bad,Ugly} pattern.
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
a63b08156e
commit
693964145e
11 changed files with 145 additions and 145 deletions
|
|
@ -1055,9 +1055,9 @@ func TestAuth_RotateKeyPair_Ugly(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "user not found")
|
||||
}
|
||||
|
||||
// TestAuth_RotateKeyPair_OldKeyCannotDecrypt_Good verifies old private key
|
||||
// TestAuth_RotateKeyPairOldKeyCannotDecrypt_Good verifies old private key
|
||||
// cannot decrypt metadata after rotation.
|
||||
func TestAuth_RotateKeyPair_OldKeyCannotDecrypt_Good(t *testing.T) {
|
||||
func TestAuth_RotateKeyPairOldKeyCannotDecrypt_Good(t *testing.T) {
|
||||
a, m := newTestAuth()
|
||||
|
||||
_, err := a.Register("rotate-crypto", "pass-a")
|
||||
|
|
@ -1156,9 +1156,9 @@ func TestAuth_RevokeKey_Ugly(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "user not found")
|
||||
}
|
||||
|
||||
// TestAuth_IsRevoked_Placeholder_Good verifies that the legacy placeholder is not
|
||||
// TestAuth_IsRevokedPlaceholder_Good verifies that the legacy placeholder is not
|
||||
// treated as a valid revocation.
|
||||
func TestAuth_IsRevoked_Placeholder_Good(t *testing.T) {
|
||||
func TestAuth_IsRevokedPlaceholder_Good(t *testing.T) {
|
||||
a, m := newTestAuth()
|
||||
|
||||
_, err := a.Register("placeholder-user", "pass")
|
||||
|
|
@ -1174,16 +1174,16 @@ func TestAuth_IsRevoked_Placeholder_Good(t *testing.T) {
|
|||
assert.False(t, a.IsRevoked(userID))
|
||||
}
|
||||
|
||||
// TestAuth_IsRevoked_NoRevFile_Good verifies that a missing .rev file returns false.
|
||||
func TestAuth_IsRevoked_NoRevFile_Good(t *testing.T) {
|
||||
// TestAuth_IsRevokedNoRevFile_Good verifies that a missing .rev file returns false.
|
||||
func TestAuth_IsRevokedNoRevFile_Good(t *testing.T) {
|
||||
a, _ := newTestAuth()
|
||||
|
||||
assert.False(t, a.IsRevoked("completely-nonexistent"))
|
||||
}
|
||||
|
||||
// TestAuth_RevokeKey_LegacyUser_Good verifies revocation works for a legacy user
|
||||
// TestAuth_RevokeKeyLegacyUser_Good verifies revocation works for a legacy user
|
||||
// with only a .lthn hash file (no .hash file).
|
||||
func TestAuth_RevokeKey_LegacyUser_Good(t *testing.T) {
|
||||
func TestAuth_RevokeKeyLegacyUser_Good(t *testing.T) {
|
||||
m := io.NewMockMedium()
|
||||
a := New(m)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
// --- MemorySessionStore ---
|
||||
|
||||
func TestSessionStore_MemorySessionStore_GetSetDelete_Good(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreGetSetDelete_Good(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
session := &Session{
|
||||
|
|
@ -44,21 +44,21 @@ func TestSessionStore_MemorySessionStore_GetSetDelete_Good(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_MemorySessionStore_GetNotFound_Bad(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreGetNotFound_Bad(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
_, err := store.Get("nonexistent-token")
|
||||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_MemorySessionStore_DeleteNotFound_Bad(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreDeleteNotFound_Bad(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
err := store.Delete("nonexistent-token")
|
||||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_MemorySessionStore_DeleteByUser_Good(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreDeleteByUser_Good(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
// Create sessions for two users
|
||||
|
|
@ -94,7 +94,7 @@ func TestSessionStore_MemorySessionStore_DeleteByUser_Good(t *testing.T) {
|
|||
assert.Equal(t, "user-b", got.UserID)
|
||||
}
|
||||
|
||||
func TestSessionStore_MemorySessionStore_Cleanup_Good(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreCleanup_Good(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
// Create expired and valid sessions
|
||||
|
|
@ -134,7 +134,7 @@ func TestSessionStore_MemorySessionStore_Cleanup_Good(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_MemorySessionStore_Concurrent_Good(t *testing.T) {
|
||||
func TestSessionStore_MemorySessionStoreConcurrent_Good(t *testing.T) {
|
||||
store := NewMemorySessionStore()
|
||||
|
||||
const n = 20
|
||||
|
|
@ -164,7 +164,7 @@ func TestSessionStore_MemorySessionStore_Concurrent_Good(t *testing.T) {
|
|||
|
||||
// --- SQLiteSessionStore ---
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_GetSetDelete_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreGetSetDelete_Good(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -194,7 +194,7 @@ func TestSessionStore_SQLiteSessionStore_GetSetDelete_Good(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_GetNotFound_Bad(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreGetNotFound_Bad(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -203,7 +203,7 @@ func TestSessionStore_SQLiteSessionStore_GetNotFound_Bad(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_DeleteNotFound_Bad(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreDeleteNotFound_Bad(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -212,7 +212,7 @@ func TestSessionStore_SQLiteSessionStore_DeleteNotFound_Bad(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_DeleteByUser_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreDeleteByUser_Good(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -250,7 +250,7 @@ func TestSessionStore_SQLiteSessionStore_DeleteByUser_Good(t *testing.T) {
|
|||
assert.Equal(t, "user-b", got.UserID)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_Cleanup_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreCleanup_Good(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -292,7 +292,7 @@ func TestSessionStore_SQLiteSessionStore_Cleanup_Good(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrSessionNotFound)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_Persistence_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStorePersistence_Good(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
dbPath := core.Path(dir, "sessions.db")
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ func TestSessionStore_SQLiteSessionStore_Persistence_Good(t *testing.T) {
|
|||
assert.Equal(t, "persist-token", got.Token)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_Concurrent_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreConcurrent_Good(t *testing.T) {
|
||||
// Use a temp file — :memory: SQLite has concurrency limitations
|
||||
dbPath := core.Path(t.TempDir(), "concurrent.db")
|
||||
store, err := NewSQLiteSessionStore(dbPath)
|
||||
|
|
@ -359,7 +359,7 @@ func TestSessionStore_SQLiteSessionStore_Concurrent_Good(t *testing.T) {
|
|||
|
||||
// --- Authenticator with SessionStore ---
|
||||
|
||||
func TestSessionStore_Authenticator_WithSessionStore_Good(t *testing.T) {
|
||||
func TestSessionStore_AuthenticatorWithSessionStore_Good(t *testing.T) {
|
||||
sqliteStore, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer sqliteStore.Close()
|
||||
|
|
@ -398,7 +398,7 @@ func TestSessionStore_Authenticator_WithSessionStore_Good(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "session not found")
|
||||
}
|
||||
|
||||
func TestSessionStore_Authenticator_DefaultStore_Good(t *testing.T) {
|
||||
func TestSessionStore_AuthenticatorDefaultStore_Good(t *testing.T) {
|
||||
m := io.NewMockMedium()
|
||||
a := New(m)
|
||||
|
||||
|
|
@ -407,7 +407,7 @@ func TestSessionStore_Authenticator_DefaultStore_Good(t *testing.T) {
|
|||
assert.True(t, ok, "default store should be MemorySessionStore")
|
||||
}
|
||||
|
||||
func TestSessionStore_Authenticator_StartCleanup_Good(t *testing.T) {
|
||||
func TestSessionStore_AuthenticatorStartCleanup_Good(t *testing.T) {
|
||||
m := io.NewMockMedium()
|
||||
a := New(m, WithSessionTTL(1*time.Millisecond))
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ func TestSessionStore_Authenticator_StartCleanup_Good(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "session not found")
|
||||
}
|
||||
|
||||
func TestSessionStore_Authenticator_StartCleanup_CancelStops_Good(t *testing.T) {
|
||||
func TestSessionStore_AuthenticatorStartCleanupCancelStops_Good(t *testing.T) {
|
||||
m := io.NewMockMedium()
|
||||
a := New(m)
|
||||
|
||||
|
|
@ -448,7 +448,7 @@ func TestSessionStore_Authenticator_StartCleanup_CancelStops_Good(t *testing.T)
|
|||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_UpdateExisting_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreUpdateExisting_Good(t *testing.T) {
|
||||
store, err := NewSQLiteSessionStore(":memory:")
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
|
@ -476,7 +476,7 @@ func TestSessionStore_SQLiteSessionStore_UpdateExisting_Good(t *testing.T) {
|
|||
"updated session should have later expiry")
|
||||
}
|
||||
|
||||
func TestSessionStore_SQLiteSessionStore_TempFile_Good(t *testing.T) {
|
||||
func TestSessionStore_SQLiteSessionStoreTempFile_Good(t *testing.T) {
|
||||
// Verify we can use a real temp file (not :memory:)
|
||||
tmpFile := core.Path(t.TempDir(), "go-crypt-test-session-store.db")
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ FAIL dappco.re/go/core/pkg/bar
|
|||
assert.Equal(t, 50.0, results.packages[0].coverage)
|
||||
}
|
||||
|
||||
func TestOutput_PrintCoverageSummary_Good_LongPackageNames(t *testing.T) {
|
||||
func TestOutput_PrintCoverageSummaryLongPackageNames_Good(t *testing.T) {
|
||||
// This tests the bug fix for long package names causing negative Repeat count
|
||||
results := testResults{
|
||||
packages: []packageCoverage{
|
||||
|
|
|
|||
|
|
@ -31,14 +31,14 @@ func TestChachapoly_EncryptDecrypt_Good(t *testing.T) {
|
|||
assert.Equal(t, plaintext, decrypted)
|
||||
}
|
||||
|
||||
func TestChachapoly_Encrypt_Bad_InvalidKeySize(t *testing.T) {
|
||||
func TestChachapoly_EncryptInvalidKeySize_Bad(t *testing.T) {
|
||||
key := make([]byte, 16) // Wrong size
|
||||
plaintext := []byte("test")
|
||||
_, err := Encrypt(plaintext, key)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestChachapoly_Decrypt_Bad_WrongKey(t *testing.T) {
|
||||
func TestChachapoly_DecryptWrongKey_Bad(t *testing.T) {
|
||||
key1 := make([]byte, 32)
|
||||
key2 := make([]byte, 32)
|
||||
key2[0] = 1 // Different key
|
||||
|
|
@ -51,7 +51,7 @@ func TestChachapoly_Decrypt_Bad_WrongKey(t *testing.T) {
|
|||
assert.Error(t, err) // Should fail authentication
|
||||
}
|
||||
|
||||
func TestChachapoly_Decrypt_Bad_TamperedCiphertext(t *testing.T) {
|
||||
func TestChachapoly_DecryptTamperedCiphertext_Bad(t *testing.T) {
|
||||
key := make([]byte, 32)
|
||||
plaintext := []byte("secret")
|
||||
ciphertext, err := Encrypt(plaintext, key)
|
||||
|
|
@ -64,7 +64,7 @@ func TestChachapoly_Decrypt_Bad_TamperedCiphertext(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestChachapoly_Encrypt_Good_EmptyPlaintext(t *testing.T) {
|
||||
func TestChachapoly_EncryptEmptyPlaintext_Good(t *testing.T) {
|
||||
key := make([]byte, 32)
|
||||
plaintext := []byte("")
|
||||
ciphertext, err := Encrypt(plaintext, key)
|
||||
|
|
@ -76,7 +76,7 @@ func TestChachapoly_Encrypt_Good_EmptyPlaintext(t *testing.T) {
|
|||
assert.Equal(t, plaintext, decrypted)
|
||||
}
|
||||
|
||||
func TestChachapoly_Decrypt_Bad_ShortCiphertext(t *testing.T) {
|
||||
func TestChachapoly_DecryptShortCiphertext_Bad(t *testing.T) {
|
||||
key := make([]byte, 32)
|
||||
shortCiphertext := []byte("short")
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ func TestChachapoly_CiphertextDiffersFromPlaintext_Good(t *testing.T) {
|
|||
assert.NotEqual(t, plaintext, ciphertext)
|
||||
}
|
||||
|
||||
func TestChachapoly_Encrypt_Bad_NonceError(t *testing.T) {
|
||||
func TestChachapoly_EncryptNonceError_Bad(t *testing.T) {
|
||||
key := make([]byte, 32)
|
||||
plaintext := []byte("test")
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ func TestChachapoly_Encrypt_Bad_NonceError(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestChachapoly_Decrypt_Bad_InvalidKeySize(t *testing.T) {
|
||||
func TestChachapoly_DecryptInvalidKeySize_Bad(t *testing.T) {
|
||||
key := make([]byte, 16) // Wrong size
|
||||
ciphertext := []byte("test")
|
||||
_, err := Decrypt(ciphertext, key)
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ func TestSymmetric_AESGCM_Good(t *testing.T) {
|
|||
|
||||
// --- Phase 0 Additions ---
|
||||
|
||||
// TestSymmetric_AESGCM_Bad_WrongKey verifies wrong key returns error, not corrupt data.
|
||||
func TestSymmetric_AESGCM_Bad_WrongKey(t *testing.T) {
|
||||
// TestSymmetric_AESGCMWrongKey_Bad verifies wrong key returns error, not corrupt data.
|
||||
func TestSymmetric_AESGCMWrongKey_Bad(t *testing.T) {
|
||||
key := make([]byte, 32)
|
||||
wrongKey := make([]byte, 32)
|
||||
_, _ = rand.Read(key)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func TestApproval_ApprovalStatusString_Good(t *testing.T) {
|
|||
assert.Equal(t, "denied", ApprovalDenied.String())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalStatusString_Bad_Unknown(t *testing.T) {
|
||||
func TestApproval_ApprovalStatusStringUnknown_Bad(t *testing.T) {
|
||||
assert.Contains(t, ApprovalStatus(99).String(), "unknown")
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ func TestApproval_ApprovalSubmit_Good(t *testing.T) {
|
|||
assert.Equal(t, 1, q.Len())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalSubmit_Good_MultipleRequests(t *testing.T) {
|
||||
func TestApproval_ApprovalSubmitMultipleRequests_Good(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id1, err := q.Submit("Clotho", CapMergePR, "host-uk/core")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -42,7 +42,7 @@ func TestApproval_ApprovalSubmit_Good_MultipleRequests(t *testing.T) {
|
|||
assert.Equal(t, 2, q.Len())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalSubmit_Good_EmptyRepo(t *testing.T) {
|
||||
func TestApproval_ApprovalSubmitEmptyRepo_Good(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id, err := q.Submit("Clotho", CapMergePR, "")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -53,14 +53,14 @@ func TestApproval_ApprovalSubmit_Good_EmptyRepo(t *testing.T) {
|
|||
assert.Empty(t, req.Repo)
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalSubmit_Bad_EmptyAgent(t *testing.T) {
|
||||
func TestApproval_ApprovalSubmitEmptyAgent_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
_, err := q.Submit("", CapMergePR, "")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "agent name is required")
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalSubmit_Bad_EmptyCapability(t *testing.T) {
|
||||
func TestApproval_ApprovalSubmitEmptyCapability_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
_, err := q.Submit("Clotho", "", "")
|
||||
assert.Error(t, err)
|
||||
|
|
@ -85,7 +85,7 @@ func TestApproval_ApprovalGet_Good(t *testing.T) {
|
|||
assert.True(t, req.ReviewedAt.IsZero())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalGet_Good_ReturnsSnapshot(t *testing.T) {
|
||||
func TestApproval_ApprovalGetReturnsSnapshot_Good(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id, err := q.Submit("Clotho", CapMergePR, "host-uk/core")
|
||||
require.NoError(t, err)
|
||||
|
|
@ -99,7 +99,7 @@ func TestApproval_ApprovalGet_Good_ReturnsSnapshot(t *testing.T) {
|
|||
assert.Equal(t, ApprovalPending, original.Status)
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalGet_Bad_NotFound(t *testing.T) {
|
||||
func TestApproval_ApprovalGetNotFound_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
assert.Nil(t, q.Get("nonexistent"))
|
||||
}
|
||||
|
|
@ -121,14 +121,14 @@ func TestApproval_ApprovalApprove_Good(t *testing.T) {
|
|||
assert.False(t, req.ReviewedAt.IsZero())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalApprove_Bad_NotFound(t *testing.T) {
|
||||
func TestApproval_ApprovalApproveNotFound_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
err := q.Approve("nonexistent", "admin", "")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalApprove_Bad_AlreadyApproved(t *testing.T) {
|
||||
func TestApproval_ApprovalApproveAlreadyApproved_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id, _ := q.Submit("Clotho", CapMergePR, "host-uk/core")
|
||||
require.NoError(t, q.Approve(id, "admin", ""))
|
||||
|
|
@ -138,7 +138,7 @@ func TestApproval_ApprovalApprove_Bad_AlreadyApproved(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "already approved")
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalApprove_Bad_AlreadyDenied(t *testing.T) {
|
||||
func TestApproval_ApprovalApproveAlreadyDenied_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id, _ := q.Submit("Clotho", CapMergePR, "host-uk/core")
|
||||
require.NoError(t, q.Deny(id, "admin", "nope"))
|
||||
|
|
@ -165,14 +165,14 @@ func TestApproval_ApprovalDeny_Good(t *testing.T) {
|
|||
assert.False(t, req.ReviewedAt.IsZero())
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalDeny_Bad_NotFound(t *testing.T) {
|
||||
func TestApproval_ApprovalDenyNotFound_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
err := q.Deny("nonexistent", "admin", "")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalDeny_Bad_AlreadyDenied(t *testing.T) {
|
||||
func TestApproval_ApprovalDenyAlreadyDenied_Bad(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
id, _ := q.Submit("Clotho", CapMergePR, "host-uk/core")
|
||||
require.NoError(t, q.Deny(id, "admin", ""))
|
||||
|
|
@ -196,7 +196,7 @@ func TestApproval_ApprovalPending_Good(t *testing.T) {
|
|||
assert.Len(t, pending, 2)
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalPending_Good_Empty(t *testing.T) {
|
||||
func TestApproval_ApprovalPendingEmpty_Good(t *testing.T) {
|
||||
q := NewApprovalQueue()
|
||||
assert.Empty(t, q.Pending())
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@ func TestApproval_ApprovalConcurrent_Good(t *testing.T) {
|
|||
|
||||
// --- Integration: PolicyEngine + ApprovalQueue ---
|
||||
|
||||
func TestApproval_ApprovalWorkflow_Good_EndToEnd(t *testing.T) {
|
||||
func TestApproval_ApprovalWorkflowEndToEnd_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
q := NewApprovalQueue()
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ func TestApproval_ApprovalWorkflow_Good_EndToEnd(t *testing.T) {
|
|||
assert.Equal(t, "Virgil", req.ReviewedBy)
|
||||
}
|
||||
|
||||
func TestApproval_ApprovalWorkflow_Good_DenyEndToEnd(t *testing.T) {
|
||||
func TestApproval_ApprovalWorkflowDenyEndToEnd_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
q := NewApprovalQueue()
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ func TestAudit_AuditRecord_Good(t *testing.T) {
|
|||
assert.Equal(t, 1, log.Len())
|
||||
}
|
||||
|
||||
func TestAudit_AuditRecord_Good_EntryFields(t *testing.T) {
|
||||
func TestAudit_AuditRecordEntryFields_Good(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
|
||||
result := EvalResult{
|
||||
|
|
@ -50,7 +50,7 @@ func TestAudit_AuditRecord_Good_EntryFields(t *testing.T) {
|
|||
assert.False(t, e.Timestamp.IsZero())
|
||||
}
|
||||
|
||||
func TestAudit_AuditRecord_Good_NoRepo(t *testing.T) {
|
||||
func TestAudit_AuditRecordNoRepo_Good(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
result := EvalResult{
|
||||
Decision: Allow,
|
||||
|
|
@ -66,7 +66,7 @@ func TestAudit_AuditRecord_Good_NoRepo(t *testing.T) {
|
|||
assert.Empty(t, entries[0].Repo)
|
||||
}
|
||||
|
||||
func TestAudit_AuditEntries_Good_Snapshot(t *testing.T) {
|
||||
func TestAudit_AuditEntriesSnapshot_Good(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
log.Record(EvalResult{Agent: "A", Cap: CapPushRepo, Decision: Allow, Reason: "ok"}, "")
|
||||
|
||||
|
|
@ -78,12 +78,12 @@ func TestAudit_AuditEntries_Good_Snapshot(t *testing.T) {
|
|||
assert.Equal(t, "A", log.Entries()[0].Agent)
|
||||
}
|
||||
|
||||
func TestAudit_AuditEntries_Good_Empty(t *testing.T) {
|
||||
func TestAudit_AuditEntriesEmpty_Good(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
assert.Empty(t, log.Entries())
|
||||
}
|
||||
|
||||
func TestAudit_AuditEntries_Good_AppendOnly(t *testing.T) {
|
||||
func TestAudit_AuditEntriesAppendOnly_Good(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
|
||||
for i := range 5 {
|
||||
|
|
@ -133,7 +133,7 @@ func TestAudit_AuditEntriesSeq_Good(t *testing.T) {
|
|||
assert.Equal(t, 2, count)
|
||||
}
|
||||
|
||||
func TestAudit_AuditEntriesFor_Bad_NotFound(t *testing.T) {
|
||||
func TestAudit_AuditEntriesForNotFound_Bad(t *testing.T) {
|
||||
log := NewAuditLog(nil)
|
||||
log.Record(EvalResult{Agent: "Athena", Cap: CapPushRepo, Decision: Allow, Reason: "ok"}, "")
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ func TestAudit_AuditEntriesFor_Bad_NotFound(t *testing.T) {
|
|||
|
||||
// --- Writer output ---
|
||||
|
||||
func TestAudit_AuditRecord_Good_WritesToWriter(t *testing.T) {
|
||||
func TestAudit_AuditRecordWritesToWriter_Good(t *testing.T) {
|
||||
buf := core.NewBuilder()
|
||||
log := NewAuditLog(buf)
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ func TestAudit_AuditRecord_Good_WritesToWriter(t *testing.T) {
|
|||
assert.Equal(t, "host-uk/core", entry.Repo)
|
||||
}
|
||||
|
||||
func TestAudit_AuditRecord_Good_MultipleLines(t *testing.T) {
|
||||
func TestAudit_AuditRecordMultipleLines_Good(t *testing.T) {
|
||||
buf := core.NewBuilder()
|
||||
log := NewAuditLog(buf)
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ func TestAudit_AuditRecord_Good_MultipleLines(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAudit_AuditRecord_Bad_WriterError(t *testing.T) {
|
||||
func TestAudit_AuditRecordWriterError_Bad(t *testing.T) {
|
||||
log := NewAuditLog(&failWriter{})
|
||||
|
||||
result := EvalResult{
|
||||
|
|
@ -218,7 +218,7 @@ func (f *failWriter) Write(_ []byte) (int, error) {
|
|||
|
||||
// --- Decision JSON marshalling ---
|
||||
|
||||
func TestAudit_DecisionJSON_Good_RoundTrip(t *testing.T) {
|
||||
func TestAudit_DecisionJSONRoundTrip_Good(t *testing.T) {
|
||||
decisions := []Decision{Deny, Allow, NeedsApproval}
|
||||
expected := []string{`"deny"`, `"allow"`, `"needs_approval"`}
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ func TestAudit_DecisionJSON_Good_RoundTrip(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAudit_DecisionJSON_Bad_UnknownString(t *testing.T) {
|
||||
func TestAudit_DecisionJSONUnknownString_Bad(t *testing.T) {
|
||||
var d Decision
|
||||
result := core.JSONUnmarshal([]byte(`"invalid"`), &d)
|
||||
err, _ := result.Value.(error)
|
||||
|
|
@ -242,7 +242,7 @@ func TestAudit_DecisionJSON_Bad_UnknownString(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), "unknown decision")
|
||||
}
|
||||
|
||||
func TestAudit_DecisionJSON_Bad_NonString(t *testing.T) {
|
||||
func TestAudit_DecisionJSONNonString_Bad(t *testing.T) {
|
||||
var d Decision
|
||||
result := core.JSONUnmarshal([]byte(`42`), &d)
|
||||
err, _ := result.Value.(error)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func TestConfig_LoadPolicies_Good(t *testing.T) {
|
|||
assert.Len(t, policies, 3)
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Good_FieldMapping(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesFieldMapping_Good(t *testing.T) {
|
||||
policies, err := LoadPolicies(core.NewReader(validPolicyJSON))
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -60,33 +60,33 @@ func TestConfig_LoadPolicies_Good_FieldMapping(t *testing.T) {
|
|||
assert.Len(t, policies[2].Denied, 2)
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Good_EmptyPolicies(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesEmptyPolicies_Good(t *testing.T) {
|
||||
input := `{"policies": []}`
|
||||
policies, err := LoadPolicies(core.NewReader(input))
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, policies)
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Bad_InvalidJSON(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesInvalidJSON_Bad(t *testing.T) {
|
||||
_, err := LoadPolicies(core.NewReader(`{invalid`))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Bad_InvalidTier(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesInvalidTier_Bad(t *testing.T) {
|
||||
input := `{"policies": [{"tier": 0, "allowed": ["repo.push"]}]}`
|
||||
_, err := LoadPolicies(core.NewReader(input))
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid tier")
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Bad_TierTooHigh(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesTierTooHigh_Bad(t *testing.T) {
|
||||
input := `{"policies": [{"tier": 99, "allowed": ["repo.push"]}]}`
|
||||
_, err := LoadPolicies(core.NewReader(input))
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid tier")
|
||||
}
|
||||
|
||||
func TestConfig_LoadPolicies_Bad_UnknownField(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesUnknownField_Bad(t *testing.T) {
|
||||
input := `{"policies": [{"tier": 1, "allowed": ["repo.push"], "bogus": true}]}`
|
||||
_, err := LoadPolicies(core.NewReader(input))
|
||||
assert.Error(t, err, "DisallowUnknownFields should reject unknown fields")
|
||||
|
|
@ -104,7 +104,7 @@ func TestConfig_LoadPoliciesFromFile_Good(t *testing.T) {
|
|||
assert.Len(t, policies, 3)
|
||||
}
|
||||
|
||||
func TestConfig_LoadPoliciesFromFile_Bad_NotFound(t *testing.T) {
|
||||
func TestConfig_LoadPoliciesFromFileNotFound_Bad(t *testing.T) {
|
||||
_, err := LoadPoliciesFromFile("/nonexistent/path/policies.json")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ func TestConfig_ApplyPolicies_Good(t *testing.T) {
|
|||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestConfig_ApplyPolicies_Bad_InvalidJSON(t *testing.T) {
|
||||
func TestConfig_ApplyPoliciesInvalidJSON_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
pe := NewPolicyEngine(r)
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ func TestConfig_ApplyPolicies_Bad_InvalidJSON(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestConfig_ApplyPolicies_Bad_InvalidTier(t *testing.T) {
|
||||
func TestConfig_ApplyPoliciesInvalidTier_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
pe := NewPolicyEngine(r)
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ func TestConfig_ApplyPoliciesFromFile_Good(t *testing.T) {
|
|||
assert.Len(t, p.Allowed, 3)
|
||||
}
|
||||
|
||||
func TestConfig_ApplyPoliciesFromFile_Bad_NotFound(t *testing.T) {
|
||||
func TestConfig_ApplyPoliciesFromFileNotFound_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
pe := NewPolicyEngine(r)
|
||||
err := pe.ApplyPoliciesFromFile("/nonexistent/policies.json")
|
||||
|
|
@ -196,7 +196,7 @@ func TestConfig_ExportPolicies_Good(t *testing.T) {
|
|||
assert.Len(t, cfg.Policies, 3)
|
||||
}
|
||||
|
||||
func TestConfig_ExportPolicies_Good_RoundTrip(t *testing.T) {
|
||||
func TestConfig_ExportPoliciesRoundTrip_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{Name: "A", Tier: TierFull}))
|
||||
pe := NewPolicyEngine(r)
|
||||
|
|
@ -239,7 +239,7 @@ func TestConfig_ToCapabilities_Good(t *testing.T) {
|
|||
assert.Equal(t, CapMergePR, caps[1])
|
||||
}
|
||||
|
||||
func TestConfig_ToCapabilities_Good_Empty(t *testing.T) {
|
||||
func TestConfig_ToCapabilitiesEmpty_Good(t *testing.T) {
|
||||
assert.Nil(t, toCapabilities(nil))
|
||||
assert.Nil(t, toCapabilities([]string{}))
|
||||
}
|
||||
|
|
@ -251,7 +251,7 @@ func TestConfig_FromCapabilities_Good(t *testing.T) {
|
|||
assert.Equal(t, "pr.merge", ss[1])
|
||||
}
|
||||
|
||||
func TestConfig_FromCapabilities_Good_Empty(t *testing.T) {
|
||||
func TestConfig_FromCapabilitiesEmpty_Good(t *testing.T) {
|
||||
assert.Nil(t, fromCapabilities(nil))
|
||||
assert.Nil(t, fromCapabilities([]Capability{}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ func TestPolicy_DecisionString_Good(t *testing.T) {
|
|||
assert.Equal(t, "needs_approval", NeedsApproval.String())
|
||||
}
|
||||
|
||||
func TestPolicy_DecisionString_Bad_Unknown(t *testing.T) {
|
||||
func TestPolicy_DecisionStringUnknown_Bad(t *testing.T) {
|
||||
assert.Contains(t, Decision(99).String(), "unknown")
|
||||
}
|
||||
|
||||
// --- Tier 3 (Full Trust) ---
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier3CanDoAnything(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier3CanDoAnything_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
|
||||
caps := []Capability{
|
||||
|
|
@ -57,56 +57,56 @@ func TestPolicy_Evaluate_Good_Tier3CanDoAnything(t *testing.T) {
|
|||
|
||||
// --- Tier 2 (Verified) ---
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier2CanCreatePR(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CanCreatePR_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapCreatePR, "host-uk/core")
|
||||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier2CanPushToScopedRepo(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CanPushToScopedRepo_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapPushRepo, "host-uk/core")
|
||||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier2NeedsApprovalToMerge(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2NeedsApprovalToMerge_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapMergePR, "host-uk/core")
|
||||
assert.Equal(t, NeedsApproval, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier2CanCreateIssue(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CanCreateIssue_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapCreateIssue, "")
|
||||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier2CannotAccessWorkspace(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CannotAccessWorkspace_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapAccessWorkspace, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier2CannotModifyFlows(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CannotModifyFlows_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapModifyFlows, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier2CannotRunPrivileged(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CannotRunPrivileged_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapRunPrivileged, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier2CannotPushToUnscopedRepo(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2CannotPushToUnscopedRepo_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Clotho", CapPushRepo, "host-uk/secret-repo")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
assert.Contains(t, result.Reason, "does not have access")
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier2RepoScopeEmptyRepo(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2RepoScopeEmptyRepo_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
// Push without specifying a repo should be denied for scoped agents.
|
||||
result := pe.Evaluate("Clotho", CapPushRepo, "")
|
||||
|
|
@ -115,43 +115,43 @@ func TestPolicy_Evaluate_Bad_Tier2RepoScopeEmptyRepo(t *testing.T) {
|
|||
|
||||
// --- Tier 1 (Untrusted) ---
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier1CanCreatePR(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CanCreatePR_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapCreatePR, "")
|
||||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier1CanCommentIssue(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CanCommentIssue_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapCommentIssue, "")
|
||||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier1CannotPush(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CannotPush_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapPushRepo, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier1CannotMerge(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CannotMerge_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapMergePR, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier1CannotCreateIssue(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CannotCreateIssue_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapCreateIssue, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier1CannotReadSecrets(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CannotReadSecrets_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapReadSecrets, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Bad_Tier1CannotRunPrivileged(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier1CannotRunPrivileged_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("BugSETI-001", CapRunPrivileged, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
|
|
@ -159,14 +159,14 @@ func TestPolicy_Evaluate_Bad_Tier1CannotRunPrivileged(t *testing.T) {
|
|||
|
||||
// --- Edge cases ---
|
||||
|
||||
func TestPolicy_Evaluate_Bad_UnknownAgent(t *testing.T) {
|
||||
func TestPolicy_EvaluateUnknownAgent_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Unknown", CapCreatePR, "")
|
||||
assert.Equal(t, Deny, result.Decision)
|
||||
assert.Contains(t, result.Reason, "not registered")
|
||||
}
|
||||
|
||||
func TestPolicy_Evaluate_Good_EvalResultFields(t *testing.T) {
|
||||
func TestPolicy_EvaluateEvalResultFields_Good(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
result := pe.Evaluate("Athena", CapPushRepo, "")
|
||||
assert.Equal(t, "Athena", result.Agent)
|
||||
|
|
@ -189,7 +189,7 @@ func TestPolicy_SetPolicy_Good(t *testing.T) {
|
|||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestPolicy_SetPolicy_Bad_InvalidTier(t *testing.T) {
|
||||
func TestPolicy_SetPolicyInvalidTier_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
err := pe.SetPolicy(Policy{Tier: Tier(0)})
|
||||
assert.Error(t, err)
|
||||
|
|
@ -203,7 +203,7 @@ func TestPolicy_GetPolicy_Good(t *testing.T) {
|
|||
assert.Equal(t, TierFull, p.Tier)
|
||||
}
|
||||
|
||||
func TestPolicy_GetPolicy_Bad_NotFound(t *testing.T) {
|
||||
func TestPolicy_GetPolicyNotFound_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
assert.Nil(t, pe.GetPolicy(Tier(99)))
|
||||
}
|
||||
|
|
@ -217,7 +217,7 @@ func TestPolicy_IsRepoScoped_Good(t *testing.T) {
|
|||
assert.True(t, isRepoScoped(CapReadSecrets))
|
||||
}
|
||||
|
||||
func TestPolicy_IsRepoScoped_Bad_NotScoped(t *testing.T) {
|
||||
func TestPolicy_IsRepoScopedNotScoped_Bad(t *testing.T) {
|
||||
assert.False(t, isRepoScoped(CapRunPrivileged))
|
||||
assert.False(t, isRepoScoped(CapAccessWorkspace))
|
||||
assert.False(t, isRepoScoped(CapModifyFlows))
|
||||
|
|
@ -229,24 +229,24 @@ func TestPolicy_RepoAllowed_Good(t *testing.T) {
|
|||
assert.True(t, repoAllowed(scoped, "host-uk/docs"))
|
||||
}
|
||||
|
||||
func TestPolicy_RepoAllowed_Bad_NotInScope(t *testing.T) {
|
||||
func TestPolicy_RepoAllowedNotInScope_Bad(t *testing.T) {
|
||||
scoped := []string{"host-uk/core"}
|
||||
assert.False(t, repoAllowed(scoped, "host-uk/secret"))
|
||||
}
|
||||
|
||||
func TestPolicy_RepoAllowed_Bad_EmptyRepo(t *testing.T) {
|
||||
func TestPolicy_RepoAllowedEmptyRepo_Bad(t *testing.T) {
|
||||
scoped := []string{"host-uk/core"}
|
||||
assert.False(t, repoAllowed(scoped, ""))
|
||||
}
|
||||
|
||||
func TestPolicy_RepoAllowed_Bad_EmptyScope(t *testing.T) {
|
||||
func TestPolicy_RepoAllowedEmptyScope_Bad(t *testing.T) {
|
||||
assert.False(t, repoAllowed(nil, "host-uk/core"))
|
||||
assert.False(t, repoAllowed([]string{}, "host-uk/core"))
|
||||
}
|
||||
|
||||
// --- Tier 3 ignores repo scoping ---
|
||||
|
||||
func TestPolicy_Evaluate_Good_Tier3IgnoresRepoScope(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier3IgnoresRepoScope_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "Virgil",
|
||||
|
|
@ -270,11 +270,11 @@ func TestPolicy_DefaultRateLimit_Good(t *testing.T) {
|
|||
|
||||
// --- Phase 0 Additions ---
|
||||
|
||||
// TestPolicy_Evaluate_Good_Tier2EmptyScopedReposAllowsAll verifies that a Tier 2
|
||||
// TestPolicy_EvaluateTier2EmptyScopedReposAllowsAll_Good verifies that a Tier 2
|
||||
// agent with empty ScopedRepos is treated as "unrestricted" for repo-scoped
|
||||
// capabilities. NOTE: This is a potential security concern documented in
|
||||
// FINDINGS.md — empty ScopedRepos bypasses the repo scope check entirely.
|
||||
func TestPolicy_Evaluate_Good_Tier2EmptyScopedReposAllowsAll(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2EmptyScopedReposAllowsAll_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "Hypnos",
|
||||
|
|
@ -301,9 +301,9 @@ func TestPolicy_Evaluate_Good_Tier2EmptyScopedReposAllowsAll(t *testing.T) {
|
|||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
// TestPolicy_Evaluate_Bad_CapabilityNotInAnyList verifies that a capability not in
|
||||
// TestPolicy_EvaluateCapabilityNotInAnyList_Bad verifies that a capability not in
|
||||
// allowed, denied, or requires_approval lists defaults to deny.
|
||||
func TestPolicy_Evaluate_Bad_CapabilityNotInAnyList(t *testing.T) {
|
||||
func TestPolicy_EvaluateCapabilityNotInAnyList_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "TestAgent",
|
||||
|
|
@ -325,9 +325,9 @@ func TestPolicy_Evaluate_Bad_CapabilityNotInAnyList(t *testing.T) {
|
|||
assert.Contains(t, result.Reason, "not granted")
|
||||
}
|
||||
|
||||
// TestPolicy_Evaluate_Bad_UnknownCapability verifies that a completely invented
|
||||
// TestPolicy_EvaluateUnknownCapability_Bad verifies that a completely invented
|
||||
// capability string is denied.
|
||||
func TestPolicy_Evaluate_Bad_UnknownCapability(t *testing.T) {
|
||||
func TestPolicy_EvaluateUnknownCapability_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
|
||||
result := pe.Evaluate("Athena", Capability("nonexistent.capability"), "")
|
||||
|
|
@ -360,10 +360,10 @@ func TestPolicy_ConcurrentEvaluate_Good(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
// TestPolicy_Evaluate_Bad_Tier2ScopedReposWithEmptyRepoParam verifies that
|
||||
// TestPolicy_EvaluateTier2ScopedReposWithEmptyRepoParam_Bad verifies that
|
||||
// a scoped agent requesting a repo-scoped capability without specifying
|
||||
// the repo is denied.
|
||||
func TestPolicy_Evaluate_Bad_Tier2ScopedReposWithEmptyRepoParam(t *testing.T) {
|
||||
func TestPolicy_EvaluateTier2ScopedReposWithEmptyRepoParam_Bad(t *testing.T) {
|
||||
pe := newTestEngine(t)
|
||||
|
||||
// Clotho has ScopedRepos but passes empty repo
|
||||
|
|
|
|||
|
|
@ -9,62 +9,62 @@ import (
|
|||
|
||||
// --- matchScope ---
|
||||
|
||||
func TestScope_MatchScope_Good_ExactMatch(t *testing.T) {
|
||||
func TestScope_MatchScopeExactMatch_Good(t *testing.T) {
|
||||
assert.True(t, matchScope("host-uk/core", "host-uk/core"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Good_SingleWildcard(t *testing.T) {
|
||||
func TestScope_MatchScopeSingleWildcard_Good(t *testing.T) {
|
||||
assert.True(t, matchScope("core/*", "core/php"))
|
||||
assert.True(t, matchScope("core/*", "core/go-crypt"))
|
||||
assert.True(t, matchScope("host-uk/*", "host-uk/core"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Good_RecursiveWildcard(t *testing.T) {
|
||||
func TestScope_MatchScopeRecursiveWildcard_Good(t *testing.T) {
|
||||
assert.True(t, matchScope("core/**", "core/php"))
|
||||
assert.True(t, matchScope("core/**", "core/php/sub"))
|
||||
assert.True(t, matchScope("core/**", "core/a/b/c"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_ExactMismatch(t *testing.T) {
|
||||
func TestScope_MatchScopeExactMismatch_Bad(t *testing.T) {
|
||||
assert.False(t, matchScope("host-uk/core", "host-uk/docs"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_SingleWildcardNoNested(t *testing.T) {
|
||||
func TestScope_MatchScopeSingleWildcardNoNested_Bad(t *testing.T) {
|
||||
// "core/*" should NOT match "core/php/sub" — only single level.
|
||||
assert.False(t, matchScope("core/*", "core/php/sub"))
|
||||
assert.False(t, matchScope("core/*", "core/a/b"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_SingleWildcardNoPrefix(t *testing.T) {
|
||||
func TestScope_MatchScopeSingleWildcardNoPrefix_Bad(t *testing.T) {
|
||||
// "core/*" should NOT match "other/php".
|
||||
assert.False(t, matchScope("core/*", "other/php"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_RecursiveWildcardNoPrefix(t *testing.T) {
|
||||
func TestScope_MatchScopeRecursiveWildcardNoPrefix_Bad(t *testing.T) {
|
||||
assert.False(t, matchScope("core/**", "other/php"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_EmptyRepo(t *testing.T) {
|
||||
func TestScope_MatchScopeEmptyRepo_Bad(t *testing.T) {
|
||||
assert.False(t, matchScope("core/*", ""))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_WildcardInMiddle(t *testing.T) {
|
||||
func TestScope_MatchScopeWildcardInMiddle_Bad(t *testing.T) {
|
||||
// Wildcard not at the end — should not match.
|
||||
assert.False(t, matchScope("core/*/sub", "core/php/sub"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_WildcardOnlyPrefix(t *testing.T) {
|
||||
func TestScope_MatchScopeWildcardOnlyPrefix_Bad(t *testing.T) {
|
||||
// "core/*" should not match the prefix itself.
|
||||
assert.False(t, matchScope("core/*", "core"))
|
||||
assert.False(t, matchScope("core/*", "core/"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Good_RecursiveWildcardSingleLevel(t *testing.T) {
|
||||
func TestScope_MatchScopeRecursiveWildcardSingleLevel_Good(t *testing.T) {
|
||||
// "core/**" should also match single-level children.
|
||||
assert.True(t, matchScope("core/**", "core/php"))
|
||||
}
|
||||
|
||||
func TestScope_MatchScope_Bad_RecursiveWildcardPrefixOnly(t *testing.T) {
|
||||
func TestScope_MatchScopeRecursiveWildcardPrefixOnly_Bad(t *testing.T) {
|
||||
assert.False(t, matchScope("core/**", "core"))
|
||||
assert.False(t, matchScope("core/**", "corefoo"))
|
||||
}
|
||||
|
|
@ -78,31 +78,31 @@ func TestScope_RepoAllowedWildcard_Good(t *testing.T) {
|
|||
assert.True(t, repoAllowed(scoped, "host-uk/docs"))
|
||||
}
|
||||
|
||||
func TestScope_RepoAllowedWildcard_Good_Recursive(t *testing.T) {
|
||||
func TestScope_RepoAllowedWildcardRecursive_Good(t *testing.T) {
|
||||
scoped := []string{"core/**"}
|
||||
assert.True(t, repoAllowed(scoped, "core/php"))
|
||||
assert.True(t, repoAllowed(scoped, "core/php/sub"))
|
||||
}
|
||||
|
||||
func TestScope_RepoAllowedWildcard_Bad_NoMatch(t *testing.T) {
|
||||
func TestScope_RepoAllowedWildcardNoMatch_Bad(t *testing.T) {
|
||||
scoped := []string{"core/*"}
|
||||
assert.False(t, repoAllowed(scoped, "other/repo"))
|
||||
assert.False(t, repoAllowed(scoped, "core/php/sub"))
|
||||
}
|
||||
|
||||
func TestScope_RepoAllowedWildcard_Bad_EmptyRepo(t *testing.T) {
|
||||
func TestScope_RepoAllowedWildcardEmptyRepo_Bad(t *testing.T) {
|
||||
scoped := []string{"core/*"}
|
||||
assert.False(t, repoAllowed(scoped, ""))
|
||||
}
|
||||
|
||||
func TestScope_RepoAllowedWildcard_Bad_EmptyScope(t *testing.T) {
|
||||
func TestScope_RepoAllowedWildcardEmptyScope_Bad(t *testing.T) {
|
||||
assert.False(t, repoAllowed(nil, "core/php"))
|
||||
assert.False(t, repoAllowed([]string{}, "core/php"))
|
||||
}
|
||||
|
||||
// --- Integration: PolicyEngine with wildcard scopes ---
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Good_SingleLevel(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeSingleLevel_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "WildAgent",
|
||||
|
|
@ -118,7 +118,7 @@ func TestScope_EvaluateWildcardScope_Good_SingleLevel(t *testing.T) {
|
|||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Bad_OutOfScope(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeOutOfScope_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "WildAgent",
|
||||
|
|
@ -132,7 +132,7 @@ func TestScope_EvaluateWildcardScope_Bad_OutOfScope(t *testing.T) {
|
|||
assert.Contains(t, result.Reason, "does not have access")
|
||||
}
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Bad_NestedNotAllowedBySingleStar(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeNestedNotAllowedBySingleStar_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "WildAgent",
|
||||
|
|
@ -145,7 +145,7 @@ func TestScope_EvaluateWildcardScope_Bad_NestedNotAllowedBySingleStar(t *testing
|
|||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Good_RecursiveAllowsNested(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeRecursiveAllowsNested_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "DeepAgent",
|
||||
|
|
@ -158,7 +158,7 @@ func TestScope_EvaluateWildcardScope_Good_RecursiveAllowsNested(t *testing.T) {
|
|||
assert.Equal(t, Allow, result.Decision)
|
||||
}
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Good_MixedExactAndWildcard(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeMixedExactAndWildcard_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "MixedAgent",
|
||||
|
|
@ -180,7 +180,7 @@ func TestScope_EvaluateWildcardScope_Good_MixedExactAndWildcard(t *testing.T) {
|
|||
assert.Equal(t, Deny, result.Decision)
|
||||
}
|
||||
|
||||
func TestScope_EvaluateWildcardScope_Good_ReadSecretsScoped(t *testing.T) {
|
||||
func TestScope_EvaluateWildcardScopeReadSecretsScoped_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{
|
||||
Name: "ScopedSecrets",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func TestTrust_TierString_Good(t *testing.T) {
|
|||
assert.Equal(t, "full", TierFull.String())
|
||||
}
|
||||
|
||||
func TestTrust_TierString_Bad_Unknown(t *testing.T) {
|
||||
func TestTrust_TierStringUnknown_Bad(t *testing.T) {
|
||||
assert.Contains(t, Tier(99).String(), "unknown")
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ func TestTrust_RegistryRegister_Good(t *testing.T) {
|
|||
assert.Equal(t, 1, r.Len())
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Good_SetsDefaults(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterSetsDefaults_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
err := r.Register(Agent{Name: "Athena", Tier: TierFull})
|
||||
require.NoError(t, err)
|
||||
|
|
@ -54,7 +54,7 @@ func TestTrust_RegistryRegister_Good_SetsDefaults(t *testing.T) {
|
|||
assert.False(t, a.CreatedAt.IsZero())
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Good_TierDefaults(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterTierDefaults_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{Name: "A", Tier: TierUntrusted}))
|
||||
require.NoError(t, r.Register(Agent{Name: "B", Tier: TierVerified}))
|
||||
|
|
@ -65,14 +65,14 @@ func TestTrust_RegistryRegister_Good_TierDefaults(t *testing.T) {
|
|||
assert.Equal(t, 0, r.Get("C").RateLimit)
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Good_PreservesExplicitRateLimit(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterPreservesExplicitRateLimit_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
err := r.Register(Agent{Name: "Custom", Tier: TierVerified, RateLimit: 30})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 30, r.Get("Custom").RateLimit)
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Good_Update(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterUpdate_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{Name: "Athena", Tier: TierVerified}))
|
||||
require.NoError(t, r.Register(Agent{Name: "Athena", Tier: TierFull}))
|
||||
|
|
@ -81,14 +81,14 @@ func TestTrust_RegistryRegister_Good_Update(t *testing.T) {
|
|||
assert.Equal(t, TierFull, r.Get("Athena").Tier)
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Bad_EmptyName(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterEmptyName_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
err := r.Register(Agent{Tier: TierFull})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "name is required")
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRegister_Bad_InvalidTier(t *testing.T) {
|
||||
func TestTrust_RegistryRegisterInvalidTier_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
err := r.Register(Agent{Name: "Bad", Tier: Tier(0)})
|
||||
assert.Error(t, err)
|
||||
|
|
@ -103,7 +103,7 @@ func TestTrust_RegistryGet_Good(t *testing.T) {
|
|||
assert.Equal(t, "Athena", a.Name)
|
||||
}
|
||||
|
||||
func TestTrust_RegistryGet_Bad_NotFound(t *testing.T) {
|
||||
func TestTrust_RegistryGetNotFound_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
assert.Nil(t, r.Get("nonexistent"))
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ func TestTrust_RegistryRemove_Good(t *testing.T) {
|
|||
assert.Equal(t, 0, r.Len())
|
||||
}
|
||||
|
||||
func TestTrust_RegistryRemove_Bad_NotFound(t *testing.T) {
|
||||
func TestTrust_RegistryRemoveNotFound_Bad(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
assert.False(t, r.Remove("nonexistent"))
|
||||
}
|
||||
|
|
@ -136,12 +136,12 @@ func TestTrust_RegistryList_Good(t *testing.T) {
|
|||
assert.True(t, names["Clotho"])
|
||||
}
|
||||
|
||||
func TestTrust_RegistryList_Good_Empty(t *testing.T) {
|
||||
func TestTrust_RegistryListEmpty_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
assert.Empty(t, r.List())
|
||||
}
|
||||
|
||||
func TestTrust_RegistryList_Good_Snapshot(t *testing.T) {
|
||||
func TestTrust_RegistryListSnapshot_Good(t *testing.T) {
|
||||
r := NewRegistry()
|
||||
require.NoError(t, r.Register(Agent{Name: "Athena", Tier: TierFull}))
|
||||
agents := r.List()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue