Loading...
Searching...
No Matches
test_transform_serializer.cpp
Go to the documentation of this file.
1//
2// Created by denzel on 08/12/2025.
3//
4
5
6#include <catch2/catch_test_macros.hpp>
7#include "hellfire/serializers/Serializer.h"
8#include <glm/gtc/epsilon.hpp>
9#include <sstream>
10
11#include "catch2/matchers/catch_matchers_floating_point.hpp"
12
13using namespace hellfire;
14using Catch::Matchers::WithinAbs;
15
16// Helper to compare vec3 with tolerance
17bool vec3_equal(const glm::vec3 &a, const glm::vec3 &b, float epsilon = 0.0001f) {
18 return glm::all(glm::epsilonEqual(a, b, epsilon));
19}
20
21TEST_CASE("TransformComponent serialization", "[serialization][transform]") {
22 SECTION("Round-trip preserves default values") {
23 TransformComponent original;
24
25 std::stringstream ss;
26 REQUIRE(Serializer<TransformComponent>::serialize(ss, &original));
27
28 TransformComponent loaded;
29 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &loaded));
30
31 CHECK(vec3_equal(loaded.get_position(), glm::vec3(0, 0, 0)));
32 CHECK(vec3_equal(loaded.get_rotation(), glm::vec3(0, 0, 0)));
33 CHECK(vec3_equal(loaded.get_scale(), glm::vec3(1, 1, 1)));
34 }
35
36 SECTION("Round-trip preserves custom values") {
37 TransformComponent original;
38 original.set_position(1.5f, -25.6f, 100.0f);
39 original.set_rotation(45.0f, 90.0f, 180.0f);
40 original.set_scale(2.0f, 0.5f, 1.0f);
41
42 std::stringstream ss;
43 REQUIRE(Serializer<TransformComponent>::serialize(ss, &original));
44
45 TransformComponent loaded;
46 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &loaded));
47
48 CHECK(vec3_equal(loaded.get_position(), original.get_position()));
49 CHECK(vec3_equal(loaded.get_rotation(), original.get_rotation()));
50 CHECK(vec3_equal(loaded.get_scale(), original.get_scale()));
51 }
52
53 SECTION("Handles extreme values") {
54 TransformComponent original;
55 original.set_position(FLT_MAX, FLT_MIN, -FLT_MAX);
56 original.set_rotation(360.0f, -360.0f, 720.0f);
57 original.set_scale(0.000001f, 10000.0f, 1.0f);
58
59 std::stringstream ss;
60 REQUIRE(Serializer<TransformComponent>::serialize(ss, &original));
61
62 TransformComponent loaded;
63 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &loaded));
64
65 CHECK(vec3_equal(loaded.get_position(), original.get_position()));
66 CHECK(vec3_equal(loaded.get_rotation(), original.get_rotation()));
67 CHECK(vec3_equal(loaded.get_scale(), original.get_scale()));
68 }
69
70 SECTION("Handles negative values") {
71 TransformComponent original;
72 original.set_position(-10.0f, -20.0f, -30.0f);
73 original.set_rotation(-45.0f, -90.0f, -180.0f);
74 original.set_scale(-1.0f, -1.0f, -1.0f); // Negative scale for mirroring
75
76 std::stringstream ss;
77 REQUIRE(Serializer<TransformComponent>::serialize(ss, &original));
78
79 TransformComponent loaded;
80 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &loaded));
81
82 CHECK(vec3_equal(loaded.get_position(), original.get_position()));
83 CHECK(vec3_equal(loaded.get_rotation(), original.get_rotation()));
84 CHECK(vec3_equal(loaded.get_scale(), original.get_scale()));
85 }
86
87 SECTION("Preserves floating point precision") {
88 TransformComponent original;
89 original.set_position(0.123456789f, 3.14159265f, 0.987654321f);
90
91 std::stringstream ss;
92 REQUIRE(Serializer<TransformComponent>::serialize(ss, &original));
93
94 TransformComponent loaded;
95 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &loaded));
96
97 CHECK(vec3_equal(loaded.get_position(), original.get_position(), 0.00001f));
98 }
99}
100
101TEST_CASE("TransformComponent serialization error handling", "[serialization][transform]") {
102 SECTION("Serialize returns false for nullptr") {
103 std::stringstream ss;
104 REQUIRE_FALSE(Serializer<TransformComponent>::serialize(ss, nullptr));
105 }
106
107 SECTION("Deserialize returns false for nullptr") {
108 std::stringstream ss;
109 ss << R"({"position":[0,0,0],"rotation":[0,0,0],"scale":[1,1,1]})";
110 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, nullptr));
111 }
112
113 SECTION("Deserialize returns false for empty input") {
114 std::stringstream ss;
115 TransformComponent comp;
116 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
117 }
118
119 SECTION("Deserialize returns false for invalid JSON") {
120 std::stringstream ss;
121 ss << "not valid json {{{";
122
123 TransformComponent comp;
124 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
125 }
126
127 SECTION("Deserialize returns false for missing position field") {
128 std::stringstream ss;
129 ss << R"({"rotation":[0,0,0],"scale":[1,1,1]})";
130
131 TransformComponent comp;
132 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
133 }
134
135 SECTION("Deserialize returns false for missing rotation field") {
136 std::stringstream ss;
137 ss << R"({"position":[0,0,0],"scale":[1,1,1]})";
138
139 TransformComponent comp;
140 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
141 }
142
143 SECTION("Deserialize returns false for missing scale field") {
144 std::stringstream ss;
145 ss << R"({"position":[0,0,0],"rotation":[0,0,0]})";
146
147 TransformComponent comp;
148 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
149 }
150
151 SECTION("Deserialize returns false for wrong type in position") {
152 std::stringstream ss;
153 ss << R"({"position":"not an array","rotation":[0,0,0],"scale":[1,1,1]})";
154
155 TransformComponent comp;
156 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
157 }
158
159 SECTION("Deserialize returns false for wrong array size") {
160 std::stringstream ss;
161 ss << R"({"position":[0,0],"rotation":[0,0,0],"scale":[1,1,1]})"; // Only 2 elements
162
163 TransformComponent comp;
164 REQUIRE_FALSE(Serializer<TransformComponent>::deserialize(ss, &comp));
165 }
166}
167
168TEST_CASE("TransformComponent JSON output format", "[serialization][transform]") {
169 SECTION("Output is valid JSON") {
170 TransformComponent comp;
171 comp.set_rotation(1, 2, 3);
172
173 std::stringstream ss;
174 REQUIRE(Serializer<TransformComponent>::serialize(ss, &comp));
175
176 // Verify it parses as valid json
177 nlohmann::json j;
178 REQUIRE_NOTHROW(j = nlohmann::json::parse(ss.str()));
179 }
180
181 SECTION("Output contains expected keys") {
182 TransformComponent comp;
183
184 std::stringstream ss;
185 Serializer<TransformComponent>::serialize(ss, &comp);
186
187 nlohmann::json j = nlohmann::json::parse(ss.str());
188
189 CHECK(j.contains("position"));
190 CHECK(j.contains("rotation"));
191 CHECK(j.contains("scale"));
192 }
193
194 SECTION("Position is serialized as array") {
195 TransformComponent comp;
196 comp.set_position(1, 2, 3);
197
198 std::stringstream ss;
199 Serializer<TransformComponent>::serialize(ss, &comp);
200
201 nlohmann::json j = nlohmann::json::parse(ss.str());
202
203 REQUIRE(j["position"].is_array());
204 REQUIRE(j["position"].size() == 3);
205
206 REQUIRE(j["position"][0] == 1.0f);
207 REQUIRE(j["position"][1] == 2.0f);
208 REQUIRE(j["position"][2] == 3.0f);
209 }
210}
211
212TEST_CASE("TransformComponent deserialization from manual JSON", "[serialization][transform]") {
213 SECTION("Can load hand-written JSON") {
214 std::stringstream ss;
215 ss << R"({
216 "position": [10.0, 20.0, 30.0],
217 "rotation": [0.0, 90.0, 180.0],
218 "scale": [1.0, 1.0, 1.0]
219 })";
220
221 TransformComponent comp;
222 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &comp));
223
224 CHECK(vec3_equal(comp.get_position(), glm::vec3(10, 20, 30)));
225 CHECK(vec3_equal(comp.get_rotation(), glm::vec3(0, 90, 180)));
226 CHECK(vec3_equal(comp.get_scale(), glm::vec3(1, 1, 1)));
227 }
228
229 SECTION("Ignore extra fields") {
230 std::stringstream ss;
231 ss << R"({
232 "position": [1.0, 2.0, 3.0],
233 "rotation": [0.0, 0.0, 0.0],
234 "scale": [1.0, 1.0, 1.0],
235 "some_random_field": "should be ignored"
236 })";
237
238 TransformComponent comp;
239 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &comp));
240 CHECK(vec3_equal(comp.get_position(), glm::vec3(1, 2, 3)));
241 }
242
243 SECTION("Handles integer values in JSON") {
244 std::stringstream ss;
245 ss << R"({"position":[1.0,2.0,3.0],"rotation":[0.0,0.0,0.0],"scale":[1.0,1.0,1.0]})";
246
247 TransformComponent comp;
248 REQUIRE(Serializer<TransformComponent>::deserialize(ss, &comp));
249 CHECK(vec3_equal(comp.get_position(), glm::vec3(1, 2, 3)));
250 }
251}
TEST_CASE("")
Definition main_test.cpp:6
bool vec3_equal(const glm::vec3 &a, const glm::vec3 &b, float epsilon=0.0001f)