/** * DbmPersistenceTest - Comprehensive persistence tests for all DBM backends * * These tests verify that data persists correctly across engine instances * for each supported DBM backend (Filesystem, GDBM, LMDB). * * Test pattern: * 1. Create an engine with the specific backend * 2. Write data (containers, documents, properties) * 3. Shutdown and destroy the engine * 4. Create a new engine with the same path * 5. Verify all data persists correctly */ using Implexus.Core; using Implexus.Engine; using Implexus.Storage; public static int main(string[] args) { int passed = 0; int failed = 0; // Filesystem Dbm Persistence Tests stdout.puts("\n=== Filesystem Dbm Persistence Tests ===\n"); if (test_filesystem_basic_persistence()) { passed++; stdout.puts("PASS: test_filesystem_basic_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_basic_persistence\n"); } if (test_filesystem_container_persistence()) { passed++; stdout.puts("PASS: test_filesystem_container_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_container_persistence\n"); } if (test_filesystem_document_persistence()) { passed++; stdout.puts("PASS: test_filesystem_document_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_document_persistence\n"); } if (test_filesystem_property_persistence()) { passed++; stdout.puts("PASS: test_filesystem_property_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_property_persistence\n"); } if (test_filesystem_nested_structure_persistence()) { passed++; stdout.puts("PASS: test_filesystem_nested_structure_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_nested_structure_persistence\n"); } if (test_filesystem_multiple_properties_persistence()) { passed++; stdout.puts("PASS: test_filesystem_multiple_properties_persistence\n"); } else { failed++; stdout.puts("FAIL: test_filesystem_multiple_properties_persistence\n"); } // GDBM Persistence Tests stdout.puts("\n=== GDBM Dbm Persistence Tests ===\n"); if (test_gdbm_basic_persistence()) { passed++; stdout.puts("PASS: test_gdbm_basic_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_basic_persistence\n"); } if (test_gdbm_container_persistence()) { passed++; stdout.puts("PASS: test_gdbm_container_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_container_persistence\n"); } if (test_gdbm_document_persistence()) { passed++; stdout.puts("PASS: test_gdbm_document_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_document_persistence\n"); } if (test_gdbm_property_persistence()) { passed++; stdout.puts("PASS: test_gdbm_property_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_property_persistence\n"); } if (test_gdbm_nested_structure_persistence()) { passed++; stdout.puts("PASS: test_gdbm_nested_structure_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_nested_structure_persistence\n"); } if (test_gdbm_multiple_properties_persistence()) { passed++; stdout.puts("PASS: test_gdbm_multiple_properties_persistence\n"); } else { failed++; stdout.puts("FAIL: test_gdbm_multiple_properties_persistence\n"); } // LMDB Persistence Tests stdout.puts("\n=== LMDB Dbm Persistence Tests ===\n"); if (test_lmdb_basic_persistence()) { passed++; stdout.puts("PASS: test_lmdb_basic_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_basic_persistence\n"); } if (test_lmdb_container_persistence()) { passed++; stdout.puts("PASS: test_lmdb_container_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_container_persistence\n"); } if (test_lmdb_document_persistence()) { passed++; stdout.puts("PASS: test_lmdb_document_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_document_persistence\n"); } if (test_lmdb_property_persistence()) { passed++; stdout.puts("PASS: test_lmdb_property_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_property_persistence\n"); } if (test_lmdb_nested_structure_persistence()) { passed++; stdout.puts("PASS: test_lmdb_nested_structure_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_nested_structure_persistence\n"); } if (test_lmdb_multiple_properties_persistence()) { passed++; stdout.puts("PASS: test_lmdb_multiple_properties_persistence\n"); } else { failed++; stdout.puts("FAIL: test_lmdb_multiple_properties_persistence\n"); } stdout.printf("\n=== Results: %d passed, %d failed ===\n", passed, failed); return failed > 0 ? 1 : 0; } // ============================================================================ // Helper Functions // ============================================================================ // Helper to create temporary directory string create_temp_dir(string prefix = "implexus_persistence_test_") { return DirUtils.mkdtemp(prefix + "XXXXXX"); } // Helper to run async operation synchronously delegate void AsyncOperation(MainLoop loop, ref Error? error); void run_async(AsyncOperation op) { var loop = new MainLoop(); Error? error = null; op(loop, ref error); loop.run(); if (error != null) { warning("Async operation error: %s", ((!)error).message); } } // Cleanup helper for directory void cleanup_dir(string path) { try { Dir dir = Dir.open(path, 0); string? name; while ((name = dir.read_name()) != null) { string file_path = Path.build_filename(path, name); if (FileUtils.test(file_path, FileTest.IS_DIR)) { cleanup_dir(file_path); } else { FileUtils.unlink(file_path); } } } catch (FileError e) { // Ignore errors } DirUtils.remove(path); } // ============================================================================ // Filesystem Dbm Persistence Tests // ============================================================================ // Test: Basic root persistence bool test_filesystem_basic_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create engine and get root var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } // Shutdown engine engine1.shutdown(); // Phase 2: Create new engine and verify root exists var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? root2 = null; bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } engine2.get_root_async.begin((obj, res) => { try { root2 = engine2.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root2 == null) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Container persistence bool test_filesystem_container_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create container var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("test_container", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); // Phase 2: Verify container persists var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/test_container"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } Entity? container2 = null; engine2.get_entity_async.begin(new EntityPath("/test_container"), (obj, res) => { try { container2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container2 == null) { cleanup_dir(temp_dir); return false; } if (((!)container2).entity_type != EntityType.CONTAINER) { cleanup_dir(temp_dir); return false; } if (((!)container2).name != "test_container") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Document persistence bool test_filesystem_document_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create document var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); // Phase 2: Verify document persists var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).entity_type != EntityType.DOCUMENT) { cleanup_dir(temp_dir); return false; } if (((!)doc2).name != "mydoc") { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "TestType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Property persistence bool test_filesystem_property_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create document with property var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set property ((!)doc1).set_entity_property_async.begin("email", new Invercargill.NativeElement("test@example.com"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); // Phase 2: Verify property persists var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? email = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("email", (obj, res) => { try { email = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || email == null || ((!)email).is_null()) { cleanup_dir(temp_dir); return false; } string email_val = ((!)email).as(); if (email_val != "test@example.com") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Nested structure persistence bool test_filesystem_nested_structure_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create nested structure var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? level1 = null; Entity? level2 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("level1", (obj, res) => { try { level1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level1 == null) { cleanup_dir(temp_dir); return false; } ((!)level1).create_container_async.begin("level2", (obj, res) => { try { level2 = ((!)level1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level2 == null) { cleanup_dir(temp_dir); return false; } ((!)level2).create_document_async.begin("deepdoc", "DeepType", (obj, res) => { try { doc1 = ((!)level2).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); // Phase 2: Verify nested structure persists var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists1 = false; bool exists2 = false; bool exists3 = false; engine2.entity_exists_async.begin(new EntityPath("/level1"), (obj, res) => { try { exists1 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists1) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2"), (obj, res) => { try { exists2 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists2) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { exists3 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists3) { cleanup_dir(temp_dir); return false; } Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "DeepType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Multiple properties persistence bool test_filesystem_multiple_properties_persistence() { string temp_dir = create_temp_dir(); try { // Phase 1: Create document with multiple properties var dbm1 = new FilesystemDbm(temp_dir); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_document_async.begin("multidoc", "MultiType", (obj, res) => { try { doc1 = ((!)root1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set multiple properties of different types ((!)doc1).set_entity_property_async.begin("name", new Invercargill.NativeElement("Test Name"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("count", new Invercargill.NativeElement(42), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("active", new Invercargill.NativeElement(true), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("score", new Invercargill.NativeElement(3.14159), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); // Phase 2: Verify all properties persist var dbm2 = new FilesystemDbm(temp_dir); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? name = null; Invercargill.Element? count = null; Invercargill.Element? active = null; Invercargill.Element? score = null; engine2.get_entity_async.begin(new EntityPath("/multidoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("name", (obj, res) => { try { name = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || name == null || ((!)name).as() != "Test Name") { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("count", (obj, res) => { try { count = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || count == null) { cleanup_dir(temp_dir); return false; } int64? count_val = ((!)count).as(); if (count_val == null || (!)count_val != 42) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("active", (obj, res) => { try { active = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || active == null) { cleanup_dir(temp_dir); return false; } bool? active_val = ((!)active).as(); if (active_val == null || (!)active_val != true) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("score", (obj, res) => { try { score = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || score == null) { cleanup_dir(temp_dir); return false; } double? score_val = ((!)score).as(); if (score_val == null || (!)score_val < 3.14158 || (!)score_val > 3.14160) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // ============================================================================ // GDBM Persistence Tests // ============================================================================ // Test: Basic root persistence with GDBM bool test_gdbm_basic_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create engine and get root var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } // Shutdown engine and close DB engine1.shutdown(); dbm1.close(); // Phase 2: Create new engine and verify root exists var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? root2 = null; bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } engine2.get_root_async.begin((obj, res) => { try { root2 = engine2.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root2 == null) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Container persistence with GDBM bool test_gdbm_container_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create container var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("test_container", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify container persists var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/test_container"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } Entity? container2 = null; engine2.get_entity_async.begin(new EntityPath("/test_container"), (obj, res) => { try { container2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container2 == null) { cleanup_dir(temp_dir); return false; } if (((!)container2).entity_type != EntityType.CONTAINER) { cleanup_dir(temp_dir); return false; } if (((!)container2).name != "test_container") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Document persistence with GDBM bool test_gdbm_document_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create document var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify document persists var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).entity_type != EntityType.DOCUMENT) { cleanup_dir(temp_dir); return false; } if (((!)doc2).name != "mydoc") { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "TestType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Property persistence with GDBM bool test_gdbm_property_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create document with property var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set property ((!)doc1).set_entity_property_async.begin("email", new Invercargill.NativeElement("test@example.com"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify property persists var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? email = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("email", (obj, res) => { try { email = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || email == null || ((!)email).is_null()) { cleanup_dir(temp_dir); return false; } string email_val = ((!)email).as(); if (email_val != "test@example.com") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Nested structure persistence with GDBM bool test_gdbm_nested_structure_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create nested structure var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? level1 = null; Entity? level2 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("level1", (obj, res) => { try { level1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level1 == null) { cleanup_dir(temp_dir); return false; } ((!)level1).create_container_async.begin("level2", (obj, res) => { try { level2 = ((!)level1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level2 == null) { cleanup_dir(temp_dir); return false; } ((!)level2).create_document_async.begin("deepdoc", "DeepType", (obj, res) => { try { doc1 = ((!)level2).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify nested structure persists var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists1 = false; bool exists2 = false; bool exists3 = false; engine2.entity_exists_async.begin(new EntityPath("/level1"), (obj, res) => { try { exists1 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists1) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2"), (obj, res) => { try { exists2 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists2) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { exists3 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists3) { cleanup_dir(temp_dir); return false; } Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "DeepType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Multiple properties persistence with GDBM bool test_gdbm_multiple_properties_persistence() { string temp_dir = create_temp_dir("implexus_gdbm_persist_"); string db_path = Path.build_filename(temp_dir, "test.db"); try { // Phase 1: Create document with multiple properties var dbm1 = new GdbmDbm(); dbm1.open(db_path, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_document_async.begin("multidoc", "MultiType", (obj, res) => { try { doc1 = ((!)root1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set multiple properties of different types ((!)doc1).set_entity_property_async.begin("name", new Invercargill.NativeElement("Test Name"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("count", new Invercargill.NativeElement(42), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("active", new Invercargill.NativeElement(true), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("score", new Invercargill.NativeElement(3.14159), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify all properties persist var dbm2 = new GdbmDbm(); dbm2.open(db_path, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? name = null; Invercargill.Element? count = null; Invercargill.Element? active = null; Invercargill.Element? score = null; engine2.get_entity_async.begin(new EntityPath("/multidoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("name", (obj, res) => { try { name = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || name == null || ((!)name).as() != "Test Name") { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("count", (obj, res) => { try { count = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || count == null) { cleanup_dir(temp_dir); return false; } int64? count_val = ((!)count).as(); if (count_val == null || (!)count_val != 42) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("active", (obj, res) => { try { active = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || active == null) { cleanup_dir(temp_dir); return false; } bool? active_val = ((!)active).as(); if (active_val == null || (!)active_val != true) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("score", (obj, res) => { try { score = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || score == null) { cleanup_dir(temp_dir); return false; } double? score_val = ((!)score).as(); if (score_val == null || (!)score_val < 3.14158 || (!)score_val > 3.14160) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // ============================================================================ // LMDB Persistence Tests // ============================================================================ // Test: Basic root persistence with LMDB bool test_lmdb_basic_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create engine and get root var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } // Shutdown engine and close DB engine1.shutdown(); dbm1.close(); // Phase 2: Create new engine and verify root exists var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? root2 = null; bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } engine2.get_root_async.begin((obj, res) => { try { root2 = engine2.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root2 == null) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Container persistence with LMDB bool test_lmdb_container_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create container var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("test_container", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify container persists var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists = false; engine2.entity_exists_async.begin(new EntityPath("/test_container"), (obj, res) => { try { exists = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists) { cleanup_dir(temp_dir); return false; } Entity? container2 = null; engine2.get_entity_async.begin(new EntityPath("/test_container"), (obj, res) => { try { container2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container2 == null) { cleanup_dir(temp_dir); return false; } if (((!)container2).entity_type != EntityType.CONTAINER) { cleanup_dir(temp_dir); return false; } if (((!)container2).name != "test_container") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Document persistence with LMDB bool test_lmdb_document_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create document var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify document persists var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).entity_type != EntityType.DOCUMENT) { cleanup_dir(temp_dir); return false; } if (((!)doc2).name != "mydoc") { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "TestType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Property persistence with LMDB bool test_lmdb_property_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create document with property var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? container1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("docs", (obj, res) => { try { container1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || container1 == null) { cleanup_dir(temp_dir); return false; } ((!)container1).create_document_async.begin("mydoc", "TestType", (obj, res) => { try { doc1 = ((!)container1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set property ((!)doc1).set_entity_property_async.begin("email", new Invercargill.NativeElement("test@example.com"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify property persists var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? email = null; engine2.get_entity_async.begin(new EntityPath("/docs/mydoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("email", (obj, res) => { try { email = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || email == null || ((!)email).is_null()) { cleanup_dir(temp_dir); return false; } string email_val = ((!)email).as(); if (email_val != "test@example.com") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Nested structure persistence with LMDB bool test_lmdb_nested_structure_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create nested structure var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? level1 = null; Entity? level2 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_container_async.begin("level1", (obj, res) => { try { level1 = ((!)root1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level1 == null) { cleanup_dir(temp_dir); return false; } ((!)level1).create_container_async.begin("level2", (obj, res) => { try { level2 = ((!)level1).create_container_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || level2 == null) { cleanup_dir(temp_dir); return false; } ((!)level2).create_document_async.begin("deepdoc", "DeepType", (obj, res) => { try { doc1 = ((!)level2).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify nested structure persists var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); bool exists1 = false; bool exists2 = false; bool exists3 = false; engine2.entity_exists_async.begin(new EntityPath("/level1"), (obj, res) => { try { exists1 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists1) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2"), (obj, res) => { try { exists2 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists2) { cleanup_dir(temp_dir); return false; } engine2.entity_exists_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { exists3 = engine2.entity_exists_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || !exists3) { cleanup_dir(temp_dir); return false; } Entity? doc2 = null; engine2.get_entity_async.begin(new EntityPath("/level1/level2/deepdoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } if (((!)doc2).type_label != "DeepType") { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } } // Test: Multiple properties persistence with LMDB bool test_lmdb_multiple_properties_persistence() { string temp_dir = create_temp_dir("implexus_lmdb_persist_"); try { // Phase 1: Create document with multiple properties var dbm1 = new LmdbDbm(); dbm1.open(temp_dir, false); var storage1 = new BasicStorage(dbm1); var config1 = new StorageConfiguration(storage1); var engine1 = new EmbeddedEngine(config1); Entity? root1 = null; Entity? doc1 = null; Error? error = null; var loop = new MainLoop(); engine1.get_root_async.begin((obj, res) => { try { root1 = engine1.get_root_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || root1 == null) { cleanup_dir(temp_dir); return false; } ((!)root1).create_document_async.begin("multidoc", "MultiType", (obj, res) => { try { doc1 = ((!)root1).create_document_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc1 == null) { cleanup_dir(temp_dir); return false; } // Set multiple properties of different types ((!)doc1).set_entity_property_async.begin("name", new Invercargill.NativeElement("Test Name"), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("count", new Invercargill.NativeElement(42), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("active", new Invercargill.NativeElement(true), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } ((!)doc1).set_entity_property_async.begin("score", new Invercargill.NativeElement(3.14159), (obj, res) => { try { ((!)doc1).set_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null) { cleanup_dir(temp_dir); return false; } engine1.shutdown(); dbm1.close(); // Phase 2: Verify all properties persist var dbm2 = new LmdbDbm(); dbm2.open(temp_dir, false); var storage2 = new BasicStorage(dbm2); var config2 = new StorageConfiguration(storage2); var engine2 = new EmbeddedEngine(config2); Entity? doc2 = null; Invercargill.Element? name = null; Invercargill.Element? count = null; Invercargill.Element? active = null; Invercargill.Element? score = null; engine2.get_entity_async.begin(new EntityPath("/multidoc"), (obj, res) => { try { doc2 = engine2.get_entity_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || doc2 == null) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("name", (obj, res) => { try { name = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || name == null || ((!)name).as() != "Test Name") { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("count", (obj, res) => { try { count = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || count == null) { cleanup_dir(temp_dir); return false; } int64? count_val = ((!)count).as(); if (count_val == null || (!)count_val != 42) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("active", (obj, res) => { try { active = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || active == null) { cleanup_dir(temp_dir); return false; } bool? active_val = ((!)active).as(); if (active_val == null || (!)active_val != true) { cleanup_dir(temp_dir); return false; } ((!)doc2).get_entity_property_async.begin("score", (obj, res) => { try { score = ((!)doc2).get_entity_property_async.end(res); } catch (Error e) { error = e; } loop.quit(); }); loop.run(); if (error != null || score == null) { cleanup_dir(temp_dir); return false; } double? score_val = ((!)score).as(); if (score_val == null || (!)score_val < 3.14158 || (!)score_val > 3.14160) { cleanup_dir(temp_dir); return false; } engine2.shutdown(); dbm2.close(); cleanup_dir(temp_dir); return true; } catch (Error e) { cleanup_dir(temp_dir); return false; } }