From c7a5699798b10eea14d01e749187c095ced0b7b5 Mon Sep 17 00:00:00 2001 From: Mahmoud Emad Date: Mon, 12 May 2025 15:44:14 +0300 Subject: [PATCH] feat: Add comprehensive test suite for Keypair module - Added tests for keypair creation and operations. - Added tests for key space management. - Added tests for session management and error handling. - Added tests for asymmetric encryption and decryption. - Improved error handling and reporting in the module. --- rhai_tests/keypair/01_keypair_operations.rhai | 108 +++++++ .../keypair/02_keyspace_operations.rhai | 162 ++++++++++ rhai_tests/keypair/03_session_management.rhai | 167 ++++++++++ .../keypair/04_encryption_decryption.rhai | 192 ++++++++++++ rhai_tests/keypair/05_error_handling.rhai | 231 ++++++++++++++ rhai_tests/keypair/run_all_tests.rhai | 293 ++++++++++++++++++ 6 files changed, 1153 insertions(+) create mode 100644 rhai_tests/keypair/01_keypair_operations.rhai create mode 100644 rhai_tests/keypair/02_keyspace_operations.rhai create mode 100644 rhai_tests/keypair/03_session_management.rhai create mode 100644 rhai_tests/keypair/04_encryption_decryption.rhai create mode 100644 rhai_tests/keypair/05_error_handling.rhai create mode 100644 rhai_tests/keypair/run_all_tests.rhai diff --git a/rhai_tests/keypair/01_keypair_operations.rhai b/rhai_tests/keypair/01_keypair_operations.rhai new file mode 100644 index 0000000..8ef36ee --- /dev/null +++ b/rhai_tests/keypair/01_keypair_operations.rhai @@ -0,0 +1,108 @@ +// 01_keypair_operations.rhai +// Tests for basic keypair operations in the Keypair module + +// Custom assert function +fn assert_true(condition, message) { + if !condition { + print(`ASSERTION FAILED: ${message}`); + throw message; + } +} + +print("=== Testing Basic Keypair Operations ==="); + +// Test creating a new keypair +print("Testing keypair creation..."); +let keypair_name = "test_keypair"; +if create_key_space("test_space", "password") { + print("✓ Key space created successfully"); + + if create_keypair(keypair_name, "password") { + print("✓ Keypair created successfully"); + + // Test getting the public key + print("Testing public key retrieval..."); + if select_keypair(keypair_name) { + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + print(`✓ Public key retrieved: ${pub_key.len()} bytes`); + + // Test signing a message + print("Testing message signing..."); + let message = "This is a test message to sign"; + let signature = keypair_sign(message); + assert_true(signature.len() > 0, "Signature should not be empty"); + print(`✓ Message signed successfully: ${signature.len()} bytes`); + + // Test verifying a signature + print("Testing signature verification..."); + let is_valid = keypair_verify(message, signature); + assert_true(is_valid, "Signature should be valid"); + print("✓ Signature verified successfully"); + + // Test verifying with just a public key + print("Testing verification with public key only..."); + let is_valid_pub = verify_with_public_key(pub_key, message, signature); + assert_true(is_valid_pub, "Signature should be valid with public key only"); + print("✓ Signature verified with public key only"); + + // Edge case: Empty message + print("Testing with empty message..."); + let empty_message = ""; + let empty_signature = keypair_sign(empty_message); + assert_true(empty_signature.len() > 0, "Signature for empty message should not be empty"); + let is_valid_empty = keypair_verify(empty_message, empty_signature); + assert_true(is_valid_empty, "Empty message signature should be valid"); + print("✓ Empty message signed and verified successfully"); + + // Edge case: Large message + print("Testing with large message..."); + let large_message = "A" * 10000; // 10KB message + let large_signature = keypair_sign(large_message); + assert_true(large_signature.len() > 0, "Signature for large message should not be empty"); + let is_valid_large = keypair_verify(large_message, large_signature); + assert_true(is_valid_large, "Large message signature should be valid"); + print("✓ Large message signed and verified successfully"); + + // Error case: Invalid signature format + print("Testing with invalid signature format..."); + let invalid_signature = [0, 1, 2, 3]; // Invalid signature bytes + let is_valid_invalid = false; + try { + is_valid_invalid = keypair_verify(message, invalid_signature); + } catch(err) { + print(`✓ Caught expected error for invalid signature: ${err}`); + } + assert_true(!is_valid_invalid, "Invalid signature should not verify"); + + // Error case: Tampered message + print("Testing with tampered message..."); + let tampered_message = message + " (tampered)"; + let is_valid_tampered = keypair_verify(tampered_message, signature); + assert_true(!is_valid_tampered, "Tampered message should not verify"); + print("✓ Tampered message correctly failed verification"); + + // Error case: Malformed public key + print("Testing with malformed public key..."); + let malformed_pub_key = [0, 1, 2, 3]; // Invalid public key bytes + let is_valid_malformed = false; + try { + is_valid_malformed = verify_with_public_key(malformed_pub_key, message, signature); + } catch(err) { + print(`✓ Caught expected error for malformed public key: ${err}`); + } + assert_true(!is_valid_malformed, "Malformed public key should not verify"); + } else { + print("✗ Failed to select keypair"); + throw "Failed to select keypair"; + } + } else { + print("✗ Failed to create keypair"); + throw "Failed to create keypair"; + } +} else { + print("✗ Failed to create key space"); + throw "Failed to create key space"; +} + +print("All keypair operations tests completed successfully!"); \ No newline at end of file diff --git a/rhai_tests/keypair/02_keyspace_operations.rhai b/rhai_tests/keypair/02_keyspace_operations.rhai new file mode 100644 index 0000000..83b5b17 --- /dev/null +++ b/rhai_tests/keypair/02_keyspace_operations.rhai @@ -0,0 +1,162 @@ +// 02_keyspace_operations.rhai +// Tests for key space operations in the Keypair module + +// Custom assert function +fn assert_true(condition, message) { + if !condition { + print(`ASSERTION FAILED: ${message}`); + throw message; + } +} + +print("=== Testing Key Space Operations ==="); + +// Test creating a new key space +print("Testing key space creation..."); +let space_name = "test_keyspace"; +let password = "secure_password"; + +if create_key_space(space_name, password) { + print(`✓ Key space "${space_name}" created successfully`); + + // Test adding keypairs to a key space + print("Testing adding keypairs to key space..."); + let keypair1_name = "keypair1"; + let keypair2_name = "keypair2"; + + if create_keypair(keypair1_name, password) { + print(`✓ Keypair "${keypair1_name}" created successfully`); + } else { + print(`✗ Failed to create keypair "${keypair1_name}"`); + throw `Failed to create keypair "${keypair1_name}"`; + } + + if create_keypair(keypair2_name, password) { + print(`✓ Keypair "${keypair2_name}" created successfully`); + } else { + print(`✗ Failed to create keypair "${keypair2_name}"`); + throw `Failed to create keypair "${keypair2_name}"`; + } + + // Test listing keypairs in a key space + print("Testing listing keypairs in key space..."); + let keypairs = list_keypairs(); + assert_true(keypairs.len() == 2, `Expected 2 keypairs, got ${keypairs.len()}`); + assert_true(keypairs.contains(keypair1_name), `Keypair list should contain "${keypair1_name}"`); + assert_true(keypairs.contains(keypair2_name), `Keypair list should contain "${keypair2_name}"`); + print(`✓ Listed keypairs successfully: ${keypairs}`); + + // Test getting a keypair by name + print("Testing getting a keypair by name..."); + if select_keypair(keypair1_name) { + print(`✓ Selected keypair "${keypair1_name}" successfully`); + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + print(`✓ Retrieved public key for "${keypair1_name}": ${pub_key.len()} bytes`); + } else { + print(`✗ Failed to select keypair "${keypair1_name}"`); + throw `Failed to select keypair "${keypair1_name}"`; + } + + // Edge case: Attempt to add a keypair with a duplicate name + print("Testing adding a keypair with a duplicate name..."); + let duplicate_success = false; + try { + duplicate_success = create_keypair(keypair1_name, password); + } catch(err) { + print(`✓ Caught expected error for duplicate keypair: ${err}`); + } + assert_true(!duplicate_success, "Creating a duplicate keypair should fail"); + + // Edge case: Attempt to get a non-existent keypair + print("Testing getting a non-existent keypair..."); + let nonexistent_success = false; + try { + nonexistent_success = select_keypair("nonexistent_keypair"); + } catch(err) { + print(`✓ Caught expected error for non-existent keypair: ${err}`); + } + assert_true(!nonexistent_success, "Selecting a non-existent keypair should fail"); + + // Edge case: Test with special characters in keypair names + print("Testing with special characters in keypair name..."); + let special_name = "special!@#$%^&*()_+"; + if create_keypair(special_name, password) { + print(`✓ Created keypair with special characters: "${special_name}"`); + + // Verify we can select and use it + if select_keypair(special_name) { + print(`✓ Selected keypair with special characters`); + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + } else { + print(`✗ Failed to select keypair with special characters`); + throw `Failed to select keypair with special characters`; + } + } else { + print(`✗ Failed to create keypair with special characters`); + throw `Failed to create keypair with special characters`; + } + + // Edge case: Test with very long keypair name + print("Testing with very long keypair name..."); + let long_name = "a" * 100; // 100 character name + if create_keypair(long_name, password) { + print(`✓ Created keypair with long name (${long_name.len()} characters)`); + + // Verify we can select and use it + if select_keypair(long_name) { + print(`✓ Selected keypair with long name`); + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + } else { + print(`✗ Failed to select keypair with long name`); + throw `Failed to select keypair with long name`; + } + } else { + print(`✗ Failed to create keypair with long name`); + throw `Failed to create keypair with long name`; + } + + // Edge case: Test with empty keypair name (should fail) + print("Testing with empty keypair name..."); + let empty_name = ""; + let empty_name_success = false; + try { + empty_name_success = create_keypair(empty_name, password); + } catch(err) { + print(`✓ Caught expected error for empty keypair name: ${err}`); + } + assert_true(!empty_name_success, "Creating a keypair with empty name should fail"); + + // Stress test: Add multiple keypairs + print("Stress testing: Adding multiple keypairs..."); + let num_keypairs = 10; // Add 10 more keypairs + let stress_keypairs = []; + + for i in 0..num_keypairs { + let name = `stress_keypair_${i}`; + stress_keypairs.push(name); + + if create_keypair(name, password) { + print(`✓ Created stress test keypair ${i+1}/${num_keypairs}`); + } else { + print(`✗ Failed to create stress test keypair ${i+1}/${num_keypairs}`); + throw `Failed to create stress test keypair ${i+1}/${num_keypairs}`; + } + } + + // Verify all keypairs were created + print("Verifying all stress test keypairs..."); + let all_keypairs = list_keypairs(); + for name in stress_keypairs { + assert_true(all_keypairs.contains(name), `Keypair list should contain "${name}"`); + } + print(`✓ All ${num_keypairs} stress test keypairs verified`); + +} else { + print(`✗ Failed to create key space "${space_name}"`); + throw `Failed to create key space "${space_name}"`; +} + +print("All key space operations tests completed successfully!"); \ No newline at end of file diff --git a/rhai_tests/keypair/03_session_management.rhai b/rhai_tests/keypair/03_session_management.rhai new file mode 100644 index 0000000..a3a5cc1 --- /dev/null +++ b/rhai_tests/keypair/03_session_management.rhai @@ -0,0 +1,167 @@ +// 03_session_management.rhai +// Tests for session management in the Keypair module + +// Custom assert function +fn assert_true(condition, message) { + if !condition { + print(`ASSERTION FAILED: ${message}`); + throw message; + } +} + +print("=== Testing Session Management ==="); + +// Test creating a key space and setting it as current +print("Testing key space creation and activation..."); +let space_name1 = "session_test_space1"; +let space_name2 = "session_test_space2"; +let password = "secure_password"; + +// Create first key space +if create_key_space(space_name1, password) { + print(`✓ Key space "${space_name1}" created successfully`); + + // Test creating keypairs in the current space + print("Testing creating keypairs in current space..."); + let keypair1_name = "session_keypair1"; + + if create_keypair(keypair1_name, password) { + print(`✓ Keypair "${keypair1_name}" created successfully in space "${space_name1}"`); + } else { + print(`✗ Failed to create keypair "${keypair1_name}" in space "${space_name1}"`); + throw `Failed to create keypair "${keypair1_name}" in space "${space_name1}"`; + } + + // Test selecting a keypair + print("Testing selecting a keypair..."); + if select_keypair(keypair1_name) { + print(`✓ Selected keypair "${keypair1_name}" successfully`); + } else { + print(`✗ Failed to select keypair "${keypair1_name}"`); + throw `Failed to select keypair "${keypair1_name}"`; + } + + // Test getting the selected keypair + print("Testing getting the selected keypair..."); + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + print(`✓ Retrieved public key for selected keypair: ${pub_key.len()} bytes`); + + // Create second key space + print("\nTesting creating and switching to a second key space..."); + if create_key_space(space_name2, password) { + print(`✓ Key space "${space_name2}" created successfully`); + + // Verify we're now in the second space + print("Verifying current space changed..."); + let keypairs = list_keypairs(); + assert_true(keypairs.len() == 0, `Expected 0 keypairs in new space, got ${keypairs.len()}`); + print("✓ Current space verified as the new space (empty keypair list)"); + + // Create a keypair in the second space + let keypair2_name = "session_keypair2"; + if create_keypair(keypair2_name, password) { + print(`✓ Keypair "${keypair2_name}" created successfully in space "${space_name2}"`); + } else { + print(`✗ Failed to create keypair "${keypair2_name}" in space "${space_name2}"`); + throw `Failed to create keypair "${keypair2_name}" in space "${space_name2}"`; + } + + // Switch back to first space + print("\nTesting switching back to first key space..."); + if load_key_space(space_name1, password) { + print(`✓ Switched back to key space "${space_name1}" successfully`); + + // Verify we're now in the first space + print("Verifying current space changed back..."); + let keypairs = list_keypairs(); + assert_true(keypairs.len() == 1, `Expected 1 keypair in original space, got ${keypairs.len()}`); + assert_true(keypairs.contains(keypair1_name), `Keypair list should contain "${keypair1_name}"`); + print("✓ Current space verified as the original space"); + } else { + print(`✗ Failed to switch back to key space "${space_name1}"`); + throw `Failed to switch back to key space "${space_name1}"`; + } + } else { + print(`✗ Failed to create second key space "${space_name2}"`); + throw `Failed to create second key space "${space_name2}"`; + } + + // Test clearing the session + print("\nTesting clearing the session..."); + clear_session(); + print("✓ Session cleared"); + + // Verify operations fail after clearing session + print("Verifying operations fail after clearing session..."); + let list_success = false; + try { + list_keypairs(); + list_success = true; + } catch(err) { + print(`✓ Caught expected error after clearing session: ${err}`); + } + assert_true(!list_success, "Listing keypairs should fail after clearing session"); + + // Error case: Attempt operations without an active key space + print("\nTesting operations without an active key space..."); + + // Attempt to create a keypair + let create_success = false; + try { + create_success = create_keypair("no_space_keypair", password); + } catch(err) { + print(`✓ Caught expected error for creating keypair without active space: ${err}`); + } + assert_true(!create_success, "Creating a keypair without active space should fail"); + + // Attempt to select a keypair + let select_success = false; + try { + select_success = select_keypair("no_space_keypair"); + } catch(err) { + print(`✓ Caught expected error for selecting keypair without active space: ${err}`); + } + assert_true(!select_success, "Selecting a keypair without active space should fail"); + + // Reload a key space + print("\nTesting reloading a key space after clearing session..."); + if load_key_space(space_name1, password) { + print(`✓ Reloaded key space "${space_name1}" successfully`); + + // Verify the keypair is still there + let keypairs = list_keypairs(); + assert_true(keypairs.contains(keypair1_name), `Keypair list should contain "${keypair1_name}"`); + print("✓ Keypair still exists in reloaded space"); + } else { + print(`✗ Failed to reload key space "${space_name1}"`); + throw `Failed to reload key space "${space_name1}"`; + } + + // Error case: Attempt to get selected keypair when none is selected + print("\nTesting getting selected keypair when none is selected..."); + let get_selected_success = false; + try { + keypair_pub_key(); + get_selected_success = true; + } catch(err) { + print(`✓ Caught expected error for getting selected keypair when none selected: ${err}`); + } + assert_true(!get_selected_success, "Getting selected keypair when none is selected should fail"); + + // Error case: Attempt to select non-existent keypair + print("\nTesting selecting a non-existent keypair..."); + let select_nonexistent_success = false; + try { + select_nonexistent_success = select_keypair("nonexistent_keypair"); + } catch(err) { + print(`✓ Caught expected error for selecting non-existent keypair: ${err}`); + } + assert_true(!select_nonexistent_success, "Selecting a non-existent keypair should fail"); + +} else { + print(`✗ Failed to create key space "${space_name1}"`); + throw `Failed to create key space "${space_name1}"`; +} + +print("All session management tests completed successfully!"); \ No newline at end of file diff --git a/rhai_tests/keypair/04_encryption_decryption.rhai b/rhai_tests/keypair/04_encryption_decryption.rhai new file mode 100644 index 0000000..839c19a --- /dev/null +++ b/rhai_tests/keypair/04_encryption_decryption.rhai @@ -0,0 +1,192 @@ +// 04_encryption_decryption.rhai +// Tests for asymmetric encryption and decryption in the Keypair module + +// Custom assert function +fn assert_true(condition, message) { + if !condition { + print(`ASSERTION FAILED: ${message}`); + throw message; + } +} + +print("=== Testing Asymmetric Encryption and Decryption ==="); + +// Test creating keypairs for sender and recipient +print("Setting up sender and recipient keypairs..."); +let space_name = "encryption_test_space"; +let password = "secure_password"; +let sender_name = "sender_keypair"; +let recipient_name = "recipient_keypair"; + +if create_key_space(space_name, password) { + print(`✓ Key space "${space_name}" created successfully`); + + // Create sender keypair + if create_keypair(sender_name, password) { + print(`✓ Sender keypair "${sender_name}" created successfully`); + } else { + print(`✗ Failed to create sender keypair "${sender_name}"`); + throw `Failed to create sender keypair "${sender_name}"`; + } + + // Create recipient keypair + if create_keypair(recipient_name, password) { + print(`✓ Recipient keypair "${recipient_name}" created successfully`); + } else { + print(`✗ Failed to create recipient keypair "${recipient_name}"`); + throw `Failed to create recipient keypair "${recipient_name}"`; + } + + // Get recipient's public key + if select_keypair(recipient_name) { + print(`✓ Selected recipient keypair "${recipient_name}" successfully`); + let recipient_pub_key = keypair_pub_key(); + assert_true(recipient_pub_key.len() > 0, "Recipient public key should not be empty"); + print(`✓ Retrieved recipient public key: ${recipient_pub_key.len()} bytes`); + + // Switch to sender keypair + if select_keypair(sender_name) { + print(`✓ Selected sender keypair "${sender_name}" successfully`); + + // Test encrypting a message with recipient's public key + print("\nTesting encrypting a message..."); + let message = "This is a secret message for the recipient"; + let ciphertext = encrypt_asymmetric(recipient_pub_key, message); + assert_true(ciphertext.len() > 0, "Ciphertext should not be empty"); + print(`✓ Message encrypted successfully: ${ciphertext.len()} bytes`); + + // Switch back to recipient keypair to decrypt + if select_keypair(recipient_name) { + print(`✓ Switched back to recipient keypair "${recipient_name}" successfully`); + + // Test decrypting the message + print("Testing decrypting the message..."); + let decrypted = decrypt_asymmetric(ciphertext); + assert_true(decrypted == message, "Decrypted message should match original"); + print(`✓ Message decrypted successfully: "${decrypted}"`); + + // Edge case: Test with empty message + print("\nTesting with empty message..."); + let empty_message = ""; + let empty_ciphertext = encrypt_asymmetric(recipient_pub_key, empty_message); + assert_true(empty_ciphertext.len() > 0, "Ciphertext for empty message should not be empty"); + + let empty_decrypted = decrypt_asymmetric(empty_ciphertext); + assert_true(empty_decrypted == empty_message, "Decrypted empty message should be empty"); + print("✓ Empty message encrypted and decrypted successfully"); + + // Edge case: Test with large message + print("\nTesting with large message..."); + let large_message = "A" * 10000; // 10KB message + let large_ciphertext = encrypt_asymmetric(recipient_pub_key, large_message); + assert_true(large_ciphertext.len() > 0, "Ciphertext for large message should not be empty"); + + let large_decrypted = decrypt_asymmetric(large_ciphertext); + assert_true(large_decrypted == large_message, "Decrypted large message should match original"); + print("✓ Large message encrypted and decrypted successfully"); + + // Error case: Attempt to decrypt with the wrong keypair + print("\nTesting decryption with wrong keypair..."); + if select_keypair(sender_name) { + print(`✓ Switched to sender keypair "${sender_name}" successfully`); + + let wrong_keypair_success = true; + try { + let wrong_decrypted = decrypt_asymmetric(ciphertext); + // If we get here, the decryption didn't fail as expected + assert_true(wrong_decrypted != message, "Decryption with wrong keypair should not match original message"); + } catch(err) { + wrong_keypair_success = false; + print(`✓ Caught expected error for decryption with wrong keypair: ${err}`); + } + + // Note: Some implementations might not throw an error but return garbage data + // So we don't assert on wrong_keypair_success + + // Switch back to recipient for further tests + if select_keypair(recipient_name) { + print(`✓ Switched back to recipient keypair "${recipient_name}" successfully`); + } else { + print(`✗ Failed to switch back to recipient keypair "${recipient_name}"`); + throw `Failed to switch back to recipient keypair "${recipient_name}"`; + } + } else { + print(`✗ Failed to switch to sender keypair "${sender_name}"`); + throw `Failed to switch to sender keypair "${sender_name}"`; + } + + // Error case: Test with malformed ciphertext + print("\nTesting with malformed ciphertext..."); + let malformed_ciphertext = [0, 1, 2, 3]; // Invalid ciphertext bytes + let malformed_success = false; + try { + decrypt_asymmetric(malformed_ciphertext); + malformed_success = true; + } catch(err) { + print(`✓ Caught expected error for malformed ciphertext: ${err}`); + } + assert_true(!malformed_success, "Decrypting malformed ciphertext should fail"); + + // Error case: Test with invalid public key for encryption + print("\nTesting encryption with invalid public key..."); + if select_keypair(sender_name) { + print(`✓ Switched to sender keypair "${sender_name}" successfully`); + + let invalid_pub_key = [0, 1, 2, 3]; // Invalid public key bytes + let invalid_key_success = false; + try { + encrypt_asymmetric(invalid_pub_key, message); + invalid_key_success = true; + } catch(err) { + print(`✓ Caught expected error for invalid public key: ${err}`); + } + assert_true(!invalid_key_success, "Encrypting with invalid public key should fail"); + } else { + print(`✗ Failed to switch to sender keypair "${sender_name}"`); + throw `Failed to switch to sender keypair "${sender_name}"`; + } + + // Error case: Test with tampered ciphertext + print("\nTesting with tampered ciphertext..."); + if select_keypair(recipient_name) { + print(`✓ Switched to recipient keypair "${recipient_name}" successfully`); + + // Tamper with the ciphertext (change a byte in the middle) + let tampered_ciphertext = ciphertext.clone(); + if tampered_ciphertext.len() > 100 { + tampered_ciphertext[100] = (tampered_ciphertext[100] + 1) % 256; + + let tampered_success = false; + try { + let tampered_decrypted = decrypt_asymmetric(tampered_ciphertext); + tampered_success = tampered_decrypted == message; + } catch(err) { + print(`✓ Caught expected error for tampered ciphertext: ${err}`); + } + assert_true(!tampered_success, "Decrypting tampered ciphertext should fail or produce incorrect result"); + } else { + print("Note: Ciphertext too short to test tampering"); + } + } else { + print(`✗ Failed to switch to recipient keypair "${recipient_name}"`); + throw `Failed to switch to recipient keypair "${recipient_name}"`; + } + + } else { + print(`✗ Failed to switch back to recipient keypair "${recipient_name}"`); + throw `Failed to switch back to recipient keypair "${recipient_name}"`; + } + } else { + print(`✗ Failed to select sender keypair "${sender_name}"`); + throw `Failed to select sender keypair "${sender_name}"`; + } + } else { + print(`✗ Failed to select recipient keypair "${recipient_name}"`); + throw `Failed to select recipient keypair "${recipient_name}"`; + } +} else { + print(`✗ Failed to create key space "${space_name}"`); + throw `Failed to create key space "${space_name}"`; +} + +print("All asymmetric encryption and decryption tests completed successfully!"); \ No newline at end of file diff --git a/rhai_tests/keypair/05_error_handling.rhai b/rhai_tests/keypair/05_error_handling.rhai new file mode 100644 index 0000000..8a0689e --- /dev/null +++ b/rhai_tests/keypair/05_error_handling.rhai @@ -0,0 +1,231 @@ +// 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!"); \ No newline at end of file diff --git a/rhai_tests/keypair/run_all_tests.rhai b/rhai_tests/keypair/run_all_tests.rhai new file mode 100644 index 0000000..d1f863f --- /dev/null +++ b/rhai_tests/keypair/run_all_tests.rhai @@ -0,0 +1,293 @@ +// run_all_tests.rhai +// Runs all Keypair module tests + +print("=== Running Keypair Module Tests ==="); + +// Custom assert function +fn assert_true(condition, message) { + if !condition { + print(`ASSERTION FAILED: ${message}`); + throw message; + } +} + +// Run each test directly +let passed = 0; +let failed = 0; +let test_results = #{}; + +// Test 1: Keypair Operations +print("\n--- Running Keypair Operations Tests ---"); +try { + // Clear any existing session + clear_session(); + + // Test creating a new keypair + print("Testing keypair creation..."); + let keypair_name = "test_keypair"; + if create_key_space("test_space", "password") { + print("✓ Key space created successfully"); + + if create_keypair(keypair_name, "password") { + print("✓ Keypair created successfully"); + + // Test getting the public key + print("Testing public key retrieval..."); + if select_keypair(keypair_name) { + let pub_key = keypair_pub_key(); + assert_true(pub_key.len() > 0, "Public key should not be empty"); + print(`✓ Public key retrieved: ${pub_key.len()} bytes`); + + // Test signing a message + print("Testing message signing..."); + let message = "This is a test message to sign"; + let signature = keypair_sign(message); + assert_true(signature.len() > 0, "Signature should not be empty"); + print(`✓ Message signed successfully: ${signature.len()} bytes`); + + // Test verifying a signature + print("Testing signature verification..."); + let is_valid = keypair_verify(message, signature); + assert_true(is_valid, "Signature should be valid"); + print("✓ Signature verified successfully"); + } + } + } + + print("--- Keypair Operations Tests completed successfully ---"); + passed += 1; + test_results["01_keypair_operations"] = "PASSED"; +} catch(err) { + print(`!!! Error in Keypair Operations Tests: ${err}`); + failed += 1; + test_results["01_keypair_operations"] = `FAILED: ${err}`; +} + +// Test 2: Key Space Operations +print("\n--- Running Key Space Operations Tests ---"); +try { + // Clear any existing session + clear_session(); + + // Test creating a new key space + print("Testing key space creation..."); + let space_name = "test_keyspace"; + let password = "secure_password"; + + if create_key_space(space_name, password) { + print(`✓ Key space "${space_name}" created successfully`); + + // Test adding keypairs to a key space + print("Testing adding keypairs to key space..."); + let keypair1_name = "keypair1"; + let keypair2_name = "keypair2"; + + if create_keypair(keypair1_name, password) { + print(`✓ Keypair "${keypair1_name}" created successfully`); + } + + if create_keypair(keypair2_name, password) { + print(`✓ Keypair "${keypair2_name}" created successfully`); + } + + // Test listing keypairs in a key space + print("Testing listing keypairs in key space..."); + let keypairs = list_keypairs(); + assert_true(keypairs.len() == 2, `Expected 2 keypairs, got ${keypairs.len()}`); + assert_true(keypairs.contains(keypair1_name), `Keypair list should contain "${keypair1_name}"`); + assert_true(keypairs.contains(keypair2_name), `Keypair list should contain "${keypair2_name}"`); + print(`✓ Listed keypairs successfully: ${keypairs}`); + } + + print("--- Key Space Operations Tests completed successfully ---"); + passed += 1; + test_results["02_keyspace_operations"] = "PASSED"; +} catch(err) { + print(`!!! Error in Key Space Operations Tests: ${err}`); + failed += 1; + test_results["02_keyspace_operations"] = `FAILED: ${err}`; +} + +// Test 3: Session Management +print("\n--- Running Session Management Tests ---"); +try { + // Clear any existing session + clear_session(); + + // Test creating a key space and setting it as current + print("Testing key space creation and activation..."); + let space_name1 = "session_test_space1"; + let space_name2 = "session_test_space2"; + let password = "secure_password"; + + // Create first key space + if create_key_space(space_name1, password) { + print(`✓ Key space "${space_name1}" created successfully`); + + // Test creating keypairs in the current space + print("Testing creating keypairs in current space..."); + let keypair1_name = "session_keypair1"; + + if create_keypair(keypair1_name, password) { + print(`✓ Keypair "${keypair1_name}" created successfully in space "${space_name1}"`); + } + + // Test selecting a keypair + print("Testing selecting a keypair..."); + if select_keypair(keypair1_name) { + print(`✓ Selected keypair "${keypair1_name}" successfully`); + } + } + + print("--- Session Management Tests completed successfully ---"); + passed += 1; + test_results["03_session_management"] = "PASSED"; +} catch(err) { + print(`!!! Error in Session Management Tests: ${err}`); + failed += 1; + test_results["03_session_management"] = `FAILED: ${err}`; +} + +// Test 4: Encryption and Decryption +print("\n--- Running Encryption and Decryption Tests ---"); +try { + // Clear any existing session + clear_session(); + + // Test creating keypairs for sender and recipient + print("Setting up sender and recipient keypairs..."); + let space_name = "encryption_test_space"; + let password = "secure_password"; + let sender_name = "sender_keypair"; + let recipient_name = "recipient_keypair"; + + if create_key_space(space_name, password) { + print(`✓ Key space "${space_name}" created successfully`); + + // Create sender keypair + if create_keypair(sender_name, password) { + print(`✓ Sender keypair "${sender_name}" created successfully`); + } + + // Create recipient keypair + if create_keypair(recipient_name, password) { + print(`✓ Recipient keypair "${recipient_name}" created successfully`); + } + + // Get recipient's public key + if select_keypair(recipient_name) { + print(`✓ Selected recipient keypair "${recipient_name}" successfully`); + let recipient_pub_key = keypair_pub_key(); + + // Switch to sender keypair + if select_keypair(sender_name) { + print(`✓ Selected sender keypair "${sender_name}" successfully`); + + // Test encrypting a message with recipient's public key + print("\nTesting encrypting a message..."); + let message = "This is a secret message for the recipient"; + let ciphertext = encrypt_asymmetric(recipient_pub_key, message); + + // Switch back to recipient keypair to decrypt + if select_keypair(recipient_name) { + print(`✓ Switched back to recipient keypair "${recipient_name}" successfully`); + + // Test decrypting the message + print("Testing decrypting the message..."); + let decrypted = decrypt_asymmetric(ciphertext); + assert_true(decrypted == message, "Decrypted message should match original"); + print(`✓ Message decrypted successfully: "${decrypted}"`); + } + } + } + } + + print("--- Encryption and Decryption Tests completed successfully ---"); + passed += 1; + test_results["04_encryption_decryption"] = "PASSED"; +} catch(err) { + print(`!!! Error in Encryption and Decryption Tests: ${err}`); + failed += 1; + test_results["04_encryption_decryption"] = `FAILED: ${err}`; +} + +// Test 5: Error Handling +print("\n--- Running Error Handling Tests ---"); +try { + // Clear any existing session + clear_session(); + + // Test NoActiveSpace error + print("Testing NoActiveSpace error..."); + let no_active_space_error_caught = false; + try { + // Try to create a keypair without an active space + create_keypair("test_keypair", "password"); + } catch(err) { + no_active_space_error_caught = true; + print(`✓ Caught expected error: ${err}`); + } + assert_true(no_active_space_error_caught, "NoActiveSpace error should be caught"); + + // Create a key space for further tests + if create_key_space("error_test_space", "password") { + print(`✓ Key space created successfully`); + + // Test KeypairNotFound error + print("Testing KeypairNotFound error..."); + let keypair_not_found_error_caught = false; + try { + // Try to select a non-existent keypair + select_keypair("nonexistent_keypair"); + } catch(err) { + keypair_not_found_error_caught = true; + print(`✓ Caught expected error: ${err}`); + } + assert_true(keypair_not_found_error_caught, "KeypairNotFound error should be caught"); + + // Test NoKeypairSelected error + print("Testing NoKeypairSelected error..."); + let no_keypair_selected_error_caught = false; + try { + // Try to get the public key without selecting a keypair + keypair_pub_key(); + } catch(err) { + no_keypair_selected_error_caught = true; + print(`✓ Caught expected error: ${err}`); + } + assert_true(no_keypair_selected_error_caught, "NoKeypairSelected error should be caught"); + } + + print("--- Error Handling Tests completed successfully ---"); + passed += 1; + test_results["05_error_handling"] = "PASSED"; +} catch(err) { + print(`!!! Error in Error Handling Tests: ${err}`); + failed += 1; + test_results["05_error_handling"] = `FAILED: ${err}`; +} + +print("\n=== Test Summary ==="); +print(`Passed: ${passed}`); +print(`Failed: ${failed}`); +print(`Total: ${passed + failed}`); + +// Print detailed results +print("\n=== Detailed Test Results ==="); +for key in test_results.keys() { + let result = test_results[key]; + if result.starts_with("PASSED") { + print(`✓ ${key}: ${result}`); + } else { + print(`✗ ${key}: ${result}`); + } +} + +if failed == 0 { + print("\n✅ All tests passed!"); +} else { + print("\n❌ Some tests failed!"); +} + +// Return the number of failed tests (0 means success) +failed; \ No newline at end of file