public async Task GetETokenTest()
        {
            var mockHttp = new MockHttpMessageHandler();

            this.ComposeETokenPayload(new TimeSpan(1, 0, 0), string.Empty, string.Empty, out string defaultRequest,
                                      out string defaultXdtsResponse);

            this.ComposeETokenPayload(new TimeSpan(1, 0, 0), DefaultScid, DefaultSandbox, out string sandboxRequest,
                                      out string sandboxResponse);

            mockHttp.Expect(DefaultXtdsEndpoint)
            .WithContent(defaultRequest)
            .Respond("application/json", defaultXdtsResponse);

            mockHttp.Expect(DefaultXtdsEndpoint)
            .WithContent(sandboxRequest)
            .Respond("application/json", sandboxResponse);

            TestHook.MockHttpHandler = mockHttp;

            var devAccount = await this.SignInAsync(DevAccountSource.WindowsDevCenter, string.Empty);

            Assert.AreEqual(DefaultId, devAccount.Id);
            Assert.AreEqual(DefaultName, devAccount.Name);
            Assert.AreEqual(DefaultAccountId, devAccount.AccountId);
            Assert.AreEqual(DefaultMoniker, devAccount.AccountMoniker);
            Assert.AreEqual(DefaultAccountType, devAccount.AccountType);
            Assert.AreEqual(DevAccountSource.WindowsDevCenter, devAccount.AccountSource);

            var token2 = await ToolAuthentication.GetDevTokenSilentlyAsync(DefaultScid, DefaultSandbox);

            Assert.AreEqual(token2, ToolAuthentication.PrepareForAuthHeader(DefaultEToken + DefaultScid + DefaultSandbox));
        }
        public async Task TokenCacheTest()
        {
            var mockHttp = new MockHttpMessageHandler();

            this.ComposeETokenPayload(new TimeSpan(1, 0, 0), string.Empty, string.Empty, out string defaultRequest,
                                      out string defaultXdtsResponse);

            // Expect to be hit twice, the second call for token will be fetched from cache
            mockHttp.Expect(DefaultXtdsEndpoint)
            .WithContent(defaultRequest)
            .Respond("application/json", defaultXdtsResponse);

            TestHook.MockHttpHandler = mockHttp;

            var devAccount = await this.SignInAsync(DevAccountSource.WindowsDevCenter, string.Empty);

            Assert.AreEqual(devAccount.Id, DefaultId);
            Assert.AreEqual(devAccount.Name, DefaultName);
            Assert.AreEqual(devAccount.AccountId, DefaultAccountId);
            Assert.AreEqual(devAccount.AccountMoniker, DefaultMoniker);
            Assert.AreEqual(devAccount.AccountType, DefaultAccountType);
            Assert.AreEqual(devAccount.AccountSource, DevAccountSource.WindowsDevCenter);

            var token = await ToolAuthentication.GetDevTokenSilentlyAsync(string.Empty, string.Empty);

            Assert.AreEqual(token, ToolAuthentication.PrepareForAuthHeader(DefaultEToken));

            mockHttp.VerifyNoOutstandingExpectation();
        }
        /// <summary>
        /// Reset one player's data in test sandboxes, includes: achievements, leaderboards, player stats and title history.
        /// </summary>
        /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title for player data resetting</param>
        /// <param name="sandbox">The target sandbox id for player resetting</param>
        /// <param name="xboxUserId">The Xbox user id of the player to be reset</param>
        /// <returns>The UserResetResult object for the reset result</returns>
        public static async Task <UserResetResult> ResetPlayerDataAsync(string serviceConfigurationId, string sandbox, string xboxUserId)
        {
            // Pre-fetch the product/sandbox etoken before getting into the loop, so that we can
            // populate the auth error up-front.
            await ToolAuthentication.GetDevTokenSilentlyAsync(serviceConfigurationId, sandbox);

            return(await SubmitJobAndPollStatus(sandbox, serviceConfigurationId, xboxUserId));
        }
        private async void ListView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count == 0)
            {
                return;
            }

            if (!this.showingOfflineSession)
            {
                this.queryCancelled = false;

                this.InitViews();
                Tuple <SessionHistoryDocumentResponse, string> queryResponse = null;

                string eToken = await ToolAuthentication.GetDevTokenSilentlyAsync(this.tbScid.Text, this.tbSandbox.Text);

                this.lblExplanation.Text = "Downloading change history for the selected historical\nMPSD document...";
                if (this.listView1.SelectedIndices.Count == 1)
                {
                    var index = this.listView1.SelectedIndices[0];
                    queryResponse = await this.QueryForDocSessionHistoryAsync(eToken, this.listView1.Items[index].SubItems[0].Text, this.listView1.Items[index].SubItems[1].Text).ConfigureAwait(true);
                }

                this.downloadPanel.Hide();

                if (queryResponse.Item2 != null)
                {
                    MessageBox.Show(string.Format("{0}\n\nThe server is busy.\nPlease try again.", queryResponse.Item2), QueryFailure);
                    return;
                }

                if (queryResponse != null && queryResponse.Item1 != null && queryResponse.Item1.Results != null)
                {
                    queryResponse.Item1.Results.Sort((foo1, foo2) => foo1.ChangeNumber.CompareTo(foo2.ChangeNumber));

                    foreach (var item in queryResponse.Item1.Results)
                    {
                        string[] lv2arr = new string[DocumentMetadataColumnCount]
                        {
                            item.ChangeNumber == SessionHistory.MaxChangeValue ? "expired" : item.ChangeNumber.ToString(),
                            item.ChangedBy,
                            this.displayDateTimesAsUTCToolStripMenuItem.Checked ? item.Timestamp.ToString() : item.Timestamp.ToLocalTime().ToString(),
                            item.TitleId,
                            item.ServiceId,
                            item.CorrelationId,
                            item.Details
                        };

                        ListViewItem lvi2 = new ListViewItem(lv2arr);
                        this.listView2.Items.Add(lvi2);
                    }

                    this.DisplayChangesInfo();
                }
            }
        }
        private async Task <Tuple <string, string> > QueryForDocSessionHistoryChangeAsync(string sessionName, string branch, long changeNumber)
        {
            string snapshot = null;
            string errorMsg = null;

            if (changeNumber == SessionHistory.MaxChangeValue)
            {
                return(new Tuple <string, string>(null, null)); // there is nothing to get, so don't bother trying
            }

            string hashKey = this.snapshotCache.GetHashString(
                sessionName,
                branch,
                changeNumber);

            if (!this.snapshotCache.TryGetSnapshot(hashKey, out snapshot))
            {
                string eToken = await ToolAuthentication.GetDevTokenSilentlyAsync(this.tbScid.Text, this.tbSandbox.Text);

                this.lblExplanation.Text = string.Format("Downloading session snapshot #{0}", changeNumber);

                var response = await SessionHistory.GetSessionHistoryDocumentChangeAsync(
                    this.tbScid.Text,
                    this.tbTemplateName.Text,
                    sessionName,
                    branch,
                    changeNumber,
                    eToken);

                if (response.Item1 == HttpStatusCode.OK)
                {
                    snapshot = response.Item2;
                    this.snapshotCache.AddSnapshotToCache(hashKey, response.Item2);
                }
                else if (response.Item1 != HttpStatusCode.NoContent)
                {
                    errorMsg = response.Item2;
                }
            }

            return(new Tuple <string, string>(snapshot, errorMsg));
        }
        private async void SaveSessionHistoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count != 1)
            {
                return;
            }

            int selectedIndex = this.listView1.SelectedIndices[0];

            HistoricalDocument document = new HistoricalDocument()
            {
                SessionName  = this.listView1.Items[selectedIndex].SubItems[0].Text,
                Branch       = this.listView1.Items[selectedIndex].SubItems[1].Text,
                NumSnapshots = int.Parse(this.listView1.Items[selectedIndex].SubItems[2].Text),
                LastModified = this.listView1.Items[selectedIndex].SubItems[3].Text,
                IsExpired    = bool.Parse(this.listView1.Items[selectedIndex].SubItems[4].Text),
                ActivityId   = this.listView1.Items[selectedIndex].SubItems[5].Text,
            };

            string eToken = await ToolAuthentication.GetDevTokenSilentlyAsync(this.tbScid.Text, this.tbSandbox.Text);

            this.lblExplanation.Text = "Downloading change history for the selected session...";

            Tuple <SessionHistoryDocumentResponse, string> queryResponse = await this.QueryForDocSessionHistoryAsync(eToken, document.SessionName, document.Branch);

            if (queryResponse.Item2 != null)
            {
                this.downloadPanel.Hide();

                MessageBox.Show(string.Format("{0}\n\nThe server may have been busy.\nPlease try again.", queryResponse.Item2), "Error!");
                return;
            }

            string errMsg = null;

            if (queryResponse.Item1 != null)
            {
                foreach (var item in queryResponse.Item1.Results)
                {
                    Tuple <string, string> getSnapshotResponse = await this.QueryForDocSessionHistoryChangeAsync(document.SessionName, document.Branch, item.ChangeNumber);

                    string snapshotBody = getSnapshotResponse.Item1;
                    errMsg = getSnapshotResponse.Item2;

                    if (errMsg != null)
                    {
                        break;
                    }

                    DocumentStateSnapshot snapshot = new DocumentStateSnapshot()
                    {
                        Change          = item.ChangeNumber,
                        ModifiedByXuids = item.ChangedBy,
                        Timestamp       = item.Timestamp,
                        TitleId         = item.TitleId,
                        ServiceId       = item.ServiceId,
                        CorrelationId   = item.CorrelationId,
                        ChangeDetails   = item.Details,
                        Body            = snapshotBody != null ? snapshotBody : string.Empty
                    };

                    document.DocumentSnapshots.Add(snapshot);
                }
            }

            this.downloadPanel.Hide();

            if (errMsg != null)
            {
                MessageBox.Show(string.Format("{0}\n\nPlease try again.", errMsg), "Error");
            }
            else
            {
                // serialize the HistoricalDocument to json
                string testString = JsonConvert.SerializeObject(document);

                var saveDialog = new SaveFileDialog()
                {
                    Filter   = SessionHistoryFileFilter,
                    FileName = string.Format("{0}~{1}", document.SessionName, document.Branch)
                };

                if (saveDialog.ShowDialog() == DialogResult.OK)
                {
                    using (StreamWriter sw = new StreamWriter(saveDialog.FileName))
                    {
                        sw.Write(testString);
                    }
                }
            }
        }
        private async Task SearchForHistoricalDocumentsAsync(QueryBundle queryBundle, bool addToStack)
        {
            this.tbSandbox.Text             = queryBundle.Sandbox;
            this.tbScid.Text                = queryBundle.Scid;
            this.tbTemplateName.Text        = queryBundle.TemplateName;
            this.tbQueryKey.Text            = queryBundle.QueryKey;
            this.cmbQueryType.SelectedIndex = queryBundle.QueryKeyIndex;
            this.dateTimePicker1.Value      = queryBundle.QueryFrom;
            this.dateTimePicker2.Value      = queryBundle.QueryTo;

            string eToken = await ToolAuthentication.GetDevTokenSilentlyAsync(this.tbScid.Text, this.tbSandbox.Text);

            this.lblExplanation.Text = "Searching for MPSD historical documents...";

            Tuple <HttpStatusCode, string> response = null;
            string continuationToken = null;

            do
            {
                response = await this.QueryForHistoricalSessionDocuments(eToken, queryBundle, continuationToken);

                if (response.Item1 == HttpStatusCode.OK)
                {
                    continuationToken = response.Item2;
                }
                else
                {
                    continuationToken = null;
                }
            }while (continuationToken != null);

            this.downloadPanel.Hide();

            if (response.Item1 != HttpStatusCode.OK)
            {
                if (response.Item1 == HttpStatusCode.Unauthorized)
                {
                    MessageBox.Show("Your auth token has expired. Re-try the query to get a new token", "Expired Token");
                }
                else if (response.Item1 == HttpStatusCode.InternalServerError)
                {
                    MessageBox.Show("The server is busy.  Please try again", QueryFailure);
                }
                else
                {
                    MessageBox.Show(response.Item2, QueryFailure);
                }
            }
            else
            {
                if (this.listView1.Items.Count == 0)
                {
                    this.btnPriorQuery.Visible = this.queryStack.Count > 0; // show the back button following un unsuccesful query (if there was a prior successul one)
                    MessageBox.Show("No results found.  Try expanding the query time window (if possible)\nor use different search criteria.", "Query Results");
                }
                else
                {
                    if (addToStack)
                    {
                        this.queryStack.Push(queryBundle); // succesful query, so remember it
                        this.btnPriorQuery.Visible = this.queryStack.Count > 1;
                    }
                    else
                    {
                        this.btnPriorQuery.Visible = this.queryStack.Count > 0;
                    }
                }
            }
        }