JD2022-TU1/main/extern/UbiServices/custom/testsIntegration/testNews.cpp

1495 lines
66 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/loginMockFixture.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/mockResultHelper.h"
#include "tests/mock/parametersMockHelper.h"
#include <ubiservices/core/errors/errorCodes.h>
#include <../private/ubiservices/core/http/httpEntity.h>
#include <../private/ubiservices/services/cacheManager.h>
#include <../private/ubiservices/services/parameters/parametersClientProxy.h>
#include <../private/ubiservices/services/news/newsProxy.h>
#include <ubiservices/facade.h>
#include <ubiservices/localizationHelper.h>
#include <ubiservices/services/http/request/httpGet.h>
#include <ubiservices/services/http/request/httpPost.h>
#include <ubiservices/services/news/newsClient.h>
#include <ubiservices/services/news/newsInfo.h>
#include <ubiservices/services/parameters/parametersClient.h>
#define DUMMY_PROFILE_ID DUMMY_GUID_ID1
namespace US_NS {;
US_DEFINE_TEST(TestNews);
typedef AuthenticationFixture<1> NEWS;
typedef LoginMockFixture<true> NEWS_MOCK;
typedef LoginMockFixtureNoInit NEWS_MOCK_NOINIT;
namespace TestNews_BF
{
#if !defined(US_DLL)
static ::testing::AssertionResult checkResultingNews(const Vector<NewsInfo>& news)
{
if (news.size() != 6)
{
return ::testing::AssertionFailure() << "There shall be 6 news in the result list";
}
else if ((news.front().m_links.size() != 2) || (news.back().m_links.size() != 2))
{
return ::testing::AssertionFailure() << "There shall be 2 links for each news";
}
return ::testing::AssertionSuccess();
}
#endif
String createMockResult()
{
return "{"
"\"news\":"
"["
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane.AC4_DLC_01\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu1\","
"\"priority\":1,"
"\"displayTime\":20,"
"\"publicationDate\":\"2014-11-11 12:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"web\","
"\"param\":\"http://acu.ubisoft.com/dlc1/description.html\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"},"
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane.AC4_DLC_02\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu1\","
"\"priority\":2,"
"\"displayTime\":10,"
"\"publicationDate\":\"2014-11-11 13:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"web\","
"\"param\":\"http://acu.ubisoft.com/dlc1/description.html\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"},"
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane.AC4_DLC_03\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu2\","
"\"priority\":1,"
"\"displayTime\":15,"
"\"publicationDate\":\"2014-11-11 14:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"web\","
"\"param\":\"http://acu.ubisoft.com/dlc1/description.html\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"},"
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane.AC4_DLC_04\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu2\","
"\"priority\":2,"
"\"displayTime\":5,"
"\"publicationDate\":\"2014-11-11 15:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"web\","
"\"param\":\"http://acu.ubisoft.com/dlc1/description.html\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"},"
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane2.AC4_DLC_05\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu3\","
"\"priority\":1,"
"\"displayTime\":30,"
"\"publicationDate\":\"2014-11-22 16:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"web\","
"\"param\":\"http://acu.ubisoft.com/dlc1/description.html\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"},"
"{"
"\"profileId\":\"" DUMMY_PROFILE_ID "\","
"\"spaceId\":\"3a441107-673a-40b7-a304-0cd5fcb7ee9b\","
"\"newsId\":\"neolane2.AC4_DLC_06\","
"\"type\":\"DLCOffer\","
"\"placement\":\"mainMenu3\","
"\"priority\":2,"
"\"displayTime\":35,"
"\"publicationDate\":\"2014-11-22 17:00:00Z\","
"\"locale\":\"en-US\","
"\"title\":\"New DLC Released\","
"\"body\":\"Get the Season Pass DLC from the Marketplace\","
"\"mediaURL\":\"http://static8.ubisoft.com/234224/asset34.png\","
"\"mediaType\":\"image/png\","
"\"links\":"
"["
"{"
"\"type\":\"pstore\","
"\"param\":\"0x555308796ea1e800\","
"\"actionName\":\"OpenedTheStoreForSeasonPass\","
"\"actionDescription\":\"Buy the Season Pass\""
"},"
"{"
"\"type\":\"sstore\","
"\"param\":\"0x555308796ea1e801\","
"\"actionName\":\"MoreInfoOnSeasonPass\","
"\"actionDescription\":\"More info...\""
"}"
"],"
"\"obj\":{\"assetId\":13}"
"}"
"]"
"}";
}
Map<int32, String> extractEventsFromRequest(const HttpPost& eventRequest)
{
const Json requestBodyJson(eventRequest.getBodyAsString());
const Vector<Json> eventsArray = requestBodyJson["events"].getValueArray();
Map<int32, String> events;
for (const auto& it : eventsArray)
{
events[it["seqId"].getValueInteger()] = it["type"].getValueString();
}
return events;
}
}
/// @test Requests news to the server, validating that the received content
/// matches with records provisioned (external requirement).
/// The following URL allows to configure news in UAT:
/// http://ingame-news-preview-backoffice.ubisoft.org/
#if (defined(US_TARGET_IOS) && !defined(US_UPLAY_LOGIN_FOR_IOS)) || defined(US_CHINA_SERVICE_UNAVAILABLE) // need the good url with rail id placeholder
TEST_F(NEWS, DISABLED_US_RequestNews) // News Services does not support Game Center tickets
#else
TEST_F(NEWS, US_MINRUN_RequestNews)
#endif
{
#if defined(ENABLING_VERBOSE_LOGGING)
LoggingHelper::enableVerbose();
LoggingHelper::enableMultiLines();
#endif
struct Local
{
static void validateInstance(const NewsInfo& info, const SpaceId& spaceId, bool checkProfile)
{
PRINT_STREAM(info);
EXPECT_TRUE(info.m_profileId.isValid() || !checkProfile);
//EXPECT_EQ(ProfileId("4d9061de-7c20-4cc9-9f55-b8d6228da6ae"), info.m_profileId);
EXPECT_EQ(spaceId, info.m_spaceId);
EXPECT_STREQ("Promo", info.m_type.getUtf8());
EXPECT_STREQ("MainMenu1", info.m_placement.getUtf8());
EXPECT_EQ(10u, info.m_priority);
EXPECT_EQ(30u, info.m_displayTime);
EXPECT_EQ(DateTime(2015, 4, 28, 13, 1, 0), info.m_publicationDate);
EXPECT_STREQ("en-US", info.m_locale.getUtf8());
EXPECT_STREQ("News Title #1", info.m_title.getUtf8());
EXPECT_STREQ("News Content #1", info.m_body.getUtf8());
EXPECT_STREQ("https://ingame-news-preview-backoffice.ubisoft.org/Content/IGN_STG_87x37.png", info.m_mediaUrl.getUtf8());
EXPECT_STREQ("Image", info.m_mediaType.getUtf8());
ASSERT_EQ(2u, info.m_links.size());
{
const NewsLink& link1 = info.m_links.front();
EXPECT_STREQ("weblink", link1.m_type.getUtf8());
EXPECT_STREQ("http://www.ubi.com", link1.m_param.getUtf8());
EXPECT_STREQ("", link1.m_actionName.getUtf8());
EXPECT_STREQ("", link1.m_actionDescription.getUtf8());
}
{
const NewsLink& link2 = info.m_links.back();
EXPECT_STREQ("weblink", link2.m_type.getUtf8());
EXPECT_STREQ("http://www.ubi.com/frca/", link2.m_param.getUtf8());
EXPECT_STREQ("", link2.m_actionName.getUtf8());
EXPECT_STREQ("", link2.m_actionDescription.getUtf8());
}
EXPECT_STREQ("{\"J\":5,\"0\":\"X\"}", info.m_object.getUtf8());
ASSERT_TRUE(info.m_summary.isSpecified());
EXPECT_STREQ("", info.m_summary.value().getUtf8());
EXPECT_EQ(0u, info.m_tags.size());
}
// ::testing::AssertionResult
// return ::testing::AssertionFailure() << "Request time out after " << NS_COMMON::DEFAULT_WAIT_TIME << " ms";
// ::testing::AssertionSuccess();
static ::testing::AssertionResult validateNews(const SpaceId& spaceId, const Vector<NewsInfo>& news, bool checkProfile)
{
bool isNewsFound = false;
for (const auto& it : news)
{
if (it.m_id == "ignt.63")
{
isNewsFound = true;
validateInstance(it, spaceId, checkProfile);
break;
}
}
return isNewsFound
? ::testing::AssertionSuccess()
: ::testing::AssertionFailure() << "News not found among " << news.size() << " news in the list";
}
};
const SpaceId spaceId(US_TEST_NS::SPACE_ID_US_SDK_PC);
{
LocalizationHelper::setLocaleCode("en-US");
{
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestProfileNews(spaceId);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_TRUE(Local::validateNews(spaceId, result.getResult(), true));
}
{
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNews(spaceId);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_TRUE(Local::validateNews(spaceId, result.getResult(), false)); //profile news points to the space news.
}
}
{
LocalizationHelper::setLocaleCode("fr-CA");
{
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestProfileNews(spaceId);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_FALSE(Local::validateNews(spaceId, result.getResult(), true));
}
{
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNews(spaceId);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_FALSE(Local::validateNews(spaceId, result.getResult(), false)); //profile news points to the space news.
}
}
}
/// @test Requests news to the server for a space that has no news provisioned.
#if (defined(US_TARGET_IOS) && !defined(US_UPLAY_LOGIN_FOR_IOS)) || defined(US_CHINA_SERVICE_UNAVAILABLE) // return HTTP_403_FORBIDDEN
TEST_F(NEWS, DISABLED_US_RequestNewsNoNewsForSpaceId) // News Services does not support Game Center tickets
#else
TEST_F(NEWS, US_RequestNewsNoNewsForSpaceId)
#endif
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 404", LogLevel::Error, Times(1));
});
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient()
.requestProfileNews(SpaceId("11111111-2222-3333-4444-555566667777")), Errors::HTTP_404_NOT_FOUND));
}
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON
TEST_F(NEWS_MOCK, USNOT_RequestNewsProfile)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(TestNews_BF::createMockResult()));
const AsyncResult<Vector<NewsInfo> > newsResult = getFacade().getNewsClient().requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
const Vector<NewsInfo>& news0 = newsResult.getResult();
ASSERT_TRUE(TestNews_BF::checkResultingNews(news0)) << "News configuration is wrong";
{
const NewsInfo& info = news0.front();
EXPECT_TRUE(info.m_profileId.isValid());
EXPECT_EQ(ProfileId(DUMMY_PROFILE_ID), info.m_profileId);
EXPECT_EQ(SpaceId("3a441107-673a-40b7-a304-0cd5fcb7ee9b"), info.m_spaceId);
EXPECT_STREQ("neolane.AC4_DLC_01", info.m_id.getUtf8());
EXPECT_STREQ("DLCOffer", info.m_type.getUtf8());
EXPECT_STREQ("mainMenu1", info.m_placement.getUtf8());
EXPECT_EQ(1u, info.m_priority);
EXPECT_EQ(20u, info.m_displayTime);
EXPECT_EQ(DateTime(2014, 11, 11, 12, 0, 0), info.m_publicationDate);
EXPECT_STREQ("en-US", info.m_locale.getUtf8());
EXPECT_STREQ("New DLC Released", info.m_title.getUtf8());
EXPECT_STREQ("Get the Season Pass DLC from the Marketplace", info.m_body.getUtf8());
EXPECT_STREQ("http://static8.ubisoft.com/234224/asset34.png", info.m_mediaUrl.getUtf8());
EXPECT_STREQ("image/png", info.m_mediaType.getUtf8());
{
const NewsLink& link1 = info.m_links.front();
EXPECT_STREQ("pstore", link1.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e800", link1.m_param.getUtf8());
EXPECT_STREQ("OpenedTheStoreForSeasonPass", link1.m_actionName.getUtf8());
EXPECT_STREQ("Buy the Season Pass", link1.m_actionDescription.getUtf8());
}
{
const NewsLink& link2 = info.m_links.back();
EXPECT_STREQ("web", link2.m_type.getUtf8());
EXPECT_STREQ("http://acu.ubisoft.com/dlc1/description.html", link2.m_param.getUtf8());
EXPECT_STREQ("MoreInfoOnSeasonPass", link2.m_actionName.getUtf8());
EXPECT_STREQ("More info...", link2.m_actionDescription.getUtf8());
}
EXPECT_STREQ("{\"assetId\":13}", info.m_object.getUtf8());
}
{
const NewsInfo& info = news0.back();
EXPECT_TRUE(info.m_profileId.isValid());
EXPECT_EQ(ProfileId(DUMMY_PROFILE_ID), info.m_profileId);
EXPECT_EQ(SpaceId("3a441107-673a-40b7-a304-0cd5fcb7ee9b"), info.m_spaceId);
EXPECT_STREQ("neolane2.AC4_DLC_06", info.m_id.getUtf8());
EXPECT_STREQ("DLCOffer", info.m_type.getUtf8());
EXPECT_STREQ("mainMenu3", info.m_placement.getUtf8());
EXPECT_EQ(2u, info.m_priority);
EXPECT_EQ(35u, info.m_displayTime);
EXPECT_EQ(DateTime(2014, 11, 22, 17, 0, 0), info.m_publicationDate);
EXPECT_STREQ("en-US", info.m_locale.getUtf8());
EXPECT_STREQ("New DLC Released", info.m_title.getUtf8());
EXPECT_STREQ("Get the Season Pass DLC from the Marketplace", info.m_body.getUtf8());
EXPECT_STREQ("http://static8.ubisoft.com/234224/asset34.png", info.m_mediaUrl.getUtf8());
EXPECT_STREQ("image/png", info.m_mediaType.getUtf8());
{
const NewsLink& link1 = info.m_links.front();
EXPECT_STREQ("pstore", link1.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e800", link1.m_param.getUtf8());
EXPECT_STREQ("OpenedTheStoreForSeasonPass", link1.m_actionName.getUtf8());
EXPECT_STREQ("Buy the Season Pass", link1.m_actionDescription.getUtf8());
}
{
const NewsLink& link2 = info.m_links.back();
EXPECT_STREQ("sstore", link2.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e801", link2.m_param.getUtf8());
EXPECT_STREQ("MoreInfoOnSeasonPass", link2.m_actionName.getUtf8());
EXPECT_STREQ("More info...", link2.m_actionDescription.getUtf8());
}
EXPECT_STREQ("{\"assetId\":13}", info.m_object.getUtf8());
}
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON
TEST_F(NEWS_MOCK, USNOT_RequestNewsProfileCache)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
const String jsonBody = TestNews_BF::createMockResult();
{
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(jsonBody));
}
NewsClient& client = getFacade().getNewsClient();
const AsyncResult<Vector<NewsInfo> > newsResult = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
const Vector<NewsInfo>& news0 = newsResult.getResult();
ASSERT_TRUE(TestNews_BF::checkResultingNews(news0)) << "News configuration is wrong";
// Requesting news a second time. This shall not affect the mock call expectations.
{
const AsyncResult<Vector<NewsInfo> > newsResult2 = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult2));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult2.getResult()));
}
// Requesting news a third time after requesting to clear the cache.
// This simulate the behaviour after a call to CacheManager::invalidateCaches()
// This requires new mock call expectations.
{
NewsProxy::invalidateCache(client, CacheUnit::NewsProfile);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult3 = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult3));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult3.getResult()));
}
// Requesting news a fourth time. This shall not affect the mock call expectations.
// The clear cache request only applies once.
{
const AsyncResult<Vector<NewsInfo> > newsResult4 = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult4));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult4.getResult()));
}
const SpaceId spaceId5("3a441107-673a-40b7-a304-0cd5fcb7FAKE");
// Requesting news a fifth time on a different space ID.
// This shall requires a new set of the mock call expectations.
{
// Note that the same JSON is sent here for a different Space Id...
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult5 = client.requestProfileNews(spaceId5);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult5));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult5.getResult()));
}
// Requesting news a sixth time for many space IDs.
// This shall requires a new set of the mock call expectations.
{
// Note that the same JSON is sent here for a different Space Id...
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult6 = client.requestProfileNews(SpaceId("3a441107-673a-40b7-a304-0cd5fcbFAKE1"));
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult6));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult6.getResult()));
}
// Requesting news a seventh time. This shall not affect the mock call expectations.
{
const AsyncResult<Vector<NewsInfo> > newsResult7 = client.requestProfileNews(spaceId5);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult7));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult7.getResult()));
}
// Requesting news shall not affect the mock call expectations
{
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
// Sleeping so all entries in cache expires
// This requires new mock call expectations.
{
// A quick check to make sure the mocked TTL is in an acceptable range
ASSERT_LT(ParametersSpaceMockHelper::s_MOCK_TIME_TO_LIVE_RESOURCE_MSEC, 15000);
US_TEST_NS::Helper::sleep(ParametersSpaceMockHelper::s_MOCK_TIME_TO_LIVE_RESOURCE_MSEC * 2);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
// Requesting news shall not affect the mock call expectations
{
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON
TEST_F(NEWS_MOCK, USNOT_RequestNewsSpace)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
SAVE_ALLOC_COUNT(count);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(TestNews_BF::createMockResult()));
EXPECT_ALLOC_COUNT_PC_EQ(28, count);
const AsyncResult<Vector<NewsInfo> > newsResult = getFacade().getNewsClient().requestSpaceNews();
EXPECT_ALLOC_COUNT_PC_EQ(31, count);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
// Check resulting news content
const Vector<NewsInfo>& news0 = newsResult.getResult();
ASSERT_TRUE(TestNews_BF::checkResultingNews(news0));
{
const NewsInfo& info = news0.front();
EXPECT_TRUE(info.m_profileId.isValid());
EXPECT_EQ(ProfileId(DUMMY_PROFILE_ID), info.m_profileId);
EXPECT_EQ(SpaceId("3a441107-673a-40b7-a304-0cd5fcb7ee9b"), info.m_spaceId);
EXPECT_STREQ("neolane.AC4_DLC_01", info.m_id.getUtf8());
EXPECT_STREQ("DLCOffer", info.m_type.getUtf8());
EXPECT_STREQ("mainMenu1", info.m_placement.getUtf8());
EXPECT_EQ(1u, info.m_priority);
EXPECT_EQ(20u, info.m_displayTime);
EXPECT_EQ(DateTime(2014, 11, 11, 12, 0, 0), info.m_publicationDate);
EXPECT_STREQ("en-US", info.m_locale.getUtf8());
EXPECT_STREQ("New DLC Released", info.m_title.getUtf8());
EXPECT_STREQ("Get the Season Pass DLC from the Marketplace", info.m_body.getUtf8());
EXPECT_STREQ("http://static8.ubisoft.com/234224/asset34.png", info.m_mediaUrl.getUtf8());
EXPECT_STREQ("image/png", info.m_mediaType.getUtf8());
{
const NewsLink& link1 = info.m_links.front();
EXPECT_STREQ("pstore", link1.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e800", link1.m_param.getUtf8());
EXPECT_STREQ("OpenedTheStoreForSeasonPass", link1.m_actionName.getUtf8());
EXPECT_STREQ("Buy the Season Pass", link1.m_actionDescription.getUtf8());
}
{
const NewsLink& link2 = info.m_links.back();
EXPECT_STREQ("web", link2.m_type.getUtf8());
EXPECT_STREQ("http://acu.ubisoft.com/dlc1/description.html", link2.m_param.getUtf8());
EXPECT_STREQ("MoreInfoOnSeasonPass", link2.m_actionName.getUtf8());
EXPECT_STREQ("More info...", link2.m_actionDescription.getUtf8());
}
EXPECT_STREQ("{\"assetId\":13}", info.m_object.getUtf8());
}
{
const NewsInfo& info = news0.back();
EXPECT_TRUE(info.m_profileId.isValid());
EXPECT_EQ(ProfileId(DUMMY_PROFILE_ID), info.m_profileId);
EXPECT_EQ(SpaceId("3a441107-673a-40b7-a304-0cd5fcb7ee9b"), info.m_spaceId);
EXPECT_STREQ("neolane2.AC4_DLC_06", info.m_id.getUtf8());
EXPECT_STREQ("DLCOffer", info.m_type.getUtf8());
EXPECT_STREQ("mainMenu3", info.m_placement.getUtf8());
EXPECT_EQ(2u, info.m_priority);
EXPECT_EQ(35u, info.m_displayTime);
EXPECT_EQ(DateTime(2014, 11, 22, 17, 0, 0), info.m_publicationDate);
EXPECT_STREQ("en-US", info.m_locale.getUtf8());
EXPECT_STREQ("New DLC Released", info.m_title.getUtf8());
EXPECT_STREQ("Get the Season Pass DLC from the Marketplace", info.m_body.getUtf8());
EXPECT_STREQ("http://static8.ubisoft.com/234224/asset34.png", info.m_mediaUrl.getUtf8());
EXPECT_STREQ("image/png", info.m_mediaType.getUtf8());
{
const NewsLink& link1 = info.m_links.front();
EXPECT_STREQ("pstore", link1.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e800", link1.m_param.getUtf8());
EXPECT_STREQ("OpenedTheStoreForSeasonPass", link1.m_actionName.getUtf8());
EXPECT_STREQ("Buy the Season Pass", link1.m_actionDescription.getUtf8());
}
{
const NewsLink& link2 = info.m_links.back();
EXPECT_STREQ("sstore", link2.m_type.getUtf8());
EXPECT_STREQ("0x555308796ea1e801", link2.m_param.getUtf8());
EXPECT_STREQ("MoreInfoOnSeasonPass", link2.m_actionName.getUtf8());
EXPECT_STREQ("More info...", link2.m_actionDescription.getUtf8());
}
EXPECT_STREQ("{\"assetId\":13}", info.m_object.getUtf8());
}
EXPECT_ALLOC_COUNT_PC_EQ(4938, count);
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON
TEST_F(NEWS_MOCK, USNOT_RequestNewsSpaceCache)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
SAVE_ALLOC_COUNT(count);
const String jsonBody = TestNews_BF::createMockResult();
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(jsonBody));
NewsClient& client = getFacade().getNewsClient();
EXPECT_ALLOC_COUNT_PC_EQ(28, count);
const AsyncResult<Vector<NewsInfo> > newsResult = client.requestSpaceNews();
EXPECT_ALLOC_COUNT_PC_EQ(31, count);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
// Check resulting news content
const Vector<NewsInfo>& news0 = newsResult.getResult();
ASSERT_TRUE(TestNews_BF::checkResultingNews(news0));
// Requesting news a second time. This shall not affect the mock call expectations.
{
const AsyncResult<Vector<NewsInfo> > newsResult2 = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult2));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult2.getResult()));
}
// Requesting news a third time after requesting to clear the cache.
// This simulate the behaviour after a call to CacheManager::invalidateCaches()
// This requires new mock call expectations.
{
NewsProxy::invalidateCache(client, CacheUnit::NewsSpace);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult3 = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult3));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult3.getResult()));
}
// Requesting news a fourth time. This shall not affect the mock call expectations.
// The clear cache request only applies once.
{
const AsyncResult<Vector<NewsInfo> > newsResult4 = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult4));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult4.getResult()));
}
const SpaceId spaceId5("3a441107-673a-40b7-a304-0cd5fcb7FAKE");
// Requesting news a fifth time on a different space ID.
// This shall requires a new set of the mock call expectations.
{
// Note that the same JSON is sent here for a different Space Id...
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult5 = client.requestSpaceNews(spaceId5);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult5));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult5.getResult()));
}
// Requesting news a sixth time for many space IDs.
// This shall requires a new set of the mock call expectations.
{
// Note that the same JSON is sent here for a different Space Id...
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResult6 = client.requestSpaceNews(SpaceId("3a441107-673a-40b7-a304-0cd5fcbFAKE1"));
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult6));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult6.getResult()));
}
// Requesting news a seventh time. This shall not affect the mock call expectations.
{
const AsyncResult<Vector<NewsInfo> > newsResult7 = client.requestSpaceNews(spaceId5);
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult7));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResult7.getResult()));
}
// Requesting news shall not affect the mock call expectations
{
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
// Sleeping so all entries in cache expires
// This requires new mock call expectations.
{
US_TEST_NS::Helper::sleep(ParametersSpaceMockHelper::s_MOCK_TIME_TO_LIVE_RESOURCE_MSEC * 2);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, MockResultHelper::createSuccessResult(jsonBody));
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
// Requesting news shall not affect the mock call expectations
{
const AsyncResult<Vector<NewsInfo> > newsResultTemp = client.requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResultTemp));
ASSERT_TRUE(TestNews_BF::checkResultingNews(newsResultTemp.getResult()));
}
EXPECT_ALLOC_COUNT_PC_EQ(4938, count);
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and an invalid JSON
TEST_F(NEWS_MOCK, USNOT_RequestNewsErrorJsonSyntax)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Request news failed. Invalid JSON in response's body", LogLevel::Error, Times(2));
});
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
{
testing::InSequence s;
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(
TestNews_BF::createMockResult().replace("{", "")); // Omitting the opening bracket for invalid JSON.
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, mockResult);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, mockResult);
}
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestProfileNews(), Errors::CORE_INVALID_JSON_FORMAT));
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestSpaceNews(), Errors::CORE_INVALID_JSON_FORMAT));
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON (missing fields)
TEST_F(NEWS_MOCK, USNOT_RequestNewsErrorJsonMissingFields)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
{
testing::InSequence s;
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(
TestNews_BF::createMockResult().replace("\"newsId\":\"neolane.AC4_DLC_01\",", ""));
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, mockResult);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, mockResult);
}
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews()));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
}
#endif
#if !defined(US_DLL)
/// @test Requests news with a successful response from server and a valid JSON (extra fields)
TEST_F(NEWS_MOCK, USNOT_RequestNewsJsonExtraFields)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
{
const String jsonBody = TestNews_BF::createMockResult()
.replace("\"newsId\":\"neolane.AC4_DLC_01\",", "\"newsId\":\"neolane.AC4_DLC_01\",\"priorityExtraField1\": 1,");
testing::InSequence s;
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBody);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, mockResult);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, mockResult);
}
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews()));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
}
#endif
#if !defined(US_DLL)
/// @test Requests News parsing a JSON structure containing extra Root node.
TEST_F(NEWS_MOCK, USNOT_RequestNewsWithExtraRootNode)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
{
const String jsonBody = TestNews_BF::createMockResult();
// Add extra root node
// Extra node must be first in json
String jsonBodyExtraNode = "{\"extraRootNode\":[{\"name\":\"extraItem\",\"quantity\":2}],";
// Remove first '{' because its now part of a json array
jsonBodyExtraNode += jsonBody.substr(jsonBody.findSubstringNoCase("{") + 1, jsonBody.getLength());
testing::InSequence s;
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBodyExtraNode);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, mockResult);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, mockResult);
}
{
const AsyncResult<Vector<NewsInfo> > newsResult = getFacade().getNewsClient().requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
EXPECT_EQ(6, newsResult.getResult().size());
}
{
const AsyncResult<Vector<NewsInfo> > newsResult = getFacade().getNewsClient().requestSpaceNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
EXPECT_EQ(6, newsResult.getResult().size());
}
}
#endif
#if !defined(US_DLL)
/// @test Requests news with an HTTP error from server.
TEST_F(NEWS_MOCK, USNOT_RequestNewsErrorHttp)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 400", LogLevel::Error, Times(2));
});
{
testing::InSequence s;
const MockAsyncResult mockResult = MockResultHelper::createHttpErrorResult(RestStatusCode::Error400, "{\"error\":\"myerror\"}");
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, mockResult);
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNewsSpace, mockResult);
}
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestProfileNews(), Errors::NEWS_GENERIC_FAILURE));
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestSpaceNews(), Errors::NEWS_GENERIC_FAILURE));
}
#endif
#if !defined(US_DLL)
/// @test Check the default spaceId when no spaceId is given
TEST_F(NEWS_MOCK, USNOT_RequestProfileNewsDefaultParameter)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
HttpGet request(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNews)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&request)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews()));
const String spaceIdQuery = [&]()
{
StringStream query;
query << "spaceId=" << getFacade().getWorkingSpaceId();
return query.getContent();
}();
EXPECT_NE(String::npos, URLInfo(request.getUrl()).getQuery().findSubstringCase(spaceIdQuery));
}
#endif
#if !defined(US_DLL)
/// @test Check the default spaceId when no spaceId is given
TEST_F(NEWS_MOCK, USNOT_RequestSpaceNewsDefaultParameter)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
HttpGet request(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&request)),
testing::Return(MockResultHelper::createSuccessResult())));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
const String spaceIdQuery = [&]()
{
StringStream query;
query << "spaceId=" << getFacade().getWorkingSpaceId();
return query.getContent();
}();
EXPECT_TRUE(URLInfo(request.getUrl()).getQuery().findSubstringCase(spaceIdQuery) != String::npos)
<< "Failed to find the Space id '" << spaceIdQuery.getUtf8() << "' into URL: " << request.getUrl().getUtf8();
}
#endif
/// @test Check that no request is sent and an error is raised when given spaceId is invalid
TEST_F(NEWS_MOCK, USNOT_RequestProfileNewsInvalidSpaceId)
{
US_EXPECT_CALL(US_TEST_NS::Action::GetNews).Times(0);
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestProfileNews(SpaceId("InvalidSpaceId")), Errors::NEWS_INVALID_PARAM));
}
/// @test Check that no request is sent and an error is raised when given spaceId is invalid
TEST_F(NEWS_MOCK, USNOT_RequestSpaceNewsInvalidSpaceId)
{
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace).Times(0);
EXPECT_TRUE(AsyncHelper::waitFailure(getFacade().getNewsClient().requestSpaceNews(SpaceId("InvalidSpaceId")), Errors::NEWS_INVALID_PARAM));
}
/// @test Check the default Ubi-Market header when a country code is given
TEST_F(NEWS_MOCK, USNOT_RequestNewsSpecifiedCountry)
{
const SpaceId spaceSdk = SpaceId("3a441107-673a-40b7-a304-0cd5fcb7ee9b");
HttpGet requestSpace(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestSpace)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews(spaceSdk, CountryName::UnitedStates)));
EXPECT_NE(String::npos, requestSpace.getHeader("Ubi-Market").findSubstringCase("US"));
HttpGet requestProfile(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNews)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestProfile)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestProfileNews(spaceSdk, CountryName::France)));
EXPECT_NE(String::npos, requestProfile.getHeader("Ubi-Market").findSubstringCase("FR"));
}
#if !defined(US_DLL)
/// @test Validates the push of the player.news.action and player.news.impression.
TEST_F(NEWS_MOCK, USNOT_NewsActionAndImpression)
{
HttpPost httpRequest(StringUrl(""), String());
{
US_EXPECT_CALL(US_TEST_NS::Action::DeleteSession)
.WillOnce(testing::Return(MockResultHelper::createSuccessResult()));
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(static_cast<HttpRequest*>(&httpRequest)),
testing::Return(MockResultHelper::createSuccessResult())));
}
waitForPostLoginCompletion();
const String newsId1("News2");
const String placement1("Placement1");
const String action("Action1");
ASSERT_TRUE(getFacade().getNewsClient().reportNewsAction(newsId1, placement1, action));
const String newsId2("News2");
const String placement2("Placement2");
const TimeSeconds duration = 10ul;
ASSERT_TRUE(getFacade().getNewsClient().reportNewsImpression(newsId2, placement2, duration));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().deleteSession()));
{
Map<int32, String> expectedEvents;
expectedEvents[0] = "game.start";
expectedEvents[1] = "player.start";
expectedEvents[2] = "player.news.action";
expectedEvents[3] = "player.news.impression";
ASSERT_THAT(TestNews_BF::extractEventsFromRequest(httpRequest), expectedEvents);
}
const Json requestBodyJson(httpRequest.getBodyAsString());
for (const auto& it : requestBodyJson["events"].getValueArray())
{
if (it["type"].getValueString() == "player.news.action")
{
EXPECT_EQ(newsId1, it["typeData"]["newsId"].getValueString());
EXPECT_EQ(placement1, it["typeData"]["placement"].getValueString());
EXPECT_EQ(action, it["typeData"]["actionName"].getValueString());
}
if (it["type"].getValueString() == "player.news.impression")
{
EXPECT_EQ(newsId2, it["typeData"]["newsId"].getValueString());
EXPECT_EQ(placement2, it["typeData"]["placement"].getValueString());
EXPECT_EQ(duration, it["typeData"]["duration"].getValueInteger());
}
}
}
#endif
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_KILI)
/// @test Checks that the country is correctly retrieved. Note : account country for PS4, console country for XBoxOne.
TEST_F(NEWS_MOCK, LOCAL_DetectMarket)
{
HttpGet requestNews(StringUrl(""));
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult();
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestNews)), testing::Return(mockResult)));
}
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
EXPECT_EQ("US", requestNews.getHeader("Ubi-Market"));
}
#endif
#if defined(US_SDK_FULL) // Market detection only done in full sdk
#if !defined(US_TARGET_PS4) && !defined(US_TARGET_XONE) && !defined(US_TARGET_KILI)
/// @test Checks that the market is correctly detected.
TEST_F(NEWS_MOCK, LOCAL_DetectMarket)
{
// Burundi chosen as value that is probably not a default value anywhere
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetUser, MockResultHelper::createSuccessResult("{\"country\":\"BI\"}"));
HttpGet requestNews(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestNews)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
EXPECT_EQ("BI", requestNews.getHeader("Ubi-Market"));
}
/// @test Checks that the Ubi-Market is not sent when requesting the user localization returns an error
TEST_F(NEWS_MOCK, LOCAL_DetectMarketUserLocalizationError)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 400", LogLevel::Error, Times(1));
});
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetUser, MockResultHelper::createHttpErrorResult(RestStatusCode::Error400, "{\"error\":\"myError\"}"));
HttpGet requestNews(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestNews)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
EXPECT_EQ(0, requestNews.getHeader("Ubi-Market").getLength());
}
#if !defined(US_DLL)
/// @test Checks that the Ubi-Market is not sent when the feature switch for user is disabled
TEST_F(NEWS_MOCK, LOCAL_DetectMarketFeatureSwitchUsersDisabled)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
US_EXPECT_CALL(US_TEST_NS::Action::GetUser).Times(0);
HttpGet requestNews(StringUrl(""));
US_EXPECT_CALL(US_TEST_NS::Action::GetNewsSpace)
.WillOnce(testing::DoAll(
testing::SaveArg<0>(reinterpret_cast<HttpRequest*>(&requestNews)),
testing::Return(MockResultHelper::createSuccessResult())));
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getNewsClient().requestSpaceNews()));
EXPECT_EQ(0, requestNews.getHeader("Ubi-Market").getLength());
}
#endif
#endif // defined(US_SDK_FULL)
#endif
#if !defined(US_DLL)
/// @test The news service guarantees the order in which the links are returned by their API.
/// The SDK must return the links and sub-links in the same order.
TEST_F(NEWS_MOCK, LOCAL_ConfirmNewsLinksOrder)
{
ParametersClientProxy::enableSwitch(getFacadeInternal(), FeatureSwitchId::Users, false); // Avoids the request to get the country
ASSERT_FALSE(getFacade().getParametersClient().isUsFeatureSwitchEnabled(FeatureSwitchId::Users));
// Allows to mock a news with various link types and multiple sub-links (2x weblink)
struct Local
{
static Json createMock()
{
JsonWriter newsWrapperWriter;
JsonWriter newsArrayWriter(JsonWriterType::Array);
JsonWriter writer;
writer["profileId"] = "aaaa1111-bbbb-2222-cccc-3333dddd4444"; // <<<<<< missing field
writer["spaceId"] = "11112222-3333-4444-5555-666677778888";
writer["newsId"] = "aaaabbbbcccc-dddd-eeee-ffff-123456781234"; // This is not a GUID
writer["type"] = "myNewsType";
writer["placement"] = "myNewsPlacement";
writer["priority"] = 123;
writer["displayTime"] = 60;
writer["publicationDate"] = "2014-11-11T12:00:00";
writer["locale"] = "en-us";
writer["title"] = "myNewsTitle";
writer["body"] = "myNewsBody";
writer["mediaURL"] = "http://myNewsUrl.com";
writer["mediaType"] = "myNewsMediaType";
{
Vector<Json> links;
links.reserve(4);
// Adding a popup type link
{
JsonWriter link;
link["type"] = "popup";
link["param"] = "myLinkParam0";
link["actionName"] = "myLinkActionName0";
link["actionDescription"] = "myLinkActionDesc0";
links.push_back(link.getJson());
}
// Adding two weblink type
for (uint32 i = 1; i < 3; ++i)
{
JsonWriter link;
link["type"] = "weblink";
link["param"] = String::formatText("myLinkParam%d", i);
link["actionName"] = String::formatText("myLinkActionName%d", i);
link["actionDescription"] = String::formatText("myLinkActionDesc%d", i);
links.push_back(link.getJson());
}
// Adding an image type link
{
JsonWriter link;
link["type"] = "image";
link["param"] = "myLinkParam3";
link["actionName"] = "myLinkActionName3";
link["actionDescription"] = "myLinkActionDesc3";
links.push_back(link.getJson());
}
writer["links"] = links;
}
{
JsonWriter obj;
obj["field"] = "value";
writer["obj"] = obj.getJson();
}
newsArrayWriter.addItemToArray(writer.getJson());
newsWrapperWriter["news"] = newsArrayWriter.getJson();
return newsWrapperWriter.getJson();
}
};
US_EXPECT_CALL_SIMPLE(US_TEST_NS::Action::GetNews, MockResultHelper::createSuccessResult(Local::createMock().renderContent()));
const AsyncResult<Vector<NewsInfo>> newsResult = getFacade().getNewsClient().requestProfileNews();
ASSERT_TRUE(AsyncHelper::waitSuccess(newsResult));
const Vector<NewsInfo>& news = newsResult.getResult();
ASSERT_TRUE(news.size() == 1u);
const NewsInfo& info = news[0];
ASSERT_TRUE(info.m_links.size() == 4u);
// Verify the order of the links type is popup->weblink->weblink->image for 4 links provided
EXPECT_STREQ("popup", info.m_links[0].m_type.getUtf8());
EXPECT_STREQ("weblink", info.m_links[1].m_type.getUtf8());
EXPECT_STREQ("weblink", info.m_links[2].m_type.getUtf8());
EXPECT_STREQ("image", info.m_links[3].m_type.getUtf8());
// Verify the order of the sub-links (weblink) is link1->link2
EXPECT_STREQ("myLinkParam2", info.m_links[2].m_param.getUtf8());
EXPECT_STREQ("myLinkParam1", info.m_links[1].m_param.getUtf8());
}
#if defined(US_TARGET_WINDOWS) && defined(US_SDK_TEST_CHINA)
/// @test Checks that the railId and the Tencent session ticket are present in the url of the news request
TEST_F(NEWS_MOCK_NOINIT, USNOT_LoginCheckChinaNewsUrl)
{
const LoginMockNoInitScopedUninit autoUninit(*this);
{
US_NS::initializeSdk();
const ApplicationId chinaPcAppId(US_TEST_NS::SPACE_ID_US_SDK_PC_CHINA_RETAIL);
const String chinaPcBuildId("CHINA_IS_PROD");
US_NS::HttpConfig httpConfig; // Proxy needed for the manual http request to azure
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
httpConfig.m_proxy.m_host = "proxy.ubisoft.org";
httpConfig.m_proxy.m_port = 3128;
configureSdk(GameConfig(
chinaPcAppId,
chinaPcBuildId,
OnlineAccessContext::China,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>()),
GameConfigConsole()),
SystemConfig(US_NS::ThreadingConfig(), httpConfig));
SetUpAfterInit();
mockFullLogin();
{
const String tencentTicket("DummyTencentSessionTicket");
// Perform the login
// Session doesn't have to be valid for our AppId 586cc2e2-29c0-4522-8626-a1159939abe4 (UbiServices SDK PC China RETAIL)
// A valid session is only possible when using this AppId
const String sessionRailId(US_TEST_NS::WEGAME_SESSION_ID);
const US_NS::String playerRailId(US_TEST_NS::WEGAME_PROFILE_RAIL_ID);
const String gameRailId(US_TEST_NS::WEGAME_GAME_RAIL_ID);
const String weGameToken(CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, CredentialsType::WeGame, playerRailId);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(credentials, {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const MockAsyncResult mockResultSuccess = MockResultHelper::createSuccessResult("{}");
HttpGet requestGetNews((StringUrl()));
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-spaces-news")
.WillOnce(DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&requestGetNews)), testing::Return(mockResultSuccess)));
const String currentProfile = getFacade().getAuthenticationClient().getSessionInfo().getProfileId();
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "/mock-users/" + currentProfile + "?fields=country,preferredLanguage")
.Times(testing::AnyNumber());
const String currentSpace = getFacade().getWorkingSpaceId();
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNewsTencent(tencentTicket, SpaceId(currentSpace));
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
// /mock-spaces-news?wegameid=playerRailId&session_ticket=tencentTicket&spaceId=currentSpace
EXPECT_TRUE(requestGetNews.getUrl().findSubstringCase("wegameid=" + playerRailId)) << "wegameid is not set.";
EXPECT_TRUE(requestGetNews.getUrl().findSubstringCase("session_ticket=" + tencentTicket)) << "session_ticket is not set.";
EXPECT_TRUE(requestGetNews.getUrl().findSubstringCase("spaceId=" + currentSpace)) << "spaceId is not set.";
}
}
}
/// @test Checks that requesting china news in a Standard online context fails
TEST_F(NEWS_MOCK_NOINIT, USNOT_RequestChinaNewsInNormalOnlineContext)
{
const LoginMockNoInitScopedUninit autoUninit(*this);
{
US_NS::initializeSdk();
const ApplicationId chinaPcAppId(US_TEST_NS::SPACE_ID_US_SDK_PC_CHINA_RETAIL);
const String chinaPcBuildId("CHINA_IS_PROD");
US_NS::HttpConfig httpConfig; // Proxy needed for the manual http request to azure
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
httpConfig.m_proxy.m_host = "proxy.ubisoft.org";
httpConfig.m_proxy.m_port = 3128;
configureSdk(GameConfig(
chinaPcAppId,
chinaPcBuildId,
OnlineAccessContext::Standard,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>()),
GameConfigConsole()),
SystemConfig(US_NS::ThreadingConfig(), httpConfig));
SetUpAfterInit();
mockFullLogin();
{
const String tencentTicket("DummyTencentSessionTicket");
// Perform the login
// Those IDs are from Identity Team
// Session doesn't have to be valid for our AppId 586cc2e2-29c0-4522-8626-a1159939abe4 (UbiServices SDK PC China RETAIL)
// A valid session is only possible when using WeGame SDK
const String sessionRailId(US_TEST_NS::WEGAME_SESSION_ID);
const US_NS::String playerRailId(US_TEST_NS::WEGAME_PROFILE_RAIL_ID);
const String gameRailId(US_TEST_NS::WEGAME_GAME_RAIL_ID);
const String weGameToken(CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, CredentialsType::WeGame, playerRailId);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(credentials, {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String currentSpace = getFacade().getWorkingSpaceId();
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Cannot perform request in an online context different than China", LogLevel::Error, Times(2));
});
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNewsTencent(tencentTicket, SpaceId(currentSpace));
const AsyncResult<Vector<NewsInfo> > result2 = getFacade().getNewsClient().requestProfileNewsTencent(tencentTicket, SpaceId(currentSpace));
ASSERT_TRUE(AsyncHelper::waitFailure(result, Errors::NEWS_GENERIC_FAILURE));
ASSERT_TRUE(AsyncHelper::waitFailure(result2, Errors::NEWS_GENERIC_FAILURE));
}
}
}
/// @test Checks that requesting china news without a valid Tencent session ticket fails
TEST_F(NEWS_MOCK_NOINIT, USNOT_RequestChinaNewsInvalidTencentSessionTicket)
{
const LoginMockNoInitScopedUninit autoUninit(*this);
{
US_NS::initializeSdk();
const ApplicationId chinaPcAppId(US_TEST_NS::SPACE_ID_US_SDK_PC_CHINA_RETAIL);
const String chinaPcBuildId("CHINA_IS_PROD");
US_NS::HttpConfig httpConfig; // Proxy needed for the manual http request to azure
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
httpConfig.m_proxy.m_host = "proxy.ubisoft.org";
httpConfig.m_proxy.m_port = 3128;
configureSdk(GameConfig(
chinaPcAppId,
chinaPcBuildId,
OnlineAccessContext::China,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>()),
GameConfigConsole()),
SystemConfig(US_NS::ThreadingConfig(), httpConfig));
SetUpAfterInit();
mockFullLogin();
{
// Perform the login
// Those IDs are from Identity Team
// Session doesn't have to be valid for our AppId 586cc2e2-29c0-4522-8626-a1159939abe4 (UbiServices SDK PC China RETAIL)
// A valid session is only possible when using WeGame SDK
const String sessionRailId(US_TEST_NS::WEGAME_SESSION_ID);
const US_NS::String playerRailId(US_TEST_NS::WEGAME_PROFILE_RAIL_ID);
const String gameRailId(US_TEST_NS::WEGAME_GAME_RAIL_ID);
const String weGameToken(CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, CredentialsType::WeGame, playerRailId);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(credentials, {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String currentSpace = getFacade().getWorkingSpaceId();
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Cannot perform request with an empty Tencent session ticket", LogLevel::Error, Times(2));
});
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNewsTencent("", SpaceId(currentSpace));
const AsyncResult<Vector<NewsInfo> > result2 = getFacade().getNewsClient().requestProfileNewsTencent("", SpaceId(currentSpace));
ASSERT_TRUE(AsyncHelper::waitFailure(result, Errors::NEWS_INVALID_PARAM));
ASSERT_TRUE(AsyncHelper::waitFailure(result2, Errors::NEWS_INVALID_PARAM));
}
}
}
/// @test Checks that requesting Standard news in a China online context fails
TEST_F(NEWS_MOCK_NOINIT, USNOT_RequestNewsInChinaOnlineContext)
{
const LoginMockNoInitScopedUninit autoUninit(*this);
{
US_NS::initializeSdk();
const ApplicationId chinaPcAppId(US_TEST_NS::SPACE_ID_US_SDK_PC_CHINA_RETAIL);
const String chinaPcBuildId("CHINA_IS_PROD");
US_NS::HttpConfig httpConfig; // Proxy needed for the manual http request to azure
httpConfig.m_proxy.m_proxyType = HttpProxyConfig::Type::Enabled;
httpConfig.m_proxy.m_host = "proxy.ubisoft.org";
httpConfig.m_proxy.m_port = 3128;
configureSdk(GameConfig(
chinaPcAppId,
chinaPcBuildId,
OnlineAccessContext::China,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>()),
GameConfigConsole()),
SystemConfig(US_NS::ThreadingConfig(), httpConfig));
SetUpAfterInit();
mockFullLogin();
{
// Perform the login
// Those IDs are from Identity Team
// Session doesn't have to be valid for our AppId 586cc2e2-29c0-4522-8626-a1159939abe4 (UbiServices SDK PC China RETAIL)
// A valid session is only possible when using WeGame SDK
const String sessionRailId(US_TEST_NS::WEGAME_SESSION_ID);
const US_NS::String playerRailId(US_TEST_NS::WEGAME_PROFILE_RAIL_ID);
const String gameRailId(US_TEST_NS::WEGAME_GAME_RAIL_ID);
const String weGameToken(CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, CredentialsType::WeGame, playerRailId);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(credentials, {}, {})));
waitForPostLoginCompletion();
ASSERT_TRUE(US_TEST_NS::Helper::waitForWebsocketInit(getFacade()));
const String currentSpace = getFacade().getWorkingSpaceId();
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Cannot perform requestNews in a China online context. Use requestNewsTencent instead", LogLevel::Error, Times(2));
});
const AsyncResult<Vector<NewsInfo> > result = getFacade().getNewsClient().requestSpaceNews(SpaceId(currentSpace));
const AsyncResult<Vector<NewsInfo> > result2 = getFacade().getNewsClient().requestProfileNews(SpaceId(currentSpace));
ASSERT_TRUE(AsyncHelper::waitFailure(result, Errors::NEWS_GENERIC_FAILURE));
ASSERT_TRUE(AsyncHelper::waitFailure(result2, Errors::NEWS_GENERIC_FAILURE));
}
}
}
#endif // defined(US_TARGET_WINDOWS) && defined(US_SDK_TEST_CHINA)
#endif
};