Implemented a deferred LoadLevel queue for the SpawnableLevelSystem (#4561)

* Moved the SettingsRegistryTests.cpp and
SettingsRegistryMergeUtilsTests.cpp to the Settings folder

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Implemented a deferred level load queue, that allows the
SpawnableLevelSystem to re-run the last LoadLevel command that occured
before it was constructed.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Added SettingsRegistryVisitorUtils to reduce Array and Object visitor
boilerplate.

The VisitArray and VisitObject functions allows iteration over each
element of array and object respectively via a callback.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Removed the queuing logic for levels that attempt to load before the SpawnableLevelSystem is available

Only the last level name that could not load is stored off and deferred until the SpawnableLevelsystem is created.

Made the FieldVisitor AggregateTypes constructor protected and added a comment specifying the expected values.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Bring in the SettingsRegistry::Visitor::Visit functions into scope to fix MSVC compilation errors.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>

* Changed the list of supported SettingsRegistry types to visit to an enum to constrain the values to Array and/or Object.

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
lumberyard-employee-dm
2021-10-08 20:09:22 -05:00
committed by GitHub
parent e4d3ab118c
commit 7b1dd01d1d
10 changed files with 456 additions and 8 deletions
@@ -0,0 +1,196 @@
/*
* 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 <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/string/string.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace SettingsRegistryVisitorUtilsTests
{
struct VisitCallbackParams
{
AZStd::string_view m_inputJsonDocument;
using VisitFieldFunction = bool(*)(AZ::SettingsRegistryInterface&,
const AZ::SettingsRegistryVisitorUtils::VisitorCallback&,
AZStd::string_view);
static inline constexpr size_t MaxFieldCount = 10;
using ObjectFields = AZStd::fixed_vector<AZStd::pair<AZStd::string_view, AZStd::string_view>, MaxFieldCount>;
using ArrayFields = AZStd::fixed_vector<AZStd::string_view, MaxFieldCount>;
ObjectFields m_objectFields;
ArrayFields m_arrayFields;
};
template <typename VisitorParams>
class SettingsRegistryVisitorUtilsParamFixture
: public UnitTest::ScopedAllocatorSetupFixture
, public ::testing::WithParamInterface<VisitorParams>
{
public:
void SetUp() override
{
m_registry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
}
void TearDown() override
{
m_registry.reset();
}
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_registry;
};
using SettingsRegistryVisitCallbackFixture = SettingsRegistryVisitorUtilsParamFixture<VisitCallbackParams>;
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfArrayType_ReturnsFields)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testArrayFields.emplace_back(AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Array");
const AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> expectedFields{
visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() };
EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedFields));
}
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfObjectType_ReturnsFields)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Object");
const AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> expectedFields{
visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() };
EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedFields));
}
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfArrayType_ReturnsFields)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testArrayFields.emplace_back(AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Array");
const AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> expectedArrayFields{
visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() };
EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedArrayFields));
}
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfObjectType_ReturnsEmpty)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testArrayFields.emplace_back(AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Object");
EXPECT_TRUE(testArrayFields.empty());
}
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfArrayType_ReturnsEmpty)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Array");
EXPECT_TRUE(testObjectFields.empty());
}
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfObjectType_ReturnsFields)
{
const VisitCallbackParams& visitParams = GetParam();
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
{
AZStd::string fieldValue;
EXPECT_TRUE(m_registry->Get(fieldValue, path));
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
};
AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Object");
const AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> expectedObjectFields{
visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() };
EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedObjectFields));
}
INSTANTIATE_TEST_CASE_P(
VisitField,
SettingsRegistryVisitCallbackFixture,
::testing::Values(
VisitCallbackParams
{
R"({)" "\n"
R"( "Test":)" "\n"
R"( {)" "\n"
R"( "Array": [ "Hello", "World" ],)" "\n"
R"( "Object": { "Foo": "Hello", "Bar": "World"})" "\n"
R"( })" "\n"
R"(})" "\n",
VisitCallbackParams::ObjectFields{{"Foo", "Hello"}, {"Bar", "World"}},
VisitCallbackParams::ArrayFields{"Hello", "World"}
}
)
);
}
@@ -75,11 +75,12 @@ set(FILES
Name/NameJsonSerializerTests.cpp
Name/NameTests.cpp
RTTI/TypeSafeIntegralTests.cpp
SettingsRegistryTests.cpp
SettingsRegistryMergeUtilsTests.cpp
Settings/CommandLineTests.cpp
Settings/SettingsRegistryTests.cpp
Settings/SettingsRegistryConsoleUtilsTests.cpp
Settings/SettingsRegistryMergeUtilsTests.cpp
Settings/SettingsRegistryScriptUtilsTests.cpp
Settings/SettingsRegistryVisitorUtilsTests.cpp
Streamer/BlockCacheTests.cpp
Streamer/DedicatedCacheTests.cpp
Streamer/FullDecompressorTests.cpp