public void PreventPlayersFromJoiningAPartyWithoutAValidInvite()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Verify that the party was successfully created.
            var partyAssociatedToPlayer = _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                                          new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).Party;

            Assert.NotNull(partyAssociatedToPlayer);

            // Verify that another player can successfully join the party.
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, CreatePlayerIdentityTokenForPlayer(PlayerId) }
            }));

            Assert.AreEqual(StatusCode.FailedPrecondition, exception.StatusCode);
            Assert.That(exception.Message, Contains.Substring("not invited"));
        }
        public void PreventPlayersFromJoiningAPartyIfTheyAreMembersOfAnotherParty()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Verify that the party was successfully created.
            var partyAssociatedToPlayer = _partyClient
                                          .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            })
                                          .Party;

            Assert.NotNull(partyAssociatedToPlayer);

            // Create another party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            _partyClient.CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            // Verify that the party was successfully created.
            partyAssociatedToPlayer = _partyClient
                                      .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                          new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            })
                                      .Party;
            Assert.NotNull(partyAssociatedToPlayer);

            // Verify that the second player is not allowed to join another party.
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }));

            Assert.AreEqual(StatusCode.AlreadyExists, exception.StatusCode);
        }
        public void PreventNonLeadersFromKickingOutOtherMembers()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Another player joins the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };

            _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            // Verify that the player who has recently joined the party is associated to it.
            var party = _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                        new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }).Party;

            Assert.NotNull(party);
            Assert.AreEqual(LeaderPlayerId, party.LeaderPlayerId);

            // Verify that the leader can kick out other players.
            _partyClient.KickOutPlayer(new KickOutPlayerRequest {
                EvictedPlayerId = PlayerId
            },
                                       new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            var exception = Assert.Throws <RpcException>(
                () => _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                      new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }));

            Assert.AreEqual(StatusCode.NotFound, exception.StatusCode);
        }
        public void ReturnPartyWhenSuccessfullyJoiningTheParty()
        {
            // Setup the client such that it will successfully add the player to the party.
            var entriesCreated = new List <Entry>();
            var entriesUpdated = new List <Entry>();

            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id)).ReturnsAsync(_partyToJoin);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Member>(TestPlayerId)).ReturnsAsync((Member)null);
            _mockTransaction.Setup(tr => tr.CreateAll(It.IsAny <IEnumerable <Entry> >()))
            .Callback <IEnumerable <Entry> >(entries => entriesCreated.AddRange(entries));
            _mockTransaction.Setup(tr => tr.UpdateAll(It.IsAny <IEnumerable <Entry> >()))
            .Callback <IEnumerable <Entry> >(entries => entriesUpdated.AddRange(entries));
            _mockTransaction.Setup(tr => tr.Dispose());
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PlayerInvites>(TestPlayerId)).ReturnsAsync(_playerInvites);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Invite>("invite")).ReturnsAsync(_invite);
            _mockAnalyticsSender.Setup(
                sender => sender.Send(AnalyticsConstants.PartyClass, AnalyticsEventType,
                                      It.Is <Dictionary <string, object> >(d =>
                                                                           AnalyticsAttributesExpectations(d)), TestPlayerId));


            // Check that the join was successfully completed and that the expected party was returned.
            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var party = _partyService.JoinParty(request, context).Result.Party;

            Assert.IsNotNull(party);
            Assert.AreEqual(_partyToJoin.Id, party.Id);
            Assert.Contains(TestPlayerId, party.MemberIds);

            // Verify that the expected entries were created/updated.
            Assert.AreEqual(1, entriesCreated.Count);
            Assert.IsInstanceOf <Member>(entriesCreated[0]);

            var member = (Member)entriesCreated[0];

            Assert.AreEqual(TestPlayerId, member.Id);
            Assert.AreEqual(_partyToJoin.Id, member.PartyId);

            Assert.AreEqual(1, entriesUpdated.Count);
            Assert.IsInstanceOf <PartyDataModel>(entriesUpdated[0]);
            var updatedParty = (PartyDataModel)entriesUpdated[0];

            Assert.AreEqual(_partyToJoin.Id, updatedParty.Id);
            Assert.IsNotNull(updatedParty.GetMember(TestPlayerId));

            _mockAnalyticsSender.VerifyAll();
        }
        public void PreventNonLeadersFromDeletingAParty()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Verify that the party was successfully created.
            var partyAssociatedToPlayer = _partyClient
                                          .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            })
                                          .Party;

            Assert.NotNull(partyAssociatedToPlayer);

            // Another player joins the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };

            _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            // Verify that it is impossible for the non-leader to delete the party.
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.DeleteParty(new DeletePartyRequest(),
                                                                                  new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }));

            Assert.AreEqual(StatusCode.PermissionDenied, exception.StatusCode);
            Assert.That(exception.Message, Contains.Substring("player needs to be the leader"));
        }
        public void ReturnNotFoundWhenTheGivenPartyDoesNotExist()
        {
            // Setup the client such that it will claim that there aren't any parties having as id TestPartyId.
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id))
            .ReturnsAsync((PartyDataModel)null);

            // Check that an exception was thrown when trying to join a non-existing party.
            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _partyService.JoinParty(request, context));

            Assert.That(exception.Message, Contains.Substring("party doesn't exist"));
            Assert.AreEqual(StatusCode.NotFound, exception.StatusCode);
        }
        public void ReturnAlreadyExistsWhenThePlayerIsAMemberOfAnotherParty()
        {
            // Setup the client such that it will claim that the player is already a member of another party.
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id)).ReturnsAsync(_partyToJoin);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Member>(TestPlayerId))
            .ReturnsAsync(new Member(TestPlayerId, "AnotherPartyId"));

            // Check that an exception was thrown when trying to join a party.
            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _partyService.JoinParty(request, context));

            Assert.That(exception.Message, Contains.Substring("player is a member of another party"));
            Assert.AreEqual(StatusCode.AlreadyExists, exception.StatusCode);
        }
        public void ReturnFailedPreconditionWhenThePlayerDoesNotHaveAnyInvites()
        {
            // Setup the client such that it will claim that the party is not in the Forming phase.
            _partyToJoin.CurrentPhase = PartyDataModel.Phase.Matchmaking;
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id)).ReturnsAsync(_partyToJoin);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Member>(TestPlayerId)).ReturnsAsync((Member)null);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PlayerInvites>(TestPlayerId)).ReturnsAsync((PlayerInvites)null);

            // Check that an exception was thrown when trying to rejoin the party.
            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _partyService.JoinParty(request, context));

            Assert.That(exception.Message, Contains.Substring("The player is not invited to this party"));
            Assert.AreEqual(StatusCode.FailedPrecondition, exception.StatusCode);
        }
        public void ReturnEarlyWhenThePlayerIsAlreadyAMemberOfTheParty()
        {
            // Setup the client such that it will claim that the player is already a member of the party they're trying
            // to join.
            _partyToJoin.AddPlayerToParty(TestPlayerId, Pit);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id)).ReturnsAsync(_partyToJoin);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Member>(TestPlayerId))
            .ReturnsAsync(_partyToJoin.GetMember(TestPlayerId));
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PlayerInvites>(TestPlayerId)).ReturnsAsync(_playerInvites);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Invite>("invite")).ReturnsAsync(_invite);

            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var response = _partyService.JoinParty(request, context).Result;

            Assert.NotNull(response.Party);
        }
Esempio n. 10
0
        public void ReturnFailedPreconditionIfPartyIsAtFullCapacity()
        {
            // Setup the client such that it will claim that the party is at full capacity.
            _partyToJoin.UpdateMinMaxMembers(1, 1);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PartyDataModel>(_partyToJoin.Id)).ReturnsAsync(_partyToJoin);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Member>(TestPlayerId)).ReturnsAsync((Member)null);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <PlayerInvites>(TestPlayerId)).ReturnsAsync(_playerInvites);
            _mockMemoryStoreClient.Setup(client => client.GetAsync <Invite>("invite")).ReturnsAsync(_invite);

            // Check that an exception was thrown when trying to join the party.
            var context = Util.CreateFakeCallContext(TestPlayerId, Pit);
            var request = new JoinPartyRequest {
                PartyId = _partyToJoin.Id
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _partyService.JoinParty(request, context));

            Assert.That(exception.Message, Contains.Substring("full capacity"));
            Assert.AreEqual(StatusCode.FailedPrecondition, exception.StatusCode);
        }
        public void PreventNonLeadersFromExtractingLeaderPit()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Another player joins the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };

            _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            // Verify that the player who has recently joined the party is associated to it.
            var party = _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                        new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }).Party;

            Assert.NotNull(party);
            Assert.AreEqual(LeaderPlayerId, party.LeaderPlayerId);
        }
Esempio n. 12
0
        public override async Task <JoinPartyResponse> JoinParty(JoinPartyRequest request, ServerCallContext context)
        {
            var playerId = AuthHeaders.ExtractPlayerId(context);

            var pit = AuthHeaders.ExtractPit(context);

            if (string.IsNullOrEmpty(request.PartyId))
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument,
                                                  "JoinParty requires a non-empty party id"));
            }

            using (var memClient = _memoryStoreClientManager.GetClient())
            {
                var partyToJoin = await memClient.GetAsync <PartyDataModel>(request.PartyId) ??
                                  throw new RpcException(new Status(StatusCode.NotFound, "The party doesn't exist"));

                var member = await memClient.GetAsync <Member>(playerId);

                if (member != null && member.PartyId != request.PartyId)
                {
                    throw new RpcException(new Status(StatusCode.AlreadyExists,
                                                      "The player is a member of another party"));
                }

                var playerInvites = await memClient.GetAsync <PlayerInvites>(playerId);

                if (playerInvites == null)
                {
                    throw new RpcException(new Status(StatusCode.FailedPrecondition,
                                                      "The player is not invited to this party"));
                }

                var invites = (await Task.WhenAll(playerInvites.InboundInviteIds
                                                  .Select(invite => memClient.GetAsync <Invite>(invite))))
                              .Where(invite =>
                {
                    if (invite == null)
                    {
                        Log.Logger.Warning("Failed to fetch an invite for {player}", playerId);
                    }

                    return(invite != null);
                }).ToList();

                var invited = invites
                              .Any(invite => invite.CurrentStatus == Invite.Status.Pending && invite.ReceiverId == playerId);

                if (!invited)
                {
                    throw new RpcException(new Status(StatusCode.FailedPrecondition,
                                                      "The player is not invited to this party"));
                }


                if (partyToJoin.CurrentPhase != PartyPhaseDataModel.Forming)
                {
                    throw new RpcException(new Status(StatusCode.FailedPrecondition,
                                                      "The party is no longer in the Forming phase"));
                }

                // TODO(iuliaharasim/dom): Move logic specific to joining a party into a separate class.
                try
                {
                    var added = partyToJoin.AddPlayerToParty(playerId, pit);
                    // If false, the player already joined the party so we should terminate early.
                    if (!added)
                    {
                        return(new JoinPartyResponse {
                            Party = ConvertToProto(partyToJoin)
                        });
                    }
                }
                catch (Exception exception)
                {
                    throw new RpcException(new Status(StatusCode.FailedPrecondition, exception.Message));
                }

                using (var transaction = memClient.CreateTransaction())
                {
                    transaction.CreateAll(new List <Entry> {
                        partyToJoin.GetMember(playerId)
                    });
                    transaction.UpdateAll(new List <Entry> {
                        partyToJoin
                    });
                }

                _analytics.Send("player_joined_party", new Dictionary <string, object>
                {
                    { "partyId", partyToJoin.Id },
                    {
                        "invites", invites.Select(invite => new Dictionary <string, string>
                        {
                            { "inviteId", invite.Id },
                            { "playerIdInviter", invite.SenderId }
                        })
                    }
                }, playerId);

                return(new JoinPartyResponse {
                    Party = ConvertToProto(partyToJoin)
                });
            }
        }
        public void RandomlyAssignAnotherLeaderWhenTheyLeaveTheParty()
        {
            // Create a party.
            var pitLeader = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var metadata  = new Dictionary <string, string> {
                { "random", "things" }
            };
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };

            createPartyRequest.Metadata.Add(metadata);
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Another player joins the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };

            _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            // The leader leaves the party.
            _partyClient.LeaveParty(new LeavePartyRequest(), new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            // Verify that the former-leader is no longer associated to any party.
            _partyClient.LeaveParty(new LeavePartyRequest(), new Metadata {
                { PitRequestHeaderName, pitLeader }
            });
            var exception = Assert.Throws <RpcException>(
                () => _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                      new Metadata {
                { PitRequestHeaderName, pitLeader }
            }));

            Assert.AreEqual(StatusCode.NotFound, exception.StatusCode);

            // Verify that the other remaining player has automatically been assigned the role of 'leader' since there
            // are no other members in the party.
            var partyAfterLeaderLeft = _partyClient
                                       .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                           new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }).Party;

            Assert.AreEqual(PlayerId, partyAfterLeaderLeft.LeaderPlayerId);
        }
        public void AllowLeadersToAppointOtherPlayersAsLeader()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Another player joins the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };

            _partyClient.JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            });

            var partyAssociatedToPlayer = _partyClient
                                          .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            })
                                          .Party;

            // Appoint the newly joined player as the leader of the party.
            partyAssociatedToPlayer.LeaderPlayerId = PlayerId;
            var updatedParty = _partyClient.UpdateParty(new UpdatePartyRequest {
                UpdatedParty = partyAssociatedToPlayer
            },
                                                        new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).Party;

            // Verify that only the leader player id has been updated.
            Assert.AreEqual(PlayerId, updatedParty.LeaderPlayerId);
            Assert.AreEqual(MinMembers, updatedParty.MinMembers);
            Assert.AreEqual(MaxMembers, updatedParty.MaxMembers);
            Assert.AreEqual(PartyPhaseProto.Forming, updatedParty.CurrentPhase);
            CollectionAssert.AreEquivalent(createPartyRequest.Metadata, updatedParty.Metadata);

            // Verify that the leader no longer has the necessary permissions to perform certain operations.
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.DeleteParty(new DeletePartyRequest(),
                                                                                  new Metadata {
                { PitRequestHeaderName, pitLeader }
            }));

            Assert.AreEqual(StatusCode.PermissionDenied, exception.StatusCode);

            updatedParty.CurrentPhase = PartyPhaseProto.Matchmaking;
            exception = Assert.Throws <RpcException>(() =>
                                                     _partyClient.UpdateParty(new UpdatePartyRequest {
                UpdatedParty = updatedParty
            },
                                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            }));
            Assert.AreEqual(StatusCode.PermissionDenied, exception.StatusCode);
        }
        public void PreventPlayersFromJoiningAPartyIfItIsAtFullCapacity()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Verify that the party was successfully created.
            var partyAssociatedToPlayer = _partyClient
                                          .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            })
                                          .Party;

            Assert.NotNull(partyAssociatedToPlayer);

            // Fill up the party such that it is at full capacity.
            for (var i = 1; i < MaxMembers; i++)
            {
                var playerId            = $"{PlayerId}:{i}";
                var pit                 = CreatePlayerIdentityTokenForPlayer(playerId);
                var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                    ReceiverPlayerId = playerId
                },
                                                                     new Metadata {
                    { PitRequestHeaderName, pitLeader }
                });
                Assert.NotNull(inviteAnotherPlayer);
                var joinRequest = new JoinPartyRequest {
                    PartyId = partyId
                };
                _partyClient.JoinParty(joinRequest, new Metadata {
                    { PitRequestHeaderName, pit }
                });
            }

            // Verify that it is impossible for another player to join the party.
            var extraPlayerPit    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteExtraPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                               new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            Assert.NotNull(inviteExtraPlayer);
            var extraJoinRequest = new JoinPartyRequest {
                PartyId = partyId
            };
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.JoinParty(extraJoinRequest, new Metadata {
                { PitRequestHeaderName, extraPlayerPit }
            }));

            Assert.AreEqual(StatusCode.FailedPrecondition, exception.StatusCode);
            Assert.That(exception.Message, Contains.Substring("full capacity"));
        }
        public void LetOtherMembersJoinAParty()
        {
            // Create a party.
            var pitLeader          = CreatePlayerIdentityTokenForPlayer(LeaderPlayerId);
            var createPartyRequest = new CreatePartyRequest {
                MinMembers = MinMembers, MaxMembers = MaxMembers
            };
            var partyId = _partyClient
                          .CreateParty(createPartyRequest, new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).PartyId;

            // Verify that the party was successfully created.
            var partyAssociatedToPlayer = _partyClient
                                          .GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                              new Metadata {
                { PitRequestHeaderName, pitLeader }
            })
                                          .Party;

            Assert.NotNull(partyAssociatedToPlayer);

            // Verify that another player can successfully join the party.
            var pitAnotherPlayer    = CreatePlayerIdentityTokenForPlayer(PlayerId);
            var inviteAnotherPlayer = _inviteClient.CreateInvite(new CreateInviteRequest {
                ReceiverPlayerId = PlayerId
            },
                                                                 new Metadata {
                { PitRequestHeaderName, pitLeader }
            }).InviteId;

            Assert.NotNull(inviteAnotherPlayer);
            var joinRequest = new JoinPartyRequest {
                PartyId = partyId
            };
            var partyJoined = _partyClient
                              .JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }).Party;

            Assert.AreEqual(2, partyJoined.MemberIds.Count);

            // Rejoining the same party should be allowed but the number of players should remain the same.
            partyJoined = _partyClient
                          .JoinParty(joinRequest, new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }).Party;
            Assert.AreEqual(2, partyJoined.MemberIds.Count);

            // Clean up.
            _partyClient.DeleteParty(new DeletePartyRequest(), new Metadata {
                { PitRequestHeaderName, pitLeader }
            });

            // Verify that its former members are no longer associated to the party since it has been deleted.
            var exception = Assert.Throws <RpcException>(() =>
                                                         _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                                                         new Metadata {
                { PitRequestHeaderName, pitLeader }
            }));

            Assert.AreEqual(StatusCode.NotFound, exception.StatusCode);

            exception = Assert.Throws <RpcException>(() =>
                                                     _partyClient.GetPartyByPlayerId(new GetPartyByPlayerIdRequest(),
                                                                                     new Metadata {
                { PitRequestHeaderName, pitAnotherPlayer }
            }));
            Assert.AreEqual(StatusCode.NotFound, exception.StatusCode);
        }