From 0d281ff9e4d6d0b0b3d026cf363b73b6aaab2cf3 Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Fri, 13 Feb 2026 10:43:51 +0100 Subject: [PATCH 1/6] temp remove field from json. --- core/source/backend_main.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/source/backend_main.cc b/core/source/backend_main.cc index 47dca7c..af37443 100644 --- a/core/source/backend_main.cc +++ b/core/source/backend_main.cc @@ -86,8 +86,7 @@ namespace #if defined(_WIN32) handle.handle = LoadLibraryA(path.string().c_str()); if (!handle.handle) - throw std::runtime_error("LoadLibrary failed for: " + - path.string()); + throw std::runtime_error("LoadLibrary failed for: " + path.string()); #else handle.handle = dlopen(path.string().c_str(), RTLD_NOW | RTLD_LOCAL); if (!handle.handle) @@ -103,8 +102,9 @@ namespace BackendPlugin() = default; - BackendPlugin(const BackendPlugin &) = delete; - BackendPlugin &operator=(const BackendPlugin &) = delete; + BackendPlugin(const BackendPlugin &) = delete; + BackendPlugin & + operator=(const BackendPlugin &) = delete; BackendPlugin(BackendPlugin &&other) noexcept { @@ -372,9 +372,10 @@ main(int argc, char *argv[]) SlogCliConfig slog_cli; fs::path plugin_path; - app.add_option("-p,--plugin", - plugin_path, - "Backend plugin path (.so/.dylib/.dll)") + app + .add_option("-p,--plugin", + plugin_path, + "Backend plugin path (.so/.dylib/.dll)") ->required() ->check(CLI::ExistingPath.description("")) ->type_name("PATH"); @@ -549,7 +550,10 @@ main(int argc, char *argv[]) if (dump_reg) { - dump_registry(register_path, backend.name); + // FIXME: we should switch back to `dump_registry(register_path, + // backend.name)` + // when the FE will validate the `__backend_name` field. + dump_registry(register_path, ""); slog_info("Dumped registered nodes to %s.", register_path.c_str()); } From c99d5fdd9ba2c845aa1afa5cb06b0374e39a9a70 Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Fri, 13 Feb 2026 11:01:17 +0100 Subject: [PATCH 2/6] Add ctest with test discovery --- CMakeLists.txt | 12 +++++++----- backends/dealii/CMakeLists.txt | 8 ++++---- backends/dealii/tests/CMakeLists.txt | 10 ++++++++++ core/tests/CMakeLists.txt | 6 ++++++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95739b1..ef474ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,11 @@ if(CORAL_BUILD_BACKEND_DEALII AND NOT CORAL_BUILD_SHARED_CORE) endif() if(CORAL_BUILD_TESTS) - # We intentionally run GoogleTest executables directly (faster than ctest). - # Do not call enable_testing() so CMake doesn't generate its own `test` target. - add_custom_target(test) + # Enable CTest for comprehensive test discovery + enable_testing() + # Custom target for running all tests via custom targets (faster than ctest) + # Note: "test" is reserved by CTest, so we use "run_all_tests" + add_custom_target(run_all_tests) endif() add_subdirectory(core) @@ -31,7 +33,7 @@ endif() if(CORAL_BUILD_TESTS) add_subdirectory(core/tests) - if(TARGET test AND TARGET run_coral_core_tests) - add_dependencies(test run_coral_core_tests) + if(TARGET run_all_tests AND TARGET run_coral_core_tests) + add_dependencies(run_all_tests run_coral_core_tests) endif() endif() diff --git a/backends/dealii/CMakeLists.txt b/backends/dealii/CMakeLists.txt index ac3805d..1a60a2b 100644 --- a/backends/dealii/CMakeLists.txt +++ b/backends/dealii/CMakeLists.txt @@ -32,10 +32,10 @@ endif() if(CORAL_BUILD_TESTS) add_subdirectory(tests) - if(TARGET test AND TARGET run_dealii_backend_tests) - add_dependencies(test run_dealii_backend_tests) + if(TARGET run_all_tests AND TARGET run_dealii_backend_tests) + add_dependencies(run_all_tests run_dealii_backend_tests) endif() - if(TARGET test AND TARGET run_dealii_plugin_tests) - add_dependencies(test run_dealii_plugin_tests) + if(TARGET run_all_tests AND TARGET run_dealii_plugin_tests) + add_dependencies(run_all_tests run_dealii_plugin_tests) endif() endif() diff --git a/backends/dealii/tests/CMakeLists.txt b/backends/dealii/tests/CMakeLists.txt index cdafd84..c7f8fd7 100644 --- a/backends/dealii/tests/CMakeLists.txt +++ b/backends/dealii/tests/CMakeLists.txt @@ -42,6 +42,11 @@ add_custom_target(run_dealii_backend_tests DEPENDS dealii_backend_tests USES_TERMINAL) +# Register backend tests with CTest +gtest_discover_tests(dealii_backend_tests + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + PROPERTIES LABELS "dealii;backend") + add_executable(dealii_plugin_tests ${_plugin_test_file}) target_link_libraries(dealii_plugin_tests coral_core ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) if(GTEST_INCLUDE_DIRS) @@ -64,3 +69,8 @@ add_custom_target(run_dealii_plugin_tests COMMAND $ DEPENDS dealii_plugin_tests coral_backend_dealii USES_TERMINAL) + +# Register plugin tests with CTest +gtest_discover_tests(dealii_plugin_tests + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + PROPERTIES LABELS "dealii;plugin") diff --git a/core/tests/CMakeLists.txt b/core/tests/CMakeLists.txt index 3b7648f..978bde9 100644 --- a/core/tests/CMakeLists.txt +++ b/core/tests/CMakeLists.txt @@ -24,3 +24,9 @@ add_custom_target(run_coral_core_tests DEPENDS coral_core_tests USES_TERMINAL) +# Register tests with CTest using GoogleTest discovery +include(GoogleTest) +gtest_discover_tests(coral_core_tests + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + PROPERTIES LABELS "core") + From d32a57022d9f46df8c5c024b91a3e66cab66bd4e Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Fri, 13 Feb 2026 11:09:31 +0100 Subject: [PATCH 3/6] fix Network.DuplicateQualifiedIdFromFile test --- backends/dealii/tests/network.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backends/dealii/tests/network.cc b/backends/dealii/tests/network.cc index 46b1c8d..ee58eed 100644 --- a/backends/dealii/tests/network.cc +++ b/backends/dealii/tests/network.cc @@ -712,6 +712,9 @@ TEST(Network, DuplicateQualifiedIdFromFile) json network_json; input >> network_json; + // Register types so the network can be deserialized + coral::register_all_types(); + // Attempting to load this network should throw DuplicateQualifiedIdException coral::Network network; ASSERT_THROW( From 15a2e2435b845c180476a58ded8b22b422156eff Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Fri, 13 Feb 2026 12:44:11 +0100 Subject: [PATCH 4/6] Extrapolated method solve() from PoissonSolver. --- backends/dealii/include/poisson.h | 6 +- backends/dealii/include/register_types.h | 5 + backends/dealii/tests/dealii_examples.cc | 6 + test_files/PoissonSolver.json | 226 +++++++++++++++++++++++ 4 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 test_files/PoissonSolver.json diff --git a/backends/dealii/include/poisson.h b/backends/dealii/include/poisson.h index 94244e4..d8fb339 100644 --- a/backends/dealii/include/poisson.h +++ b/backends/dealii/include/poisson.h @@ -51,6 +51,10 @@ class PoissonSolver , neumann_boundary_ids(neumann_boundary_ids) , neumann_function_expression(neumann_function_expression) , dof_handler(triangulation) + {} + + void + solve() { dof_handler.distribute_dofs(fe); @@ -128,4 +132,4 @@ class PoissonSolver }; -#endif \ No newline at end of file +#endif diff --git a/backends/dealii/include/register_types.h b/backends/dealii/include/register_types.h index 3ac41a1..07480b5 100644 --- a/backends/dealii/include/register_types.h +++ b/backends/dealii/include/register_types.h @@ -136,6 +136,11 @@ namespace coral "dirichlet_function_expression", "neumann_boundary_ids", "neumann_function_expression"}}); + + NodeObject::register_method, void>( + &PoissonSolver::solve, + {"PoissonSolver::solve<" + Utilities::dim_string(dim, spacedim) + ">", + "poisson_solver"}); } diff --git a/backends/dealii/tests/dealii_examples.cc b/backends/dealii/tests/dealii_examples.cc index a6ab3bb..b3acf5b 100644 --- a/backends/dealii/tests/dealii_examples.cc +++ b/backends/dealii/tests/dealii_examples.cc @@ -321,6 +321,12 @@ TEST(dealiiExamples, PoissonSolver) ASSERT_TRUE((*poisson)()); ASSERT_TRUE(poisson->ready()); + + // Create a method node for solve() and invoke it using coral machinery + auto solve_method = make_node("PoissonSolver::solve<2>"); + solve_method->set_arguments({poisson}); + (*solve_method)(); + // check that the output file was created std::ifstream file(output_dir.path() / "solution.vtu"); ASSERT_TRUE(file.good()); diff --git a/test_files/PoissonSolver.json b/test_files/PoissonSolver.json new file mode 100644 index 0000000..a3d727e --- /dev/null +++ b/test_files/PoissonSolver.json @@ -0,0 +1,226 @@ +{ + "workflow": { + "nodes": { + "0": { + "type": "GridGenerator::generate_from_name_and_arguments<2>", + "position": { + "x": 349, + "y": 285 + }, + "qualified_id": "0" + }, + "1": { + "type": "dealii::Triangulation<2, 2>", + "position": { + "x": -138.6244238453006, + "y": 235.70695519035294 + }, + "qualified_id": "1" + }, + "2": { + "type": "std::string", + "position": { + "x": -162.44546446968224, + "y": 335.4437074273444 + }, + "value": "hyper_cube", + "qualified_id": "2" + }, + "3": { + "type": "std::string", + "position": { + "x": -165.59970909934447, + "y": 453.72788103967997 + }, + "value": "0 : 1 : false", + "qualified_id": "3" + }, + "4": { + "type": "Triangulation<2>::refine_global", + "position": { + "x": 375.353244887737, + "y": 559.3950761333665 + }, + "qualified_id": "4" + }, + "6": { + "type": "unsigned int", + "position": { + "x": -130.53338013052084, + "y": 631.942702615599 + }, + "value": "1", + "qualified_id": "6" + }, + "7": { + "type": "dealii::FE_Q<2, 2>", + "position": { + "x": 320.5236019111856, + "y": 750.2268762279346 + }, + "base": "dealii::FiniteElement<2, 2>", + "qualified_id": "7" + }, + "8": { + "type": "unsigned int", + "position": { + "x": -53.50389238250847, + "y": 808.5804018766869 + }, + "value": "1", + "qualified_id": "8" + }, + "9": { + "type": "std::string", + "position": { + "x": 77.3972597484763, + "y": 969.4468779894634 + }, + "value": "\"./solution.vtk\"", + "qualified_id": "9" + }, + "10": { + "type": "std::string", + "position": { + "x": 67.93452585948947, + "y": 1094.0395408611234 + }, + "value": "1", + "qualified_id": "10" + }, + "11": { + "type": "std::set", + "position": { + "x": 83.70574900780089, + "y": 1218.6322037327836 + }, + "value": "[]", + "qualified_id": "11" + }, + "12": { + "type": "std::set", + "position": { + "x": 85.28287132263199, + "y": 1429.9665939201566 + }, + "value": "[]", + "qualified_id": "12" + }, + "13": { + "type": "std::string", + "position": { + "x": 104.20833910060571, + "y": 1327.4536434561326 + }, + "value": "0", + "qualified_id": "13" + }, + "14": { + "type": "std::string", + "position": { + "x": 101.05409447094348, + "y": 1538.7880336435053 + }, + "value": "0", + "qualified_id": "14" + }, + "15": { + "type": "PoissonSolver<2, 2>", + "position": { + "x": 1152.994678463315, + "y": 512.0814066884323 + }, + "qualified_id": "15" + } + }, + "edges": { + "0": { + "source": 1, + "target": 0, + "source_output": 0, + "target_input": 0 + }, + "1": { + "source": 2, + "target": 0, + "source_output": 0, + "target_input": 1 + }, + "2": { + "source": 3, + "target": 0, + "source_output": 0, + "target_input": 2 + }, + "3": { + "source": 0, + "target": 4, + "source_output": 0, + "target_input": 0 + }, + "4": { + "source": 6, + "target": 4, + "source_output": 0, + "target_input": 1 + }, + "5": { + "source": 8, + "target": 7, + "source_output": 0, + "target_input": 0 + }, + "6": { + "source": 4, + "target": 15, + "source_output": 0, + "target_input": 0 + }, + "7": { + "source": 7, + "target": 15, + "source_output": 0, + "target_input": 1 + }, + "8": { + "source": 9, + "target": 15, + "source_output": 0, + "target_input": 2 + }, + "9": { + "source": 10, + "target": 15, + "source_output": 0, + "target_input": 3 + }, + "10": { + "source": 11, + "target": 15, + "source_output": 0, + "target_input": 4 + }, + "11": { + "source": 13, + "target": 15, + "source_output": 0, + "target_input": 5 + }, + "12": { + "source": 12, + "target": 15, + "source_output": 0, + "target_input": 6 + }, + "13": { + "source": 14, + "target": 15, + "source_output": 0, + "target_input": 7 + } + } + }, + "version": 1, + "author": "dealiix-platform", + "date_time_utc": "2026-02-13T11:40:14.982Z" +} \ No newline at end of file From 0f9acab5025e8c8fd6b698dbdd391148c62c5c0a Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Fri, 13 Feb 2026 14:05:26 +0100 Subject: [PATCH 5/6] Add test for PoissonSolverSolution.json --- backends/dealii/include/register_types.h | 22 ++ backends/dealii/tests/dealii_examples.cc | 50 ++++ ...Solver.json => PoissonSolverCreation.json} | 0 test_files/PoissonSolverSolution.json | 240 ++++++++++++++++++ 4 files changed, 312 insertions(+) rename test_files/{PoissonSolver.json => PoissonSolverCreation.json} (100%) create mode 100644 test_files/PoissonSolverSolution.json diff --git a/backends/dealii/include/register_types.h b/backends/dealii/include/register_types.h index 07480b5..1066aea 100644 --- a/backends/dealii/include/register_types.h +++ b/backends/dealii/include/register_types.h @@ -85,6 +85,28 @@ namespace coral inline void register_dimensional_types() { + // When dim == spacedim, create aliases to handle both forms: + // - Static linking produces: Type<2> + // - Shared library produces: Type<2, 2> + // This ensures JSON compatibility between plugin and test builds + if constexpr (dim == spacedim) + { + const std::string dims_short = std::to_string(dim); + const std::string dims_full = dims_short + ", " + std::to_string(spacedim); + + // Alias for all dimensional types + coral::detail::set_type_alias>( + "dealii::Triangulation<" + dims_full + ">"); + coral::detail::set_type_alias>( + "dealii::FiniteElement<" + dims_full + ">"); + coral::detail::set_type_alias>( + "dealii::FE_Q<" + dims_full + ">"); + coral::detail::set_type_alias>( + "dealii::DoFHandler<" + dims_full + ">"); + coral::detail::set_type_alias>( + "PoissonSolver<" + dims_full + ">"); + } + NodeObject::register_type>(); NodeObject::register_type, Triangulation>("triangulation"); diff --git a/backends/dealii/tests/dealii_examples.cc b/backends/dealii/tests/dealii_examples.cc index b3acf5b..e6ccbfe 100644 --- a/backends/dealii/tests/dealii_examples.cc +++ b/backends/dealii/tests/dealii_examples.cc @@ -332,3 +332,53 @@ TEST(dealiiExamples, PoissonSolver) ASSERT_TRUE(file.good()); file.close(); } + +TEST(dealiiExamples, NetworkFromJsonPoissonSolverSolution) +{ + ScopedTestOutputDir output_dir( + "dealiiExamples_NetworkFromJsonPoissonSolverSolution"); + + register_non_dimensional_types(); + register_dimensional_types<2, 2>(); + + Network network; + network.set_touch_file_base_path(output_dir); + network.clear_network(); + + std::ifstream file(SOURCE_DIR "/test_files/PoissonSolverSolution.json"); + ASSERT_TRUE(file.is_open()) + << "Failed to open PoissonSolverSolution.json file."; + + nlohmann::json json_data; + file >> json_data; + file.close(); + + ASSERT_FALSE(json_data.empty()) << "JSON data is empty."; + + // Update the output file path to use the test output directory + // Node 9 contains the output filename + if (json_data["workflow"]["nodes"].contains("9") && + json_data["workflow"]["nodes"]["9"].contains("value")) + { + std::string output_filename = + json_data["workflow"]["nodes"]["9"]["value"]; + json_data["workflow"]["nodes"]["9"]["value"] = + (output_dir.path() / output_filename).string(); + } + + network.from_json(json_data); + + // Print some debugging information + slog_debug("Network has %u nodes and %u connections", + network.n_nodes(), + network.n_connections()); + + // Run the network + network.run(); + + // Check that the output file was created (assuming the JSON specifies + // solution.vtu) + std::ifstream solution_file(output_dir.path() / "solution.vtu"); + ASSERT_TRUE(solution_file.good()) << "Solution VTU file was not created."; + solution_file.close(); +} diff --git a/test_files/PoissonSolver.json b/test_files/PoissonSolverCreation.json similarity index 100% rename from test_files/PoissonSolver.json rename to test_files/PoissonSolverCreation.json diff --git a/test_files/PoissonSolverSolution.json b/test_files/PoissonSolverSolution.json new file mode 100644 index 0000000..d9f474c --- /dev/null +++ b/test_files/PoissonSolverSolution.json @@ -0,0 +1,240 @@ +{ + "workflow": { + "nodes": { + "0": { + "type": "GridGenerator::generate_from_name_and_arguments<2>", + "position": { + "x": 349, + "y": 285 + }, + "qualified_id": "0" + }, + "1": { + "type": "dealii::Triangulation<2, 2>", + "position": { + "x": -138.6244238453006, + "y": 235.70695519035294 + }, + "qualified_id": "1" + }, + "2": { + "type": "std::string", + "position": { + "x": -162.44546446968224, + "y": 335.4437074273444 + }, + "value": "hyper_cube", + "qualified_id": "2" + }, + "3": { + "type": "std::string", + "position": { + "x": -165.59970909934447, + "y": 453.72788103967997 + }, + "value": "0 : 1 : false", + "qualified_id": "3" + }, + "4": { + "type": "Triangulation<2>::refine_global", + "position": { + "x": 375.353244887737, + "y": 559.3950761333665 + }, + "qualified_id": "4" + }, + "6": { + "type": "unsigned int", + "position": { + "x": -130.53338013052084, + "y": 631.942702615599 + }, + "value": "1", + "qualified_id": "6" + }, + "7": { + "type": "dealii::FE_Q<2, 2>", + "position": { + "x": 320.5236019111856, + "y": 750.2268762279346 + }, + "base": "dealii::FiniteElement<2, 2>", + "qualified_id": "7" + }, + "8": { + "type": "unsigned int", + "position": { + "x": -53.50389238250847, + "y": 808.5804018766869 + }, + "value": "1", + "qualified_id": "8" + }, + "9": { + "type": "std::string", + "position": { + "x": 77.3972597484763, + "y": 969.4468779894634 + }, + "value": "solution.vtu", + "qualified_id": "9" + }, + "10": { + "type": "std::string", + "position": { + "x": 67.93452585948947, + "y": 1094.0395408611234 + }, + "value": "1", + "qualified_id": "10" + }, + "11": { + "type": "std::set", + "position": { + "x": 83.70574900780089, + "y": 1218.6322037327836 + }, + "value": "[]", + "qualified_id": "11" + }, + "12": { + "type": "std::set", + "position": { + "x": 85.28287132263199, + "y": 1429.9665939201566 + }, + "value": "[]", + "qualified_id": "12" + }, + "13": { + "type": "std::string", + "position": { + "x": 104.20833910060571, + "y": 1327.4536434561326 + }, + "value": "0", + "qualified_id": "13" + }, + "14": { + "type": "std::string", + "position": { + "x": 101.05409447094348, + "y": 1538.7880336435053 + }, + "value": "0", + "qualified_id": "14" + }, + "15": { + "type": "PoissonSolver<2, 2>", + "position": { + "x": 1152.994678463315, + "y": 512.0814066884323 + }, + "qualified_id": "15" + }, + "16": { + "type": "PoissonSolver::solve<2>", + "position": { + "x": 1800.0768250057545, + "y": 782.0812376960318 + }, + "qualified_id": "16" + } + }, + "edges": { + "0": { + "source": 1, + "target": 0, + "source_output": 0, + "target_input": 0 + }, + "1": { + "source": 2, + "target": 0, + "source_output": 0, + "target_input": 1 + }, + "2": { + "source": 3, + "target": 0, + "source_output": 0, + "target_input": 2 + }, + "3": { + "source": 0, + "target": 4, + "source_output": 0, + "target_input": 0 + }, + "4": { + "source": 6, + "target": 4, + "source_output": 0, + "target_input": 1 + }, + "5": { + "source": 8, + "target": 7, + "source_output": 0, + "target_input": 0 + }, + "6": { + "source": 4, + "target": 15, + "source_output": 0, + "target_input": 0 + }, + "7": { + "source": 7, + "target": 15, + "source_output": 0, + "target_input": 1 + }, + "8": { + "source": 9, + "target": 15, + "source_output": 0, + "target_input": 2 + }, + "9": { + "source": 10, + "target": 15, + "source_output": 0, + "target_input": 3 + }, + "10": { + "source": 11, + "target": 15, + "source_output": 0, + "target_input": 4 + }, + "11": { + "source": 13, + "target": 15, + "source_output": 0, + "target_input": 5 + }, + "12": { + "source": 12, + "target": 15, + "source_output": 0, + "target_input": 6 + }, + "13": { + "source": 14, + "target": 15, + "source_output": 0, + "target_input": 7 + }, + "14": { + "source": 15, + "target": 16, + "source_output": 0, + "target_input": 0 + } + } + }, + "version": 1, + "author": "dealiix-platform", + "date_time_utc": "2026-02-13T12:05:19.836Z" +} \ No newline at end of file From f94f821948e41d978c8f778b1491a279722e81a9 Mon Sep 17 00:00:00 2001 From: Matteo Poggi Date: Mon, 16 Feb 2026 11:04:17 +0100 Subject: [PATCH 6/6] Add test for serialization. --- backends/dealii/tests/dealii_examples.cc | 74 ++++++++++++++++++++++++ test_files/PoissonSolverSolution.json | 4 +- test_files/SetSum.json | 34 +++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 test_files/SetSum.json diff --git a/backends/dealii/tests/dealii_examples.cc b/backends/dealii/tests/dealii_examples.cc index e6ccbfe..f19e8d6 100644 --- a/backends/dealii/tests/dealii_examples.cc +++ b/backends/dealii/tests/dealii_examples.cc @@ -14,6 +14,80 @@ using namespace dealii; using namespace coral; using coral_test::ScopedTestOutputDir; +// Function to sum all numbers in a set +unsigned int +sum_set(const std::set &input_set) +{ + unsigned int sum = 0; + for (const auto &val : input_set) + sum += val; + return sum; +} + +TEST(dealiiExamples, SumSetRegistry) +{ + ScopedTestOutputDir output_dir("dealiiExamples_SumSetRegistry"); + + // Register the types + NodeObject::register_elementary_type(); + NodeObject::register_elementary_type>(); + + // Register the function + NodeObject::register_function(sum_set, {"sum_set", "result", "input_set"}); + + // Dump the registry to a file + std::ofstream registry_file(output_dir.path() / "registry.json"); + registry_file << NodeObject::get_registry().dump(2) << std::endl; + registry_file.close(); + + // Check that the file exists + std::ifstream check_file(output_dir.path() / "registry.json"); + ASSERT_TRUE(check_file.good()); + check_file.close(); + + // Load and execute the network from SetSum.json + Network network; + network.set_touch_file_base_path(output_dir); + network.clear_network(); + + std::ifstream json_file(SOURCE_DIR "/test_files/SetSum.json"); + ASSERT_TRUE(json_file.is_open()) << "Failed to open SetSum.json file."; + + nlohmann::json json_data; + json_file >> json_data; + json_file.close(); + + ASSERT_FALSE(json_data.empty()) << "JSON data is empty."; + + // Load the network from JSON + network.from_json(json_data); + + // Print debugging information + slog_debug("Network has %u nodes and %u connections", + network.n_nodes(), + network.n_connections()); + + // Run the network + network.run(); + + // Get the function node (node 1) + auto function_node = network.get_node(1); + ASSERT_TRUE(function_node != nullptr) << "Node 1 not found."; + + // For non-void functions, the result is stored in the output of the function + // node + slog_debug("Function node has %zu outputs", function_node->n_outputs()); + + auto result_node = function_node->get_output(0); + ASSERT_TRUE(result_node != nullptr) << "Function output not found."; + ASSERT_TRUE(result_node->ready()) << "Result node not ready."; + + // The result should be 15 (sum of 1 + 2 + 3 + 4 + 5) + unsigned int result = result_node->get(); + slog_debug("Function output is: %u.", result); + ASSERT_EQ(15u, result) << "Expected sum to be 15, got " << result; +} + // Void function test TEST(dealiiExamples, step01) { diff --git a/test_files/PoissonSolverSolution.json b/test_files/PoissonSolverSolution.json index d9f474c..7e8dc57 100644 --- a/test_files/PoissonSolverSolution.json +++ b/test_files/PoissonSolverSolution.json @@ -94,7 +94,7 @@ "x": 83.70574900780089, "y": 1218.6322037327836 }, - "value": "[]", + "value": "[0]", "qualified_id": "11" }, "12": { @@ -236,5 +236,5 @@ }, "version": 1, "author": "dealiix-platform", - "date_time_utc": "2026-02-13T12:05:19.836Z" + "date_time_utc": "2026-02-16T09:15:09.826Z" } \ No newline at end of file diff --git a/test_files/SetSum.json b/test_files/SetSum.json new file mode 100644 index 0000000..a624a4e --- /dev/null +++ b/test_files/SetSum.json @@ -0,0 +1,34 @@ +{ + "workflow": { + "nodes": { + "0": { + "type": "std::set", + "position": { + "x": 235.20748070627937, + "y": 16.63389801607004 + }, + "value": "[1, 2, 3, 4, 5]", + "qualified_id": "0" + }, + "1": { + "type": "sum_set", + "position": { + "x": 727.0019134920428, + "y": 74.81589338742796 + }, + "qualified_id": "1" + } + }, + "edges": { + "0": { + "source": 0, + "target": 1, + "source_output": 0, + "target_input": 0 + } + } + }, + "version": 1, + "author": "dealiix-platform", + "date_time_utc": "2026-02-16T08:33:25.780Z" +} \ No newline at end of file