metadata_unittest.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <string>
  5. #include "base/bind.h"
  6. #include "base/callback_list.h"
  7. #include "base/strings/string_number_conversions.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. #include "testing/platform_test.h"
  10. #include "ui/base/class_property.h"
  11. #include "ui/base/metadata/metadata_header_macros.h"
  12. #include "ui/base/metadata/metadata_impl_macros.h"
  13. #include "ui/base/metadata/metadata_types.h"
  14. #include "ui/gfx/geometry/insets.h"
  15. namespace UM = ui::metadata;
  16. class MetadataTest : public PlatformTest {
  17. public:
  18. MetadataTest() = default;
  19. ~MetadataTest() override = default;
  20. bool float_property_changed() const { return float_property_changed_; }
  21. void OnFloatPropertyChanged() { float_property_changed_ = true; }
  22. protected:
  23. template <typename T>
  24. UM::MemberMetaDataBase* GetMemberMetaData(T* obj,
  25. const std::string& member_name) {
  26. UM::ClassMetaData* meta_data = obj->GetClassMetaData();
  27. if (meta_data == nullptr)
  28. return nullptr;
  29. UM::MemberMetaDataBase* member_data =
  30. meta_data->FindMemberData(member_name);
  31. return member_data;
  32. }
  33. private:
  34. bool float_property_changed_ = false;
  35. };
  36. // Base class in which a simple hierarchy is created for testing metadata
  37. // iteration across class types.
  38. class MetadataTestBaseClass : public ui::metadata::MetaDataProvider,
  39. public ui::PropertyHandler {
  40. public:
  41. MetadataTestBaseClass() = default;
  42. ~MetadataTestBaseClass() override = default;
  43. METADATA_HEADER_BASE(MetadataTestBaseClass);
  44. void SetIntProperty(int new_value) {
  45. if (new_value == int_property_)
  46. return;
  47. int_property_ = new_value;
  48. TriggerChangedCallback(&int_property_);
  49. }
  50. int GetIntProperty() const { return int_property_; }
  51. [[nodiscard]] base::CallbackListSubscription AddIntPropertyChangedCallback(
  52. ui::metadata::PropertyChangedCallback callback) {
  53. return AddPropertyChangedCallback(&int_property_, std::move(callback));
  54. }
  55. private:
  56. int int_property_ = 0;
  57. };
  58. BEGIN_METADATA_BASE(MetadataTestBaseClass)
  59. ADD_PROPERTY_METADATA(int, IntProperty)
  60. END_METADATA
  61. // Descendent class in the simple hierarchy. The inherited properties are
  62. // visible within the metadata.
  63. class MetadataTestClass : public MetadataTestBaseClass {
  64. public:
  65. MetadataTestClass() = default;
  66. ~MetadataTestClass() override = default;
  67. METADATA_HEADER(MetadataTestClass);
  68. void SetFloatProperty(float new_value) {
  69. if (float_property_ == new_value)
  70. return;
  71. float_property_ = new_value;
  72. TriggerChangedCallback(&float_property_);
  73. }
  74. float GetFloatProperty() const { return float_property_; }
  75. [[nodiscard]] base::CallbackListSubscription AddFloatPropertyChangedCallback(
  76. ui::metadata::PropertyChangedCallback callback) {
  77. return AddPropertyChangedCallback(&float_property_, std::move(callback));
  78. }
  79. private:
  80. float float_property_ = 0.f;
  81. };
  82. BEGIN_METADATA(MetadataTestClass, MetadataTestBaseClass)
  83. ADD_PROPERTY_METADATA(float, FloatProperty)
  84. END_METADATA
  85. // Test view to which class properties are attached.
  86. class ClassPropertyMetaDataTestClass : public MetadataTestBaseClass {
  87. public:
  88. ClassPropertyMetaDataTestClass() = default;
  89. ~ClassPropertyMetaDataTestClass() override = default;
  90. METADATA_HEADER(ClassPropertyMetaDataTestClass);
  91. };
  92. DEFINE_UI_CLASS_PROPERTY_KEY(int, kIntKey, -1)
  93. DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Insets, kOwnedInsetsKey1, nullptr)
  94. DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Insets, kOwnedInsetsKey2, nullptr)
  95. DEFINE_UI_CLASS_PROPERTY_KEY(gfx::Insets*, kInsetsKey1, nullptr)
  96. DEFINE_UI_CLASS_PROPERTY_KEY(gfx::Insets*, kInsetsKey2, nullptr)
  97. DEFINE_UI_CLASS_PROPERTY_TYPE(gfx::Insets*)
  98. BEGIN_METADATA(ClassPropertyMetaDataTestClass, MetadataTestBaseClass)
  99. ADD_CLASS_PROPERTY_METADATA(int, kIntKey)
  100. ADD_CLASS_PROPERTY_METADATA(gfx::Insets, kOwnedInsetsKey1)
  101. ADD_CLASS_PROPERTY_METADATA(gfx::Insets*, kOwnedInsetsKey2)
  102. ADD_CLASS_PROPERTY_METADATA(gfx::Insets, kInsetsKey1)
  103. ADD_CLASS_PROPERTY_METADATA(gfx::Insets*, kInsetsKey2)
  104. END_METADATA
  105. TEST_F(MetadataTest, TestFloatMetadataPropertyAccess) {
  106. const float start_value = 12.34f;
  107. MetadataTestClass test_obj;
  108. test_obj.SetFloatProperty(start_value);
  109. UM::MemberMetaDataBase* member_data =
  110. GetMemberMetaData(&test_obj, "FloatProperty");
  111. ASSERT_TRUE(member_data);
  112. std::u16string member_value = member_data->GetValueAsString(&test_obj);
  113. EXPECT_EQ(member_value, base::NumberToString16(start_value));
  114. }
  115. TEST_F(MetadataTest, TestFloatPropertyChangedCallback) {
  116. const float start_value = 12.34f;
  117. MetadataTestClass test_obj;
  118. base::CallbackListSubscription callback =
  119. test_obj.AddFloatPropertyChangedCallback(base::BindRepeating(
  120. &MetadataTest::OnFloatPropertyChanged, base::Unretained(this)));
  121. UM::MemberMetaDataBase* member_data =
  122. GetMemberMetaData(&test_obj, "FloatProperty");
  123. ASSERT_TRUE(member_data);
  124. member_data->SetValueAsString(&test_obj, base::NumberToString16(start_value));
  125. EXPECT_TRUE(float_property_changed());
  126. std::u16string member_value = member_data->GetValueAsString(&test_obj);
  127. EXPECT_EQ(member_value, base::NumberToString16(start_value));
  128. }
  129. TEST_F(MetadataTest, TestMetaDataParentClassTracking) {
  130. UM::ClassMetaData* base_class_meta_data = MetadataTestBaseClass::MetaData();
  131. UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
  132. EXPECT_EQ(base_class_meta_data,
  133. derived_class_meta_data->parent_class_meta_data());
  134. }
  135. TEST_F(MetadataTest, TestMetaDataFindParentClassMember) {
  136. UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
  137. UM::MemberMetaDataBase* member_data =
  138. derived_class_meta_data->FindMemberData("IntProperty");
  139. EXPECT_NE(member_data, nullptr);
  140. }
  141. TEST_F(MetadataTest, TestMetaDataMemberIterator) {
  142. UM::ClassMetaData* derived_class_meta_data = MetadataTestClass::MetaData();
  143. std::string derived_class_member_name = "IntProperty";
  144. bool found_derived_class_member = false;
  145. std::string base_class_member_name = "IntProperty";
  146. bool found_base_class_member = false;
  147. for (UM::MemberMetaDataBase* member_data : *derived_class_meta_data) {
  148. if (member_data->member_name() == derived_class_member_name)
  149. found_derived_class_member = true;
  150. if (member_data->member_name() == base_class_member_name)
  151. found_base_class_member = true;
  152. }
  153. EXPECT_TRUE(found_derived_class_member);
  154. EXPECT_TRUE(found_base_class_member);
  155. }
  156. TEST_F(MetadataTest, TestTypeCacheContainsTestClass) {
  157. UM::MetaDataCache* cache = UM::MetaDataCache::GetInstance();
  158. ASSERT_TRUE(cache != nullptr);
  159. UM::ClassMetaData* test_class_meta = MetadataTestClass::MetaData();
  160. const auto& cache_meta = cache->GetCachedTypes();
  161. EXPECT_NE(std::find(cache_meta.begin(), cache_meta.end(), test_class_meta),
  162. cache_meta.end());
  163. }
  164. TEST_F(MetadataTest, TestMetaDataFile) {
  165. UM::ClassMetaData* metadata = MetadataTestBaseClass::MetaData();
  166. #if defined(__clang__) && defined(_MSC_VER)
  167. EXPECT_EQ(metadata->file(), "ui\\base\\metadata\\metadata_unittest.cc");
  168. #else
  169. EXPECT_EQ(metadata->file(), "ui/base/metadata/metadata_unittest.cc");
  170. #endif
  171. }
  172. TEST_F(MetadataTest, TestClassPropertyMetaData) {
  173. ClassPropertyMetaDataTestClass test_class;
  174. gfx::Insets insets1(8), insets2 = insets1;
  175. std::map<std::string, std::u16string> expected_kv = {
  176. {"kIntKey", u"-1"},
  177. {"kOwnedInsetsKey1", u"(not assigned)"},
  178. {"kOwnedInsetsKey2", u"(not assigned)"},
  179. {"kInsetsKey1", u"(not assigned)"},
  180. {"kInsetsKey2", u"(not assigned)"}};
  181. auto verify = [&]() {
  182. ui::metadata::ClassMetaData* metadata = test_class.GetClassMetaData();
  183. for (auto member = metadata->begin(); member != metadata->end(); member++) {
  184. std::string key = (*member)->member_name();
  185. if (expected_kv.count(key)) {
  186. EXPECT_EQ((*member)->GetValueAsString(&test_class), expected_kv[key]);
  187. expected_kv.erase(key);
  188. }
  189. }
  190. EXPECT_TRUE(expected_kv.empty());
  191. };
  192. verify();
  193. test_class.SetProperty(kIntKey, 1);
  194. test_class.SetProperty(kOwnedInsetsKey1, insets1);
  195. test_class.SetProperty(kOwnedInsetsKey2, insets1);
  196. test_class.SetProperty(kInsetsKey1, &insets1);
  197. test_class.SetProperty(kInsetsKey2, &insets2);
  198. expected_kv = {{"kIntKey", u"1"},
  199. {"kOwnedInsetsKey1", u"8,8,8,8"},
  200. {"kOwnedInsetsKey2", u"(assigned)"},
  201. {"kInsetsKey1", u"8,8,8,8"},
  202. {"kInsetsKey2", u"(assigned)"}};
  203. verify();
  204. }