ScriptProperty.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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 "TestTypes.h"
  9. #include <iostream>
  10. #include <AzCore/Script/ScriptContext.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <AzCore/Script/lua/lua.h>
  13. #include <AzCore/Script/ScriptContextDebug.h>
  14. // Script Properties
  15. #include <AzCore/Script/ScriptProperty.h>
  16. #include <AzCore/Script/ScriptPropertyTable.h>
  17. #if !defined(AZCORE_EXCLUDE_LUA)
  18. namespace UnitTest
  19. {
  20. using namespace AZ;
  21. // ScriptPropertyTests
  22. class ScriptPropertyTest
  23. : public LeakDetectionFixture
  24. {
  25. public:
  26. void SetUp() override
  27. {
  28. LeakDetectionFixture::SetUp();
  29. // Need to initialize our variables here, instead of in the constructor to avoid some memory tracking issues.
  30. m_tableName = "tableName";
  31. m_nilName = "nilValue";
  32. m_stringName = "stringValue";
  33. m_stringValue = "This is the value of the string value";
  34. m_numberName = "numberValue";
  35. m_numberValue = 1.5;
  36. m_booleanName = "booleanValue";
  37. m_booleanValue = false;
  38. m_numberArrayName = "numberArray";
  39. m_numberArray.push_back(1.9);
  40. m_numberArray.push_back(2.8);
  41. m_numberArray.push_back(3.7);
  42. m_numberArray.push_back(4.6);
  43. m_numberArray.push_back(5.5);
  44. m_hashName = "hashArray";
  45. m_hashValues["first"] = 1.9;
  46. m_hashValues["foo"] = 2.8;
  47. m_hashValues["bar"] = 3.7;
  48. m_hashValues["baz"] = 4.6;
  49. m_hashValues["last"] = 5.5;
  50. m_behavior = aznew BehaviorContext();
  51. m_script = aznew ScriptContext();
  52. m_script->BindTo(m_behavior);
  53. // Create a table so we can inspect it using the DataContexts
  54. CreateTable();
  55. WriteTableValue(m_numberName,m_numberValue);
  56. WriteTableValue(m_stringName,m_stringValue.c_str());
  57. WriteTableValue(m_booleanName, m_booleanValue);
  58. WriteTableArray(m_numberArrayName, m_numberArray);
  59. WriteTable(m_hashName,m_hashValues);
  60. m_script->InspectTable(m_tableName.c_str(),m_dataContext);
  61. }
  62. void TearDown() override
  63. {
  64. m_dataContext = ScriptDataContext();
  65. delete m_script;
  66. m_script = nullptr;
  67. delete m_behavior;
  68. m_behavior = nullptr;
  69. LeakDetectionFixture::TearDown();
  70. }
  71. void CreateTable()
  72. {
  73. std::stringstream inputStream;
  74. inputStream << m_tableName.c_str();
  75. inputStream << " = { }";
  76. m_script->Execute(inputStream.str().c_str());
  77. }
  78. template<typename T>
  79. void WriteTableValue(AZStd::string& name, T value)
  80. {
  81. std::stringstream inputStream;
  82. inputStream << m_tableName.c_str();
  83. inputStream << ".";
  84. inputStream << name.c_str();
  85. inputStream << " = ";
  86. inputStream << value;
  87. m_script->Execute(inputStream.str().c_str());
  88. }
  89. template<>
  90. void WriteTableValue<bool>(AZStd::string& name, bool value)
  91. {
  92. std::stringstream inputStream;
  93. inputStream << m_tableName.c_str();
  94. inputStream << ".";
  95. inputStream << name.c_str();
  96. inputStream << " = ";
  97. if (value)
  98. {
  99. inputStream << "true";
  100. }
  101. else
  102. {
  103. inputStream << "false";
  104. }
  105. m_script->Execute(inputStream.str().c_str());
  106. }
  107. template<>
  108. void WriteTableValue<const char*>(AZStd::string& name, const char* value)
  109. {
  110. std::stringstream inputStream;
  111. inputStream << m_tableName.c_str();
  112. inputStream << ".";
  113. inputStream << name.c_str();
  114. inputStream << " = ";
  115. inputStream << "\"";
  116. inputStream << value;
  117. inputStream << "\"";
  118. m_script->Execute(inputStream.str().c_str());
  119. }
  120. template<typename T>
  121. void WriteTableArray(AZStd::string& name, AZStd::vector<T>& valueArray)
  122. {
  123. std::stringstream inputStream;
  124. inputStream << m_tableName.c_str();
  125. inputStream << ".";
  126. inputStream << name.c_str();
  127. inputStream << " = {";
  128. for (unsigned int i=0; i < valueArray.size(); ++i)
  129. {
  130. if (i != 0)
  131. {
  132. inputStream << ",";
  133. }
  134. inputStream << valueArray[i];
  135. }
  136. inputStream << "}";
  137. m_script->Execute(inputStream.str().c_str());
  138. }
  139. template<typename T>
  140. void WriteTable(AZStd::string& name, AZStd::unordered_map<AZStd::string, T>& valueMap)
  141. {
  142. std::stringstream inputStream;
  143. inputStream << m_tableName.c_str();
  144. inputStream << ".";
  145. inputStream << name.c_str();
  146. inputStream << " = {";
  147. bool skipOnce = true;
  148. for (auto& mapPair : valueMap)
  149. {
  150. if (!skipOnce)
  151. {
  152. inputStream << " ,";
  153. }
  154. skipOnce = false;
  155. inputStream << mapPair.first.c_str();
  156. inputStream << " = ";
  157. inputStream << mapPair.second;
  158. }
  159. inputStream << "}";
  160. m_script->Execute(inputStream.str().c_str());
  161. }
  162. // Overall table name
  163. AZStd::string m_tableName;
  164. // Nil
  165. AZStd::string m_nilName;
  166. // String
  167. AZStd::string m_stringName;
  168. AZStd::string m_stringValue;
  169. // number
  170. AZStd::string m_numberName;
  171. double m_numberValue = 1.5;
  172. // boolean
  173. AZStd::string m_booleanName;
  174. bool m_booleanValue = false;
  175. // Number Array
  176. AZStd::string m_numberArrayName;
  177. AZStd::vector<double> m_numberArray;
  178. // Table
  179. AZStd::string m_hashName;
  180. AZStd::unordered_map<AZStd::string, double> m_hashValues;
  181. BehaviorContext* m_behavior = nullptr;
  182. ScriptContext* m_script = nullptr;
  183. ScriptDataContext m_dataContext;
  184. };
  185. TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PrimitiveTypes)
  186. {
  187. ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberName.c_str());
  188. ASSERT_NE(scriptProperty, nullptr);
  189. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(scriptProperty));
  190. if (azrtti_istypeof<ScriptPropertyNumber>(scriptProperty))
  191. {
  192. bool isClose = IsClose(m_numberValue, static_cast<ScriptPropertyNumber*>(scriptProperty)->m_value, 0.001);
  193. EXPECT_EQ(isClose, true);
  194. }
  195. delete scriptProperty;
  196. scriptProperty = nullptr;
  197. scriptProperty = m_dataContext.ConstructTableScriptProperty(m_stringName.c_str());
  198. ASSERT_NE(scriptProperty, nullptr);
  199. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyString>(scriptProperty));
  200. if (azrtti_istypeof<ScriptPropertyString>(scriptProperty))
  201. {
  202. EXPECT_EQ(m_stringValue.compare(static_cast<ScriptPropertyString*>(scriptProperty)->m_value.c_str()), 0);
  203. }
  204. delete scriptProperty;
  205. scriptProperty = nullptr;
  206. scriptProperty = m_dataContext.ConstructTableScriptProperty(m_booleanName.c_str());
  207. ASSERT_NE(scriptProperty, nullptr);
  208. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyBoolean>(scriptProperty));
  209. if (azrtti_istypeof<ScriptPropertyBoolean>(scriptProperty))
  210. {
  211. EXPECT_EQ(m_booleanValue, static_cast<ScriptPropertyBoolean*>(scriptProperty)->m_value);
  212. }
  213. delete scriptProperty;
  214. scriptProperty = nullptr;
  215. scriptProperty = m_dataContext.ConstructTableScriptProperty(m_nilName.c_str());
  216. EXPECT_NE(scriptProperty,nullptr);
  217. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNil>(scriptProperty));
  218. delete scriptProperty;
  219. scriptProperty = nullptr;
  220. }
  221. TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_HashMapAsTable)
  222. {
  223. const bool k_restrictToPropertyArrays = false;
  224. ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_hashName.c_str(), k_restrictToPropertyArrays);
  225. ASSERT_NE(scriptProperty, nullptr);
  226. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyTable>(scriptProperty));
  227. if (azrtti_istypeof<ScriptPropertyTable>(scriptProperty))
  228. {
  229. ScriptPropertyNumber scriptPropertyNumber;
  230. ScriptPropertyTable* scriptTable = static_cast<ScriptPropertyTable*>(scriptProperty);
  231. for (auto& mapPair : m_hashValues)
  232. {
  233. const AZStd::string& keyString = mapPair.first;
  234. ScriptProperty* mapProperty = scriptTable->FindTableValue(keyString);
  235. ASSERT_NE(mapProperty,nullptr);
  236. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(mapProperty));
  237. if (azrtti_istypeof<ScriptPropertyNumber>(mapProperty))
  238. {
  239. EXPECT_EQ(IsClose(mapPair.second,static_cast<ScriptPropertyNumber*>(mapProperty)->m_value,0.001),true);
  240. }
  241. }
  242. }
  243. delete scriptProperty;
  244. scriptProperty = nullptr;
  245. }
  246. TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PropertyArrayAsTable)
  247. {
  248. const bool k_restrictToPropertyArrays = false;
  249. ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberArrayName.c_str(), k_restrictToPropertyArrays);
  250. ASSERT_NE(scriptProperty, nullptr);
  251. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyTable>(scriptProperty));
  252. if (azrtti_istypeof<ScriptPropertyTable>(scriptProperty))
  253. {
  254. ScriptPropertyNumber scriptPropertyNumber;
  255. ScriptPropertyTable* scriptTable = static_cast<ScriptPropertyTable*>(scriptProperty);
  256. for (unsigned int i=0; i < m_numberArray.size(); ++i)
  257. {
  258. // Offset to deal with lua 1 indexing things.
  259. ScriptProperty* mapProperty = scriptTable->FindTableValue((i+ 1));
  260. ASSERT_NE(mapProperty, nullptr);
  261. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(mapProperty));
  262. if (azrtti_typeid(mapProperty) == ScriptPropertyNumber::RTTI_Type())
  263. {
  264. EXPECT_EQ(IsClose(m_numberArray[i],static_cast<ScriptPropertyNumber*>(mapProperty)->m_value,0.001),true);
  265. }
  266. }
  267. }
  268. delete scriptProperty;
  269. scriptProperty = nullptr;
  270. }
  271. TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PropertyArray)
  272. {
  273. const bool k_restrictToPropertyArrays = true;
  274. ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberArrayName.c_str(),k_restrictToPropertyArrays);
  275. ASSERT_NE(scriptProperty, nullptr);
  276. EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumberArray>(scriptProperty));
  277. if (azrtti_istypeof<ScriptPropertyNumberArray>(scriptProperty))
  278. {
  279. AZStd::vector<double>& valueArray = static_cast<ScriptPropertyNumberArray*>(scriptProperty)->m_values;
  280. ASSERT_EQ(valueArray.size(), m_numberArray.size());
  281. for (unsigned int i=0; i < valueArray.size(); ++i)
  282. {
  283. EXPECT_EQ(true, IsClose(valueArray[i],m_numberArray[i],0.001));
  284. }
  285. }
  286. }
  287. }
  288. #endif // #if !defined(AZCORE_EXCLUDE_LUA)