Skip to content

Commit d4dc131

Browse files
committed
Add unit tests for new optional fields
1 parent 523bf0e commit d4dc131

File tree

1 file changed

+144
-1
lines changed

1 file changed

+144
-1
lines changed

libs/maps/src/maps/CPointsMap_unittest.cpp

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99

1010
#include <gtest/gtest.h>
1111
#include <mrpt/maps/CColouredPointsMap.h>
12+
#include <mrpt/maps/CGenericPointsMap.h>
1213
#include <mrpt/maps/CPointsMapXYZI.h>
1314
#include <mrpt/maps/CSimplePointsMap.h>
1415
#include <mrpt/maps/CWeightedPointsMap.h>
1516
#include <mrpt/poses/CPoint2D.h>
1617

1718
#include <array>
1819
#include <sstream>
19-
#include <utility>
2020

2121
using namespace mrpt;
2222
using namespace mrpt::maps;
@@ -280,3 +280,146 @@ TEST(CSimplePointsMapTests, loadSaveStreams) { do_tests_loadSaveStreams<CSimpleP
280280
TEST(CWeightedPointsMapTests, loadSaveStreams) { do_tests_loadSaveStreams<CWeightedPointsMap>(); }
281281

282282
TEST(CColouredPointsMapTests, loadSaveStreams) { do_tests_loadSaveStreams<CColouredPointsMap>(); }
283+
284+
// ----------------------------------------------------------------------
285+
// Tests for CGenericPointsMap custom field capabilities
286+
// ----------------------------------------------------------------------
287+
288+
TEST(CGenericPointsMap, CustomFieldsLifecycle)
289+
{
290+
CGenericPointsMap pts;
291+
292+
// 1. Registration
293+
EXPECT_TRUE(pts.registerField_float("pressure"));
294+
EXPECT_TRUE(pts.registerField_double("timestamp"));
295+
EXPECT_TRUE(pts.registerField_uint16("class_id"));
296+
297+
// Ensure duplicate registration returns true (idempotent) or handles gracefully,
298+
// but strict check: hasPointField should be true.
299+
EXPECT_TRUE(pts.hasPointField("pressure"));
300+
EXPECT_TRUE(pts.hasPointField("timestamp"));
301+
EXPECT_TRUE(pts.hasPointField("class_id"));
302+
EXPECT_FALSE(pts.hasPointField("non_existent"));
303+
304+
// Check field name listings
305+
{
306+
const auto f_names = pts.getPointFieldNames_float();
307+
const auto d_names = pts.getPointFieldNames_double();
308+
const auto u_names = pts.getPointFieldNames_uint16();
309+
310+
// Note: "x", "y", "z" are always in float names
311+
EXPECT_NE(std::find(f_names.begin(), f_names.end(), "pressure"), f_names.end());
312+
EXPECT_NE(std::find(d_names.begin(), d_names.end(), "timestamp"), d_names.end());
313+
EXPECT_NE(std::find(u_names.begin(), u_names.end(), "class_id"), u_names.end());
314+
}
315+
316+
// 2. Insertion (Synchronized)
317+
const size_t N = 5;
318+
for (size_t i = 0; i < N; i++)
319+
{
320+
// Standard XYZ insert
321+
pts.insertPointFast(static_cast<float>(i), 0.0f, 0.0f);
322+
323+
// Custom fields insert (Must match size of XYZ)
324+
pts.insertPointField_float("pressure", static_cast<float>(i) * 10);
325+
pts.insertPointField_double("timestamp", static_cast<double>(i) * 1000.0);
326+
pts.insertPointField_uint16("class_id", static_cast<uint16_t>(i + 1));
327+
}
328+
329+
EXPECT_EQ(pts.size(), N);
330+
331+
// 3. Random Access (Getters)
332+
for (size_t i = 0; i < N; i++)
333+
{
334+
EXPECT_FLOAT_EQ(pts.getPointField_float(i, "pressure"), static_cast<float>(i * 10));
335+
EXPECT_DOUBLE_EQ(pts.getPointField_double(i, "timestamp"), static_cast<double>(i * 1000.0));
336+
EXPECT_EQ(pts.getPointField_uint16(i, "class_id"), static_cast<uint16_t>(i + 1));
337+
}
338+
339+
// 4. Random Access (Setters)
340+
pts.setPointField_float(0, "pressure", 99.9f);
341+
pts.setPointField_double(0, "timestamp", 888.88);
342+
pts.setPointField_uint16(0, "class_id", 55);
343+
344+
EXPECT_FLOAT_EQ(pts.getPointField_float(0, "pressure"), 99.9f);
345+
EXPECT_DOUBLE_EQ(pts.getPointField_double(0, "timestamp"), 888.88);
346+
EXPECT_EQ(pts.getPointField_uint16(0, "class_id"), 55);
347+
348+
// 5. Resize behavior
349+
// Resizing should resize auxiliary fields and initialize new elements to 0
350+
pts.resize(N + 2);
351+
EXPECT_EQ(pts.size(), N + 2);
352+
// Check old value preserved
353+
EXPECT_EQ(pts.getPointField_uint16(0, "class_id"), 55);
354+
// Check new value is zero-initialized
355+
EXPECT_EQ(pts.getPointField_float(N, "pressure"), 0.0f);
356+
EXPECT_EQ(pts.getPointField_uint16(N + 1, "class_id"), 0);
357+
358+
// 6. Unregistration
359+
EXPECT_TRUE(pts.unregisterField("pressure"));
360+
EXPECT_FALSE(pts.hasPointField("pressure"));
361+
// Trying to access a removed field: Returns 0 if field does not exist
362+
EXPECT_EQ(pts.getPointField_float(0, "pressure"), 0.0f);
363+
}
364+
365+
TEST(CGenericPointsMap, DeepCopy)
366+
{
367+
CGenericPointsMap pts1;
368+
pts1.registerField_float("intensity");
369+
370+
pts1.insertPointFast(1, 1, 1);
371+
pts1.insertPointField_float("intensity", 0.5f);
372+
373+
pts1.insertPointFast(2, 2, 2);
374+
pts1.insertPointField_float("intensity", 1.0f);
375+
376+
// Copy Constructor
377+
const CGenericPointsMap pts2 = pts1;
378+
379+
EXPECT_EQ(pts1.size(), pts2.size());
380+
EXPECT_TRUE(pts2.hasPointField("intensity"));
381+
EXPECT_FLOAT_EQ(pts2.getPointField_float(1, "intensity"), 1.0f);
382+
383+
// Modify original, ensure copy is independent
384+
pts1.setPointField_float(1, "intensity", 0.0f);
385+
EXPECT_FLOAT_EQ(pts1.getPointField_float(1, "intensity"), 0.0f);
386+
EXPECT_FLOAT_EQ(pts2.getPointField_float(1, "intensity"), 1.0f);
387+
}
388+
389+
TEST(CGenericPointsMap, DirectVectorAccess)
390+
{
391+
CGenericPointsMap pts;
392+
pts.registerField_float("temperature");
393+
394+
pts.resize(10);
395+
396+
// Access via reference
397+
auto* vec = pts.getPointsBufferRef_float_field("temperature");
398+
ASSERT_TRUE(vec != nullptr);
399+
ASSERT_EQ(vec->size(), 10u);
400+
401+
// Modify vector directly
402+
(*vec)[5] = 37.5f;
403+
404+
// Read back via API
405+
EXPECT_FLOAT_EQ(pts.getPointField_float(5, "temperature"), 37.5f);
406+
}
407+
408+
// Verify that standard maps (CSimplePointsMap) behave correctly (reject custom fields)
409+
TEST(CSimplePointsMapTests, RejectCustomFields)
410+
{
411+
CSimplePointsMap pts;
412+
413+
// Should return false as CSimplePointsMap doesn't support dynamic fields
414+
EXPECT_FALSE(pts.registerField_float("my_custom_float"));
415+
EXPECT_FALSE(pts.registerField_double("my_custom_double"));
416+
EXPECT_FALSE(pts.registerField_uint16("my_custom_uint"));
417+
418+
// Should return false/empty
419+
EXPECT_FALSE(pts.hasPointField("my_custom_float"));
420+
421+
// Standard fields should still work
422+
EXPECT_TRUE(pts.hasPointField("x"));
423+
EXPECT_TRUE(pts.hasPointField("y"));
424+
EXPECT_TRUE(pts.hasPointField("z"));
425+
}

0 commit comments

Comments
 (0)