// 05_error_handling.rhai // Comprehensive error handling tests for the Keypair module // Custom assert function fn assert_true(condition, message) { if !condition { print(`ASSERTION FAILED: ${message}`); throw message; } } // Helper function to test for expected errors fn expect_error(fn_to_test, expected_error_substring) { let error_caught = false; let error_message = ""; try { fn_to_test(); } catch(err) { error_caught = true; error_message = err.to_string(); } if !error_caught { print(`ASSERTION FAILED: Expected error containing "${expected_error_substring}" but no error was thrown`); throw `Expected error containing "${expected_error_substring}" but no error was thrown`; } if !error_message.contains(expected_error_substring) { print(`ASSERTION FAILED: Expected error containing "${expected_error_substring}" but got "${error_message}"`); throw `Expected error containing "${expected_error_substring}" but got "${error_message}"`; } print(`✓ Caught expected error: ${error_message}`); } print("=== Testing Error Handling ==="); // Test all error types defined in CryptoError // 1. Test InvalidKeyLength error print("\n--- Testing InvalidKeyLength error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); create_keypair("test_keypair", "password"); select_keypair("test_keypair"); // Try to verify with an invalid public key (wrong length) verify_with_public_key([1, 2, 3], "test message", [1, 2, 3, 4]); }, "InvalidKeyLength"); // 2. Test EncryptionFailed error print("\n--- Testing EncryptionFailed error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); create_keypair("test_keypair", "password"); select_keypair("test_keypair"); // Try to encrypt with an invalid public key encrypt_asymmetric([1, 2, 3], "test message"); }, "EncryptionFailed"); // 3. Test DecryptionFailed error print("\n--- Testing DecryptionFailed error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); create_keypair("test_keypair", "password"); select_keypair("test_keypair"); // Try to decrypt invalid ciphertext decrypt_asymmetric([1, 2, 3, 4]); }, "DecryptionFailed"); // 4. Test SignatureFormatError error print("\n--- Testing SignatureFormatError error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); create_keypair("test_keypair", "password"); select_keypair("test_keypair"); // Try to verify with an invalid signature format keypair_verify("test message", [1, 2, 3]); }, "SignatureFormatError"); // 5. Test KeypairAlreadyExists error print("\n--- Testing KeypairAlreadyExists error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); create_keypair("duplicate_keypair", "password"); // Try to create a keypair with the same name create_keypair("duplicate_keypair", "password"); }, "KeypairAlreadyExists"); // 6. Test KeypairNotFound error print("\n--- Testing KeypairNotFound error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); // Try to select a non-existent keypair select_keypair("nonexistent_keypair"); }, "KeypairNotFound"); // 7. Test NoActiveSpace error print("\n--- Testing NoActiveSpace error ---"); expect_error(|| { // Clear the session clear_session(); // Try to create a keypair without an active space create_keypair("test_keypair", "password"); }, "NoActiveSpace"); // 8. Test NoKeypairSelected error print("\n--- Testing NoKeypairSelected error ---"); expect_error(|| { // Create a key space for testing create_key_space("error_test_space", "password"); // Try to get the public key without selecting a keypair keypair_pub_key(); }, "NoKeypairSelected"); // Test error propagation through the API print("\n--- Testing error propagation ---"); let propagation_test = || { // Create a key space for testing create_key_space("error_test_space", "password"); // Create a keypair create_keypair("test_keypair", "password"); // Clear the session to force an error clear_session(); // This should fail with NoActiveSpace select_keypair("test_keypair"); // This line should never be reached print("ERROR: Code execution continued after error"); }; expect_error(propagation_test, "NoActiveSpace"); // Test recovery from errors print("\n--- Testing recovery from errors ---"); let recovery_success = false; try { // Try an operation that will fail clear_session(); list_keypairs(); // This should fail with NoActiveSpace } catch(err) { print(`✓ Caught expected error: ${err}`); // Now recover by creating a new key space if create_key_space("recovery_space", "password") { // Create a keypair to verify recovery if create_keypair("recovery_keypair", "password") { let keypairs = list_keypairs(); if keypairs.contains("recovery_keypair") { recovery_success = true; print("✓ Successfully recovered from error"); } } } } assert_true(recovery_success, "Should be able to recover from errors"); // Test behavior when multiple errors occur in sequence print("\n--- Testing sequential errors ---"); let sequential_errors_count = 0; // First error: No active space try { clear_session(); list_keypairs(); } catch(err) { sequential_errors_count += 1; print(`✓ Caught first sequential error: ${err}`); } // Second error: Keypair not found try { create_key_space("sequential_space", "password"); select_keypair("nonexistent_keypair"); } catch(err) { sequential_errors_count += 1; print(`✓ Caught second sequential error: ${err}`); } // Third error: Keypair already exists try { create_keypair("sequential_keypair", "password"); create_keypair("sequential_keypair", "password"); } catch(err) { sequential_errors_count += 1; print(`✓ Caught third sequential error: ${err}`); } assert_true(sequential_errors_count == 3, `Expected 3 sequential errors, got ${sequential_errors_count}`); // Test error handling with invalid parameters print("\n--- Testing error handling with invalid parameters ---"); // Test with null/undefined parameters try { // Note: In Rhai, we can't directly pass null/undefined, but we can test with empty arrays verify_with_public_key([], "message", []); print("ERROR: verify_with_public_key with empty arrays didn't throw an error"); } catch(err) { print(`✓ Caught expected error for invalid parameters: ${err}`); } // Test with wrong parameter types try { // Note: In Rhai, we can't easily pass wrong types, but we can test with strings instead of arrays verify_with_public_key("not an array", "message", "not an array"); print("ERROR: verify_with_public_key with wrong types didn't throw an error"); } catch(err) { print(`✓ Caught expected error for wrong parameter types: ${err}`); } print("All error handling tests completed successfully!");