first commit
This commit is contained in:
608
tests/governance/inmemorysync_test.go
Normal file
608
tests/governance/inmemorysync_test.go
Normal file
@@ -0,0 +1,608 @@
|
||||
package governance
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestInMemorySyncVirtualKeyUpdate tests that in-memory store is updated when VK is updated in DB
|
||||
func TestInMemorySyncVirtualKeyUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
testData := NewGlobalTestData()
|
||||
defer testData.Cleanup(t)
|
||||
|
||||
// Create a VK with initial budget
|
||||
vkName := "test-vk-sync-" + generateRandomID()
|
||||
initialBudget := 10.0
|
||||
createVKResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/virtual-keys",
|
||||
Body: CreateVirtualKeyRequest{
|
||||
Name: vkName,
|
||||
Budget: &BudgetRequest{
|
||||
MaxLimit: initialBudget,
|
||||
ResetDuration: "1h",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if createVKResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to create VK: status %d", createVKResp.StatusCode)
|
||||
}
|
||||
|
||||
vkID := ExtractIDFromResponse(t, createVKResp)
|
||||
testData.AddVirtualKey(vkID)
|
||||
|
||||
vk := createVKResp.Body["virtual_key"].(map[string]interface{})
|
||||
vkValue := vk["value"].(string)
|
||||
|
||||
t.Logf("Created VK %s with initial budget $%.2f", vkName, initialBudget)
|
||||
|
||||
// Verify in-memory store has the VK
|
||||
getDataResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
|
||||
if getDataResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data: status %d", getDataResp.StatusCode)
|
||||
}
|
||||
|
||||
virtualKeysMap := getDataResp.Body["virtual_keys"].(map[string]interface{})
|
||||
|
||||
// Check that VK exists in in-memory store
|
||||
vkData, exists := virtualKeysMap[vkValue]
|
||||
if !exists {
|
||||
t.Fatalf("VK %s not found in in-memory store after creation", vkValue)
|
||||
}
|
||||
|
||||
vkDataMap := vkData.(map[string]interface{})
|
||||
vkID2, _ := vkDataMap["id"].(string)
|
||||
if vkID2 != vkID {
|
||||
t.Fatalf("VK ID mismatch in in-memory store: expected %s, got %s", vkID, vkID2)
|
||||
}
|
||||
|
||||
t.Logf("VK found in in-memory store after creation ✓")
|
||||
|
||||
// Update VK budget to 20.0
|
||||
newBudget := 20.0
|
||||
updateResp := MakeRequest(t, APIRequest{
|
||||
Method: "PUT",
|
||||
Path: "/api/governance/virtual-keys/" + vkID,
|
||||
Body: UpdateVirtualKeyRequest{
|
||||
Budget: &UpdateBudgetRequest{
|
||||
MaxLimit: &newBudget,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if updateResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to update VK: status %d, body: %v", updateResp.StatusCode, updateResp.Body)
|
||||
}
|
||||
|
||||
t.Logf("Updated VK budget from $%.2f to $%.2f", initialBudget, newBudget)
|
||||
|
||||
// Verify in-memory store is updated
|
||||
time.Sleep(500 * time.Millisecond) // Small delay for async updates
|
||||
|
||||
getVKResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
|
||||
if getVKResp2.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data after update: status %d", getVKResp2.StatusCode)
|
||||
}
|
||||
|
||||
virtualKeysMap2 := getVKResp2.Body["virtual_keys"].(map[string]interface{})
|
||||
|
||||
getBudgetsResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/budgets?from_memory=true",
|
||||
})
|
||||
|
||||
budgetsMap2 := getBudgetsResp2.Body["budgets"].(map[string]interface{})
|
||||
|
||||
// Check that VK still exists
|
||||
vkData2, exists := virtualKeysMap2[vkValue]
|
||||
if !exists {
|
||||
t.Fatalf("VK %s not found in in-memory store after update", vkValue)
|
||||
}
|
||||
|
||||
vkDataMap2 := vkData2.(map[string]interface{})
|
||||
budgetID, _ := vkDataMap2["budget_id"].(string)
|
||||
|
||||
// Check that budget in in-memory store is updated
|
||||
if budgetID != "" {
|
||||
budgetData, budgetExists := budgetsMap2[budgetID]
|
||||
if !budgetExists {
|
||||
t.Fatalf("Budget %s not found in in-memory store", budgetID)
|
||||
}
|
||||
|
||||
budgetDataMap := budgetData.(map[string]interface{})
|
||||
maxLimit, _ := budgetDataMap["max_limit"].(float64)
|
||||
if maxLimit != newBudget {
|
||||
t.Fatalf("Budget max_limit not updated in in-memory store: expected %.2f, got %.2f", newBudget, maxLimit)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("VK budget updated in in-memory store ✓")
|
||||
}
|
||||
|
||||
// TestInMemorySyncTeamUpdate tests that in-memory store is updated when Team is updated
|
||||
func TestInMemorySyncTeamUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
testData := NewGlobalTestData()
|
||||
defer testData.Cleanup(t)
|
||||
|
||||
// Create a team with initial budget
|
||||
teamName := "test-team-sync-" + generateRandomID()
|
||||
initialBudget := 50.0
|
||||
createTeamResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/teams",
|
||||
Body: CreateTeamRequest{
|
||||
Name: teamName,
|
||||
Budgets: []BudgetRequest{{
|
||||
MaxLimit: initialBudget,
|
||||
ResetDuration: "1h",
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
||||
if createTeamResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to create team: status %d", createTeamResp.StatusCode)
|
||||
}
|
||||
|
||||
teamID := ExtractIDFromResponse(t, createTeamResp)
|
||||
testData.AddTeam(teamID)
|
||||
|
||||
t.Logf("Created team %s with initial budget $%.2f", teamName, initialBudget)
|
||||
|
||||
// Verify in-memory store has the team
|
||||
getDataResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/teams?from_memory=true",
|
||||
})
|
||||
|
||||
if getDataResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data: status %d", getDataResp.StatusCode)
|
||||
}
|
||||
|
||||
teamsMap := getDataResp.Body["teams"].(map[string]interface{})
|
||||
|
||||
_, exists := teamsMap[teamID]
|
||||
if !exists {
|
||||
t.Fatalf("Team %s not found in in-memory store after creation", teamID)
|
||||
}
|
||||
|
||||
t.Logf("Team found in in-memory store after creation ✓")
|
||||
|
||||
// Update team budget to 100.0
|
||||
newTeamBudget := 100.0
|
||||
updateResp := MakeRequest(t, APIRequest{
|
||||
Method: "PUT",
|
||||
Path: "/api/governance/teams/" + teamID,
|
||||
Body: UpdateTeamRequest{
|
||||
Budgets: &[]BudgetRequest{{
|
||||
MaxLimit: newTeamBudget,
|
||||
ResetDuration: "1h",
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
||||
if updateResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to update team: status %d", updateResp.StatusCode)
|
||||
}
|
||||
|
||||
t.Logf("Updated team budget from $%.2f to $%.2f", initialBudget, newTeamBudget)
|
||||
|
||||
// Verify in-memory store is updated
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
getTeamsResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/teams?from_memory=true",
|
||||
})
|
||||
|
||||
if getTeamsResp2.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data after update: status %d", getTeamsResp2.StatusCode)
|
||||
}
|
||||
|
||||
teamsMap2 := getTeamsResp2.Body["teams"].(map[string]interface{})
|
||||
|
||||
getBudgetsResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/budgets?from_memory=true",
|
||||
})
|
||||
|
||||
budgetsMap2 := getBudgetsResp2.Body["budgets"].(map[string]interface{})
|
||||
|
||||
teamData2, exists := teamsMap2[teamID]
|
||||
if !exists {
|
||||
t.Fatalf("Team %s not found in in-memory store after update", teamID)
|
||||
}
|
||||
|
||||
teamDataMap := teamData2.(map[string]interface{})
|
||||
// Teams now expose a `budgets` array instead of a single `budget_id` — read the first.
|
||||
var budgetID string
|
||||
if budgetsList, ok := teamDataMap["budgets"].([]interface{}); ok && len(budgetsList) > 0 {
|
||||
if b, ok := budgetsList[0].(map[string]interface{}); ok {
|
||||
budgetID, _ = b["id"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
if budgetID != "" {
|
||||
budgetData, budgetExists := budgetsMap2[budgetID]
|
||||
if !budgetExists {
|
||||
t.Fatalf("Budget %s not found in in-memory store", budgetID)
|
||||
}
|
||||
|
||||
budgetDataMap := budgetData.(map[string]interface{})
|
||||
maxLimit, _ := budgetDataMap["max_limit"].(float64)
|
||||
if maxLimit != newTeamBudget {
|
||||
t.Fatalf("Team budget max_limit not updated in in-memory store: expected %.2f, got %.2f", newTeamBudget, maxLimit)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Team budget updated in in-memory store ✓")
|
||||
}
|
||||
|
||||
// TestInMemorySyncCustomerUpdate tests that in-memory store is updated when Customer is updated
|
||||
func TestInMemorySyncCustomerUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
testData := NewGlobalTestData()
|
||||
defer testData.Cleanup(t)
|
||||
|
||||
// Create a customer with initial budget
|
||||
customerName := "test-customer-sync-" + generateRandomID()
|
||||
initialBudget := 100.0
|
||||
createCustomerResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/customers",
|
||||
Body: CreateCustomerRequest{
|
||||
Name: customerName,
|
||||
Budget: &BudgetRequest{
|
||||
MaxLimit: initialBudget,
|
||||
ResetDuration: "1h",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if createCustomerResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to create customer: status %d", createCustomerResp.StatusCode)
|
||||
}
|
||||
|
||||
customerID := ExtractIDFromResponse(t, createCustomerResp)
|
||||
testData.AddCustomer(customerID)
|
||||
|
||||
t.Logf("Created customer %s with initial budget $%.2f", customerName, initialBudget)
|
||||
|
||||
// Verify in-memory store has the customer
|
||||
getDataResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/customers?from_memory=true",
|
||||
})
|
||||
|
||||
if getDataResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data: status %d", getDataResp.StatusCode)
|
||||
}
|
||||
|
||||
customersMap := getDataResp.Body["customers"].(map[string]interface{})
|
||||
|
||||
_, exists := customersMap[customerID]
|
||||
if !exists {
|
||||
t.Fatalf("Customer %s not found in in-memory store after creation", customerID)
|
||||
}
|
||||
|
||||
t.Logf("Customer found in in-memory store after creation ✓")
|
||||
|
||||
// Update customer budget to 250.0
|
||||
newCustomerBudget := 250.0
|
||||
updateResp := MakeRequest(t, APIRequest{
|
||||
Method: "PUT",
|
||||
Path: "/api/governance/customers/" + customerID,
|
||||
Body: UpdateCustomerRequest{
|
||||
Budget: &UpdateBudgetRequest{
|
||||
MaxLimit: &newCustomerBudget,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if updateResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to update customer: status %d", updateResp.StatusCode)
|
||||
}
|
||||
|
||||
t.Logf("Updated customer budget from $%.2f to $%.2f", initialBudget, newCustomerBudget)
|
||||
|
||||
// Verify in-memory store is updated
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
getCustomersResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/customers?from_memory=true",
|
||||
})
|
||||
|
||||
if getCustomersResp2.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get governance data after update: status %d", getCustomersResp2.StatusCode)
|
||||
}
|
||||
|
||||
customersMap2 := getCustomersResp2.Body["customers"].(map[string]interface{})
|
||||
|
||||
getBudgetsResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/budgets?from_memory=true",
|
||||
})
|
||||
|
||||
budgetsMap2 := getBudgetsResp2.Body["budgets"].(map[string]interface{})
|
||||
|
||||
customerData2, exists := customersMap2[customerID]
|
||||
if !exists {
|
||||
t.Fatalf("Customer %s not found in in-memory store after update", customerID)
|
||||
}
|
||||
|
||||
customerDataMap := customerData2.(map[string]interface{})
|
||||
budgetID, _ := customerDataMap["budget_id"].(string)
|
||||
|
||||
if budgetID != "" {
|
||||
budgetData, budgetExists := budgetsMap2[budgetID]
|
||||
if !budgetExists {
|
||||
t.Fatalf("Budget %s not found in in-memory store", budgetID)
|
||||
}
|
||||
|
||||
budgetDataMap := budgetData.(map[string]interface{})
|
||||
maxLimit, _ := budgetDataMap["max_limit"].(float64)
|
||||
if maxLimit != newCustomerBudget {
|
||||
t.Fatalf("Customer budget max_limit not updated in in-memory store: expected %.2f, got %.2f", newCustomerBudget, maxLimit)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Customer budget updated in in-memory store ✓")
|
||||
}
|
||||
|
||||
// TestInMemorySyncVirtualKeyDelete tests that in-memory store is updated when VK is deleted
|
||||
func TestInMemorySyncVirtualKeyDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
testData := NewGlobalTestData()
|
||||
defer testData.Cleanup(t)
|
||||
|
||||
// Create a VK
|
||||
vkName := "test-vk-delete-" + generateRandomID()
|
||||
createVKResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/virtual-keys",
|
||||
Body: CreateVirtualKeyRequest{
|
||||
Name: vkName,
|
||||
Budget: &BudgetRequest{
|
||||
MaxLimit: 10.0,
|
||||
ResetDuration: "1h",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if createVKResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to create VK: status %d", createVKResp.StatusCode)
|
||||
}
|
||||
|
||||
vkID := ExtractIDFromResponse(t, createVKResp)
|
||||
testData.AddVirtualKey(vkID)
|
||||
|
||||
vk := createVKResp.Body["virtual_key"].(map[string]interface{})
|
||||
vkValue := vk["value"].(string)
|
||||
|
||||
// Verify in-memory store has the VK (poll to ensure sync completed)
|
||||
vkExists := WaitForCondition(t, func() bool {
|
||||
getDataResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
|
||||
if getDataResp.StatusCode != 200 {
|
||||
return false
|
||||
}
|
||||
|
||||
virtualKeysMap, ok := getDataResp.Body["virtual_keys"].(map[string]interface{})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
_, exists := virtualKeysMap[vkValue]
|
||||
return exists
|
||||
}, 5*time.Second, "VK exists in in-memory store after creation")
|
||||
|
||||
if !vkExists {
|
||||
t.Fatalf("VK not found in in-memory store after creation (timeout after 5s)")
|
||||
}
|
||||
|
||||
t.Logf("VK found in in-memory store after creation ✓")
|
||||
|
||||
// Delete the VK
|
||||
deleteResp := MakeRequest(t, APIRequest{
|
||||
Method: "DELETE",
|
||||
Path: "/api/governance/virtual-keys/" + vkID,
|
||||
})
|
||||
|
||||
if deleteResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to delete VK: status %d", deleteResp.StatusCode)
|
||||
}
|
||||
|
||||
t.Logf("Deleted VK from database")
|
||||
|
||||
// Verify in-memory store is updated (poll with timeout instead of fixed sleep)
|
||||
vkRemoved := WaitForCondition(t, func() bool {
|
||||
getDataResp2 := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
|
||||
if getDataResp2.StatusCode != 200 {
|
||||
return false
|
||||
}
|
||||
|
||||
virtualKeysMap2, ok := getDataResp2.Body["virtual_keys"].(map[string]interface{})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
_, exists := virtualKeysMap2[vkValue]
|
||||
return !exists // Return true when VK is NOT found (successfully removed)
|
||||
}, 5*time.Second, "VK removed from in-memory store after deletion")
|
||||
|
||||
if !vkRemoved {
|
||||
t.Fatalf("VK %s still exists in in-memory store after deletion (timeout after 5s)", vkValue)
|
||||
}
|
||||
|
||||
t.Logf("VK removed from in-memory store ✓")
|
||||
}
|
||||
|
||||
// TestDataEndpointConsistency tests that governance endpoints return consistent data
|
||||
func TestDataEndpointConsistency(t *testing.T) {
|
||||
t.Parallel()
|
||||
testData := NewGlobalTestData()
|
||||
defer testData.Cleanup(t)
|
||||
|
||||
// Create multiple resources
|
||||
vkName := "test-vk-consistency-" + generateRandomID()
|
||||
createVKResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/virtual-keys",
|
||||
Body: CreateVirtualKeyRequest{
|
||||
Name: vkName,
|
||||
Budget: &BudgetRequest{
|
||||
MaxLimit: 15.0,
|
||||
ResetDuration: "1h",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
vkID := ExtractIDFromResponse(t, createVKResp)
|
||||
testData.AddVirtualKey(vkID)
|
||||
|
||||
teamName := "test-team-consistency-" + generateRandomID()
|
||||
createTeamResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/teams",
|
||||
Body: CreateTeamRequest{
|
||||
Name: teamName,
|
||||
Budgets: []BudgetRequest{{
|
||||
MaxLimit: 30.0,
|
||||
ResetDuration: "1h",
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
||||
teamID := ExtractIDFromResponse(t, createTeamResp)
|
||||
testData.AddTeam(teamID)
|
||||
|
||||
customerName := "test-customer-consistency-" + generateRandomID()
|
||||
createCustomerResp := MakeRequest(t, APIRequest{
|
||||
Method: "POST",
|
||||
Path: "/api/governance/customers",
|
||||
Body: CreateCustomerRequest{
|
||||
Name: customerName,
|
||||
Budget: &BudgetRequest{
|
||||
MaxLimit: 60.0,
|
||||
ResetDuration: "1h",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
customerID := ExtractIDFromResponse(t, createCustomerResp)
|
||||
testData.AddCustomer(customerID)
|
||||
|
||||
// Wait for all resources to be available in in-memory store
|
||||
allResourcesReady := WaitForCondition(t, func() bool {
|
||||
getVKResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
if getVKResp.StatusCode != 200 {
|
||||
return false
|
||||
}
|
||||
|
||||
getTeamsResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/teams?from_memory=true",
|
||||
})
|
||||
if getTeamsResp.StatusCode != 200 {
|
||||
return false
|
||||
}
|
||||
|
||||
getCustomersResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/customers?from_memory=true",
|
||||
})
|
||||
return getCustomersResp.StatusCode == 200
|
||||
}, 3*time.Second, "all resources available in in-memory store")
|
||||
|
||||
if !allResourcesReady {
|
||||
t.Fatalf("Resources not available in in-memory store (timeout after 3s)")
|
||||
}
|
||||
|
||||
// Get data from separate endpoints
|
||||
getVKResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys?from_memory=true",
|
||||
})
|
||||
|
||||
if getVKResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get virtual keys: status %d", getVKResp.StatusCode)
|
||||
}
|
||||
|
||||
getTeamsResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/teams?from_memory=true",
|
||||
})
|
||||
|
||||
if getTeamsResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get teams: status %d", getTeamsResp.StatusCode)
|
||||
}
|
||||
|
||||
getCustomersResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/customers?from_memory=true",
|
||||
})
|
||||
|
||||
if getCustomersResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get customers: status %d", getCustomersResp.StatusCode)
|
||||
}
|
||||
|
||||
virtualKeysMap := getVKResp.Body["virtual_keys"].(map[string]interface{})
|
||||
teamsMap := getTeamsResp.Body["teams"].(map[string]interface{})
|
||||
customersMap := getCustomersResp.Body["customers"].(map[string]interface{})
|
||||
|
||||
// Verify all created resources are in the in-memory data
|
||||
vkCount := len(virtualKeysMap)
|
||||
teamCount := len(teamsMap)
|
||||
customerCount := len(customersMap)
|
||||
|
||||
if vkCount == 0 {
|
||||
t.Fatalf("No virtual keys found in data endpoint")
|
||||
}
|
||||
if teamCount == 0 {
|
||||
t.Fatalf("No teams found in data endpoint")
|
||||
}
|
||||
if customerCount == 0 {
|
||||
t.Fatalf("No customers found in data endpoint")
|
||||
}
|
||||
|
||||
t.Logf("Data endpoint returned consistent data: %d VKs, %d teams, %d customers ✓", vkCount, teamCount, customerCount)
|
||||
|
||||
// Get the individual endpoints and verify consistency
|
||||
getVKsResp := MakeRequest(t, APIRequest{
|
||||
Method: "GET",
|
||||
Path: "/api/governance/virtual-keys",
|
||||
})
|
||||
|
||||
if getVKsResp.StatusCode != 200 {
|
||||
t.Fatalf("Failed to get virtual keys: status %d", getVKsResp.StatusCode)
|
||||
}
|
||||
|
||||
vksFromEndpoint, _ := getVKsResp.Body["count"].(float64)
|
||||
if int(vksFromEndpoint) != vkCount {
|
||||
// Can fail because sqlite db might get locked because of all parallel tests
|
||||
t.Logf("[WARN]VK count mismatch between /data endpoint and /virtual-keys endpoint: %d vs %d (this can happen because of parallel tests)", vkCount, int(vksFromEndpoint))
|
||||
}
|
||||
|
||||
t.Logf("Data consistency verified between endpoints ✓")
|
||||
}
|
||||
Reference in New Issue
Block a user