SettingsRegistryScriptUtilsTests.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  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/RTTI/BehaviorContext.h>
  9. #include <AzCore/Settings/SettingsRegistryImpl.h>
  10. #include <AzCore/Settings/SettingsRegistryScriptUtils.h>
  11. #include <AzCore/UnitTest/TestTypes.h>
  12. #include <AzCore/std/containers/variant.h>
  13. namespace SettingsRegistryScriptUtilsTests
  14. {
  15. static constexpr const char* SettingsRegistryScriptClassName = "SettingsRegistryInterface";
  16. class SettingsRegistryBehaviorContextFixture
  17. : public UnitTest::LeakDetectionFixture
  18. {
  19. public:
  20. void SetUp() override
  21. {
  22. m_registry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
  23. m_behaviorContext = AZStd::make_unique<AZ::BehaviorContext>();
  24. AZ::SettingsRegistryScriptUtils::ReflectSettingsRegistryToBehaviorContext(*m_behaviorContext);
  25. }
  26. void TearDown() override
  27. {
  28. m_behaviorContext.reset();
  29. m_registry.reset();
  30. }
  31. AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_registry;
  32. AZStd::unique_ptr<AZ::BehaviorContext> m_behaviorContext;
  33. };
  34. TEST_F(SettingsRegistryBehaviorContextFixture, CreateSettingsRegistryImpl_BehaviorClassCreate_Succeeds)
  35. {
  36. // Create a Settings Registry Interface Proxy Object
  37. static constexpr const char* SettingsRegistryCreateMethodName = "SettingsRegistry";
  38. // Lookup SettingsRegistry() method on the BehaviorContext
  39. const auto createSettingsRegistryIter = m_behaviorContext->m_methods.find(SettingsRegistryCreateMethodName);
  40. ASSERT_NE(m_behaviorContext->m_methods.end(), createSettingsRegistryIter);
  41. AZ::BehaviorMethod* settingsRegistryCreate = createSettingsRegistryIter->second;
  42. ASSERT_NE(nullptr, settingsRegistryCreate);
  43. using SettingsRegistryScriptProxy = AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy;
  44. SettingsRegistryScriptProxy settingsRegistryObject;
  45. EXPECT_TRUE(settingsRegistryCreate->InvokeResult(settingsRegistryObject));
  46. EXPECT_NE(nullptr, settingsRegistryObject.m_settingsRegistry);
  47. }
  48. TEST_F(SettingsRegistryBehaviorContextFixture, GlobalSettingsRegistry_CanBeQueried_Succeeds)
  49. {
  50. constexpr const char* GlobalSettingsRegistryPropertyName = "g_SettingsRegistry";
  51. auto propIt = m_behaviorContext->m_properties.find(GlobalSettingsRegistryPropertyName);
  52. ASSERT_NE(m_behaviorContext->m_properties.end(), propIt);
  53. AZ::BehaviorMethod* globalSettingsRegistryGetter = propIt->second->m_getter;
  54. ASSERT_NE(nullptr, globalSettingsRegistryGetter);
  55. // Create a Settings Registry Interface Proxy Object
  56. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  57. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  58. AZ::BehaviorClass* settingsRegistryClass = classIter->second;
  59. ASSERT_NE(nullptr, settingsRegistryClass);
  60. using SettingsRegistryScriptProxy = AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy;
  61. SettingsRegistryScriptProxy settingsRegistryObject;
  62. // Check if the Proxy Object wraps a valid Settings Registry
  63. // No global settings registry should be registered at this point
  64. // so the invoking the getter on global Settings Registry should succeed, but return nullptr
  65. EXPECT_TRUE(globalSettingsRegistryGetter->InvokeResult(settingsRegistryObject));
  66. EXPECT_EQ(nullptr, settingsRegistryObject.m_settingsRegistry);
  67. // Register the Settings Registry stored on the fixture with the SettingsRegistry Interface<T>
  68. AZ::SettingsRegistry::Register(m_registry.get());
  69. EXPECT_TRUE(globalSettingsRegistryGetter->InvokeResult(settingsRegistryObject));
  70. EXPECT_NE(nullptr, settingsRegistryObject.m_settingsRegistry);
  71. AZ::SettingsRegistry::Unregister(m_registry.get());
  72. }
  73. TEST_F(SettingsRegistryBehaviorContextFixture, MergeJsonString_UsingBehaviorContext_Succeeds)
  74. {
  75. constexpr const char* MergeSettingMethodName = "MergeSettings";
  76. constexpr AZStd::string_view TestJsonString =
  77. R"({)" "\n"
  78. R"( "TestObject" : {)" "\n"
  79. R"( "boolValue" : false,)" "\n"
  80. R"( "intValue" : 17,)" "\n"
  81. R"( "floatValue" : 32.0,)" "\n"
  82. R"( "stringValue" : "Hello World")" "\n"
  83. R"( },)" "\n"
  84. R"( "TestArray" : [)" "\n"
  85. R"( {)" "\n"
  86. R"( "intIndex" : 3)" "\n"
  87. R"( },)" "\n"
  88. R"( {)" "\n"
  89. R"( "intIndex" : -55)" "\n"
  90. R"( })" "\n"
  91. R"( ])" "\n"
  92. R"(})" "\n";
  93. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  94. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  95. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  96. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  97. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(MergeSettingMethodName);
  98. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  99. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  100. bool mergeSettingsResult{};
  101. // Pass in both the json data string and the patch format argument
  102. EXPECT_TRUE(foundIt->second->InvokeResult(mergeSettingsResult, &settingsRegistryObject,
  103. TestJsonString, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
  104. EXPECT_TRUE(mergeSettingsResult);
  105. mergeSettingsResult = {};
  106. // Pass in only the json data string without the patch format argument which should use the default value
  107. EXPECT_TRUE(foundIt->second->InvokeResult(mergeSettingsResult, &settingsRegistryObject, TestJsonString));
  108. EXPECT_TRUE(mergeSettingsResult);
  109. // Query the Settings Registry for the Merged Content
  110. {
  111. // Retrieve
  112. auto settingsRegistry = m_registry.get();
  113. bool boolValue = true;
  114. EXPECT_TRUE(settingsRegistry->Get(boolValue, "/TestObject/boolValue"));
  115. EXPECT_FALSE(boolValue);
  116. AZ::s64 intValue{};
  117. EXPECT_TRUE(settingsRegistry->Get(intValue, "/TestObject/intValue"));
  118. EXPECT_EQ(17, intValue);
  119. double floatValue{};
  120. EXPECT_TRUE(settingsRegistry->Get(floatValue, "/TestObject/floatValue"));
  121. EXPECT_DOUBLE_EQ(32.0, floatValue);
  122. AZ::SettingsRegistryInterface::FixedValueString stringValue{};
  123. EXPECT_TRUE(settingsRegistry->Get(stringValue, "/TestObject/stringValue"));
  124. EXPECT_STREQ("Hello World", stringValue.c_str());
  125. intValue = {};
  126. EXPECT_TRUE(settingsRegistry->Get(intValue, "/TestArray/1/intIndex"));
  127. EXPECT_EQ(-55, intValue);
  128. }
  129. }
  130. TEST_F(SettingsRegistryBehaviorContextFixture, MergeJsonString_WithJsonPatchFormat__Succeeds)
  131. {
  132. constexpr const char* MergeSettingMethodName = "MergeSettings";
  133. constexpr AZStd::string_view TestJsonString =
  134. R"([)" "\n"
  135. R"( { "op": "add", "path": "/TestObject", "value": {} },)" "\n"
  136. R"( { "op": "add", "path": "/TestObject/boolValue", "value": false },)" "\n"
  137. R"( { "op": "add", "path": "/TestObject/intValue", "value": 17 },)" "\n"
  138. R"( { "op": "add", "path": "/TestObject/floatValue", "value": 32.0 },)" "\n"
  139. R"( { "op": "add", "path": "/TestObject/stringValue", "value": "Hello World" },)" "\n"
  140. R"( { "op": "add", "path": "/TestArray", "value": [] },)" "\n"
  141. R"( { "op": "add", "path": "/TestArray/0", "value": { "intIndex": 3 } },)" "\n"
  142. R"( { "op": "add", "path": "/TestArray/1", "value": { "intIndex": -55 } })" "\n"
  143. R"(])" "\n";
  144. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  145. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  146. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  147. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  148. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(MergeSettingMethodName);
  149. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  150. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  151. bool mergeSettingsResult{};
  152. // Pass in both the json data string and the patch format argument
  153. EXPECT_TRUE(foundIt->second->InvokeResult(mergeSettingsResult, &settingsRegistryObject,
  154. TestJsonString, AZ::SettingsRegistryInterface::Format::JsonPatch));
  155. EXPECT_TRUE(mergeSettingsResult);
  156. // Query the Settings Registry for the Merged Content
  157. {
  158. // Retrieve
  159. auto settingsRegistry = m_registry.get();
  160. bool boolValue = true;
  161. EXPECT_TRUE(settingsRegistry->Get(boolValue, "/TestObject/boolValue"));
  162. EXPECT_FALSE(boolValue);
  163. AZ::s64 intValue{};
  164. EXPECT_TRUE(settingsRegistry->Get(intValue, "/TestObject/intValue"));
  165. EXPECT_EQ(17, intValue);
  166. double floatValue{};
  167. EXPECT_TRUE(settingsRegistry->Get(floatValue, "/TestObject/floatValue"));
  168. EXPECT_DOUBLE_EQ(32.0, floatValue);
  169. AZ::SettingsRegistryInterface::FixedValueString stringValue{};
  170. EXPECT_TRUE(settingsRegistry->Get(stringValue, "/TestObject/stringValue"));
  171. EXPECT_STREQ("Hello World", stringValue.c_str());
  172. intValue = {};
  173. EXPECT_TRUE(settingsRegistry->Get(intValue, "/TestArray/1/intIndex"));
  174. EXPECT_EQ(-55, intValue);
  175. }
  176. }
  177. TEST_F(SettingsRegistryBehaviorContextFixture, DumpSettings_FromSettingsRegistry_ResultsInExpectedJsonDocument)
  178. {
  179. constexpr const char* DumpSettingMethodName = "DumpSettings";
  180. constexpr AZStd::string_view ExpectedTestObjectResultString =
  181. R"({)" "\n"
  182. R"( "boolValue": false,)" "\n"
  183. R"( "intValue": 17,)" "\n"
  184. R"( "floatValue": 32.0,)" "\n"
  185. R"( "stringValue": "Hello World")" "\n"
  186. R"(})";
  187. constexpr AZStd::string_view ExpectedTestArrayResultString =
  188. R"([)" "\n"
  189. R"( {)" "\n"
  190. R"( "intIndex": 3)" "\n"
  191. R"( },)" "\n"
  192. R"( {)" "\n"
  193. R"( "intIndex": -55)" "\n"
  194. R"( })" "\n"
  195. R"(])";
  196. // Populate the settings registry to match the expected json values
  197. m_registry->Set("/TestObject/boolValue", false);
  198. m_registry->Set("/TestObject/intValue", aznumeric_cast<AZ::s64>(17));
  199. m_registry->Set("/TestObject/floatValue", 32.0);
  200. m_registry->Set("/TestObject/stringValue", "Hello World");
  201. m_registry->Set("/TestArray/0/intIndex", aznumeric_cast<AZ::s64>(3));
  202. m_registry->Set("/TestArray/1/intIndex", aznumeric_cast<AZ::s64>(-55));
  203. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  204. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  205. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  206. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  207. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(DumpSettingMethodName);
  208. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  209. // Dump the Settings Registry into an AZStd::string
  210. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  211. AZStd::optional<AZStd::string> settingsDump{};
  212. // Dump the TestObject first
  213. EXPECT_TRUE(foundIt->second->InvokeResult(settingsDump, &settingsRegistryObject, AZStd::string_view{"/TestObject" }));
  214. EXPECT_TRUE(settingsDump);
  215. EXPECT_STREQ(ExpectedTestObjectResultString.data(), settingsDump->c_str());
  216. // Dump the TestArray next
  217. settingsDump = {};
  218. EXPECT_TRUE(foundIt->second->InvokeResult(settingsDump, &settingsRegistryObject, AZStd::string_view{ "/TestArray" }));
  219. EXPECT_TRUE(settingsDump);
  220. EXPECT_STREQ(ExpectedTestArrayResultString.data(), settingsDump->c_str());
  221. }
  222. struct SettingsRegistryBehaviorContextParams
  223. {
  224. AZStd::string_view m_jsonPointerPath{ "" };
  225. AZStd::variant<bool, AZ::s64, double, AZStd::string_view> m_expectedValue;
  226. const char* m_getMethodName{ "" };
  227. const char* m_setMethodName{ "" };
  228. };
  229. class SettingsRegistryBehaviorContextParamFixture
  230. : public SettingsRegistryBehaviorContextFixture
  231. , public ::testing::WithParamInterface<SettingsRegistryBehaviorContextParams>
  232. {
  233. };
  234. TEST_P(SettingsRegistryBehaviorContextParamFixture, GetValue_FromSettingsRegistry_ReturnsSuccess)
  235. {
  236. auto&& testParam = GetParam();
  237. // Set the expected value within the SettingsRegistry
  238. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, methodName = testParam.m_getMethodName](auto&& value)
  239. {
  240. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  241. // Set value into the Settings Registry instance so that it can be queried from the BehaviorContext
  242. EXPECT_TRUE(m_registry->Set(jsonPath, value));
  243. // Find Reflected SettingsRegistryInterface Get* Method
  244. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  245. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  246. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  247. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  248. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(methodName);
  249. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  250. // Invoke Get* method
  251. // SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
  252. // So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
  253. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  254. AZStd::string, ValueType>;
  255. AZStd::optional<GetValueType> outputValue{};
  256. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  257. EXPECT_TRUE(foundIt->second->InvokeResult(outputValue, &settingsRegistryObject, jsonPath));
  258. EXPECT_TRUE(outputValue);
  259. EXPECT_EQ(value, *outputValue);
  260. };
  261. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  262. }
  263. TEST_P(SettingsRegistryBehaviorContextParamFixture, GetValue_FromSettingsRegistry_Fails)
  264. {
  265. auto&& testParam = GetParam();
  266. // Set the expected value within the SettingsRegistry
  267. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, getMethodName = testParam.m_getMethodName](auto&& value)
  268. {
  269. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  270. // Set value into the Settings Registry instance so that it can be queried from the BehaviorContext
  271. EXPECT_TRUE(m_registry->Set(jsonPath, value));
  272. // Find Reflected SettingsRegistryInterface Get* Method
  273. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  274. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  275. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  276. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  277. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(getMethodName);
  278. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  279. // Invoke Get* method
  280. // SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
  281. // So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
  282. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  283. AZStd::string, ValueType>;
  284. AZStd::optional<GetValueType> outputValue{};
  285. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  286. EXPECT_TRUE(foundIt->second->InvokeResult(outputValue, &settingsRegistryObject, AZStd::string_view{ "InvalidJsonPointerPath" }));
  287. EXPECT_FALSE(outputValue);
  288. };
  289. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  290. }
  291. TEST_P(SettingsRegistryBehaviorContextParamFixture, SetValue_IntoSettingsRegistry_ReturnsSuccess)
  292. {
  293. auto&& testParam = GetParam();
  294. // Set the expected value within the SettingsRegistry
  295. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, setMethodName = testParam.m_setMethodName](auto&& value)
  296. {
  297. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  298. // Find Reflected SettingsRegistryInterface Set* Method
  299. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  300. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  301. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  302. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  303. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(setMethodName);
  304. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  305. // Invoke Set* method
  306. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  307. bool setResult{};
  308. EXPECT_TRUE(foundIt->second->InvokeResult(setResult, &settingsRegistryObject, jsonPath, value));
  309. EXPECT_TRUE(setResult);
  310. // Check value set through the BehaviorContext against the Settings Registry instance
  311. // SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
  312. // So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
  313. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  314. AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
  315. GetValueType outputValue{};
  316. EXPECT_TRUE(m_registry->Get(outputValue, jsonPath));
  317. EXPECT_EQ(value, outputValue);
  318. };
  319. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  320. }
  321. TEST_P(SettingsRegistryBehaviorContextParamFixture, SetValue_IntoSettingsRegistry_Fails)
  322. {
  323. auto&& testParam = GetParam();
  324. // Set the expected value within the SettingsRegistry
  325. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, setMethodName = testParam.m_setMethodName](auto&& value)
  326. {
  327. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  328. // Find Reflected SettingsRegistryInterface Set* Method
  329. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  330. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  331. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  332. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  333. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(setMethodName);
  334. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  335. // Invoke Set* method
  336. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  337. bool setResult = true;
  338. EXPECT_TRUE(foundIt->second->InvokeResult(setResult, &settingsRegistryObject, AZStd::string_view{ "InvalidJsonPointerPath" }, value));
  339. EXPECT_FALSE(setResult);
  340. // Check value set through the BehaviorContext against the Settings Registry instance
  341. // SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
  342. // So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
  343. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  344. AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
  345. GetValueType outputValue{};
  346. EXPECT_FALSE(m_registry->Get(outputValue, jsonPath));
  347. EXPECT_NE(value, outputValue);
  348. };
  349. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  350. }
  351. TEST_P(SettingsRegistryBehaviorContextParamFixture, RemoveKey_FromSettingsRegistry_ReturnsSuccess)
  352. {
  353. auto&& testParam = GetParam();
  354. // Set the expected value within the SettingsRegistry
  355. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath](auto&& value)
  356. {
  357. constexpr AZStd::string_view removeMethodName{ "RemoveKey" };
  358. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  359. // Set value with the Settings Registry, so it can checked for removal later
  360. EXPECT_TRUE(m_registry->Set(jsonPath, value));
  361. // Find Reflected SettingsRegistryInterface RemoveKey Method
  362. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  363. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  364. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  365. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  366. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(removeMethodName);
  367. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  368. // Invoke RemoveKey method
  369. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  370. bool removeResult{};
  371. EXPECT_TRUE(foundIt->second->InvokeResult(removeResult, &settingsRegistryObject, jsonPath));
  372. EXPECT_TRUE(removeResult);
  373. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  374. AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
  375. GetValueType outputValue{};
  376. //The value should have been removed from the Settings Registry instance
  377. EXPECT_FALSE(m_registry->Get(outputValue, jsonPath));
  378. };
  379. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  380. }
  381. TEST_P(SettingsRegistryBehaviorContextParamFixture, RemoveKey_FromSettingsRegistry_Fails)
  382. {
  383. auto&& testParam = GetParam();
  384. // Set the expected value within the SettingsRegistry
  385. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath](auto&& value)
  386. {
  387. constexpr AZStd::string_view removeMethodName{ "RemoveKey" };
  388. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  389. // Set value with the Settings Registry, so it can checked for removal later
  390. EXPECT_TRUE(m_registry->Set(jsonPath, value));
  391. // Find Reflected SettingsRegistryInterface RemoveKey Method
  392. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  393. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  394. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  395. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  396. auto foundIt = settingsRegistryInterfaceClass->m_methods.find(removeMethodName);
  397. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  398. // Invoke RemoveKey method
  399. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  400. bool removeResult = true;
  401. EXPECT_TRUE(foundIt->second->InvokeResult(removeResult, &settingsRegistryObject, AZStd::string_view{ "InvalidJsonPointerPath" }));
  402. EXPECT_FALSE(removeResult);
  403. // Check that value was not removed from the Settings Registry instance
  404. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  405. AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
  406. GetValueType outputValue{};
  407. EXPECT_TRUE(m_registry->Get(outputValue, jsonPath));
  408. EXPECT_EQ(value, outputValue);
  409. };
  410. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  411. }
  412. TEST_P(SettingsRegistryBehaviorContextParamFixture, GetNotifyEvent_AllowsRegistrationOfAzEventHandler_Succeeds)
  413. {
  414. auto&& testParam = GetParam();
  415. bool updateNotifySent{};
  416. // Set the expected value within the SettingsRegistry
  417. auto ExpectedValueVisitor = [this, jsonPath = testParam.m_jsonPointerPath, setMethodName = testParam.m_setMethodName,
  418. &updateNotifySent](auto&& value)
  419. {
  420. using ValueType = AZStd::remove_cvref_t<decltype(value)>;
  421. const auto classIter = m_behaviorContext->m_classes.find(SettingsRegistryScriptClassName);
  422. ASSERT_NE(m_behaviorContext->m_classes.end(), classIter);
  423. AZ::BehaviorClass* settingsRegistryInterfaceClass = classIter->second;
  424. ASSERT_NE(nullptr, settingsRegistryInterfaceClass);
  425. // Lookup the SettingsRegistry Proxy GetNotifyEvent
  426. auto foundIt = settingsRegistryInterfaceClass->m_methods.find("GetNotifyEvent");
  427. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  428. // Create local settings registry proxy object
  429. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy settingsRegistryObject(m_registry.get());
  430. // Register a notification call back
  431. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy::ScriptNotifyEvent::Handler scriptNotifyHandler(
  432. [&updateNotifySent, jsonPath](AZStd::string_view path)
  433. {
  434. if (path == jsonPath)
  435. {
  436. updateNotifySent = true;
  437. }
  438. });
  439. AZ::SettingsRegistryScriptUtils::Internal::SettingsRegistryScriptProxy::ScriptNotifyEvent* scriptNotifyEvent{};
  440. EXPECT_TRUE(foundIt->second->InvokeResult(scriptNotifyEvent, &settingsRegistryObject));
  441. ASSERT_NE(nullptr, scriptNotifyEvent);
  442. // connect the scriptNotifyHandler to the settings registry script proxy event
  443. scriptNotifyHandler.Connect(*scriptNotifyEvent);
  444. // Find Reflected SettingsRegistryInterface Set* Method
  445. foundIt = settingsRegistryInterfaceClass->m_methods.find(setMethodName);
  446. ASSERT_NE(settingsRegistryInterfaceClass->m_methods.end(), foundIt);
  447. // Invoke Set* method
  448. bool setResult{};
  449. EXPECT_TRUE(foundIt->second->InvokeResult(setResult, &settingsRegistryObject, jsonPath, value));
  450. EXPECT_TRUE(setResult);
  451. // Check value set through the BehaviorContext against the Settings Registry instance
  452. // SettingsRegistryInterface::Get() can store the string result in an AZStd::fixed_string/AZStd::string
  453. // So the AZStd::string_view is mapped to an AZStd::fixed_string for the purpose of calling Get()
  454. using GetValueType = AZStd::conditional_t<AZStd::is_same_v<AZStd::string_view, ValueType>,
  455. AZ::SettingsRegistryInterface::FixedValueString, ValueType>;
  456. GetValueType outputValue{};
  457. EXPECT_TRUE(m_registry->Get(outputValue, jsonPath));
  458. EXPECT_EQ(value, outputValue);
  459. };
  460. AZStd::visit(ExpectedValueVisitor, testParam.m_expectedValue);
  461. EXPECT_TRUE(updateNotifySent);
  462. }
  463. INSTANTIATE_TEST_SUITE_P(
  464. SettingsRegistryBehaviorContextGetFunctions,
  465. SettingsRegistryBehaviorContextParamFixture,
  466. testing::Values(
  467. SettingsRegistryBehaviorContextParams{ "/TestObject/boolValue", true, "GetBool", "SetBool" },
  468. SettingsRegistryBehaviorContextParams{ "/TestObject/intValue", AZ::s64(17), "GetInt", "SetInt" },
  469. SettingsRegistryBehaviorContextParams{ "/TestObject/floatValue", 32.0, "GetFloat", "SetFloat" },
  470. SettingsRegistryBehaviorContextParams{ "/TestObject/stringValue", AZStd::string_view{"Hello World"}, "GetString", "SetString" }
  471. )
  472. );
  473. }