46 TestWidget(
const std::string&
name ) : m_name(
name )
48 SetProperty(
"widget_name",
name );
49 SetProperty(
"default_enabled",
true );
52 const std::string& GetName()
const {
return m_name; }
66 CustomData(
int v,
const std::string& t ) : value( v ), text( t ) {}
68 bool operator==(
const CustomData& other )
const
70 return value == other.value && text == other.text;
77struct PROPERTY_HOLDER_TEST_FIXTURE
79 PROPERTY_HOLDER_TEST_FIXTURE()
82 m_populatedHolder.SetProperty(
"bool_prop",
true );
83 m_populatedHolder.SetProperty(
"int_prop", 42 );
84 m_populatedHolder.SetProperty(
"double_prop", 3.14159 );
85 m_populatedHolder.SetProperty(
"string_prop", std::string(
"hello world" ) );
86 m_populatedHolder.SetProperty(
"cstring_prop",
"c-style string" );
89 m_populatedHolder.SetProperty(
"custom_prop", CustomData( 100,
"custom" ) );
92 std::vector<int> numbers = { 1, 2, 3, 4, 5 };
93 m_populatedHolder.SetProperty(
"vector_prop", numbers );
96 PROPERTY_HOLDER m_emptyHolder;
97 PROPERTY_HOLDER m_populatedHolder;
105BOOST_FIXTURE_TEST_SUITE( TEST_PROPERTY_HOLDER, PROPERTY_HOLDER_TEST_FIXTURE )
118 holder.
SetProperty(
"test_string", std::string(
"test value" ) );
121 auto boolResult = holder.
GetProperty<
bool>(
"test_bool" );
122 BOOST_CHECK( boolResult.has_value() );
125 auto intResult = holder.
GetProperty<
int>(
"test_int" );
126 BOOST_CHECK( intResult.has_value() );
129 auto doubleResult = holder.
GetProperty<
double>(
"test_double" );
130 BOOST_CHECK( doubleResult.has_value() );
131 BOOST_CHECK_CLOSE( *doubleResult, 2.71828, 0.0001 );
133 auto stringResult = holder.
GetProperty<std::string>(
"test_string" );
134 BOOST_CHECK( stringResult.has_value() );
147 auto intResult = holder.
GetProperty<
int>(
"int_value" );
148 BOOST_CHECK( intResult.has_value() );
152 auto stringResult = holder.
GetProperty<std::string>(
"int_value" );
153 BOOST_CHECK( !stringResult.has_value() );
155 auto doubleResult = holder.
GetProperty<
double>(
"int_value" );
156 BOOST_CHECK( !doubleResult.has_value() );
158 auto boolResult = holder.
GetProperty<
bool>(
"int_value" );
159 BOOST_CHECK( !boolResult.has_value() );
171 int existingValue = holder.
GetPropertyOr(
"existing_prop", 999 );
175 int nonExistingValue = holder.
GetPropertyOr(
"missing_prop", 777 );
179 std::string wrongTypeValue = holder.
GetPropertyOr<std::string>(
"existing_prop",
"default" );
183 bool defaultBool = holder.
GetPropertyOr(
"missing_bool",
false );
186 std::string defaultString = holder.
GetPropertyOr<std::string>(
"missing_string",
"fallback" );
199 BOOST_CHECK( m_populatedHolder.HasProperty(
"bool_prop" ) );
200 BOOST_CHECK( m_populatedHolder.HasProperty(
"int_prop" ) );
201 BOOST_CHECK( m_populatedHolder.HasProperty(
"string_prop" ) );
211 BOOST_CHECK( m_populatedHolder.HasPropertyOfType<
bool>(
"bool_prop" ) );
212 BOOST_CHECK( m_populatedHolder.HasPropertyOfType<
int>(
"int_prop" ) );
213 BOOST_CHECK( m_populatedHolder.HasPropertyOfType<
double>(
"double_prop" ) );
214 BOOST_CHECK( m_populatedHolder.HasPropertyOfType<std::string>(
"string_prop" ) );
217 BOOST_CHECK_EQUAL(
false, m_populatedHolder.HasPropertyOfType<
int>(
"bool_prop" ) );
218 BOOST_CHECK_EQUAL(
false, m_populatedHolder.HasPropertyOfType<
bool>(
"int_prop" ) );
219 BOOST_CHECK_EQUAL(
false, m_populatedHolder.HasPropertyOfType<std::string>(
"int_prop" ) );
222 BOOST_CHECK_EQUAL(
false, m_populatedHolder.HasPropertyOfType<
bool>(
"missing_prop" ) );
239 BOOST_CHECK( removed );
264 BOOST_CHECK( holder.
Empty() );
277 BOOST_CHECK( m_emptyHolder.Empty() );
284 m_populatedHolder.SetProperty(
"new_prop", 999 );
288 m_populatedHolder.RemoveProperty(
"new_prop" );
306 std::sort( keys.begin(), keys.end() );
307 std::vector<std::string>
expected = {
"key1",
"key2",
"key3" };
310 BOOST_CHECK_EQUAL_COLLECTIONS( keys.begin(), keys.end(),
expected.begin(),
expected.end() );
313 auto emptyKeys = m_emptyHolder.GetKeys();
324 holder.
SetProperty(
"string_val", std::string(
"hello" ) );
328 BOOST_CHECK( intTypeInfo.has_value() );
329 BOOST_CHECK( intTypeInfo->get() ==
typeid(
int ) );
332 BOOST_CHECK( stringTypeInfo.has_value() );
333 BOOST_CHECK( stringTypeInfo->get() ==
typeid( std::string ) );
337 BOOST_CHECK( !missingTypeInfo.has_value() );
348 CustomData original( 123,
"test data" );
352 auto retrieved = holder.
GetProperty<CustomData>(
"custom" );
353 BOOST_CHECK( retrieved.has_value() );
354 BOOST_CHECK( *retrieved == original );
357 std::vector<std::string> stringVec = {
"one",
"two",
"three" };
360 auto vecRetrieved = holder.
GetProperty<std::vector<std::string>>(
"string_vector" );
361 BOOST_CHECK( vecRetrieved.has_value() );
362 BOOST_CHECK_EQUAL_COLLECTIONS( vecRetrieved->begin(), vecRetrieved->end(),
363 stringVec.begin(), stringVec.end() );
366 auto smartPtr = std::make_shared<int>( 456 );
369 auto ptrRetrieved = holder.
GetProperty<std::shared_ptr<int>>(
"smart_ptr" );
370 BOOST_CHECK( ptrRetrieved.has_value() );
393 holder.
SetProperty(
"changeable", std::string(
"now a string" ) );
398 auto intResult = holder.
GetProperty<
int>(
"changeable" );
399 BOOST_CHECK( !intResult.has_value() );
414 TestWidget widget(
"test_widget" );
417 BOOST_CHECK_EQUAL( widget.GetPropertyOr<std::string>(
"widget_name",
"" ),
"test_widget" );
421 widget.SetProperty(
"runtime_prop", 42 );
425 BOOST_CHECK( widget.HasProperty(
"widget_name" ) );
426 BOOST_CHECK( widget.HasProperty(
"default_enabled" ) );
427 BOOST_CHECK( widget.HasProperty(
"runtime_prop" ) );
436 TestWidget widget1(
"widget1" );
437 TestWidget widget2(
"widget2" );
440 widget1.SetProperty(
"unique_to_1", 100 );
441 widget2.SetProperty(
"unique_to_2", 200 );
450 BOOST_CHECK_EQUAL( widget1.GetPropertyOr<std::string>(
"widget_name",
"" ),
"widget1" );
451 BOOST_CHECK_EQUAL( widget2.GetPropertyOr<std::string>(
"widget_name",
"" ),
"widget2" );
459 TestWidget widget(
"access_test" );
470 BOOST_CHECK( constHolder.
HasProperty(
"widget_name" ) );
471 auto keys = constHolder.
GetKeys();
472 BOOST_CHECK( keys.size() >= 2 );
495 std::string longKey( 1000,
'x' );
508 std::vector<int> bigVector( 1000, 42 );
509 holder.
SetProperty(
"big_vector", std::move( bigVector ) );
512 auto retrieved = holder.
GetProperty<std::vector<int>>(
"big_vector" );
513 BOOST_CHECK( retrieved.has_value() );
527 BOOST_CHECK( !
result.has_value() );
531 BOOST_CHECK( !emptyResult.has_value() );
535 BOOST_CHECK( !typeInfo.has_value() );
556 BOOST_CHECK( holder.
IsValid() );
575 void* clientData =
static_cast<void*
>( original );
579 BOOST_CHECK_NE(
nullptr, casted );
580 BOOST_CHECK( casted->
IsValid() );
587 const void* constClientData =
static_cast<const void*
>( original );
589 BOOST_CHECK_NE(
nullptr, constCasted );
590 BOOST_CHECK( constCasted->
IsValid() );
606 uint64_t randomValue = 12345;
607 void* randomPtr = &randomValue;
612 uint64_t wrong_magic = 0x1234567890ABCDEFULL;
617 void* fakePtr = &fake;
631#if defined( __has_feature )
632 #if __has_feature( address_sanitizer ) || __has_feature( thread_sanitizer )
633 #define KICAD_ASAN_ENABLED 1
637#if defined( __SANITIZE_ADDRESS__ ) || defined( __SANITIZE_THREAD__ )
638 #define KICAD_ASAN_ENABLED 1
641#ifndef KICAD_ASAN_ENABLED
648 BOOST_CHECK( holder->
IsValid() );
650 void* ptr =
static_cast<void*
>( holder );
661#undef KICAD_ASAN_ENABLED
669 BOOST_CHECK_NE(
nullptr, holder );
670 BOOST_CHECK( holder->
IsValid() );
673 BOOST_CHECK( holder->
SetProperty(
"client_test", 999 ) );
681 uint64_t randomData = 42;
693 BOOST_CHECK( original.
IsValid() );
697 BOOST_CHECK(
copied.IsValid() );
702 BOOST_CHECK(
moved.IsValid() );
706 BOOST_CHECK( original.
IsValid() );
720 BOOST_CHECK( source.
IsValid() );
721 BOOST_CHECK( target.
IsValid() );
725 BOOST_CHECK( target.
IsValid() );
733 target = std::move( another );
734 BOOST_CHECK( target.
IsValid() );
736 BOOST_CHECK( another.
IsValid() );
745 struct FakePropertyHolder {
746 uint64_t wrong_magic = 0xDEADBEEF;
747 std::unordered_map<std::string, std::any> fake_properties;
750 FakePropertyHolder fake;
760 BOOST_CHECK( fakeHolder->
Empty() );
766 BOOST_CHECK( !
result.has_value() );
773 BOOST_CHECK( !typeInfo.has_value() );
bool operator==(const wxAuiPaneInfo &aLhs, const wxAuiPaneInfo &aRhs)
bool SetProperty(const std::string &aKey, T &&aValue)
Set a property with the given key and value.
static bool SafeDelete(void *aPtr) noexcept
Safely delete a PROPERTY_HOLDER from client data.
std::optional< std::reference_wrapper< const std::type_info > > GetPropertyType(const std::string &aKey) const
Get the type information for a property.
bool Empty() const
Check if there are no properties stored.
std::vector< std::string > GetKeys() const
Get all property keys.
static PROPERTY_HOLDER * SafeCast(void *aPtr) noexcept
Safely cast a void pointer to PROPERTY_HOLDER*.
bool RemoveProperty(const std::string &aKey)
Remove a property.
static constexpr uint64_t MAGIC_VALUE
Magic value for memory validation (ASCII: "PROP" + "HLDR")
std::optional< T > GetProperty(const std::string &aKey) const
Get a property value with type checking.
T GetPropertyOr(const std::string &aKey, T &&aDefaultValue) const
Get a property value with a default fallback.
bool HasPropertyOfType(const std::string &aKey) const
Check if a property exists and has the expected type.
bool HasProperty(const std::string &aKey) const
Check if a property exists.
bool IsValid() const noexcept
Check if this instance has a valid magic value.
bool Clear()
Clear all properties.
size_t Size() const
Get the number of stored properties.
Mixin class to add property support to any class.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
VECTOR3I expected(15, 30, 45)
BOOST_AUTO_TEST_CASE(BasicSetGet)
Declare the test suite.
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")