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

1465 lines
65 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#if defined(US_SDK_LIGHT_MOBILE)
#error This file shall not be part of the solution
#endif
#include "tests/fixture/authenticationFixture.h"
#include "tests/fixture/memoryCheckFixture.h"
#include "tests/fixture/paramFixture.h"
#include "tests/mock/mockLogDevice.h"
#include "tests/mock/mockProfileHelper.h"
#include "tests/mock/mockResultHelper.h"
#include "tests/mock/parametersMockHelper.h"
#include "tests/common/cancelTest.h"
#include "tests/fixture/loginMockFixture.h"
#include <ubiservices/facade.h>
#include <ubiservices/core/errors/errorCodes.h>
#include <ubiservices/core/helpers/resultRange.h>
#include <ubiservices/core/types/containers.h>
#include <ubiservices/platformHelper.h>
#include <ubiservices/services/authentication/sessionInfo.h>
#include <ubiservices/services/friend/friendClient.h>
#include <../private/ubiservices/core/helpers/instancesManager.h>
#include <../private/ubiservices/services/friend/friendClientProxy.h>
#include <ubiservices/services/friend/friendInfoClub.h>
#include <ubiservices/services/friend/xone/xoneSocialRelationshipChangeEventArgs.h>
#include <ubiservices/services/http/request/httpGet.h>
#include <ubiservices/services/http/request/httpPost.h>
#include <ubiservices/services/profile/profileClient.h>
#include <../private/ubiservices/services/profile/profileTypeHelper.h>
#include <usCommon/authenticationHelper.h>
#include <usCommon/settings.h>
// Please do not delete yet ! DomD
//#if defined(US_TARGET_PS4)
//#include "usCommon/ps4/firstPartyInit.h"
//#endif
namespace US_NS {;
US_DEFINE_TEST(TestFriendsCommon);
const char* const HTTP_EMPTY_BODY = "";
const char* const UPLAY_PROFILE_ID = "9070605b-ecc4-4153-86bc-2eacc1c5faaa";
const char* const TEST_PROFILE_ID = "68e7e6f5-cf7e-4650-ba1a-f8ac546c9d71";
const char* const TEST_PROFILE_ID_2 = "11111111-2222-3333-4444-555566667777";
const char* const TEST_PROFILE_ID_CERT2 = "68e7e6f5-cf7e-4650-ba1a-f8ac546c9d71";
const char* const TEST_PROFILE_ID_INVALID = "11111111-2222-3333-4444-555566667777";
typedef AuthenticationFixture<1, true> FRIENDS;
typedef AuthenticationFixture<1, false> FRIENDS_NO_LOGIN;
typedef LoginMockFixture<true> FRIENDS_MOCK;
typedef LoginMockFixture<true> FRIENDS_MOCK_CANCEL;
typedef LoginMockFixture<false> FRIENDS_MOCK_NOLOGIN;
typedef LeakChecker FRIENDS_NO_FACADE;
typedef LeakCheckerNoInit FRIENDS_NO_INIT;
// Cancel test settings
typedef AuthenticationFixtureWithParam<TestConfigCancel>::type FRIENDS_CANCEL;
US_DEFINE_LONG_TEST_P(FRIENDS_CANCEL, TestConfigCancel(20), TestConfigCancel(10));
/// @cond PRIVATE_API
namespace TestFriends_BF
{
const static char* s_TEXT_REPLACEMENT = "(Forbidden Terms)";
/// Validates that the result contains the players "ussdk002" and "ussdk003".
void validateClubFriends(
const AsyncResult<Vector<FriendInfo> >& resultFriends,
bool usingForbiddenTerms = false)
{
const String USSDK_2_NAME = "ussdk002";
const String USSDK_3_NAME = "ussdk003";
ASSERT_LE(2u, resultFriends.getResult().size());
ASSERT_TRUE(resultFriends.getResult().front().getInfoClub() != NULL);
const uint32 EXPECTED_USERNAME_COUNT = 2u;
uint32 usernameCount = 0;
for(const auto& itRelation : resultFriends.getResult())
{
const FriendInfoClub* info = itRelation.getInfoClub();
ASSERT_TRUE(info != NULL);
if (usingForbiddenTerms &&
((info->m_profileInfo.m_nameOnPlatform == s_TEXT_REPLACEMENT) ||
(info->m_profileInfo.m_nameOnPlatform == USSDK_3_NAME)))
{
usernameCount++;
}
else if (
(info->m_profileInfo.m_nameOnPlatform == USSDK_2_NAME) ||
(info->m_profileInfo.m_nameOnPlatform == USSDK_3_NAME))
{
usernameCount++;
}
ASSERT_TRUE(info->m_profileInfo.m_userId.isSpecified());
ASSERT_TRUE(info->m_profileInfo.m_userId.value().isValid());
if (info->m_relation != FriendInfoClub::Friends &&
info->m_relation != FriendInfoClub::PendingSentInvite &&
info->m_relation != FriendInfoClub::PendingReceivedInvite)
{
EXPECT_TRUE(false); // Received an unknown value
}
// Ignoring info->m_date for now
}
EXPECT_EQ(EXPECTED_USERNAME_COUNT, usernameCount); // Only 1 friend when requesting with Club as entry point
#if defined(US_LOG_ENABLED)
// Temp debug code
if (EXPECTED_USERNAME_COUNT != usernameCount)
{
::std::cout << "Invalid number of friends. Dumping friends:";
for(const auto& itRelation : resultFriends.getResult())
{
StringStream msg;
msg << itRelation << US_NS::endl;
::std::cout << msg.getContent().getAnsi();
}
}
#endif
}
/// Requests Club friends and validates that the result contains the expected players
void requestClubFriends(Facade& facade, bool usingForbiddenTerms = false)
{
const AsyncResult<Vector<FriendInfo> > resultFriends = facade.getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
validateClubFriends(resultFriends, usingForbiddenTerms);
for (const auto& it : resultFriends.getResult())
{
EXPECT_TRUE(it.getInfoClub()->m_profileInfo.m_profileId.isValid());
EXPECT_FALSE(it.getInfoClub()->m_profileInfo.m_nameOnPlatform.isEmpty());
}
}
#if defined(US_TARGET_XONE)
AsyncResult<US_NS::Vector<FriendInfo>> checkRelationShipChange(Facade& facade, bool& eventReceived, FriendClient::Mode friendRequestMode)
{
Windows::Xbox::System::User^ user = Helper::getUser(facade.getAuthenticationClient().getSessionInfo().getPlayerCredentials());
AsyncResult<US_NS::Vector<FriendInfo>> resultChange;
#if defined(US_XONE_USE_XSAPI_CPP)
std::shared_ptr<xbox::services::xbox_live_context> xboxLiveContext(new xbox::services::xbox_live_context(user));
xboxLiveContext->real_time_activity_service()->activate();
xboxLiveContext->social_service().add_social_relationship_changed_handler(
[&facade, &eventReceived, friendRequestMode, &resultChange](xbox::services::social::social_relationship_change_event_args args)
{
PRINT_LINE("Friend change event detected.");
// Invalidate cache
PlatformHelper::forwardSocialRelationShipChange(args);
// 3rd friend request, after invalidating cache
resultChange = facade.getFriendClient().requestFriends(friendRequestMode);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultChange));
ASSERT_EQ(3, resultChange.getResult().size()); // This value might change depending on the friends setup for current user.
eventReceived = true;
});
xboxLiveContext->social_service().subscribe_to_social_relationship_change(user->XboxUserId->Data());
#else
Microsoft::Xbox::Services::XboxLiveContext^ xboxLiveContext = ref new Microsoft::Xbox::Services::XboxLiveContext(user);
xboxLiveContext->RealTimeActivityService->Activate();
Windows::Foundation::EventRegistrationToken onSocialRelationshipChangedRegistration =
xboxLiveContext->SocialService->SocialRelationshipChanged +=
ref new Windows::Foundation::EventHandler<Microsoft::Xbox::Services::Social::SocialRelationshipChangeEventArgs^ >(
[&facade, &eventReceived, friendRequestMode, &resultChange]
(::Platform::Object^, Microsoft::Xbox::Services::Social::SocialRelationshipChangeEventArgs^ args)
{
PRINT_LINE("Friend change event detected.");
// Invalidate cache
PlatformHelper::forwardSocialRelationShipChange(XoneSocialRelationshipChangeEventArgs(args));
// 3rd friend request, after invalidating cache
resultChange = facade.getFriendClient().requestFriends(friendRequestMode);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultChange));
ASSERT_EQ(3, resultChange.getResult().size()); // This value might change depending on the friends setup for current user.
eventReceived = true;
});
US_UNUSED(onSocialRelationshipChangedRegistration);
xboxLiveContext->SocialService->SubscribeToSocialRelationshipChange(user->XboxUserId);
#endif
return resultChange;
}
#endif
}
/// @endcond
// China infrastructure is not ready yet, currently only supports Windows
#if defined(US_TARGET_WINDOWS) && defined(US_SDK_TEST_CHINA)
/// @test Request club friends while simulating China context
/// @disabled uplaycn platformtype is currently not supported by the service. JIRA US-16595 to reenable it.
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // 0 friends in china
TEST_F(FRIENDS_NO_INIT, DISABLED_US_RequestClubFriendsChina)
#else
TEST_F(FRIENDS_NO_INIT, US_RequestClubFriendsChina)
#endif
{
const US_TEST_NS::ScopedInit autoInit;
{
ApplicationId chinaPcAppId("586cc2e2-29c0-4522-8626-a1159939abe4");
String chinaPcBuildId("CHINA_IS_PROD");
configureSdk(GameConfig(
chinaPcAppId,
chinaPcBuildId,
#if defined(US_SDK_S2S)
NS_COMMON::Options::environment(),
#endif
OnlineAccessContext::China,
GameConfigEvent(String(), US_TEST_NS::US_SDK_DUMMY_GAME_SKU, Vector<EventTypeInfo>()),
GameConfigConsole()),
SystemConfig(US_NS::ThreadingConfig()));
// Perform the login
Facade facade;
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 US_NS::String weGameToken(US_NS::CredentialsTypeHelper::getWeGameToken(sessionRailId, playerRailId, gameRailId));
const PlayerCredentials credentials(weGameToken, US_NS::CredentialsType::WeGame, playerRailId);
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(credentials, {}, {})));
const AsyncResult<Vector<FriendInfo> > resultFriends = facade.getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
const Vector<FriendInfo> friends = resultFriends.getResult();
EXPECT_EQ(friends.size(), 3);
for (const auto& it : friends)
{
EXPECT_TRUE(it.getInfoClub()->m_profileInfo.m_profileId.isValid());
EXPECT_FALSE(it.getInfoClub()->m_profileInfo.m_nameOnPlatform.isEmpty());
}
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#endif
// Disabled on Xbox One because of friend community segregation between X360 and XONE players.
#if !defined(US_TARGET_XONE)
/// @test Requests Club friends...
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // 0 friends in china
TEST_F(FRIENDS, DISABLED_US_RequestClubFriendsCheckingProfileIds)
#elif defined(US_TARGET_GGP)
// To run this test your ggp account needs to be linked to a ubisoft profile
// And your ubisoft profile needs to be friends with another ubisoft profile that has a ggp linked to that account.
TEST_F(FRIENDS, DISABLED_MANUAL_US_RequestClubFriendsCheckingProfileIds)
#else
TEST_F(FRIENDS, US_MINRUN_RequestClubFriendsCheckingProfileIds)
#endif
{
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
const Vector<FriendInfo> friends = resultFriends.getResult();
EXPECT_GE(friends.size(), 1ul);
for(const auto& it : friends)
{
EXPECT_TRUE(it.getInfoClub()->m_profileInfo.m_profileId.isValid());
EXPECT_FALSE(it.getInfoClub()->m_profileInfo.m_nameOnPlatform.isEmpty());
}
}
#if defined(US_TARGET_WINDOWS)
/// @test Request Club friends with modified response having useless data
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsCheckingProfileIdsConsolidatedWithModifiedResponseForForwardCompatibility)
{
Vector<Json> friendsMock;
{
JsonWriter friend1;
friend1["pid"] = "68e7e6f5-cf7e-4650-ba1a-f8ac546c9d71";
friend1["lastModified"] = "2017-11-09T04:22:53.6570000";
friend1["state"] = "PendingSentInvite";
friendsMock.push_back(friend1.getJson());
JsonWriter friend2;
friend2["pid"] = "fa6fd9aa-7726-4e83-a08f-ee61523c6cfa";
friend2["lastModified"] = "2017-08-07T20:03:54.9470000";
friend2["state"] = "PendingReceivedInvite";
friendsMock.push_back(friend2.getJson());
Vector<String> uselessArray;
uselessArray.push_back("1");
uselessArray.push_back("2");
uselessArray.push_back("3");
JsonWriter friend3;
friend3["pid"] = "b2cfc7a1-a08e-4bd8-adf3-73cb1c19faf1";
friend3["lastModified"] = "2014-08-06T00:00:00.0000000";
friend3["state"] = "Friends";
friend3["uselessData"] = true;
friend3["uselessArray"] = uselessArray;
friendsMock.push_back(friend3.getJson());
JsonWriter friend4;
friend4["pid"] = "a701a60d-1fd9-4c4f-98a2-b33fa8beb00f";
friend4["lastModified"] = "2014-06-30T00:00:00.0000000";
friend4["state"] = "Friends";
friendsMock.push_back(friend4.getJson());
}
JsonWriter writerFriends;
writerFriends["before"] = true;
writerFriends["friends"] = friendsMock;
writerFriends["other"] = 5;
Vector<Json> profilesMock;
{
JsonWriter profile1;
profile1["profileId"] = "b2cfc7a1-a08e-4bd8-adf3-73cb1c19faf1";
profile1["userId"] = "b2cfc7a1-a08e-4bd8-adf3-73cb1c19faf1";
profile1["platformType"] = "uplay";
profile1["idOnPlatform"] = "B2CFC7A1-A08E-4BD8-ADF3-73CB1C19FAF1";
profile1["nameOnPlatform"] = "ussdk002";
profilesMock.push_back(profile1.getJson());
JsonWriter profile2;
profile2["profileId"] = "a701a60d-1fd9-4c4f-98a2-b33fa8beb00f";
profile2["userId"] = "a701a60d-1fd9-4c4f-98a2-b33fa8beb00f";
profile2["platformType"] = "uplay";
profile2["idOnPlatform"] = "A701A60D-1FD9-4C4F-98A2-B33FA8BEB00F";
profile2["nameOnPlatform"] = "ussdk003";
profilesMock.push_back(profile2.getJson());
}
JsonWriter writerProfiles;
writerProfiles["profiles"] = profilesMock;
::testing::Sequence s;
{
const MockAsyncResult friendsMockResult = MockResultHelper::createSuccessResult(writerFriends.renderContent());
StringStream friendsExpectedUrl;
friendsExpectedUrl << "/mock-friendsClub";
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, friendsExpectedUrl.getContent(), friendsMockResult);
}
{
const MockAsyncResult profilesMockResult = MockResultHelper::createSuccessResult(writerProfiles.renderContent());
StringStream profilesExpectedUrl;
profilesExpectedUrl << "/mock-profiles?userId";
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, profilesExpectedUrl.getContent(), profilesMockResult);
}
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::Consolidated);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
const Vector<FriendInfo> friends = resultFriends.getResult();
ASSERT_GE(friends.size(), 1ul);
for (const auto& it : friends)
{
EXPECT_TRUE(it.getInfoClub()->m_profileInfo.m_profileId.isValid());
EXPECT_FALSE(it.getInfoClub()->m_profileInfo.m_nameOnPlatform.isEmpty());
}
}
#endif
/// @test Requests Club friends from the first Test environment player.
/// @note The test currently only targets Win32 because it requires the
/// player profile to have a Ubi Account with two friends to succeed.
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // 0 friends in china
TEST_F(FRIENDS, DISABLED_US_Win32RequestClubFriends)
#else
TEST_F(FRIENDS, US_Win32RequestClubFriends)
#endif
{
TestFriends_BF::requestClubFriends(getFacade());
}
TEST_F(FRIENDS, US_RequestFriendsListShareCount)
{
AsyncResult<Vector<FriendInfo> > h1;
{
const AsyncResult<Vector<FriendInfo> > h = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleWithClubInfo);
h1 = h;
EXPECT_TRUE(h1.isProcessing());
} // Friend service is still in scope
ASSERT_TRUE(AsyncHelper::waitSuccess(h1));
}
#if !defined(US_DLL)
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // 0 friends in china
TEST_F(FRIENDS, DISABLED_US_RequestProfileId)
#else
TEST_F(FRIENDS, US_MINRUN_RequestProfileId)
#endif
{
const SessionInfo sessionInfo = (getFacade().getAuthenticationClient().getSessionInfo());
ProfileInfo profileInfo;
{
#if (defined(US_ENABLE_UPLAY_LOGIN) && !defined(US_TARGET_IOS)) || defined(US_UPLAY_LOGIN_FOR_IOS) || defined(US_TARGET_MANJARO) //manjaro tempo
const String onlineId = sessionInfo.getUserId();
#elif defined(US_TARGET_XONE)
const String onlineId = sessionInfo.getPlayerCredentials().getXuid();
#elif defined(US_TARGET_PS4) || defined(US_TARGET_KILI)
SceNpAccountId accountId;
sceNpGetAccountIdA(sessionInfo.getPlayerCredentials().getUserId(), &accountId);
const String onlineId = String::formatText("%lld", accountId);
#elif defined(US_TARGET_SWITCH)
const uint64 id = sessionInfo.getPlayerCredentials().getNsaId().id;
const String onlineId = String::formatText("%08X%08X",
static_cast<uint32>((id >> 32) & 0xFFFFFFFF),
static_cast<uint32>(id & 0xFFFFFFFF));
#elif defined(US_TARGET_IOS)
const String onlineId = sessionInfo.getPlayerCredentials().getPlayerID();
#elif defined(US_TARGET_GGP)
const String onlineId = String::formatText("%llu", sessionInfo.getPlayerCredentials().getPlayerId());
#else
#error Oups, not yet supported!!!
#endif
#if defined(US_ENABLE_UPLAY_LOGIN)
const AsyncResult<Map<String, ProfileInfo> > result =
getFacade().getProfileClient().requestProfiles({ onlineId }, ProfileTypeHelper::getProfileTypeDefault());
#else
const AsyncResult<Map<String, ProfileInfo> > result = getFacade().getProfileClient().requestProfiles({ onlineId });
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_GT(result.getResult().size(), 0ull);
EXPECT_TRUE(result.getResult().find(onlineId)->second.m_profileId.isValid());
EXPECT_EQ(getFacade().getAuthenticationClient().getSessionInfo().getProfileId(), result.getResult().find(onlineId)->second.m_profileId);
profileInfo = result.getResult().find(onlineId)->second;
}
{
const AsyncResult<Map<ProfileId, ProfileInfo> > result = getFacade().getProfileClient().requestProfiles(Vector<ProfileId>({ profileInfo.m_profileId }));
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_GT(result.getResult().size(), 0ull);
Map<ProfileId, ProfileInfo>::const_iterator profileIt = result.getResult().find(profileInfo.m_profileId);
EXPECT_TRUE(profileIt != result.getResult().end());
if (profileIt != result.getResult().end())
{
ProfileInfo resultProfileInfo = profileIt->second;
EXPECT_TRUE(resultProfileInfo.m_profileId.isValid());
EXPECT_EQ(getFacade().getAuthenticationClient().getSessionInfo().getProfileId(), resultProfileInfo.m_profileId);
EXPECT_EQ(profileInfo.m_profileId, resultProfileInfo.m_profileId);
EXPECT_TRUE(resultProfileInfo.m_userId.isSpecified());
if (profileInfo.m_userId.isSpecified() && resultProfileInfo.m_userId.isSpecified())
{
EXPECT_EQ(profileInfo.m_userId.value(), resultProfileInfo.m_userId.value());
}
EXPECT_EQ(profileInfo.m_profileType, resultProfileInfo.m_profileType);
EXPECT_EQ(profileInfo.m_idOnPlatform, resultProfileInfo.m_idOnPlatform);
EXPECT_EQ(profileInfo.m_nameOnPlatform, resultProfileInfo.m_nameOnPlatform);
}
}
{
const UserId uplayId = sessionInfo.getUserId();
const AsyncResult<Map<UserId, ProfileInfo> > result = getFacade().getProfileClient().requestUplayProfiles(Vector<UserId>{ uplayId });
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_GT(result.getResult().size(), 0ull);
Map<UserId, ProfileInfo>::const_iterator itUserId = result.getResult().find(uplayId);
ASSERT_TRUE(itUserId != result.getResult().end());
EXPECT_TRUE(itUserId->second.m_profileId.isValid());
// The profile id from the sessionInfo is specific for the console platform,
// whereas the profile from the lookup belongs to Club.
ASSERT_TRUE(itUserId->second.m_userId.isSpecified());
EXPECT_EQ(sessionInfo.getUserId(), itUserId->second.m_userId.value());
}
}
#endif
/// @test Validates that \c FriendClient::requestFriends may be fire and forgotten
// TODO: This test shall be performed using mock. There is no way to confirm
// that the call completed successfully in the current implementation.
TEST_F(FRIENDS, US_RequestClubFriendsFireAndForget)
{
{
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
EXPECT_FALSE(resultFriends.wait(100)); // Just make sure the job is started, not just scheduled.
EXPECT_TRUE(resultFriends.isProcessing());
}
// The test must not end before the job complete (otherwise, it will be canceled).
// Wait for the requestFriends to complete using an arbitrary time interval.
// The test assumes fire & forget succeed if no crash occurs...
US_TEST_NS::Helper::sleep(2000);
}
#endif // US_TARGET_XONE
TEST_F(FRIENDS, US_InviteFriendClub)
{
const Environment currentEnvironment = getFacade().getAuthenticationClient().getSessionInfo().getEnvironmentCode();
const ProfileId profileId(currentEnvironment == Environment::Cert2
? TEST_PROFILE_ID_CERT2
: TEST_PROFILE_ID);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().sendFriendsClubInvite({ profileId })));
}
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // 0 friends in china
TEST_F(FRIENDS, DISABLED_US_RequestPendingFriendsClub)
#else
TEST_F(FRIENDS, US_RequestPendingFriendsClub)
#endif
{
const AsyncResult<Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriendsClubInvites();
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
const Vector<FriendInfo>& friends = result.getResult();
//all test accounts should have a pending friend invitation from ussdk010
EXPECT_GE(friends.size(), 1ul) << "Configuration requires a pending friend for this test to be valid.";
for(const auto& it : friends)
{
const FriendInfoClub* info = it.getInfoClub();
EXPECT_TRUE(info != NULL && info->m_relation == FriendInfoClub::PendingReceivedInvite);
}
}
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // return HTTP_404_NOT_FOUND instead of HTTP_403_FORBIDDEN
TEST_F(FRIENDS, DISABLED_US_AcceptInviteClub)
#else
TEST_F(FRIENDS, US_AcceptInviteClub)
#endif
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 403", LogLevel::Error, Times(1));
US_EXPECT_LOG("Friends accept/invite for the following error:", LogLevel::Error, Times(1));
});
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().acceptFriendClubInvite(ProfileId(UPLAY_PROFILE_ID)), Errors::HTTP_403_FORBIDDEN));
}
/// @tests that declining a non existant invitation returns a 200
/// @note service is returning 200 because it does not validate if the profileId passed is actually a friend/inviting
TEST_F(FRIENDS, US_DeclineInviteClub)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().declineFriendClubInvite(ProfileId(UPLAY_PROFILE_ID))));
}
/// @tests that removing a friend that does not exist in a friend list returns 200.
/// @note service is returning 200 because it does not validate if the profileId passed is actually a friend/inviting
TEST_F(FRIENDS, US_RemoveFriendClub)
{
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().removeFriendClub(ProfileId(TEST_PROFILE_ID_INVALID))));
}
/// @test Requests console friends twice in parallel.
/// @note service is returning 200 because it does not validate if the profileId passed is actually a friend/inviting
TEST_F(FRIENDS, US_RequestConsoleFriendsTwiceInParallel)
{
const AsyncResult< US_NS::Vector<FriendInfo> > result1 = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleWithClubInfo);
const AsyncResult< US_NS::Vector<FriendInfo> > result2 = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleWithClubInfo);
EXPECT_TRUE(result1.isProcessing());
EXPECT_TRUE(result2.isProcessing());
EXPECT_TRUE(result1.wait(NS_COMMON::DEFAULT_WAIT_TIME));
EXPECT_TRUE(result1.hasSucceeded());
EXPECT_TRUE(result2.wait(NS_COMMON::DEFAULT_WAIT_TIME));
EXPECT_TRUE(result2.hasSucceeded());
}
// Disabled on XOne due to community segregation between X360 and XOne
#if !defined(US_TARGET_XONE)
/// @test Validates that \c FriendClient::requestFriends can be cancelled at anytime
/// This tests passes 75% of the time. When it fails, server seems to bump out the token and reject all user request.
/// TODO: FIXME Is this iteration legit for online test? Should it be mocked instead?
TEST_P(FRIENDS_CANCEL, US_RequestClubFriendsCancelled)
{
TestCanceler<> canceler(this->getParam());
while (!canceler.isComplete())
{
EXPECT_TRUE(canceler.cancel(getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo)));
}
}
#endif
TEST_P(FRIENDS_CANCEL, US_RequestFriendsCancel)
{
TestCanceler<> canceler(this->getParam());
while (!canceler.isComplete())
{
EXPECT_TRUE(canceler.cancel(getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly)));
}
}
// Disabled on XOne due to community segregation between X360 and XOne
#if !defined(US_TARGET_XONE)
/// @test Requests Club friends with an account with no Club friends
TEST_F(FRIENDS_NO_LOGIN, US_Win32RequestClubFriendsNoClubFriends)
{
Facade facade;
{
#if defined(US_CHINA_ACCOUNTS_SETUP_NOT_DONE) // Work right now but when friends get added it will break. We need to make a specific user for this test.
const std::unique_ptr<PlayerCredentials> credentials(NS_COMMON::AuthenticationHelper::createPlayerCredentials());
#elif defined(US_TARGET_WINDOWS)
const std::unique_ptr<PlayerCredentials> credentials(NS_COMMON::AuthenticationHelper::createPlayerCredentialsWithNoFriends());
#else
const std::unique_ptr<PlayerCredentials> credentials(NS_COMMON::AuthenticationHelper::createPlayerCredentials(8));
#endif
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.createSession(*credentials, {}, {})));
}
{
const AsyncResult<Vector<FriendInfo> > resultFriends = facade.getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
EXPECT_EQ(0u, resultFriends.getResult().size());
}
{
ASSERT_TRUE(AsyncHelper::waitSuccess(facade.deleteSession()));
}
}
#if defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_SWITCH) || defined(US_TARGET_KILI)
/// @test Validates the maximum concurrent calls allowed for requesting ConsoleWithClubInfo friends using a range.
TEST_F(FRIENDS_MOCK, USNOT_RequestFriendsConsoleWithClubInfoTooManyTimes)
{
const uint32 COUNT = 6;
{
// In order to reduce test timing sensitivity, the HTTP GET asynchronous
// result is returned in the pending state, so the request friends jobs
// remain processing until the sixth call to request friends.
// (Returning success, especially using a mock, may end up having the
// first request call completing before the sixth request (especially
// in DEBUG configuration, where logging and memory validations may slow
// down the process considerably.
const MockAsyncResult pending = MockResultHelper::createPendingResult();
//::testing::Sequence s;
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub")
.Times(::testing::AtMost(COUNT))
.WillRepeatedly(testing::Return(pending));
}
AsyncResult<Vector<FriendInfo> > results[COUNT];
const ClockSteady::TTimeMilli t1 = ClockSteady::getTimeMilli();
US_UNUSED(t1);
for(uint32 i = 0; i < COUNT; ++i)
{
results[i] = getFacade().getFriendClient().requestFriendsConsoleWithClubInfo(ResultRange(0, 2));
}
const ClockSteady::TTimeMilli t2 = ClockSteady::getTimeMilli();
US_UNUSED(t2);
PRINT_LINE("Requesting Friends Time: %d ms", (t2 - t1));
Helper::sleep(25);
for(uint32 i = 0; i < COUNT - 1; ++i)
{
EXPECT_FALSE(results[i].hasFailed());
EXPECT_FALSE(results[i].hasSucceeded());
EXPECT_TRUE(results[i].isProcessing());
}
EXPECT_FALSE(results[COUNT - 1].isProcessing()); // No more than 1 call at a time
US_EXPECT_FAILURE(results[COUNT - 1], Errors::CORE_TOO_MANY_JOBS_IN_PROGRESS);
}
/// @test Validates the maximum concurrent calls allowed for requesting ConsoleOnly friends using a range.
TEST_F(FRIENDS_MOCK, USNOT_RequestFriendsConsoleOnlyTooManyTimes)
{
const uint32 COUNT = 6;
{
// In order to reduce test timing sensitivity, the HTTP GET asynchronous
// result is returned in the pending state, so the request friends jobs
// remain processing until the sixth call to request friends.
// (Returning success, especially using a mock, may end up having the
// first request call completing before the sixth request (especially
// in DEBUG configuration, where logging and memory validations may slow
// down the process considerably.
const MockAsyncResult pending = MockResultHelper::createPendingResult();
//::testing::Sequence s;
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub")
.Times(::testing::AtMost(COUNT))
.WillRepeatedly(testing::Return(pending));
}
AsyncResult<Vector<FriendInfo> > results[COUNT];
const ClockSteady::TTimeMilli t1 = ClockSteady::getTimeMilli();
US_UNUSED(t1);
for (uint32 i = 0; i < COUNT; ++i)
{
results[i] = getFacade().getFriendClient().requestFriendsConsoleOnly(ResultRange(0, 2));
}
const ClockSteady::TTimeMilli t2 = ClockSteady::getTimeMilli();
US_UNUSED(t2);
PRINT_LINE("Requesting Friends Time: %d ms", (t2 - t1));
Helper::sleep(25);
for (uint32 i = 0; i < COUNT - 1; ++i)
{
EXPECT_FALSE(results[i].hasFailed());
EXPECT_FALSE(results[i].hasSucceeded());
EXPECT_TRUE(results[i].isProcessing());
}
EXPECT_FALSE(results[COUNT - 1].isProcessing()); // No more than 1 call at a time
US_EXPECT_FAILURE(results[COUNT - 1], Errors::CORE_TOO_MANY_JOBS_IN_PROGRESS);
}
#endif //defined(US_TARGET_PS4) || defined(US_TARGET_XONE) || defined(US_TARGET_SWITCH) || defined(US_TARGET_KILI)
/// @test Requests Club friends from the first Test environment player.
#if defined(US_TARGET_GGP)
// Unfortunately this tests even though is mocked needs an specific setup for ussdk002 and ussdk003.
// The tests uses first party api to recover first party information for the user above.
// Those users, however do not have ggp valid accounts.
TEST_F(FRIENDS_MOCK, DISABLED_USNOT_RequestClubFriends)
#else
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriends)
#endif
{
const Vector<uint32> indices = { 2u, 3u };
::testing::Sequence s;
{
const String json = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles?userId", mockResult);
}
TestFriends_BF::requestClubFriends(getFacade());
}
/// @test Requests Club friends parsing an empty list from JSON body.
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsEmptyJSON)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult("{\"friends\":[]}");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
EXPECT_EQ(0u, resultFriends.getResult().size());
}
/// @test Requests Club friends parsing an invalid JSON body.
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsInvalidJSON)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult("{\"Friends\":[],}");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitFailure(resultFriends, Errors::CORE_INVALID_JSON_FORMAT));
EXPECT_EQ(0u, resultFriends.getResult().size());
}
/// @test Requests Club friends parsing a JSON structure containing extra fields.
#if defined(US_TARGET_GGP)
// Unfortunately this tests even though is mocked needs an specific setup for ussdk002 and ussdk003.
// The tests uses first party api to recover first party information for the user above.
// Those users, however do not have ggp valid accounts.
TEST_F(FRIENDS_MOCK, DISABLED_USNOT_RequestClubFriendsFieldsVariations)
#else
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsFieldsVariations)
#endif
{
const Vector<uint32> indices = { 2u, 3u };
::testing::Sequence s;
{
const String json = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
const String field = "\"pid";
const String addfield = "\t\t\"EXTRA FIELD\":\"TEST CONTENT\",\n" + field;
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json.replace(field, addfield));
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles?userId", mockResult);
}
const AsyncResult< Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
EXPECT_EQ(2u, resultFriends.getResult().size());
}
/// @test Requests Club friends parsing a JSON structure containing extra Root node.
#if defined(US_TARGET_GGP)
// Unfortunately this tests even though is mocked needs an specific setup for ussdk002 and ussdk003.
// The tests uses first party api to recover first party information for the user above.
// Those users, however do not have ggp valid accounts.
TEST_F(FRIENDS_MOCK, DISABLED_USNOT_RequestClubFriendsWithExtraRootNode)
#else
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsWithExtraRootNode)
#endif
{
const Vector<uint32> indices = { 2u, 3u };
::testing::Sequence s;
{
const String jsonBody = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
// Add extra root node
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());
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(jsonBodyExtraNode);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles?userId", mockResult);
}
const AsyncResult< Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
EXPECT_EQ(2, resultFriends.getResult().size());
}
/// @test Requests Club friends expecting an HTTP error.
TEST_F(FRIENDS_MOCK, USNOT_RequestClubFriendsHttp404)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 404", LogLevel::Error, Times(1));
});
{
const MockAsyncResult mockResult = MockResultHelper::createHttpErrorResult(
RestStatusCode::Error404, "{\"ErrorNumber\":7,\"Description\":\"One or more parameters are missing}");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo), Errors::HTTP_404_NOT_FOUND));
}
/// @test Cancels request friends after 1st HTTP call
/// @note The first HTTP call happens in JobRequestFriendsConsole::syncFriends.
/// The job will not reach the JobRequestFriendsConsole::lookupClubInfo step.
TEST_F(FRIENDS_MOCK_CANCEL, USNOT_RequestFriendsFirst)
{
{
const MockAsyncResult mockResult = MockResultHelper::createPendingResult();
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
EXPECT_FALSE(resultFriends.wait(100)); // Wait so jobs are in progress
resultFriends.cancel();
#if defined(US_LOG_ENABLED)
EXPECT_TRUE(resultFriends.isCanceled()) << "Call state is not canceled? " << US_STREAM_CSTR(static_cast<AsyncResultBase&>(resultFriends));
#else
EXPECT_TRUE(resultFriends.isCanceled()) << "Call state is not canceled?";
#endif
US_EXPECT_FAILURE(resultFriends, Errors::CANCELED);
}
/// @test Cancels request friends after call is terminated
TEST_F(FRIENDS_MOCK_CANCEL, USNOT_RequestFriendsDoneBeforeCancel)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult("{\"friends\":[]}");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
EXPECT_TRUE(resultFriends.wait(NS_COMMON::DEFAULT_WAIT_TIME));
// Canceling a call after call is terminated is a no-op
resultFriends.cancel();
EXPECT_FALSE(resultFriends.isCanceled());
US_EXPECT_SUCCESS(resultFriends);
EXPECT_EQ(0u, resultFriends.getResult().size());
}
/// @test Ensures the same call can be issued after canceling it first.
/// This test makes sure that up on cancel, number of active calls is decreased.USNOT_InviteFriendClubInvalidProfileId
TEST_F(FRIENDS_MOCK_CANCEL, USNOT_RequestFriendsAfterCancel)
{
{
const MockAsyncResult mockPending = MockResultHelper::createPendingResult();
const MockAsyncResult mockSuccess = MockResultHelper::createSuccessResult("{\"friends\":[]}");
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub")
.WillOnce(testing::Return(mockPending))
.WillOnce(testing::Return(mockSuccess));
}
{
AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
EXPECT_FALSE(resultFriends.wait(100));
resultFriends.cancel();
#if defined(US_LOG_ENABLED)
EXPECT_TRUE(resultFriends.isCanceled()) << "Call state is not canceled? " << US_STREAM_CSTR(static_cast<AsyncResultBase&>(resultFriends));
#else
EXPECT_TRUE(resultFriends.isCanceled()) << "Call state is not canceled?";
#endif
EXPECT_TRUE(resultFriends.hasFailed());
}
// Ensure calling requestFriends succeeds after a cancel.
{
const AsyncResult<Vector<FriendInfo> > resultFriends = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultFriends));
EXPECT_EQ(0u, resultFriends.getResult().size());
}
}
#endif // US_TARGET_XONE
TEST_F(FRIENDS_MOCK, USNOT_InviteFriendClub)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult("");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub", mockResult);
}
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().sendFriendsClubInvite({ ProfileId(TEST_PROFILE_ID) })));
}
TEST_F(FRIENDS_MOCK, USNOT_InviteFriendClubSeveralProfiles)
{
HttpPost request(StringUrl(""), String());
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult("");
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub")
.WillOnce(testing::DoAll(testing::SaveArg<0>(static_cast<HttpRequest*>(&request)), testing::Return(mockResult)));
}
EXPECT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().sendFriendsClubInvite({ ProfileId(TEST_PROFILE_ID), ProfileId(TEST_PROFILE_ID_2) })));
EXPECT_NE(String::npos, request.getBodyAsString().findSubstringCase(TEST_PROFILE_ID));
EXPECT_NE(String::npos, request.getBodyAsString().findSubstringCase(TEST_PROFILE_ID_2));
}
TEST_F(FRIENDS_MOCK, USNOT_InviteFriendClubFailed)
{
PrepareLoggingMock([](US_TEST_NS::MockLogDevice& device)
{
US_EXPECT_LOG("Status code: 400", LogLevel::Error, Times(1));
US_EXPECT_LOG("Friends invitation failed for the following error:", LogLevel::Error, Times(1));
});
{
const MockAsyncResult mockResult = MockResultHelper::createHttpErrorResult(
RestStatusCode::Error400, "{\"FaultNum\":12345, \"FaultDesc\":\"My Mocked Error\"}");
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().sendFriendsClubInvite({ ProfileId(TEST_PROFILE_ID) }), Errors::FRIEND_GENERIC_FAILURE));
}
TEST_F(FRIENDS_MOCK, USNOT_AcceptInviteClubSuccess)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(HTTP_EMPTY_BODY);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_PUT, "friendsClub", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().acceptFriendClubInvite(ProfileId(UPLAY_PROFILE_ID))));
}
TEST_F(FRIENDS_MOCK, USNOT_DeclineInviteClubSuccess)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(HTTP_EMPTY_BODY);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_DELETE, "friendsClub", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().declineFriendClubInvite(ProfileId(UPLAY_PROFILE_ID))));
}
TEST_F(FRIENDS_MOCK, USNOT_RemoveFriendClubSuccess)
{
{
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(HTTP_EMPTY_BODY);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_DELETE, "friendsClub", mockResult);
}
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().getFriendClient().removeFriendClub(ProfileId(TEST_PROFILE_ID_INVALID))));
}
#if !defined(US_TARGET_WINDOWS) && !defined(US_TARGET_OSX) || defined(US_TARGET_LINUX) || defined(US_TARGET_GGP)
typedef LoginMockFixture<false> FRIENDS_MOCK_NOLOGIN;
/// @test Validates that requesting console friends fails if not logged in to Uplay.
/// @note This test does not apply for Win32 and OSX as there are no platform-specific friends.
TEST_F(FRIENDS_MOCK_NOLOGIN, USNOT_RequestFriendsNotLoggedIn)
{
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly), Errors::AUTH_SESSION_NOT_CREATED));
}
#endif
// Disabled on XONE due to community segregation between X360 and XONE
// This test does not make sense on ClubLogin targets
#if !defined(US_ENABLE_UPLAY_LOGIN) && !defined(US_TARGET_XONE)
TEST_F(FRIENDS, US_RequestFriendsClubCheckConsoleInfo)
{
const AsyncResult<Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriends(FriendClient::ClubWithConsoleInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
for(const auto& it : result.getResult())
{
const FriendInfoClub* club = it.getInfoClub();
if(club != NULL && club->m_profileInfo.m_nameOnPlatform == "ussdk002")
{
const FriendInfoConsole* info = it.getInfoConsole();
ASSERT_TRUE(info != NULL);
EXPECT_TRUE(info->hasAlreadyPlayedUbisoftGame());
EXPECT_TRUE(info->m_profileInfo.m_profileId.isValid());
EXPECT_NE(0u, info->m_profileInfo.m_nameOnPlatform.getLength());
break;
}
}
}
#endif
/// @test Checks that an error is raised and no request is sent when an invalid profile is given
TEST_F(FRIENDS_MOCK, USNOT_InviteFriendClubInvalidProfileId)
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub").Times(0);
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().sendFriendsClubInvite({ ProfileId("Invalid") }), Errors::FRIEND_INVALID_PARAM));
}
/// @test Checks that an error is raised and no request is sent when an invalid profile is given
TEST_F(FRIENDS_MOCK, USNOT_RemoveFriendClubInvalidProfileId)
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub").Times(0);
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().removeFriendClub(ProfileId("Invalid")), Errors::FRIEND_INVALID_PARAM));
}
/// @test Checks that an error is raised and no request is sent when an invalid profile is given
TEST_F(FRIENDS_MOCK, USNOT_AcceptFriendClubInviteInvalidProfileId)
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub").Times(0);
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().acceptFriendClubInvite(ProfileId("Invalid")), Errors::FRIEND_INVALID_PARAM));
}
/// @test Checks that an error is raised and no request is sent when an invalid profile is given
TEST_F(FRIENDS_MOCK, USNOT_DeclineFriendClubInviteInvalidProfileId)
{
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_POST, "friendsClub").Times(0);
ASSERT_TRUE(AsyncHelper::waitFailure(getFacade().getFriendClient().declineFriendClubInvite(ProfileId("Invalid")), Errors::FRIEND_INVALID_PARAM));
}
#if !defined(US_DLL)
/// @test Validates Caching on requestClubFriends.
#if defined(US_TARGET_GGP)
// Unfortunately this tests even though is mocked needs an specific setup for ussdk002 and ussdk003.
// The tests uses first party api to recover first party information for the user above.
// Those users, however do not have ggp valid accounts.
TEST_F(FRIENDS_MOCK_NOLOGIN, DISABLED_USNOT_FriendCaching)
#else
TEST_F(FRIENDS_MOCK_NOLOGIN, USNOT_FriendCaching)
#endif
{
{
// Note : It seems that first-party calls to friends can take more than 3 seconds
// The cache ttl (default 3s in mock tests) is therefore increased in this test
class LongTTLParametersSpaceMockHelper : public ParametersSpaceMockHelper
{
private:
Json buildParameterGroupSettingsCacheTTL() const override
{
const uint32 ttl = 3*60; // 3 minutes instead of 3 seconds
JsonWriter fields;
fields["defaultSec"] = ttl;
fields["profilesNewsSec"] = ttl;
fields["spacesNewsSec"] = ttl;
fields["profilesActionsSec"] = ttl;
fields["profilesChallengesSec"] = ttl;
fields["profilesRewardsSec"] = ttl;
fields["friendsListSec"] = ttl;
return renderParameterGroup(fields.getJson());
}
};
const MockAsyncResult parametersSpaceResult = MockResultHelper::createSuccessResult(
LongTTLParametersSpaceMockHelper().getParameters().renderContent());
mockFullLogin(nullptr, nullptr, &parametersSpaceResult);
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(GET_CREDENTIALS(), {}, {})));
}
{
const Vector<uint32> indices = { 2u, 3u };
::testing::Sequence s;
{
const String json = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles?userId", mockResult);
}
}
// First call sends requests
TestFriends_BF::requestClubFriends(getFacade());
// Second call must return with the cache (no HTTP call)
TestFriends_BF::requestClubFriends(getFacade());
// Invalidate the cache so the third call triggers HTTP requests
FriendClientProxy::invalidateCache(getFacade().getFriendClient());
{
const Vector<uint32> indices = { 2u, 3u };
::testing::Sequence s;
{
const String json = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "friendsClub", mockResult);
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP_SIMPLE(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "profiles?userId", mockResult);
}
}
TestFriends_BF::requestClubFriends(getFacade());
}
#endif // !defined(US_DLL)
#if defined(US_TARGET_PS4)
// TODO transform this test in Mock and check that calls are made the second time.
// we want to verify that the InstancesManager::unregisterUser method has been called and that it resets the friend cache
// US-12808
TEST_F(FRIENDS_NO_FACADE, US_PS4FriendCacheInvalidatesWhenFacadeIsDeleted)
{
{
Facade facade;
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
const AsyncResult<Vector<FriendInfo> > result = facade.getFriendClient().requestFriends(FriendClient::ConsoleOnly);
EXPECT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_LE(0u, result.getResult().size());
}
{
Facade facade;
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
const AsyncResult<Vector<FriendInfo> > result = facade.getFriendClient().requestFriends(FriendClient::ConsoleOnly);
EXPECT_TRUE(AsyncHelper::waitSuccess(result));
EXPECT_LE(0u, result.getResult().size());
}
}
/// @test Validates the account has 100 friends and 55 of them as their new name and not the one stored in our services
/// @note This test requires a specific account: Manual Hundredfriends
/// This is how the test work:
/// The account has 100 friends, where 55 of them were connected once to our services with an old name.
/// Afterward, these accounts name were all changed to specific pattern: manualXXfriends (where XX is a number from 1 to 55).
/// Theses 55 accounts are to never be connected again to our services, so our services still has the old name registered.
/// The test verifies that we're batching to group of 50(being the limit per batch), and that the names in both batch that
/// were changed are the ones from the primary network and not from our services(e.g. manualXXfriends).
TEST_F(FRIENDS_NO_FACADE, DISABLED_MANUAL_US_PS4FriendRequest)
{
std::unique_ptr<PlayerCredentials> creds(NS_COMMON::AuthenticationHelper::createPlayerCredentials());
Facade facade;
EXPECT_TRUE(AsyncHelper::waitSuccess(facade.createSession(*creds, {}, {})));
FriendClient& client = facade.getFriendClient();
AsyncResult<Vector<FriendInfo> > result = client.requestFriends(FriendClient::ConsoleOnly);
EXPECT_TRUE(AsyncHelper::waitSuccess(result));
Vector<FriendInfo> friendsInfo = result.getResult();
ASSERT_EQ(friendsInfo.size(), 100);
unsigned int newNamesCount = 0;
for (Vector<FriendInfo>::const_iterator it = friendsInfo.begin(); it != friendsInfo.end(); ++it)
{
const FriendInfoConsole* friendInfoConsole = it->getInfoConsole();
if (friendInfoConsole)
{
const String id = friendInfoConsole->m_profileInfo.m_idOnPlatform;
const String name = friendInfoConsole->m_profileInfo.m_nameOnPlatform;
if (name.findSubstringNoCase("manual") != String::npos)
{
++newNamesCount;
}
PRINT_LINE("Requesting Friends = %30s - %30s", id.getUtf8(), name.getUtf8());
}
}
ASSERT_EQ(newNamesCount, 55);
}
// Please do not delete yet ! DomD
//TEST_F(FRIENDS, DISABLED_MANUAL_TestAddFriendsAndRequestFriendsList)
//{
// LoggingHelper::enableVerbose();
// LoggingHelper::enableMultiLines();
// for (;;)
// {
// if (NS_COMMON::isFriendCallBackReceived) //when we receive the notification from PS4 that the friends were changed
// {
// NS_COMMON::isFriendCallBackReceived = false;
// FriendClient& client = getFacade().getFriendClient();
// const AsyncResult<US_NS::Vector<FriendInfo> > resultAll = client.requestFriends(FriendClient::ConsoleWithClubInfo);
// ASSERT_TRUE(AsyncHelper::waitSuccess(resultAll));
// }
// else
// {
// Helper::sleep(100);
// }
// }
//}
#endif
#if defined(US_TARGET_XONE)
#if !defined(US_DLL)
/// @test Validates that after receiving a callback event from the Xbox social service,
/// the cache for ConsoleWithClubInfo is invalidated.
/// Three Http friends requests are made.
/// 1st request: to get get friend request, we check for size to validate content (expects call)
/// 2nd request: to verify that cache is being used. (no call expected)
/// 3rd request: to verify that the cache was invalidated after receiving callback and that an actual Http request is sent. (expects call)
/// To run this test you must add/remove friend from user while the test is running
TEST_F(FRIENDS_MOCK_NOLOGIN, DISABLED_MANUAL_TestFriendClientConsoleWithClubInfoCacheInvalidationOnCallback)
{
// Set expect Http request for event.
// Events might be sent while waiting for tester to add/remove a friend
{
mockFullLogin();
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(MockResultHelper::createSuccessResult()));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Expected calls for friend requests
const Vector<uint32> indices = { 2u, 3u };
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-profiles?idOnPlatform")
.Times(2).WillRepeatedly(testing::Return(mockResult));
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-profiles?userId")
.Times(2).WillRepeatedly(testing::Return(mockResult));
}
static bool eventReceived = false;
// Initial friend request
const AsyncResult<Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleWithClubInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(4, result.getResult().size()); // This value might change depending on the friends setup for current user.
// 2nd friend request (should use cache)
const AsyncResult<Vector<FriendInfo> > resultCache = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleWithClubInfo);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultCache));
ASSERT_EQ(4, resultCache.getResult().size()); // This value might change depending on the friends setup for current user.
// Setup friend callback
TestFriends_BF::checkRelationShipChange(getFacade(), eventReceived, FriendClient::ConsoleWithClubInfo);
// Loop waits for friend change
while (!eventReceived)
{
Helper::sleep(1000);
PRINT_LINE("Waiting for friend change event...");
}
}
// @test Validates that after receiving a callback event from the Xbox social service,
/// the cache for Consolidated is invalidated.
/// Three Http friends requests are made.
/// 1st request: to get get friend request, we check for size to validate content (expects call)
/// 2nd request: to verify that cache is being used. (no call expected)
/// 3rd request: to verify that the cache was invalidated after receiving callback and that an actual Http request is sent. (expects call)
/// To run this test you must add/remove friend from user while the test is running
TEST_F(FRIENDS_MOCK_NOLOGIN, DISABLED_MANUAL_TestFriendClientConsolidatedCacheInvalidationOnCallback)
{
// Set expect Http request for event.
// Events might be sent while waiting for tester to add/remove a friend
{
mockFullLogin();
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(MockResultHelper::createSuccessResult()));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Expected calls for friend requests
const Vector<uint32> indices = { 2u, 3u };
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-profiles?idOnPlatform")
.Times(2).WillRepeatedly(testing::Return(mockResult));
}
{
const String json = MockProfileHelper::buildRequestFriendsResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-friendsClub")
.Times(2).WillRepeatedly(testing::Return(mockResult));
}
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-profiles?userId")
.Times(4).WillRepeatedly(testing::Return(mockResult));
}
static bool eventReceived = false;
// Initial friend request
const AsyncResult<US_NS::Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriends(FriendClient::Consolidated);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(4, result.getResult().size()); // This value might change depending on the friends setup for current user.
// 2nd friend request (should use cache)
const AsyncResult<US_NS::Vector<FriendInfo> > resultCache = getFacade().getFriendClient().requestFriends(FriendClient::Consolidated);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultCache));
ASSERT_EQ(4, resultCache.getResult().size()); // This value might change depending on the friends setup for current user.
// Setup friend callback
TestFriends_BF::checkRelationShipChange(getFacade(), eventReceived, FriendClient::Consolidated);
// Loop waits for friend change
while (!eventReceived)
{
Helper::sleep(1000);
PRINT_LINE("Waiting for friend change event...");
}
}
/// @test validates that after receiving a callback event from the Xbox social service,
/// the cache for ConsoleOnly is invalidated.
/// Three Http friends requests are made.
/// 1st request: to get get friend request, we check for size to validate content (expects call)
/// 2nd request: to verify that cache is being used. (no call expected)
/// 3rd request: to verify that the cache was invalidated after receiving callback and that an actual Http request is sent. (expects call)
/// To run this test you must add/remove friend from user while the test is running
TEST_F(FRIENDS_MOCK_NOLOGIN, DISABLED_MANUAL_TestFriendClientConsoleOnlyCacheInvalidationOnCallback)
{
// Set expect Http request for event.
// Events might be sent while waiting for tester to add/remove a friend
{
mockFullLogin();
US_EXPECT_CALL(US_TEST_NS::Action::SendEvents)
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Return(MockResultHelper::createSuccessResult()));
ASSERT_TRUE(AsyncHelper::waitSuccess(getFacade().createSession(*NS_COMMON::AuthenticationHelper::createCredentials(), {}, {})));
waitForPostLoginCompletion();
}
// Expected calls for friend requests
const Vector<uint32> indices = { 2u, 3u };
{
const String json = MockProfileHelper::buildRequestProfilesResponse(indices).renderContent();
const MockAsyncResult mockResult = MockResultHelper::createSuccessResult(json);
US_EXPECT_CALL_HTTP(getMockHttpClientImpl(), HttpMethod::HTTP_GET, "mock-profiles?idOnPlatform")
.Times(2).WillRepeatedly(testing::Return(mockResult));
}
static bool eventReceived = false;
// Initial friend request
const AsyncResult<US_NS::Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
ASSERT_EQ(4, result.getResult().size()); // This value might change depending on the friends setup for current user.
// 2nd friend request (should use cache)
const AsyncResult<US_NS::Vector<FriendInfo> > resultCache = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly);
ASSERT_TRUE(AsyncHelper::waitSuccess(resultCache));
ASSERT_EQ(4, resultCache.getResult().size()); // This value might change depending on the friends setup for current user.
// Setup friend callback
TestFriends_BF::checkRelationShipChange(getFacade(), eventReceived, FriendClient::ConsoleOnly);
// Loop waits for friend change
while (!eventReceived)
{
Helper::sleep(1000);
PRINT_LINE("Waiting for friend change event...");
}
}
#endif //US_DLL
/// @test validates that after receiving a callback event from the Xbox social service,
/// the cache for ConsoleOnly is invalidated
/// and that the new friend list contains the right friends.
/// @note To run this test you must add/remove friend from user while the test is running and observe the resulting friend list changes
TEST_F(FRIENDS, DISABLED_MANUAL_TestFriendClientConsoleOnlyCacheAfterRemoveFriend)
{
// Initial friend request
const AsyncResult<US_NS::Vector<FriendInfo> > result = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly);
ASSERT_TRUE(AsyncHelper::waitSuccess(result));
const AsyncResult<US_NS::Vector<FriendInfo> > resultCache = getFacade().getFriendClient().requestFriends(FriendClient::ConsoleOnly);
EXPECT_EQ(result, resultCache);
bool eventReceived = false;
// Setup friend callback
AsyncResult<US_NS::Vector<FriendInfo>> updatedResult = TestFriends_BF::checkRelationShipChange(getFacade(), eventReceived, FriendClient::ConsoleOnly);
// Loop waits for friend change
while (!eventReceived)
{
Helper::sleep(1000);
PRINT_LINE("Waiting for a friend change event...");
}
auto printFriendList = [] (const char* title, const Vector<FriendInfo>& friendList)
{
PRINT_LINE(title);
for (const FriendInfo& friendInfo : friendList)
{
PRINT_LINE("Player display name: %s", friendInfo.getInfoConsole()->m_profileInfo.m_nameOnPlatform.getUtf8());
}
};
printFriendList("Initial friend list:", result.getResult());
printFriendList("Cached Friend list:", resultCache.getResult());
printFriendList("Friend list after change:", updatedResult.getResult());
}
#endif
};