public Task TestDeleteAllManyObjects()
        {
            List <IObjectState> states = new List <IObjectState>();

            for (int i = 0; i < 102; ++i)
            {
                states.Add(new MutableObjectState
                {
                    ClassName  = "Corgi",
                    ObjectId   = "st4nl3yW" + i,
                    ServerData = new Dictionary <string, object> {
                        ["corgi"] = "isNotDoge"
                    }
                });
            }

            // Make multiple response since the batch will be splitted.
            List <IDictionary <string, object> > results = new List <IDictionary <string, object> >();

            for (int i = 0; i < 50; ++i)
            {
                results.Add(new Dictionary <string, object> {
                    ["success"] = null
                });
            }

            Dictionary <string, object> responseDict = new Dictionary <string, object> {
                ["results"] = results
            };
            Tuple <HttpStatusCode, IDictionary <string, object> > response = new Tuple <HttpStatusCode, IDictionary <string, object> >(HttpStatusCode.OK, responseDict);

            List <IDictionary <string, object> > results2 = new List <IDictionary <string, object> >();

            for (int i = 0; i < 2; ++i)
            {
                results2.Add(new Dictionary <string, object> {
                    ["success"] = null
                });
            }

            Dictionary <string, object> responseDict2 = new Dictionary <string, object> {
                ["results"] = results2
            };
            Tuple <HttpStatusCode, IDictionary <string, object> > response2 = new Tuple <HttpStatusCode, IDictionary <string, object> >(HttpStatusCode.OK, responseDict2);

            Mock <IParseCommandRunner> mockRunner = new Mock <IParseCommandRunner>();

            mockRunner.SetupSequence(obj => obj.RunCommandAsync(It.IsAny <ParseCommand>(), It.IsAny <IProgress <ParseUploadProgressEventArgs> >(), It.IsAny <IProgress <ParseDownloadProgressEventArgs> >(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(response)).Returns(Task.FromResult(response)).Returns(Task.FromResult(response2));

            ParseObjectController controller = new ParseObjectController(mockRunner.Object);
            IList <Task>          tasks      = controller.DeleteAllAsync(states, null, CancellationToken.None);

            return(Task.WhenAll(tasks).ContinueWith(_ =>
            {
                Assert.IsTrue(tasks.All(task => task.IsCompleted && !task.IsCanceled && !task.IsFaulted));

                mockRunner.Verify(obj => obj.RunCommandAsync(It.Is <ParseCommand>(command => command.Uri.AbsolutePath == "/1/batch"), It.IsAny <IProgress <ParseUploadProgressEventArgs> >(), It.IsAny <IProgress <ParseDownloadProgressEventArgs> >(), It.IsAny <CancellationToken>()), Times.Exactly(3));
            }));
        }
        public Task TestDeleteAllInconsistent()
        {
            List <IObjectState> states = new List <IObjectState>();

            for (int i = 0; i < 30; ++i)
            {
                states.Add(new MutableObjectState
                {
                    ClassName  = "Corgi",
                    ObjectId   = "st4nl3yW" + i,
                    ServerData = new Dictionary <string, object>()
                    {
                        { "corgi", "isNotDoge" },
                    }
                });
            }

            List <IDictionary <string, object> > results = new List <IDictionary <string, object> >();

            for (int i = 0; i < 36; ++i)
            {
                results.Add(new Dictionary <string, object>()
                {
                    { "success", null }
                });
            }
            Dictionary <string, object> responseDict = new Dictionary <string, object>()
            {
                { "results", results }
            };

            Tuple <HttpStatusCode, IDictionary <string, object> > response = new Tuple <HttpStatusCode, IDictionary <string, object> >(HttpStatusCode.OK, responseDict);
            Mock <IParseCommandRunner> mockRunner = CreateMockRunner(response);

            ParseObjectController controller = new ParseObjectController(mockRunner.Object);
            IList <Task>          tasks      = controller.DeleteAllAsync(states, null, CancellationToken.None);

            return(Task.WhenAll(tasks).ContinueWith(_ =>
            {
                Assert.IsTrue(tasks.All(task => task.IsFaulted));
                Assert.IsInstanceOfType(tasks[0].Exception.InnerException, typeof(InvalidOperationException));

                mockRunner.Verify(obj => obj.RunCommandAsync(It.Is <ParseCommand>(command => command.Uri.AbsolutePath == "/1/batch"),
                                                             It.IsAny <IProgress <ParseUploadProgressEventArgs> >(),
                                                             It.IsAny <IProgress <ParseDownloadProgressEventArgs> >(),
                                                             It.IsAny <CancellationToken>()), Times.Exactly(1));
            }));
        }
        public Task TestDeleteAllFailSome()
        {
            List <IObjectState> states = new List <IObjectState>();

            for (int i = 0; i < 30; ++i)
            {
                states.Add(new MutableObjectState
                {
                    ClassName  = "Corgi",
                    ObjectId   = ((i % 2 == 0) ? null : "st4nl3yW" + i),
                    ServerData = new Dictionary <string, object> {
                        ["corgi"] = "isNotDoge"
                    }
                });
            }

            List <IDictionary <string, object> > results = new List <IDictionary <string, object> >();

            for (int i = 0; i < 15; ++i)
            {
                if (i % 2 == 0)
                {
                    results.Add(new Dictionary <string, object>
                    {
                        ["error"] = new Dictionary <string, object>
                        {
                            ["code"]  = (long)ParseException.ErrorCode.ObjectNotFound,
                            ["error"] = "Object not found."
                        }
                    });
                }
                else
                {
                    results.Add(new Dictionary <string, object> {
                        ["success"] = null
                    });
                }
            }

            Dictionary <string, object> responseDict = new Dictionary <string, object> {
                ["results"] = results
            };

            Tuple <HttpStatusCode, IDictionary <string, object> > response = new Tuple <HttpStatusCode, IDictionary <string, object> >(HttpStatusCode.OK, responseDict);
            Mock <IParseCommandRunner> mockRunner = CreateMockRunner(response);

            ParseObjectController controller = new ParseObjectController(mockRunner.Object);
            IList <Task>          tasks      = controller.DeleteAllAsync(states, null, CancellationToken.None);

            return(Task.WhenAll(tasks).ContinueWith(_ =>
            {
                for (int i = 0; i < 15; ++i)
                {
                    if (i % 2 == 0)
                    {
                        Assert.IsTrue(tasks[i].IsFaulted);
                        Assert.IsInstanceOfType(tasks[i].Exception.InnerException, typeof(ParseException));
                        ParseException exception = tasks[i].Exception.InnerException as ParseException;
                        Assert.AreEqual(ParseException.ErrorCode.ObjectNotFound, exception.Code);
                    }
                    else
                    {
                        Assert.IsTrue(tasks[i].IsCompleted);
                        Assert.IsFalse(tasks[i].IsFaulted || tasks[i].IsCanceled);
                    }
                }

                mockRunner.Verify(obj => obj.RunCommandAsync(It.Is <ParseCommand>(command => command.Uri.AbsolutePath == "/1/batch"),
                                                             It.IsAny <IProgress <ParseUploadProgressEventArgs> >(),
                                                             It.IsAny <IProgress <ParseDownloadProgressEventArgs> >(),
                                                             It.IsAny <CancellationToken>()), Times.Exactly(1));
            }));
        }