You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Framework/AzCore/Tests/ScriptProperty.cpp

386 lines
12 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "TestTypes.h"
#include <iostream>
#include <AzCore/Script/ScriptContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Script/lua/lua.h>
#include <AzCore/Script/ScriptContextDebug.h>
// Script Properties
#include <AzCore/Script/ScriptProperty.h>
#include <AzCore/Script/ScriptPropertyTable.h>
#if !defined(AZCORE_EXCLUDE_LUA)
namespace UnitTest
{
using namespace AZ;
// ScriptPropertyTests
class ScriptPropertyTest
: public AllocatorsFixture
{
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
// Need to initialize our variables here, instead of in the constructor to avoid some memory tracking issues.
m_tableName = "tableName";
m_nilName = "nilValue";
m_stringName = "stringValue";
m_stringValue = "This is the value of the string value";
m_numberName = "numberValue";
m_numberValue = 1.5;
m_booleanName = "booleanValue";
m_booleanValue = false;
m_numberArrayName = "numberArray";
m_numberArray.push_back(1.9);
m_numberArray.push_back(2.8);
m_numberArray.push_back(3.7);
m_numberArray.push_back(4.6);
m_numberArray.push_back(5.5);
m_hashName = "hashArray";
m_hashValues["first"] = 1.9;
m_hashValues["foo"] = 2.8;
m_hashValues["bar"] = 3.7;
m_hashValues["baz"] = 4.6;
m_hashValues["last"] = 5.5;
m_behavior = aznew BehaviorContext();
m_script = aznew ScriptContext();
m_script->BindTo(m_behavior);
// Create a table so we can inspect it using the DataContexts
CreateTable();
WriteTableValue(m_numberName,m_numberValue);
WriteTableValue(m_stringName,m_stringValue.c_str());
WriteTableValue(m_booleanName, m_booleanValue);
WriteTableArray(m_numberArrayName, m_numberArray);
WriteTable(m_hashName,m_hashValues);
m_script->InspectTable(m_tableName.c_str(),m_dataContext);
}
void TearDown() override
{
m_dataContext = ScriptDataContext();
delete m_script;
m_script = nullptr;
delete m_behavior;
m_behavior = nullptr;
AllocatorsFixture::TearDown();
}
void CreateTable()
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << " = { }";
m_script->Execute(inputStream.str().c_str());
}
template<typename T>
void WriteTableValue(AZStd::string& name, T value)
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << ".";
inputStream << name.c_str();
inputStream << " = ";
inputStream << value;
m_script->Execute(inputStream.str().c_str());
}
template<>
void WriteTableValue<bool>(AZStd::string& name, bool value)
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << ".";
inputStream << name.c_str();
inputStream << " = ";
if (value)
{
inputStream << "true";
}
else
{
inputStream << "false";
}
m_script->Execute(inputStream.str().c_str());
}
template<>
void WriteTableValue<const char*>(AZStd::string& name, const char* value)
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << ".";
inputStream << name.c_str();
inputStream << " = ";
inputStream << "\"";
inputStream << value;
inputStream << "\"";
m_script->Execute(inputStream.str().c_str());
}
template<typename T>
void WriteTableArray(AZStd::string& name, AZStd::vector<T>& valueArray)
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << ".";
inputStream << name.c_str();
inputStream << " = {";
for (unsigned int i=0; i < valueArray.size(); ++i)
{
if (i != 0)
{
inputStream << ",";
}
inputStream << valueArray[i];
}
inputStream << "}";
m_script->Execute(inputStream.str().c_str());
}
template<typename T>
void WriteTable(AZStd::string& name, AZStd::unordered_map<AZStd::string, T>& valueMap)
{
std::stringstream inputStream;
inputStream << m_tableName.c_str();
inputStream << ".";
inputStream << name.c_str();
inputStream << " = {";
bool skipOnce = true;
for (auto& mapPair : valueMap)
{
if (!skipOnce)
{
inputStream << " ,";
}
skipOnce = false;
inputStream << mapPair.first.c_str();
inputStream << " = ";
inputStream << mapPair.second;
}
inputStream << "}";
m_script->Execute(inputStream.str().c_str());
}
// Overall table name
AZStd::string m_tableName;
// Nil
AZStd::string m_nilName;
// String
AZStd::string m_stringName;
AZStd::string m_stringValue;
// number
AZStd::string m_numberName;
double m_numberValue = 1.5;
// boolean
AZStd::string m_booleanName;
bool m_booleanValue = false;
// Number Array
AZStd::string m_numberArrayName;
AZStd::vector<double> m_numberArray;
// Table
AZStd::string m_hashName;
AZStd::unordered_map<AZStd::string, double> m_hashValues;
BehaviorContext* m_behavior = nullptr;
ScriptContext* m_script = nullptr;
ScriptDataContext m_dataContext;
};
TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PrimitiveTypes)
{
ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberName.c_str());
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyNumber>(scriptProperty))
{
bool isClose = IsClose(m_numberValue, static_cast<ScriptPropertyNumber*>(scriptProperty)->m_value, 0.001);
EXPECT_EQ(isClose, true);
}
delete scriptProperty;
scriptProperty = nullptr;
scriptProperty = m_dataContext.ConstructTableScriptProperty(m_stringName.c_str());
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyString>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyString>(scriptProperty))
{
EXPECT_EQ(m_stringValue.compare(static_cast<ScriptPropertyString*>(scriptProperty)->m_value.c_str()), 0);
}
delete scriptProperty;
scriptProperty = nullptr;
scriptProperty = m_dataContext.ConstructTableScriptProperty(m_booleanName.c_str());
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyBoolean>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyBoolean>(scriptProperty))
{
EXPECT_EQ(m_booleanValue, static_cast<ScriptPropertyBoolean*>(scriptProperty)->m_value);
}
delete scriptProperty;
scriptProperty = nullptr;
scriptProperty = m_dataContext.ConstructTableScriptProperty(m_nilName.c_str());
EXPECT_NE(scriptProperty,nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNil>(scriptProperty));
delete scriptProperty;
scriptProperty = nullptr;
}
TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_HashMapAsTable)
{
const bool k_restrictToPropertyArrays = false;
ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_hashName.c_str(), k_restrictToPropertyArrays);
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyTable>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyTable>(scriptProperty))
{
ScriptPropertyNumber scriptPropertyNumber;
ScriptPropertyTable* scriptTable = static_cast<ScriptPropertyTable*>(scriptProperty);
for (auto& mapPair : m_hashValues)
{
const AZStd::string& keyString = mapPair.first;
ScriptProperty* mapProperty = scriptTable->FindTableValue(keyString);
ASSERT_NE(mapProperty,nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(mapProperty));
if (azrtti_istypeof<ScriptPropertyNumber>(mapProperty))
{
EXPECT_EQ(IsClose(mapPair.second,static_cast<ScriptPropertyNumber*>(mapProperty)->m_value,0.001),true);
}
}
}
delete scriptProperty;
scriptProperty = nullptr;
}
TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PropertyArrayAsTable)
{
const bool k_restrictToPropertyArrays = false;
ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberArrayName.c_str(), k_restrictToPropertyArrays);
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyTable>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyTable>(scriptProperty))
{
ScriptPropertyNumber scriptPropertyNumber;
ScriptPropertyTable* scriptTable = static_cast<ScriptPropertyTable*>(scriptProperty);
for (unsigned int i=0; i < m_numberArray.size(); ++i)
{
// Offset to deal with lua 1 indexing things.
ScriptProperty* mapProperty = scriptTable->FindTableValue((i+ 1));
ASSERT_NE(mapProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumber>(mapProperty));
if (azrtti_typeid(mapProperty) == ScriptPropertyNumber::RTTI_Type())
{
EXPECT_EQ(IsClose(m_numberArray[i],static_cast<ScriptPropertyNumber*>(mapProperty)->m_value,0.001),true);
}
}
}
delete scriptProperty;
scriptProperty = nullptr;
}
TEST_F(ScriptPropertyTest, ScriptPropertyTest_ParseTest_PropertyArray)
{
const bool k_restrictToPropertyArrays = true;
ScriptProperty* scriptProperty = m_dataContext.ConstructTableScriptProperty(m_numberArrayName.c_str(),k_restrictToPropertyArrays);
ASSERT_NE(scriptProperty, nullptr);
EXPECT_TRUE(azrtti_istypeof<ScriptPropertyNumberArray>(scriptProperty));
if (azrtti_istypeof<ScriptPropertyNumberArray>(scriptProperty))
{
AZStd::vector<double>& valueArray = static_cast<ScriptPropertyNumberArray*>(scriptProperty)->m_values;
ASSERT_EQ(valueArray.size(), m_numberArray.size());
for (unsigned int i=0; i < valueArray.size(); ++i)
{
EXPECT_EQ(true, IsClose(valueArray[i],m_numberArray[i],0.001));
}
}
}
}
#endif // #if !defined(AZCORE_EXCLUDE_LUA)