/* * test_verifier.c -- Conformance Tests for Sovereign Stack Machine Verifier * * FORGE Phase 2 Conformance */ #include #include #include #include #include #include "src/verifier/sov_verifier.h" #define TEST_PASS(name) printf("[PASS] %s\n", name) #define TEST_FAIL(name, reason) printf("[FAIL] %s: %s\n", name, reason) #define ASSERT(cond, name, reason) do { if (!(cond)) { TEST_FAIL(name, reason); return 1; } } while(0) static int test_verify_inv_identity_2x2(void) { int64_t I[] = {1, 0, 0, 1}; VerifyResult res = sov_verify_inv(I, 4, I, 4, 2, NULL); ASSERT(res == VER_OK, "test_verify_inv_identity_2x2", sov_verify_result_to_string(res)); TEST_PASS("test_verify_inv_identity_2x2"); return 0; } static int test_verify_inv_inverse_2x2(void) { int64_t A[] = {1, 1, 0, 1}; int64_t A_inv[] = {1, -1, 0, 1}; VerifyResult res = sov_verify_inv(A, 4, A_inv, 4, 2, NULL); ASSERT(res == VER_OK, "test_verify_inv_inverse_2x2", sov_verify_result_to_string(res)); TEST_PASS("test_verify_inv_inverse_2x2"); return 0; } static int test_verify_inv_fail_not_inverse(void) { int64_t A[] = {1, 2, 3, 4}; int64_t B[] = {5, 6, 7, 8}; VerifyResult res = sov_verify_inv(A, 4, B, 4, 2, NULL); ASSERT(res == VER_FAIL, "test_verify_inv_fail_not_inverse", sov_verify_result_to_string(res)); TEST_PASS("test_verify_inv_fail_not_inverse"); return 0; } static int test_verify_sol_2x2_system(void) { int64_t A[] = {2, 0, 0, 2}; int64_t x[] = {2, 3}; int64_t b[] = {4, 6}; VerifyResult res = sov_verify_sol(A, 4, x, 2, b, 2, 2, 2, NULL); ASSERT(res == VER_OK, "test_verify_sol_2x2_system", sov_verify_result_to_string(res)); TEST_PASS("test_verify_sol_2x2_system"); return 0; } static int test_verify_sol_overdetermined(void) { int64_t A[] = {1, 0, 0, 1, 1, 1}; int64_t x[] = {1, 1}; int64_t b[] = {1, 1, 2}; VerifyResult res = sov_verify_sol(A, 6, x, 2, b, 3, 3, 2, NULL); ASSERT(res == VER_OK, "test_verify_sol_overdetermined", sov_verify_result_to_string(res)); TEST_PASS("test_verify_sol_overdetermined"); return 0; } static int test_verify_sol_fail_wrong_solution(void) { int64_t A[] = {2, 0, 0, 2}; int64_t x[] = {1, 1}; int64_t b[] = {4, 6}; VerifyResult res = sov_verify_sol(A, 4, x, 2, b, 2, 2, 2, NULL); ASSERT(res == VER_FAIL, "test_verify_sol_fail_wrong_solution", sov_verify_result_to_string(res)); TEST_PASS("test_verify_sol_fail_wrong_solution"); return 0; } static int test_verify_lstsq_perfect_system(void) { int64_t A[] = {1, 0, 0, 1}; int64_t x[] = {1, 2}; int64_t b[] = {1, 2}; VerifyResult res = sov_verify_lstsq(A, 4, x, 2, b, 2, 2, 2, NULL); ASSERT(res == VER_OK, "test_verify_lstsq_perfect_system", sov_verify_result_to_string(res)); TEST_PASS("test_verify_lstsq_perfect_system"); return 0; } static int test_verify_lstsq_overdetermined_exact(void) { int64_t A[] = {1, 0, 0, 1, 1, 1}; int64_t x[] = {1, 1}; int64_t b[] = {1, 1, 2}; VerifyResult res = sov_verify_lstsq(A, 6, x, 2, b, 3, 3, 2, NULL); ASSERT(res == VER_OK, "test_verify_lstsq_overdetermined_exact", sov_verify_result_to_string(res)); TEST_PASS("test_verify_lstsq_overdetermined_exact"); return 0; } static int test_verify_lstsq_fail_not_solution(void) { int64_t A[] = {1, 0, 0, 1}; int64_t x[] = {2, 3}; int64_t b[] = {1, 2}; VerifyResult res = sov_verify_lstsq(A, 4, x, 2, b, 2, 2, 2, NULL); ASSERT(res == VER_FAIL, "test_verify_lstsq_fail_not_solution", sov_verify_result_to_string(res)); TEST_PASS("test_verify_lstsq_fail_not_solution"); return 0; } static int test_overflow_detection(void) { int64_t A[] = {INT64_MAX, 0, 0, 1}; int64_t x[] = {2, 1}; int64_t result[2]; VerifyResult res = sov_matrix_vec_mult(A, x, result, 2, 2); ASSERT(res == VER_OVERFLOW, "test_overflow_detection", sov_verify_result_to_string(res)); TEST_PASS("test_overflow_detection"); return 0; } static int test_null_input_handling(void) { int64_t A[] = {1, 0, 0, 1}; VerifyResult res = sov_verify_inv(NULL, 4, A, 4, 2, NULL); ASSERT(res == VER_NULL_INPUT, "test_null_input_handling", sov_verify_result_to_string(res)); TEST_PASS("test_null_input_handling"); return 0; } /* ============================================================================ * MEMORY SAFETY TESTS (Phase 1, Step 1) * ============================================================================ */ static int test_safe_alloc_matrix_valid(void) { SafeMatrix *m = safe_alloc_matrix(5, 10); ASSERT(m != NULL, "test_safe_alloc_matrix_valid", "Allocation failed"); ASSERT(m->rows == 5, "test_safe_alloc_matrix_valid", "Rows mismatch"); ASSERT(m->cols == 10, "test_safe_alloc_matrix_valid", "Cols mismatch"); ASSERT(m->capacity == 50, "test_safe_alloc_matrix_valid", "Capacity mismatch"); ASSERT(m->data != NULL, "test_safe_alloc_matrix_valid", "Data pointer null"); safe_free_matrix(m); TEST_PASS("test_safe_alloc_matrix_valid"); return 0; } static int test_safe_alloc_matrix_zero_size(void) { SafeMatrix *m = safe_alloc_matrix(0, 10); ASSERT(m != NULL, "test_safe_alloc_matrix_zero_size", "Allocation failed"); ASSERT(m->capacity == 0, "test_safe_alloc_matrix_zero_size", "Capacity should be 0"); safe_free_matrix(m); TEST_PASS("test_safe_alloc_matrix_zero_size"); return 0; } static int test_safe_alloc_matrix_overflow_rows_cols(void) { /* Test overflow in rows * cols */ SafeMatrix *m = safe_alloc_matrix(SIZE_MAX / 2 + 1, 2); ASSERT(m == NULL, "test_safe_alloc_matrix_overflow_rows_cols", "Should reject overflow"); TEST_PASS("test_safe_alloc_matrix_overflow_rows_cols"); return 0; } static int test_safe_alloc_matrix_overflow_size(void) { /* Test overflow in nelems * sizeof(int64_t) */ /* SIZE_MAX / sizeof(int64_t) is the max elements that fit */ size_t max_safe = SIZE_MAX / sizeof(int64_t); SafeMatrix *m = safe_alloc_matrix(max_safe + 1, 1); ASSERT(m == NULL, "test_safe_alloc_matrix_overflow_size", "Should reject size overflow"); TEST_PASS("test_safe_alloc_matrix_overflow_size"); return 0; } static int test_validate_matrix_buffer_valid(void) { int64_t buf[20]; VerifyResult res = validate_matrix_buffer(buf, 4, 5, 20); ASSERT(res == VER_OK, "test_validate_matrix_buffer_valid", sov_verify_result_to_string(res)); TEST_PASS("test_validate_matrix_buffer_valid"); return 0; } static int test_validate_matrix_buffer_null(void) { VerifyResult res = validate_matrix_buffer(NULL, 4, 5, 20); ASSERT(res == VER_NULL_INPUT, "test_validate_matrix_buffer_null", sov_verify_result_to_string(res)); TEST_PASS("test_validate_matrix_buffer_null"); return 0; } static int test_validate_matrix_buffer_undersized(void) { int64_t buf[19]; /* Need 4*5=20 elements, only have 19 */ VerifyResult res = validate_matrix_buffer(buf, 4, 5, 19); ASSERT(res == VER_BUFFER_OVERFLOW, "test_validate_matrix_buffer_undersized", sov_verify_result_to_string(res)); TEST_PASS("test_validate_matrix_buffer_undersized"); return 0; } static int test_validate_matrix_buffer_overflow_dims(void) { int64_t buf[100]; /* SIZE_MAX / 2 * 2 will overflow */ VerifyResult res = validate_matrix_buffer(buf, SIZE_MAX / 2 + 1, 2, 100); ASSERT(res == VER_OVERFLOW, "test_validate_matrix_buffer_overflow_dims", sov_verify_result_to_string(res)); TEST_PASS("test_validate_matrix_buffer_overflow_dims"); return 0; } static int test_verify_inv_buffer_validation(void) { int64_t I[] = {1, 0, 0, 1}; /* Undersized buffer: claiming 3x3 but only have 4 elements */ VerifyResult res = sov_verify_inv(I, 4, I, 4, 3, NULL); ASSERT(res == VER_BUFFER_OVERFLOW, "test_verify_inv_buffer_validation", sov_verify_result_to_string(res)); TEST_PASS("test_verify_inv_buffer_validation"); return 0; } static int test_verify_sol_buffer_validation(void) { int64_t A[] = {2, 0, 0, 2}; int64_t x[] = {2, 3}; int64_t b[] = {4, 6}; /* A buffer undersized: claiming 3x3 but only have 4 */ VerifyResult res = sov_verify_sol(A, 4, x, 3, b, 2, 3, 3, NULL); ASSERT(res == VER_BUFFER_OVERFLOW, "test_verify_sol_buffer_validation", sov_verify_result_to_string(res)); TEST_PASS("test_verify_sol_buffer_validation"); return 0; } static int test_verify_lstsq_buffer_validation(void) { int64_t A[] = {1, 0, 0, 1}; int64_t x[] = {1, 1}; int64_t b[] = {1, 2}; /* x buffer undersized: claiming 3 but only have 2 */ VerifyResult res = sov_verify_lstsq(A, 4, x, 2, b, 2, 2, 3, NULL); ASSERT(res == VER_BUFFER_OVERFLOW, "test_verify_lstsq_buffer_validation", sov_verify_result_to_string(res)); TEST_PASS("test_verify_lstsq_buffer_validation"); return 0; } static int test_safe_free_matrix_null(void) { /* Should not crash */ safe_free_matrix(NULL); TEST_PASS("test_safe_free_matrix_null"); return 0; } /* ============================================================================ * RESOURCE LIMITS TESTS (Phase 1, Step 2) * ============================================================================ */ static int test_resource_init(void) { SovResourceBudget budget; VerifyResult res = sov_init_resource_budget(&budget); ASSERT(res == VER_OK, "test_resource_init", sov_verify_result_to_string(res)); ASSERT(budget.max_dimensions == SOV_MAX_MATRIX_DIM, "test_resource_init", "max_dimensions mismatch"); ASSERT(budget.max_cells == SOV_MAX_MATRIX_CELLS, "test_resource_init", "max_cells mismatch"); ASSERT(budget.max_operations == SOV_OPERATION_BUDGET_PER_CALL, "test_resource_init", "max_operations mismatch"); ASSERT(budget.operation_count == 0, "test_resource_init", "operation_count not 0"); ASSERT(budget.budget_exceeded == false, "test_resource_init", "budget_exceeded not false"); TEST_PASS("test_resource_init"); return 0; } static int test_check_dimensions_valid(void) { VerifyResult res = sov_check_dimensions(100, 100); ASSERT(res == VER_OK, "test_check_dimensions_valid", sov_verify_result_to_string(res)); TEST_PASS("test_check_dimensions_valid"); return 0; } static int test_check_dimensions_max_valid(void) { /* 65535 should be valid (just under limit) */ VerifyResult res = sov_check_dimensions(65535, 65535); ASSERT(res == VER_OK, "test_check_dimensions_max_valid", sov_verify_result_to_string(res)); TEST_PASS("test_check_dimensions_max_valid"); return 0; } static int test_check_dimensions_exceeded(void) { /* 65537 exceeds SOV_MAX_MATRIX_DIM (65536) */ VerifyResult res = sov_check_dimensions(65537, 1); ASSERT(res == VER_DIMS_EXCEEDED, "test_check_dimensions_exceeded", sov_verify_result_to_string(res)); TEST_PASS("test_check_dimensions_exceeded"); return 0; } static int test_check_matrix_cells_valid(void) { /* 10x10 = 100 cells, well under limit */ VerifyResult res = sov_check_matrix_cells(10, 10); ASSERT(res == VER_OK, "test_check_matrix_cells_valid", sov_verify_result_to_string(res)); TEST_PASS("test_check_matrix_cells_valid"); return 0; } static int test_check_matrix_cells_max_valid(void) { /* 16384 x 16384 = 268435456 (max cells exactly) */ VerifyResult res = sov_check_matrix_cells(16384, 16384); ASSERT(res == VER_OK, "test_check_matrix_cells_max_valid", sov_verify_result_to_string(res)); TEST_PASS("test_check_matrix_cells_max_valid"); return 0; } static int test_check_matrix_cells_exceeded(void) { /* 65536 x 65536 would exceed limit */ VerifyResult res = sov_check_matrix_cells(65536, 65536); ASSERT(res == VER_CELLS_EXCEEDED, "test_check_matrix_cells_exceeded", sov_verify_result_to_string(res)); TEST_PASS("test_check_matrix_cells_exceeded"); return 0; } static int test_add_operation_cost_valid(void) { SovResourceBudget budget; sov_init_resource_budget(&budget); VerifyResult res = sov_add_operation_cost(&budget, 1000); ASSERT(res == VER_OK, "test_add_operation_cost_valid", sov_verify_result_to_string(res)); ASSERT(budget.operation_count == 1000, "test_add_operation_cost_valid", "operation_count mismatch"); ASSERT(budget.budget_exceeded == false, "test_add_operation_cost_valid", "budget_exceeded should be false"); TEST_PASS("test_add_operation_cost_valid"); return 0; } static int test_add_operation_cost_exceeded(void) { SovResourceBudget budget; sov_init_resource_budget(&budget); /* Try to add more than the budget allows */ VerifyResult res = sov_add_operation_cost(&budget, SOV_OPERATION_BUDGET_PER_CALL + 1); ASSERT(res == VER_OPS_EXCEEDED, "test_add_operation_cost_exceeded", sov_verify_result_to_string(res)); ASSERT(budget.budget_exceeded == true, "test_add_operation_cost_exceeded", "budget_exceeded should be true"); TEST_PASS("test_add_operation_cost_exceeded"); return 0; } static int test_verify_inv_with_budget_valid(void) { int64_t I[] = {1, 0, 0, 1}; SovResourceBudget budget; sov_init_resource_budget(&budget); VerifyResult res = sov_verify_inv(I, 4, I, 4, 2, &budget); ASSERT(res == VER_OK, "test_verify_inv_with_budget_valid", sov_verify_result_to_string(res)); ASSERT(budget.operation_count > 0, "test_verify_inv_with_budget_valid", "operation_count should be tracked"); TEST_PASS("test_verify_inv_with_budget_valid"); return 0; } static int test_verify_sol_with_budget_valid(void) { int64_t A[] = {2, 0, 0, 2}; int64_t x[] = {2, 3}; int64_t b[] = {4, 6}; SovResourceBudget budget; sov_init_resource_budget(&budget); VerifyResult res = sov_verify_sol(A, 4, x, 2, b, 2, 2, 2, &budget); ASSERT(res == VER_OK, "test_verify_sol_with_budget_valid", sov_verify_result_to_string(res)); ASSERT(budget.operation_count > 0, "test_verify_sol_with_budget_valid", "operation_count should be tracked"); TEST_PASS("test_verify_sol_with_budget_valid"); return 0; } int main(void) { int failed = 0; printf("=== Sovereign Stack Machine Verifier Conformance Tests ===\n\n"); printf("[TEST GROUP] Matrix Inversion (A*X = I)\n"); failed += test_verify_inv_identity_2x2(); failed += test_verify_inv_inverse_2x2(); failed += test_verify_inv_fail_not_inverse(); printf("\n"); printf("[TEST GROUP] Linear System Solution (A*x = b)\n"); failed += test_verify_sol_2x2_system(); failed += test_verify_sol_overdetermined(); failed += test_verify_sol_fail_wrong_solution(); printf("\n"); printf("[TEST GROUP] Least Squares (A^T(Ax-b) = 0)\n"); failed += test_verify_lstsq_perfect_system(); failed += test_verify_lstsq_overdetermined_exact(); failed += test_verify_lstsq_fail_not_solution(); printf("\n"); printf("[TEST GROUP] Error Handling\n"); failed += test_overflow_detection(); failed += test_null_input_handling(); printf("\n"); printf("[TEST GROUP] Memory Safety (Phase 1, Step 1)\n"); failed += test_safe_alloc_matrix_valid(); failed += test_safe_alloc_matrix_zero_size(); failed += test_safe_alloc_matrix_overflow_rows_cols(); failed += test_safe_alloc_matrix_overflow_size(); failed += test_validate_matrix_buffer_valid(); failed += test_validate_matrix_buffer_null(); failed += test_validate_matrix_buffer_undersized(); failed += test_validate_matrix_buffer_overflow_dims(); failed += test_verify_inv_buffer_validation(); failed += test_verify_sol_buffer_validation(); failed += test_verify_lstsq_buffer_validation(); failed += test_safe_free_matrix_null(); printf("\n"); printf("[TEST GROUP] Resource Limits (Phase 1, Step 2)\n"); failed += test_resource_init(); failed += test_check_dimensions_valid(); failed += test_check_dimensions_max_valid(); failed += test_check_dimensions_exceeded(); failed += test_check_matrix_cells_valid(); failed += test_check_matrix_cells_max_valid(); failed += test_check_matrix_cells_exceeded(); failed += test_add_operation_cost_valid(); failed += test_add_operation_cost_exceeded(); failed += test_verify_inv_with_budget_valid(); failed += test_verify_sol_with_budget_valid(); printf("\n"); if (failed == 0) { printf("=== ALL TESTS PASSED ===\n"); } else { printf("=== %d TESTS FAILED ===\n", failed); } return failed; }