Refactor: Amf3 implementation (#998)

* Update AMFDeserializeTests.cpp

Redo Amf3 functionality

Overhaul the whole thing due to it being outdated and clunky to use

Sometimes you want to keep the value

Update AMFDeserializeTests.cpp

* Fix enum and constructors

Correct enum to a class and simplify names.
Add a proper default constructor

* Update MasterServer.cpp

* Fix bugs and add more tests

* Refactor: AMF with templates in mind

- Remove hard coded bodge
- Use templates and generics to allow for much looser typing and strengthened implementation
- Move code into header only implementation for portability

Refactor: Convert AMF implementation to templates

- Rip out previous implementation
- Remove all extraneous terminology
- Add proper overloads for all types of inserts
- Fix up tests and codebase

* Fix compiler errors

* Check for null first

* Add specialization for const char*

* Update tests for new template specialization

* Switch BitStream to use references

* Rename files

* Check enum bounds on deserialize

I did this on a phone
This commit is contained in:
David Markowitz
2023-05-13 15:22:00 -07:00
committed by GitHub
parent 9d105a287d
commit 4fe335cc66
46 changed files with 1081 additions and 1420 deletions

View File

@@ -3,14 +3,17 @@
#include <gtest/gtest.h>
#include "AMFDeserialize.h"
#include "AMFFormat.h"
#include "Amf3.h"
#include "Game.h"
#include "dLogger.h"
/**
* Helper method that all tests use to get their respective AMF.
*/
std::unique_ptr<AMFValue> ReadFromBitStream(RakNet::BitStream* bitStream) {
AMFBaseValue* ReadFromBitStream(RakNet::BitStream* bitStream) {
AMFDeserialize deserializer;
std::unique_ptr<AMFValue> returnValue(deserializer.Read(bitStream));
AMFBaseValue* returnValue(deserializer.Read(bitStream));
return returnValue;
}
@@ -18,10 +21,10 @@ std::unique_ptr<AMFValue> ReadFromBitStream(RakNet::BitStream* bitStream) {
* @brief Test reading an AMFUndefined value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFUndefinedTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x00);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFUndefined);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Undefined);
}
/**
@@ -29,54 +32,54 @@ TEST(dCommonTests, AMFDeserializeAMFUndefinedTest) {
*
*/
TEST(dCommonTests, AMFDeserializeAMFNullTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x01);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFNull);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Null);
}
/**
* @brief Test reading an AMFFalse value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFFalseTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x02);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFFalse);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::False);
}
/**
* @brief Test reading an AMFTrue value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFTrueTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x03);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFTrue);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::True);
}
/**
* @brief Test reading an AMFInteger value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFIntegerTest) {
CBITSTREAM
CBITSTREAM;
{
bitStream.Write<uint8_t>(0x04);
// 127 == 01111111
bitStream.Write<uint8_t>(127);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Integer);
// Check that the max value of a byte can be read correctly
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), 127);
ASSERT_EQ(static_cast<AMFIntValue*>(res.get())->GetValue(), 127);
}
bitStream.Reset();
{
bitStream.Write<uint8_t>(0x04);
bitStream.Write<uint32_t>(UINT32_MAX);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Integer);
// Check that we can read the maximum value correctly
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), 536870911);
ASSERT_EQ(static_cast<AMFIntValue*>(res.get())->GetValue(), 536870911);
}
bitStream.Reset();
{
@@ -87,10 +90,10 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) {
bitStream.Write<uint8_t>(255);
// 127 == 01111111
bitStream.Write<uint8_t>(127);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Integer);
// Check that short max can be read correctly
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), UINT16_MAX);
ASSERT_EQ(static_cast<AMFIntValue*>(res.get())->GetValue(), UINT16_MAX);
}
bitStream.Reset();
{
@@ -99,10 +102,10 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) {
bitStream.Write<uint8_t>(255);
// 127 == 01111111
bitStream.Write<uint8_t>(127);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFInteger);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Integer);
// Check that 2 byte max can be read correctly
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), 16383);
ASSERT_EQ(static_cast<AMFIntValue*>(res.get())->GetValue(), 16383);
}
}
@@ -110,42 +113,42 @@ TEST(dCommonTests, AMFDeserializeAMFIntegerTest) {
* @brief Test reading an AMFDouble value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFDoubleTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x05);
bitStream.Write<double>(25346.4f);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFDouble);
ASSERT_EQ(static_cast<AMFDoubleValue*>(res.get())->GetDoubleValue(), 25346.4f);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Double);
ASSERT_EQ(static_cast<AMFDoubleValue*>(res.get())->GetValue(), 25346.4f);
}
/**
* @brief Test reading an AMFString value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFStringTest) {
CBITSTREAM
CBITSTREAM;
bitStream.Write<uint8_t>(0x06);
bitStream.Write<uint8_t>(0x0F);
std::string toWrite = "stateID";
for (auto e : toWrite) bitStream.Write<char>(e);
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFString);
ASSERT_EQ(static_cast<AMFStringValue*>(res.get())->GetStringValue(), "stateID");
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::String);
ASSERT_EQ(static_cast<AMFStringValue*>(res.get())->GetValue(), "stateID");
}
/**
* @brief Test reading an AMFArray value from a BitStream.
*/
TEST(dCommonTests, AMFDeserializeAMFArrayTest) {
CBITSTREAM
CBITSTREAM;
// Test empty AMFArray
bitStream.Write<uint8_t>(0x09);
bitStream.Write<uint8_t>(0x01);
bitStream.Write<uint8_t>(0x01);
{
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFArray);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetAssociativeMap().size(), 0);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetDenseArray().size(), 0);
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Array);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetAssociative().size(), 0);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetDense().size(), 0);
}
bitStream.Reset();
// Test a key'd value and dense value
@@ -161,32 +164,32 @@ TEST(dCommonTests, AMFDeserializeAMFArrayTest) {
bitStream.Write<uint8_t>(0x0B);
for (auto e : "10447") if (e != '\0') bitStream.Write<char>(e);
{
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFArray);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetAssociativeMap().size(), 1);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetDenseArray().size(), 1);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->FindValue<AMFStringValue>("BehaviorID")->GetStringValue(), "10447");
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetValueAt<AMFStringValue>(0)->GetStringValue(), "10447");
std::unique_ptr<AMFBaseValue> res(ReadFromBitStream(&bitStream));
ASSERT_EQ(res->GetValueType(), eAmf::Array);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetAssociative().size(), 1);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetDense().size(), 1);
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->Get<std::string>("BehaviorID")->GetValue(), "10447");
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->Get<std::string>(0)->GetValue(), "10447");
}
}
/**
* @brief This test checks that if we recieve an unimplemented AMFValueType
* @brief This test checks that if we recieve an unimplemented eAmf
* we correctly throw an error and can actch it.
* Yes this leaks memory.
*/
TEST(dCommonTests, AMFDeserializeUnimplementedValuesTest) {
std::vector<AMFValueType> unimplementedValues = {
AMFValueType::AMFXMLDoc,
AMFValueType::AMFDate,
AMFValueType::AMFObject,
AMFValueType::AMFXML,
AMFValueType::AMFByteArray,
AMFValueType::AMFVectorInt,
AMFValueType::AMFVectorUInt,
AMFValueType::AMFVectorDouble,
AMFValueType::AMFVectorObject,
AMFValueType::AMFDictionary
std::vector<eAmf> unimplementedValues = {
eAmf::XMLDoc,
eAmf::Date,
eAmf::Object,
eAmf::XML,
eAmf::ByteArray,
eAmf::VectorInt,
eAmf::VectorUInt,
eAmf::VectorDouble,
eAmf::VectorObject,
eAmf::Dictionary
};
// Run unimplemented tests to check that errors are thrown if
// unimplemented AMF values are attempted to be parsed.
@@ -202,16 +205,16 @@ TEST(dCommonTests, AMFDeserializeUnimplementedValuesTest) {
fileStream.close();
for (auto amfValueType : unimplementedValues) {
for (auto value : unimplementedValues) {
RakNet::BitStream testBitStream;
for (auto element : baseBitStream) {
testBitStream.Write(element);
}
testBitStream.Write(amfValueType);
testBitStream.Write(value);
bool caughtException = false;
try {
ReadFromBitStream(&testBitStream);
} catch (AMFValueType unimplementedValueType) {
} catch (eAmf unimplementedValueType) {
caughtException = true;
}
@@ -235,116 +238,116 @@ TEST(dCommonTests, AMFDeserializeLivePacketTest) {
testFileStream.close();
auto resultFromFn = ReadFromBitStream(&testBitStream);
std::unique_ptr<AMFBaseValue> resultFromFn(ReadFromBitStream(&testBitStream));
auto result = static_cast<AMFArrayValue*>(resultFromFn.get());
// Test the outermost array
ASSERT_EQ(result->FindValue<AMFStringValue>("BehaviorID")->GetStringValue(), "10447");
ASSERT_EQ(result->FindValue<AMFStringValue>("objectID")->GetStringValue(), "288300744895913279");
ASSERT_EQ(result->Get<std::string>("BehaviorID")->GetValue(), "10447");
ASSERT_EQ(result->Get<std::string>("objectID")->GetValue(), "288300744895913279");
// Test the execution state array
auto executionState = result->FindValue<AMFArrayValue>("executionState");
auto executionState = result->GetArray("executionState");
ASSERT_NE(executionState, nullptr);
auto strips = executionState->FindValue<AMFArrayValue>("strips")->GetDenseArray();
auto strips = executionState->GetArray("strips")->GetDense();
ASSERT_EQ(strips.size(), 1);
auto stripsPosition0 = dynamic_cast<AMFArrayValue*>(strips[0]);
auto actionIndex = stripsPosition0->FindValue<AMFDoubleValue>("actionIndex");
auto actionIndex = stripsPosition0->Get<double>("actionIndex");
ASSERT_EQ(actionIndex->GetDoubleValue(), 0.0f);
ASSERT_EQ(actionIndex->GetValue(), 0.0f);
auto stripIdExecution = stripsPosition0->FindValue<AMFDoubleValue>("id");
auto stripIdExecution = stripsPosition0->Get<double>("id");
ASSERT_EQ(stripIdExecution->GetDoubleValue(), 0.0f);
ASSERT_EQ(stripIdExecution->GetValue(), 0.0f);
auto stateIDExecution = executionState->FindValue<AMFDoubleValue>("stateID");
auto stateIdExecution = executionState->Get<double>("stateID");
ASSERT_EQ(stateIDExecution->GetDoubleValue(), 0.0f);
ASSERT_EQ(stateIdExecution->GetValue(), 0.0f);
auto states = result->FindValue<AMFArrayValue>("states")->GetDenseArray();
auto states = result->GetArray("states")->GetDense();
ASSERT_EQ(states.size(), 1);
auto firstState = dynamic_cast<AMFArrayValue*>(states[0]);
auto stateID = firstState->FindValue<AMFDoubleValue>("id");
auto stateID = firstState->Get<double>("id");
ASSERT_EQ(stateID->GetDoubleValue(), 0.0f);
ASSERT_EQ(stateID->GetValue(), 0.0f);
auto stripsInState = firstState->FindValue<AMFArrayValue>("strips")->GetDenseArray();
auto stripsInState = firstState->GetArray("strips")->GetDense();
ASSERT_EQ(stripsInState.size(), 1);
auto firstStrip = dynamic_cast<AMFArrayValue*>(stripsInState[0]);
auto actionsInFirstStrip = firstStrip->FindValue<AMFArrayValue>("actions")->GetDenseArray();
auto actionsInFirstStrip = firstStrip->GetArray("actions")->GetDense();
ASSERT_EQ(actionsInFirstStrip.size(), 3);
auto actionID = firstStrip->FindValue<AMFDoubleValue>("id");
auto actionID = firstStrip->Get<double>("id");
ASSERT_EQ(actionID->GetDoubleValue(), 0.0f);
ASSERT_EQ(actionID->GetValue(), 0.0f);
auto uiArray = firstStrip->FindValue<AMFArrayValue>("ui");
auto uiArray = firstStrip->GetArray("ui");
auto xPos = uiArray->FindValue<AMFDoubleValue>("x");
auto yPos = uiArray->FindValue<AMFDoubleValue>("y");
auto xPos = uiArray->Get<double>("x");
auto yPos = uiArray->Get<double>("y");
ASSERT_EQ(xPos->GetDoubleValue(), 103.0f);
ASSERT_EQ(yPos->GetDoubleValue(), 82.0f);
ASSERT_EQ(xPos->GetValue(), 103.0f);
ASSERT_EQ(yPos->GetValue(), 82.0f);
auto stripId = firstStrip->FindValue<AMFDoubleValue>("id");
auto stripId = firstStrip->Get<double>("id");
ASSERT_EQ(stripId->GetDoubleValue(), 0.0f);
ASSERT_EQ(stripId->GetValue(), 0.0f);
auto firstAction = dynamic_cast<AMFArrayValue*>(actionsInFirstStrip[0]);
auto firstType = firstAction->FindValue<AMFStringValue>("Type");
auto firstType = firstAction->Get<std::string>("Type");
ASSERT_EQ(firstType->GetStringValue(), "OnInteract");
ASSERT_EQ(firstType->GetValue(), "OnInteract");
auto firstCallback = firstAction->FindValue<AMFStringValue>("__callbackID__");
auto firstCallback = firstAction->Get<std::string>("__callbackID__");
ASSERT_EQ(firstCallback->GetStringValue(), "");
ASSERT_EQ(firstCallback->GetValue(), "");
auto secondAction = dynamic_cast<AMFArrayValue*>(actionsInFirstStrip[1]);
auto secondType = secondAction->FindValue<AMFStringValue>("Type");
auto secondType = secondAction->Get<std::string>("Type");
ASSERT_EQ(secondType->GetStringValue(), "FlyUp");
ASSERT_EQ(secondType->GetValue(), "FlyUp");
auto secondCallback = secondAction->FindValue<AMFStringValue>("__callbackID__");
auto secondCallback = secondAction->Get<std::string>("__callbackID__");
ASSERT_EQ(secondCallback->GetStringValue(), "");
ASSERT_EQ(secondCallback->GetValue(), "");
auto secondDistance = secondAction->FindValue<AMFDoubleValue>("Distance");
auto secondDistance = secondAction->Get<double>("Distance");
ASSERT_EQ(secondDistance->GetDoubleValue(), 25.0f);
ASSERT_EQ(secondDistance->GetValue(), 25.0f);
auto thirdAction = dynamic_cast<AMFArrayValue*>(actionsInFirstStrip[2]);
auto thirdType = thirdAction->FindValue<AMFStringValue>("Type");
auto thirdType = thirdAction->Get<std::string>("Type");
ASSERT_EQ(thirdType->GetStringValue(), "FlyDown");
ASSERT_EQ(thirdType->GetValue(), "FlyDown");
auto thirdCallback = thirdAction->FindValue<AMFStringValue>("__callbackID__");
auto thirdCallback = thirdAction->Get<std::string>("__callbackID__");
ASSERT_EQ(thirdCallback->GetStringValue(), "");
ASSERT_EQ(thirdCallback->GetValue(), "");
auto thirdDistance = thirdAction->FindValue<AMFDoubleValue>("Distance");
auto thirdDistance = thirdAction->Get<double>("Distance");
ASSERT_EQ(thirdDistance->GetDoubleValue(), 25.0f);
ASSERT_EQ(thirdDistance->GetValue(), 25.0f);
}
/**
* @brief Tests that having no BitStream returns a nullptr.
*/
TEST(dCommonTests, AMFDeserializeNullTest) {
auto result = ReadFromBitStream(nullptr);
std::unique_ptr<AMFBaseValue> result(ReadFromBitStream(nullptr));
ASSERT_EQ(result.get(), nullptr);
}
@@ -361,25 +364,25 @@ TEST(dCommonTests, AMFBadConversionTest) {
testFileStream.close();
auto resultFromFn = ReadFromBitStream(&testBitStream);
std::unique_ptr<AMFBaseValue> resultFromFn(ReadFromBitStream(&testBitStream));
auto result = static_cast<AMFArrayValue*>(resultFromFn.get());
// Actually a string value.
ASSERT_EQ(result->FindValue<AMFDoubleValue>("BehaviorID"), nullptr);
ASSERT_EQ(result->Get<double>("BehaviorID"), nullptr);
// Does not exist in the associative portion
ASSERT_EQ(result->FindValue<AMFNullValue>("DOES_NOT_EXIST"), nullptr);
ASSERT_EQ(result->Get<nullptr_t>("DOES_NOT_EXIST"), nullptr);
result->PushBackValue(new AMFTrueValue());
result->Push(true);
// Exists and is correct type
ASSERT_NE(result->GetValueAt<AMFTrueValue>(0), nullptr);
ASSERT_NE(result->Get<bool>(0), nullptr);
// Value exists but is wrong typing
ASSERT_EQ(result->GetValueAt<AMFFalseValue>(0), nullptr);
ASSERT_EQ(result->Get<std::string>(0), nullptr);
// Value is out of bounds
ASSERT_EQ(result->GetValueAt<AMFTrueValue>(1), nullptr);
ASSERT_EQ(result->Get<bool>(1), nullptr);
}
/**

View File

@@ -0,0 +1,116 @@
#include <gtest/gtest.h>
#include <vector>
#include "Amf3.h"
TEST(dCommonTests, AMF3AssociativeArrayTest) {
AMFArrayValue array;
array.Insert("true", true);
array.Insert("false", false);
// test associative can insert values
ASSERT_EQ(array.GetAssociative().size(), 2);
ASSERT_EQ(array.Get<bool>("true")->GetValueType(), eAmf::True);
ASSERT_EQ(array.Get<bool>("false")->GetValueType(), eAmf::False);
// Test associative can remove values
array.Remove("true");
ASSERT_EQ(array.GetAssociative().size(), 1);
ASSERT_EQ(array.Get<bool>("true"), nullptr);
ASSERT_EQ(array.Get<bool>("false")->GetValueType(), eAmf::False);
array.Remove("false");
ASSERT_EQ(array.GetAssociative().size(), 0);
ASSERT_EQ(array.Get<bool>("true"), nullptr);
ASSERT_EQ(array.Get<bool>("false"), nullptr);
// Test that multiple of the same key respect only the first element of that key
array.Insert("true", true);
array.Insert("true", false);
ASSERT_EQ(array.GetAssociative().size(), 1);
ASSERT_EQ(array.Get<bool>("true")->GetValueType(), eAmf::True);
array.Remove("true");
// Now test the dense portion
// Get some out of bounds values and cast to incorrect template types
array.Push(true);
array.Push(false);
ASSERT_EQ(array.GetDense().size(), 2);
ASSERT_EQ(array.Get<bool>(0)->GetValueType(), eAmf::True);
ASSERT_EQ(array.Get<std::string>(0), nullptr);
ASSERT_EQ(array.Get<bool>(1)->GetValueType(), eAmf::False);
ASSERT_EQ(array.Get<bool>(155), nullptr);
array.Pop();
ASSERT_EQ(array.GetDense().size(), 1);
ASSERT_EQ(array.Get<bool>(0)->GetValueType(), eAmf::True);
ASSERT_EQ(array.Get<std::string>(0), nullptr);
ASSERT_EQ(array.Get<bool>(1), nullptr);
array.Pop();
ASSERT_EQ(array.GetDense().size(), 0);
ASSERT_EQ(array.Get<bool>(0), nullptr);
ASSERT_EQ(array.Get<std::string>(0), nullptr);
ASSERT_EQ(array.Get<bool>(1), nullptr);
}
TEST(dCommonTests, AMF3InsertionAssociativeTest) {
AMFArrayValue array;
array.Insert("CString", "string");
array.Insert("String", std::string("string"));
array.Insert("False", false);
array.Insert("True", true);
array.Insert<int32_t>("Integer", 42U);
array.Insert("Double", 42.0);
array.InsertArray("Array");
array.Insert<std::vector<uint32_t>>("Undefined", {});
array.Insert("Null", nullptr);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<std::string>("String")->GetValueType(), eAmf::String);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<bool>("False")->GetValueType(), eAmf::False);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<bool>("True")->GetValueType(), eAmf::True);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<int32_t>("Integer")->GetValueType(), eAmf::Integer);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<double>("Double")->GetValueType(), eAmf::Double);
std::cout << "test" << std::endl;
ASSERT_EQ(array.GetArray("Array")->GetValueType(), eAmf::Array);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<nullptr_t>("Null")->GetValueType(), eAmf::Null);
std::cout << "test" << std::endl;
ASSERT_EQ(array.Get<std::vector<uint32_t>>("Undefined")->GetValueType(), eAmf::Undefined);
std::cout << "test" << std::endl;
}
TEST(dCommonTests, AMF3InsertionDenseTest) {
AMFArrayValue array;
array.Push<std::string>("string");
array.Push("CString");
array.Push(false);
array.Push(true);
array.Push<int32_t>(42U);
array.Push(42.0);
array.PushArray();
array.Push(nullptr);
array.Push<std::vector<uint32_t>>({});
ASSERT_EQ(array.Get<std::string>(0)->GetValueType(), eAmf::String);
ASSERT_EQ(array.Get<const char*>(1)->GetValueType(), eAmf::String);
ASSERT_EQ(array.Get<bool>(2)->GetValueType(), eAmf::False);
ASSERT_EQ(array.Get<bool>(3)->GetValueType(), eAmf::True);
ASSERT_EQ(array.Get<int32_t>(4)->GetValueType(), eAmf::Integer);
ASSERT_EQ(array.Get<double>(5)->GetValueType(), eAmf::Double);
ASSERT_EQ(array.GetArray(6)->GetValueType(), eAmf::Array);
ASSERT_EQ(array.Get<nullptr_t>(7)->GetValueType(), eAmf::Null);
ASSERT_EQ(array.Get<std::vector<uint32_t>>(8)->GetValueType(), eAmf::Undefined);
}

View File

@@ -1,5 +1,6 @@
set(DCOMMONTEST_SOURCES
"AMFDeserializeTests.cpp"
"Amf3Tests.cpp"
"HeaderSkipTest.cpp"
"TestLDFFormat.cpp"
"TestNiPoint3.cpp"

View File

@@ -1,5 +1,5 @@
#include "Action.h"
#include "AMFFormat.h"
#include "Amf3.h"
#include "AMFDeserialize.h"
#include "GameMessages.h"
#include "GameDependencies.h"
@@ -40,8 +40,8 @@ protected:
}
AMFArrayValue* ReadArrayFromBitStream(RakNet::BitStream* inStream) {
AMFDeserialize des;
AMFValue* readArray = des.Read(inStream);
EXPECT_EQ(readArray->GetValueType(), AMFValueType::AMFArray);
AMFBaseValue* readArray = des.Read(inStream);
EXPECT_EQ(readArray->GetValueType(), eAmf::Array);
return static_cast<AMFArrayValue*>(readArray);
}
};