FingerprintingTests.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/UnitTest/TestTypes.h>
  9. #include <AzToolsFramework/Fingerprinting/TypeFingerprinter.h>
  10. using namespace AzToolsFramework;
  11. using namespace AzToolsFramework::Fingerprinting;
  12. namespace UnitTest
  13. {
  14. class ReflectedTestClass
  15. {
  16. public:
  17. AZ_TYPE_INFO(ReflectedTestClass, "{AE55A3D4-845B-457F-94BA-A708BBDD6307}");
  18. AZ_CLASS_ALLOCATOR(ReflectedTestClass, AZ::SystemAllocator);
  19. ~ReflectedTestClass()
  20. {
  21. delete m_property1AsPointer;
  22. }
  23. int m_property1;
  24. bool m_property1AsBool;
  25. int *m_property1AsPointer = nullptr;
  26. int m_property2;
  27. static void ReflectDefault(AZ::SerializeContext& context)
  28. {
  29. context.Class<ReflectedTestClass>()
  30. ->Field("Property1", &ReflectedTestClass::m_property1);
  31. }
  32. static void ReflectHigherVersion(AZ::SerializeContext& context)
  33. {
  34. context.Class<ReflectedTestClass>()
  35. ->Version(2)
  36. ->Field("Property1", &ReflectedTestClass::m_property1);
  37. }
  38. static void ReflectRenamedProperty(AZ::SerializeContext& context)
  39. {
  40. context.Class<ReflectedTestClass>()
  41. ->Field("Property1Renamed", &ReflectedTestClass::m_property1);
  42. }
  43. static void ReflectPropertyWithDifferentType(AZ::SerializeContext& context)
  44. {
  45. context.Class<ReflectedTestClass>()
  46. ->Field("Property", &ReflectedTestClass::m_property1AsBool);
  47. }
  48. static void ReflectPropertyAsPointer(AZ::SerializeContext& context)
  49. {
  50. context.Class<ReflectedTestClass>()
  51. ->Field("Property1", &ReflectedTestClass::m_property1AsPointer);
  52. }
  53. static void ReflectTwoProperties(AZ::SerializeContext& context)
  54. {
  55. context.Class<ReflectedTestClass>()
  56. ->Field("Property1", &ReflectedTestClass::m_property1)
  57. ->Field("Property2", &ReflectedTestClass::m_property2);
  58. }
  59. };
  60. class ReflectedBaseClass
  61. {
  62. public:
  63. AZ_TYPE_INFO(ReflectedBaseClass, "{B53DC61E-6E8A-4F0A-82E4-864FA50326E5}");
  64. virtual ~ReflectedBaseClass() = default;
  65. static void ReflectDefault(AZ::SerializeContext& context)
  66. {
  67. context.Class<ReflectedBaseClass>();
  68. }
  69. };
  70. class ReflectedSubClass : public ReflectedBaseClass
  71. {
  72. public:
  73. AZ_TYPE_INFO(ReflectedSubClass, "{B95E143C-D97E-44F3-8F38-BAB6F317A03C}");
  74. static void ReflectWithInheritance(AZ::SerializeContext& context)
  75. {
  76. context.Class<ReflectedSubClass, ReflectedBaseClass>();
  77. }
  78. static void ReflectWithoutInheritance(AZ::SerializeContext& context)
  79. {
  80. context.Class<ReflectedSubClass>();
  81. }
  82. };
  83. class ReflectedClassWithPointer
  84. {
  85. public:
  86. AZ_TYPE_INFO(ReflectedClassWithPointer, "{03DE24B9-288B-41B5-952D-4749F8F400D2}");
  87. ~ReflectedClassWithPointer()
  88. {
  89. delete m_pointer;
  90. }
  91. ReflectedTestClass* m_pointer = nullptr;
  92. static void Reflect(AZ::SerializeContext& context)
  93. {
  94. context.Class<ReflectedClassWithPointer>()
  95. ->Field("Pointer", &ReflectedClassWithPointer::m_pointer);
  96. }
  97. };
  98. using FingerprintTests = UnitTest::LeakDetectionFixture;
  99. TEST_F(FingerprintTests, IntFingerprint_IsValid)
  100. {
  101. AZ::SerializeContext serializeContext;
  102. TypeFingerprinter fingerprinter{ serializeContext };
  103. EXPECT_NE(InvalidTypeFingerprint, fingerprinter.GetFingerprint<int>());
  104. }
  105. TEST_F(FingerprintTests, ClassFingerprint_IsValid)
  106. {
  107. AZ::SerializeContext serializeContext;
  108. ReflectedTestClass::ReflectDefault(serializeContext);
  109. TypeFingerprinter fingerprinter{ serializeContext };
  110. EXPECT_NE(InvalidTypeFingerprint, fingerprinter.GetFingerprint<ReflectedTestClass>());
  111. }
  112. TEST_F(FingerprintTests, ClassWithNewVersionNumber_ChangesFingerprint)
  113. {
  114. AZ::SerializeContext serializeContext1;
  115. ReflectedTestClass::ReflectDefault(serializeContext1);
  116. TypeFingerprinter fingerprinter1{ serializeContext1 };
  117. AZ::SerializeContext serializeContext2;
  118. ReflectedTestClass::ReflectHigherVersion(serializeContext2);
  119. TypeFingerprinter fingerprinter2{ serializeContext2 };
  120. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedTestClass>(), fingerprinter2.GetFingerprint<ReflectedTestClass>());
  121. }
  122. TEST_F(FingerprintTests, ClassWithRenamedProperty_ChangesFingerprint)
  123. {
  124. AZ::SerializeContext serializeContext1;
  125. ReflectedTestClass::ReflectDefault(serializeContext1);
  126. TypeFingerprinter fingerprinter1{ serializeContext1 };
  127. AZ::SerializeContext serializeContext2;
  128. ReflectedTestClass::ReflectRenamedProperty(serializeContext2);
  129. TypeFingerprinter fingerprinter2{ serializeContext2 };
  130. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedTestClass>(), fingerprinter2.GetFingerprint<ReflectedTestClass>());
  131. }
  132. TEST_F(FingerprintTests, ClassWithPropertyThatChangesType_ChangesFingerprint)
  133. {
  134. AZ::SerializeContext serializeContext1;
  135. ReflectedTestClass::ReflectDefault(serializeContext1);
  136. TypeFingerprinter fingerprinter1{ serializeContext1 };
  137. AZ::SerializeContext serializeContext2;
  138. ReflectedTestClass::ReflectPropertyWithDifferentType(serializeContext2);
  139. TypeFingerprinter fingerprinter2{ serializeContext2 };
  140. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedTestClass>(), fingerprinter2.GetFingerprint<ReflectedTestClass>());
  141. }
  142. TEST_F(FingerprintTests, ClassWithPropertyThatChangesToPointer_ChangesFingerprint)
  143. {
  144. AZ::SerializeContext serializeContext1;
  145. ReflectedTestClass::ReflectDefault(serializeContext1);
  146. TypeFingerprinter fingerprinter1{ serializeContext1 };
  147. AZ::SerializeContext serializeContext2;
  148. ReflectedTestClass::ReflectPropertyAsPointer(serializeContext2);
  149. TypeFingerprinter fingerprinter2{ serializeContext2 };
  150. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedTestClass>(), fingerprinter2.GetFingerprint<ReflectedTestClass>());
  151. }
  152. TEST_F(FingerprintTests, ClassWithNewProperty_ChangesFingerprint)
  153. {
  154. AZ::SerializeContext serializeContext1;
  155. ReflectedTestClass::ReflectDefault(serializeContext1);
  156. TypeFingerprinter fingerprinter1{ serializeContext1 };
  157. AZ::SerializeContext serializeContext2;
  158. ReflectedTestClass::ReflectTwoProperties(serializeContext2);
  159. TypeFingerprinter fingerprinter2{ serializeContext2 };
  160. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedTestClass>(), fingerprinter2.GetFingerprint<ReflectedTestClass>());
  161. }
  162. TEST_F(FingerprintTests, ClassGainingBaseClass_ChangesFingerprint)
  163. {
  164. AZ::SerializeContext serializeContext1;
  165. ReflectedBaseClass::ReflectDefault(serializeContext1);
  166. ReflectedSubClass::ReflectWithoutInheritance(serializeContext1);
  167. TypeFingerprinter fingerprinter1{ serializeContext1 };
  168. AZ::SerializeContext serializeContext2;
  169. ReflectedBaseClass::ReflectDefault(serializeContext2);
  170. ReflectedSubClass::ReflectWithInheritance(serializeContext2);
  171. TypeFingerprinter fingerprinter2{ serializeContext2 };
  172. EXPECT_NE(fingerprinter1.GetFingerprint<ReflectedSubClass>(), fingerprinter2.GetFingerprint<ReflectedSubClass>());
  173. }
  174. TEST_F(FingerprintTests, GatherAllTypesInObject_FindsCorrectTypes)
  175. {
  176. AZ::SerializeContext serializeContext;
  177. ReflectedTestClass::ReflectDefault(serializeContext);
  178. TypeFingerprinter fingerprinter{ serializeContext };
  179. ReflectedTestClass object;
  180. TypeCollection typesInObject;
  181. fingerprinter.GatherAllTypesInObject(&object, typesInObject);
  182. EXPECT_EQ(2, typesInObject.size());
  183. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<int>::GetUuid()));
  184. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedTestClass>::GetUuid()));
  185. }
  186. TEST_F(FingerprintTests, GatherAllTypesInObjectWithBaseClass_FindsCorrectTypes)
  187. {
  188. AZ::SerializeContext serializeContext;
  189. ReflectedBaseClass::ReflectDefault(serializeContext);
  190. ReflectedSubClass::ReflectWithInheritance(serializeContext);
  191. TypeFingerprinter fingerprinter{ serializeContext };
  192. ReflectedSubClass object;
  193. TypeCollection typesInObject;
  194. fingerprinter.GatherAllTypesInObject(&object, typesInObject);
  195. EXPECT_EQ(2, typesInObject.size());
  196. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedSubClass>::GetUuid()));
  197. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedBaseClass>::GetUuid()));
  198. }
  199. TEST_F(FingerprintTests, GatherTypesInObjectWithNullPointer_FindsCorrectTypes)
  200. {
  201. AZ::SerializeContext serializeContext;
  202. ReflectedClassWithPointer::Reflect(serializeContext);
  203. ReflectedTestClass::ReflectDefault(serializeContext);
  204. TypeFingerprinter fingerprinter{ serializeContext };
  205. ReflectedClassWithPointer classWithPointer;
  206. classWithPointer.m_pointer = nullptr;
  207. TypeCollection typesInObject;
  208. fingerprinter.GatherAllTypesInObject(&classWithPointer, typesInObject);
  209. // shouldn't gather types from ReflectedTestClass, since m_pointer is null
  210. EXPECT_EQ(1, typesInObject.size());
  211. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedClassWithPointer>::GetUuid()));
  212. }
  213. TEST_F(FingerprintTests, GatherTypesInObjectWithValidPointer_FindsCorrectTypes)
  214. {
  215. AZ::SerializeContext serializeContext;
  216. ReflectedClassWithPointer::Reflect(serializeContext);
  217. ReflectedTestClass::ReflectDefault(serializeContext);
  218. TypeFingerprinter fingerprinter{ serializeContext };
  219. ReflectedClassWithPointer classWithPointer;
  220. classWithPointer.m_pointer = aznew ReflectedTestClass();
  221. TypeCollection typesInObject;
  222. fingerprinter.GatherAllTypesInObject(&classWithPointer, typesInObject);
  223. // should have followed m_pointer and gathered types from ReflectedTestClass
  224. EXPECT_EQ(3, typesInObject.size());
  225. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedClassWithPointer>::GetUuid()));
  226. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<ReflectedTestClass>::GetUuid()));
  227. EXPECT_EQ(1, typesInObject.count(AZ::SerializeTypeInfo<int>::GetUuid()));
  228. }
  229. TEST_F(FingerprintTests, GenerateFingerprintForAllTypesInObject_Works)
  230. {
  231. AZ::SerializeContext serializeContext;
  232. ReflectedTestClass::ReflectDefault(serializeContext);
  233. TypeFingerprinter fingerprinter{ serializeContext };
  234. ReflectedTestClass object;
  235. EXPECT_NE(InvalidTypeFingerprint, fingerprinter.GenerateFingerprintForAllTypesInObject(&object));
  236. }
  237. } // namespace UnitTest