Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
TestNodeGraphCore.cpp
Go to the documentation of this file.
1/**
2 * @file TestNodeGraphCore.cpp
3 * @brief Basic tests for NodeGraphCore module
4 * @author Olympe Engine
5 * @date 2026-02-18
6 *
7 * This file contains basic tests to validate NodeGraphCore functionality.
8 * These tests can be compiled separately for validation purposes.
9 */
10
20
21#include <iostream>
22#include <cassert>
23#include <string>
24
25using namespace Olympe::NodeGraph;
26
27// Test 1: Create GraphDocument
29{
30 std::cout << "Test 1: Create GraphDocument... ";
31
33 doc.type = "AIGraph";
34 doc.graphKind = "BehaviorTree";
35
36 assert(doc.GetNodes().empty());
37 assert(doc.GetLinks().empty());
38
39 std::cout << "PASSED" << std::endl;
40}
41
42// Test 2: CRUD Nodes
44{
45 std::cout << "Test 2: CRUD Nodes... ";
46
48
49 NodeId id1 = doc.CreateNode("BT_Selector", Vector2(100, 100));
50 NodeId id2 = doc.CreateNode("BT_Action", Vector2(200, 200));
51
52 assert(doc.GetNodes().size() == 2);
53 assert(doc.GetNode(id1) != nullptr);
54
55 bool deleted = doc.DeleteNode(id1);
56 assert(deleted == true);
57 assert(doc.GetNodes().size() == 1);
58 assert(doc.GetNode(id1) == nullptr);
59
60 std::cout << "PASSED" << std::endl;
61}
62
63// Test 3: Connect Pins
65{
66 std::cout << "Test 3: Connect Pins... ";
67
69
70 NodeId id1 = doc.CreateNode("BT_Selector", Vector2(0, 0));
71 NodeId id2 = doc.CreateNode("BT_Action", Vector2(0, 100));
72
73 PinId pin1;
74 pin1.value = id1.value;
75 PinId pin2;
76 pin2.value = id2.value;
77
78 LinkId link = doc.ConnectPins(pin1, pin2);
79
80 assert(doc.GetLinks().size() == 1);
81 assert(doc.GetLinks()[0].fromPin.value == pin1.value);
82
83 std::cout << "PASSED" << std::endl;
84}
85
86// Test 4: Serialization
88{
89 std::cout << "Test 4: Serialization... ";
90
92 doc.type = "AIGraph";
93 doc.graphKind = "BehaviorTree";
94 doc.CreateNode("BT_Selector", Vector2(100, 100));
95
96 json j = doc.ToJson();
97
98 assert(JsonHelper::GetInt(j, "schemaVersion", 0) == 2);
99 assert(JsonHelper::GetString(j, "type", "") == "AIGraph");
100 assert(JsonHelper::GetString(j, "graphKind", "") == "BehaviorTree");
101 assert(j["data"]["nodes"].is_array());
102 assert(j["data"]["nodes"].size() == 1);
103
104 std::cout << "PASSED" << std::endl;
105}
106
107// Test 5: Multi-graph
109{
110 std::cout << "Test 5: Multi-graph... ";
111
113
114 GraphId g1 = mgr.CreateGraph("AIGraph", "BehaviorTree");
115 GraphId g2 = mgr.CreateGraph("AIGraph", "HFSM");
116
117 assert(mgr.GetAllGraphIds().size() >= 2);
118
119 mgr.SetActiveGraph(g2);
120 assert(mgr.GetActiveGraphId().value == g2.value);
121
122 // Clean up
123 mgr.CloseGraph(g1);
124 mgr.CloseGraph(g2);
125
126 std::cout << "PASSED" << std::endl;
127}
128
129// Test 6: Undo/Redo
131{
132 std::cout << "Test 6: Undo/Redo... ";
133
136
137 auto cmd = std::unique_ptr<ICommand>(new CreateNodeCommand(&doc, "BT_Selector", Vector2(0, 0)));
138 stack.ExecuteCommand(std::move(cmd));
139
140 assert(doc.GetNodes().size() == 1);
141
142 stack.Undo();
143 assert(doc.GetNodes().empty());
144
145 stack.Redo();
146 assert(doc.GetNodes().size() == 1);
147
148 std::cout << "PASSED" << std::endl;
149}
150
151// Test 7: HasCycles
153{
154 std::cout << "Test 7: HasCycles... ";
155
157
158 // Create simple tree without cycles
159 NodeId idA = doc.CreateNode("A", Vector2(0, 0));
160 NodeId idB = doc.CreateNode("B", Vector2(100, 0));
161
162 NodeData* nodeA = doc.GetNode(idA);
163 if (nodeA != nullptr)
164 {
165 nodeA->children.push_back(idB);
166 }
167
168 assert(doc.HasCycles() == false);
169
170 // Create cycle: B -> A
171 NodeData* nodeB = doc.GetNode(idB);
172 if (nodeB != nullptr)
173 {
174 nodeB->children.push_back(idA);
175 }
176
177 assert(doc.HasCycles() == true);
178
179 std::cout << "PASSED" << std::endl;
180}
181
182// Test 8: ValidateGraph
184{
185 std::cout << "Test 8: ValidateGraph... ";
186
188 std::string error;
189
190 // Empty graph should fail
192 assert(valid == false);
193
194 // Add a node
195 doc.CreateNode("BT_Selector", Vector2(0, 0));
196
197 // Graph with selector without children should fail
198 valid = doc.ValidateGraph(error);
199 assert(valid == false);
200 assert(error.find("0 children") != std::string::npos);
201
202 std::cout << "PASSED" << std::endl;
203}
204
205int main()
206{
207 std::cout << "==================================" << std::endl;
208 std::cout << "NodeGraphCore Basic Tests" << std::endl;
209 std::cout << "==================================" << std::endl;
210
211 try
212 {
221
222 std::cout << "==================================" << std::endl;
223 std::cout << "All tests PASSED!" << std::endl;
224 std::cout << "==================================" << std::endl;
225
226 return 0;
227 }
228 catch (const std::exception& e)
229 {
230 std::cerr << "Test FAILED with exception: " << e.what() << std::endl;
231 return 1;
232 }
233}
nlohmann::json json
Command pattern for undo/redo operations.
Command for connecting pins.
Command for creating a node.
Command for deleting a node.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Document class for managing node graphs.
Migration system for JSON versions.
Command for moving a node.
Core data structures for generic node graph system.
Singleton manager for multiple node graphs.
void Test6_UndoRedo()
void Test4_Serialization()
void Test3_ConnectPins()
void Test2_CRUDNodes()
void Test7_HasCycles()
void Test8_ValidateGraph()
void Test1_CreateGraphDocument()
void Test5_MultiGraph()
int main()
Manages undo/redo stacks for commands.
Creates a new node in the graph.
Main document class for a node graph.
bool ValidateGraph(std::string &errorMessage) const
Validate the graph structure.
Singleton manager for multiple node graphs.
static NodeGraphManager & Get()
Get singleton instance.
std::string GetString(const json &j, const std::string &key, const std::string &defaultValue="")
Safely get a string value from JSON.
int GetInt(const json &j, const std::string &key, int defaultValue=0)
Safely get an integer value from JSON.
std::vector< NodeId > children