Skip to content

Commit 7a6b6b3

Browse files
[NT-0] fix: Removing an asset collection assert (#841)
A CSP client app developer recently reported a crash when attempting to enter a space. Turns out it was due to there being an asset collection/prototype in the space that did not conform to the types CSP expects, which caused CSP to fire an assert. To fix, we follow the same pattern as with Asset.cpp and emit an Error log message instead of an assert.
1 parent f62bd69 commit 7a6b6b3

File tree

4 files changed

+117
-12
lines changed

4 files changed

+117
-12
lines changed

Library/src/Systems/Assets/AssetCollection.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
#include "CSP/Systems/Assets/AssetCollection.h"
17+
#include "Debug/Logging.h"
1718

1819
#include "CSP/Common/Systems/Log/LogSystem.h"
1920
#include "Services/ApiBase/ApiBase.h"
@@ -31,8 +32,6 @@ csp::systems::EAssetCollectionType ConvertDTOPrototypeType(const csp::common::St
3132
{
3233
if (DTOPrototypeType == "Default")
3334
return csp::systems::EAssetCollectionType::DEFAULT;
34-
else if (DTOPrototypeType == "Charity")
35-
return csp::systems::EAssetCollectionType::FOUNDATION_INTERNAL;
3635
else if (DTOPrototypeType == "FoundationInternal")
3736
return csp::systems::EAssetCollectionType::FOUNDATION_INTERNAL;
3837
else if (DTOPrototypeType == "CommentContainer")
@@ -43,7 +42,8 @@ csp::systems::EAssetCollectionType ConvertDTOPrototypeType(const csp::common::St
4342
return csp::systems::EAssetCollectionType::SPACE_THUMBNAIL;
4443
else
4544
{
46-
assert(false && "Unsupported Prototype Type!");
45+
CSP_LOG_FORMAT(csp::common::LogLevel::Error, "Encountered unknown prototype type whilst processing an asset collection DTO: %s",
46+
DTOPrototypeType.c_str());
4747
return csp::systems::EAssetCollectionType::DEFAULT;
4848
}
4949
}
@@ -56,8 +56,15 @@ namespace csp::systems
5656
// Currently known to be compatible with both chs::PrototypeDto and chs::CopiedPrototypeDto.
5757
template <class PrototypeDto> void AssetCollectionFromDtoOfType(const PrototypeDto& Dto, csp::systems::AssetCollection& AssetCollection)
5858
{
59-
AssetCollection.Id = Dto.GetId();
60-
AssetCollection.Name = Dto.GetName();
59+
if (Dto.HasId())
60+
{
61+
AssetCollection.Id = Dto.GetId();
62+
}
63+
64+
if (Dto.HasName())
65+
{
66+
AssetCollection.Name = Dto.GetName();
67+
}
6168

6269
if (Dto.HasType())
6370
{
@@ -106,10 +113,25 @@ template <class PrototypeDto> void AssetCollectionFromDtoOfType(const PrototypeD
106113
}
107114
}
108115

109-
AssetCollection.CreatedBy = Dto.GetCreatedBy();
110-
AssetCollection.CreatedAt = Dto.GetCreatedAt();
111-
AssetCollection.UpdatedBy = Dto.GetUpdatedBy();
112-
AssetCollection.UpdatedAt = Dto.GetUpdatedAt();
116+
if (Dto.HasCreatedBy())
117+
{
118+
AssetCollection.CreatedBy = Dto.GetCreatedBy();
119+
}
120+
121+
if (Dto.HasCreatedAt())
122+
{
123+
AssetCollection.CreatedAt = Dto.GetCreatedAt();
124+
}
125+
126+
if (Dto.HasUpdatedBy())
127+
{
128+
AssetCollection.UpdatedBy = Dto.GetUpdatedBy();
129+
}
130+
131+
if (Dto.HasUpdatedAt())
132+
{
133+
AssetCollection.UpdatedAt = Dto.GetUpdatedAt();
134+
}
113135

114136
if (Dto.HasHighlander())
115137
{

Tests/src/PublicAPITests/AssetSystemTests.cpp

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "CSP/Systems/Spaces/SpaceSystem.h"
2222
#include "CSP/Systems/SystemsManager.h"
2323
#include "RAIIMockLogger.h"
24+
#include "Services/PrototypeService/PrototypeServiceApiMock.h"
2425
#include "SpaceSystemTestHelpers.h"
2526
#include "Systems/ResultHelpers.h"
2627
#include "TestHelpers.h"
@@ -36,9 +37,13 @@
3637

3738
#include "gtest/gtest.h"
3839
#include <filesystem>
40+
#include <future>
41+
#include <gmock/gmock.h>
3942

4043
using namespace csp::multiplayer;
4144

45+
namespace chs_prototype = csp::services::generated::prototypeservice;
46+
4247
namespace
4348
{
4449

@@ -2481,4 +2486,79 @@ CSP_PUBLIC_TEST(CSPEngine, AssetSystemTests, GetAssetCollectionCountTest)
24812486
DeleteSpace(SpaceSystem, Space.Id);
24822487

24832488
LogOut(UserSystem);
2484-
}
2489+
}
2490+
2491+
class AssetCollectionTypeDtoMock
2492+
: public PublicTestBaseWithParam<std::tuple<csp::common::String, csp::systems::EAssetCollectionType, csp::common::String>>
2493+
{
2494+
};
2495+
2496+
TEST_P(AssetCollectionTypeDtoMock, AssetCollectionTypeDtoMockTest)
2497+
{
2498+
const auto PrototypeServiceMock = std::make_unique<csp::services::generated::prototypeservice::PrototypeApiMock>();
2499+
2500+
csp::systems::SystemsManager::Get().GetLogSystem()->SetSystemLevel(csp::common::LogLevel::Error);
2501+
2502+
// Test parameters
2503+
const csp::common::String& DtoTypeString = std::get<0>(GetParam());
2504+
const csp::systems::EAssetCollectionType ExpectedAssetCollectionType = std::get<1>(GetParam());
2505+
const csp::common::String& ExpectedLogMessage = std::get<2>(GetParam());
2506+
2507+
const csp::common::String& MockAssetCollectionId = "1234";
2508+
2509+
// The promise
2510+
std::promise<csp::systems::AssetCollectionResult> ResultPromise;
2511+
std::future<csp::systems::AssetCollectionResult> ResultFuture = ResultPromise.get_future();
2512+
2513+
EXPECT_CALL(*PrototypeServiceMock, prototypesIdGet)
2514+
.WillOnce(
2515+
[DtoTypeString](const chs_prototype::IPrototypeApiBase::prototypesIdGetParams& /*Params*/,
2516+
csp::services::ApiResponseHandlerBase* ResponseHandler, csp::common::CancellationToken& /*CancellationToken*/)
2517+
{
2518+
chs_prototype::PrototypeDto Dto;
2519+
auto Response = csp::web::HttpResponse();
2520+
Response.SetResponseCode(csp::web::EResponseCodes::ResponseOK);
2521+
2522+
csp::web::HttpPayload Payload;
2523+
2524+
const csp::common::String RequestBody = R"(
2525+
{
2526+
"type": ")"
2527+
+ DtoTypeString + R"("
2528+
}
2529+
)";
2530+
2531+
Payload.AddHeader(CSP_TEXT("Content-Type"), CSP_TEXT("application/json"));
2532+
Payload.SetContent(RequestBody);
2533+
2534+
Response.GetMutablePayload() = Payload;
2535+
ResponseHandler->OnHttpResponse(Response);
2536+
});
2537+
2538+
csp::systems::AssetCollectionResultCallback Callback
2539+
= [&ResultPromise](const csp::systems::AssetCollectionResult& Result) { ResultPromise.set_value(Result); };
2540+
2541+
csp::services::ResponseHandlerPtr ResponseHandler = PrototypeServiceMock->CreateHandler<csp::systems::AssetCollectionResultCallback,
2542+
csp::systems::AssetCollectionResult, void, csp::services::generated::prototypeservice::PrototypeDto>(Callback, nullptr);
2543+
2544+
RAIIMockLogger MockLogger {};
2545+
if (ExpectedLogMessage.IsEmpty() == false)
2546+
{
2547+
EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Error, testing::HasSubstr(ExpectedLogMessage))).Times(1);
2548+
}
2549+
2550+
PrototypeServiceMock->prototypesIdGet({ MockAssetCollectionId }, ResponseHandler, csp::common::CancellationToken::Dummy());
2551+
auto Result = ResultFuture.get();
2552+
2553+
EXPECT_EQ(Result.GetHttpResultCode(), static_cast<uint16_t>(csp::web::EResponseCodes::ResponseOK));
2554+
EXPECT_EQ(Result.GetAssetCollection().Type, ExpectedAssetCollectionType);
2555+
}
2556+
2557+
INSTANTIATE_TEST_SUITE_P(AssetSystemTests, AssetCollectionTypeDtoMock,
2558+
testing::Values(std::make_tuple("Default", csp::systems::EAssetCollectionType::DEFAULT, ""),
2559+
std::make_tuple("FoundationInternal", csp::systems::EAssetCollectionType::FOUNDATION_INTERNAL, ""),
2560+
std::make_tuple("CommentContainer", csp::systems::EAssetCollectionType::COMMENT_CONTAINER, ""),
2561+
std::make_tuple("Comment", csp::systems::EAssetCollectionType::COMMENT, ""),
2562+
std::make_tuple("SpaceThumbnail", csp::systems::EAssetCollectionType::SPACE_THUMBNAIL, ""),
2563+
std::make_tuple("NotARealType", csp::systems::EAssetCollectionType::DEFAULT,
2564+
"Encountered unknown prototype type whilst processing an asset collection DTO:")));

Tests/src/PublicTestBase.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,5 @@ template class PublicTestBaseWithParam<std::tuple<csp::common::RealtimeEngineTyp
131131
template class PublicTestBaseWithParam<csp::common::RealtimeEngineType>;
132132
template class PublicTestBaseWithParam<std::tuple<csp::common::RealtimeEngineType, bool>>;
133133
template class PublicTestBaseWithParam<std::tuple<csp::systems::AvatarType, csp::common::String, bool>>;
134-
template class PublicTestBaseWithParam<std::tuple<csp::systems::EResultCode, csp::web::EResponseCodes, csp::common::String, bool>>;
134+
template class PublicTestBaseWithParam<std::tuple<csp::systems::EResultCode, csp::web::EResponseCodes, csp::common::String, bool>>;
135+
template class PublicTestBaseWithParam<std::tuple<csp::common::String, csp::systems::EAssetCollectionType, csp::common::String>>;

Tests/src/PublicTestBase.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "CSP/Common/Interfaces/IRealtimeEngine.h"
1919
#include "CSP/Common/SharedEnums.h"
20+
#include "CSP/Systems/Assets/AssetCollection.h"
2021
#include "CSP/Systems/Settings/SettingsCollection.h"
2122
#include "CSP/Systems/Spaces/Space.h"
2223
#include "Mocks/SignalRConnectionMock.h"
@@ -75,4 +76,5 @@ extern template class PublicTestBaseWithParam<std::tuple<csp::common::RealtimeEn
7576
extern template class PublicTestBaseWithParam<csp::common::RealtimeEngineType>;
7677
extern template class PublicTestBaseWithParam<std::tuple<csp::common::RealtimeEngineType, bool>>;
7778
extern template class PublicTestBaseWithParam<std::tuple<csp::systems::AvatarType, csp::common::String, bool>>;
78-
extern template class PublicTestBaseWithParam<std::tuple<csp::systems::EResultCode, csp::web::EResponseCodes, csp::common::String, bool>>;
79+
extern template class PublicTestBaseWithParam<std::tuple<csp::systems::EResultCode, csp::web::EResponseCodes, csp::common::String, bool>>;
80+
extern template class PublicTestBaseWithParam<std::tuple<csp::common::String, csp::systems::EAssetCollectionType, csp::common::String>>;

0 commit comments

Comments
 (0)