public async Task ReadAsyncWithIntIdTypeAndNullIdFilter()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("[{\"id\":null,\"String\":\"Hey\"}]");

            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

            IMobileServiceTable<LongIdType> table = service.GetTable<LongIdType>();

            List<LongIdType> items = await table.Where(t => t.Id == null).ToListAsync();
            Uri expectedUri = new Uri(mobileAppUriValidator.GetTableUri("LongIdType?$filter=(id eq null)"));

            Assert.AreEqual(1, items.Count());
            Assert.AreEqual(0L, items[0].Id);
            Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
        }
        public async Task ReadAsyncWithStringIdTypeAndStringIdProjection()
        {
            string[] testIdData = IdTestData.ValidStringIds.Concat(
                                  IdTestData.EmptyStringIds).Concat(
                                  IdTestData.InvalidStringIds).ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();

                // Make the testId JSON safe
                string jsonTestId = testId.Replace("\\", "\\\\").Replace("\"", "\\\"");

                hijack.SetResponseContent("[{\"id\":\"" + jsonTestId + "\",\"String\":\"Hey\"}]");

                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                var items = await table.Select(s => new { Id = s.Id, Message = s.String }).ToListAsync();
                Uri expectedUri = new Uri(mobileAppUriValidator.GetTableUri("StringIdType?$select=id,String"));

                Assert.AreEqual(1, items.Count());
                Assert.AreEqual(testId, items[0].Id);
                Assert.AreEqual("Hey", items[0].Message);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task ReadAsyncWithIntIdTypeAndIntIdFilter()
        {
            long[] testIdData = IdTestData.ValidIntIds.Concat(
                                IdTestData.InvalidIntIds).ToArray();

            foreach (long testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":" + testId + ",\"String\":\"Hey\"}]");

                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<LongIdType> table = service.GetTable<LongIdType>();

                List<LongIdType> items = await table.Where(t => t.Id == testId).ToListAsync();
                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("LongIdType?$filter=(id eq {0}L)"), testId));

                Assert.AreEqual(1, items.Count());
                Assert.AreEqual(testId, items[0].Id);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task PullAsync_DoesNotUpdateDeltaToken_AfterEachResult_IfOrderByIsNotSupported()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent(@"[{""id"":""abc"",""String"":""Hey"", ""updatedAt"": ""2001-02-03T00:00:00.0000000+00:00""},
                                         {""id"":""def"",""String"":""How"", ""updatedAt"": ""2001-02-04T00:00:00.0000000+00:00""}]"); // first page
            hijack.Responses.Add(new HttpResponseMessage(HttpStatusCode.InternalServerError)); // throw on second page

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();
            table.SupportedOptions &= ~MobileServiceRemoteTableOptions.OrderBy;

            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            await ThrowsAsync<MobileServiceInvalidOperationException>(() => table.PullAsync("items", table.CreateQuery()));

            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 2);
            Assert.AreEqual(store.TableMap["stringId_test_table"]["abc"].Value<string>("String"), "Hey");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["def"].Value<string>("String"), "How");

            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'1970-01-01T00:00:00.0000000%2B00:00')&$skip=0&$top=50&__includeDeleted=true"),
                                                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'1970-01-01T00:00:00.0000000%2B00:00')&$skip=2&$top=50&__includeDeleted=true"));

            Assert.IsFalse(store.TableMap[MobileServiceLocalSystemTables.Config].ContainsKey("deltaToken|stringId_test_table|items"));
        }
        public async Task ReadAsyncWithStringIdTypeAndStringIdFilter()
        {
            string[] testIdData = IdTestData.ValidStringIds.Concat(
                                  IdTestData.EmptyStringIds).Concat(
                                  IdTestData.InvalidStringIds).ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();

                // Make the testId JSON safe
                string jsonTestId = testId.Replace("\\", "\\\\").Replace("\"", "\\\"");

                hijack.SetResponseContent("[{\"id\":\"" + jsonTestId + "\",\"String\":\"Hey\"}]");

                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                List<StringIdType> items = await table.Where(t => t.Id == testId).ToListAsync();
                string idForOdataQuery = Uri.EscapeDataString(testId.Replace("'", "''"));
                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("StringIdType?$filter=(id eq '{0}')"), idForOdataQuery));

                Assert.AreEqual(1, items.Count());
                Assert.AreEqual(testId, items[0].Id);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task LookupAsyncWithStringIdTypeAndStringIdParameter()
        {
            string[] testIdData = IdTestData.ValidStringIds.ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = await table.LookupAsync(testId);

                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("StringIdType/{0}"), Uri.EscapeDataString(testId)));

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task ReadAsyncWithNullIdFilter()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("[{\"id\":null,\"String\":\"Hey\"}]");

            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

            IMobileServiceTable table = service.GetTable("someTable");

            JToken results = await table.ReadAsync("$filter=id eq null");
            JToken[] items = results.ToArray();
            JObject item0 = items[0] as JObject;

            Uri expectedUri = new Uri(mobileAppUriValidator.GetTableUri("someTable?$filter=id eq null"));

            Assert.AreEqual(1, items.Count());
            Assert.AreEqual(null, (string)items[0]["id"]);
            Assert.AreEqual("Hey", (string)items[0]["String"]);
            Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
        }
        public async Task PurgeAsync_ResetsDeltaToken_WhenQueryIdIsSpecified()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent(@"[{""id"":""abc"",""String"":""Hey"", ""updatedAt"": ""2001-02-03T00:00:00.0000000+00:00""},
                                         {""id"":""def"",""String"":""How"", ""updatedAt"": ""2001-02-04T00:00:00.0000000+00:00""}]"); // first page
            hijack.AddResponseContent("[]"); // last page of first pull
            hijack.AddResponseContent("[]"); // second pull

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();

            // ensure there is no delta token present already
            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            // now pull down data
            await table.PullAsync("items", table.CreateQuery());

            // ensure items were pulled down
            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 2);
            Assert.AreEqual(store.TableMap["stringId_test_table"]["abc"].Value<string>("String"), "Hey");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["def"].Value<string>("String"), "How");

            // ensure delta token was updated
            Assert.Equals(store.TableMap[MobileServiceLocalSystemTables.Config]["deltaToken|stringId_test_table|items"]["value"], "2001-02-04T00:00:00.0000000+00:00");

            // now purge and forget the delta token
            await table.PurgeAsync("items", null, false, CancellationToken.None);

            // make sure data is purged
            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 0);
            // make sure delta token is removed
            Assert.IsFalse(store.TableMap[MobileServiceLocalSystemTables.Config].ContainsKey("deltaToken|stringId_test_table|items"));

            // pull again
            await table.PullAsync("items", table.CreateQuery());

            // verify request urls
            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'1970-01-01T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true"),
                                                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'2001-02-04T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true"),
                                                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'1970-01-01T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true"));
        }
        public async Task RefreshAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds.ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":\"" + testId + "\",\"String\":\"Hey\"}]");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.RefreshAsync(item);

                string idForOdataQuery = Uri.EscapeDataString(testId.Replace("'", "''"));
                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("StringIdType?$filter=(id eq '{0}')"), idForOdataQuery));

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task PullAsync_Incremental_MovesByUpdatedAt_ThenUsesSkipAndTop_WhenUpdatedAtDoesNotChange()
        {
            var hijack = new TestHttpHandler();
            hijack.OnSendingRequest = req =>
            {
                return Task.FromResult(req);
            };
            hijack.AddResponseContent(@"[{""id"":""abc"",""String"":""Hey"", ""updatedAt"": ""2001-02-03T00:00:00.0000000+00:00""}]");
            hijack.AddResponseContent(@"[{""id"":""def"",""String"":""World"", ""updatedAt"": ""2001-02-03T00:00:00.0000000+00:00""}]");
            hijack.AddResponseContent("[]"); // last page

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();

            await table.PullAsync("items", table.CreateQuery());
            AssertEx.MatchUris(hijack.Requests,
                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'1970-01-01T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true"),
                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'2001-02-03T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true"),
                mobileAppUriValidator.GetTableUri("stringId_test_table?$filter=(updatedAt ge datetimeoffset'2001-02-03T00:00:00.0000000%2B00:00')&$orderby=updatedAt&$skip=1&$top=50&__includeDeleted=true"));
        }
        private static async Task TestIncrementalPull(MobileServiceLocalStoreMock store, MobileServiceRemoteTableOptions options, params string[] expectedTableUriComponents)
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent(@"[{""id"":""abc"",""String"":""Hey"", ""updatedAt"": ""2001-02-03T00:00:00.0000000+00:00""},
                                        {""id"":""def"",""String"":""World"", ""updatedAt"": ""2001-02-03T00:03:00.0000000+07:00""}]"); // for pull
            hijack.AddResponseContent(@"[]");

            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();
            table.SupportedOptions = options;
            var query = table.Where(t => t.String == "world")
                             .WithParameters(new Dictionary<string, string>() { { "param1", "val1" } })
                             .IncludeTotalCount();

            await table.PullAsync("incquery", query, cancellationToken: CancellationToken.None);

            var expectedTableUris =
                expectedTableUriComponents.Select(
                    expectedTableUriComponent => mobileAppUriValidator.GetTableUri(expectedTableUriComponent)).ToArray();

            AssertEx.MatchUris(hijack.Requests, expectedTableUris);
        }
        public async Task PullAsync_DefaultsTo50_IfGreaterThanMaxPageSize()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"How\"}]"); // first page
            hijack.AddResponseContent("[]"); // end of the list

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();

            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            var pullOptions = new PullOptions
            {
                MaxPageSize = 50,
            };
            await table.PullAsync(null, table.Take(51), pullOptions);

            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 2);

            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=0&$top=50&__includeDeleted=true"),
                                        mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=2&$top=49&__includeDeleted=true"));
        }
        public async Task PullAsync_DoesNotFollowLink_IfLinkHasNonSupportedOptions()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"How\"}]"); // first page
            hijack.Responses[0].Headers.Add("Link", "http://contoso.com:31475/tables/Green?$top=1&$select=Text%2CDone%2CId&$skip=2; rel=next");
            hijack.AddResponseContent("[{\"id\":\"ghi\",\"String\":\"Are\"},{\"id\":\"jkl\",\"String\":\"You\"}]"); // second page
            hijack.AddResponseContent("[]"); // end of the list

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();
            table.SupportedOptions &= ~MobileServiceRemoteTableOptions.Skip;

            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            await table.PullAsync(null, null);

            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 2);

            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$top=50&__includeDeleted=true"));
        }
        public async Task PullAsync_UsesSkipAndTakeThenFollowsLinkThenUsesSkipAndTake()
        {
            var hijack = new TestHttpHandler();
            // first page
            hijack.AddResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"How\"}]");
            // second page with a link
            hijack.AddResponseContent("[{\"id\":\"ghi\",\"String\":\"Are\"},{\"id\":\"jkl\",\"String\":\"You\"}]");
            hijack.Responses[1].Headers.Add("Link", "http://localhost:31475/tables/Green?$top=1&$select=Text%2CDone%2CId&$skip=2; rel=next");
            // forth page without link
            hijack.AddResponseContent("[{\"id\":\"mno\",\"String\":\"Mr\"},{\"id\":\"pqr\",\"String\":\"X\"}]");
            // last page
            hijack.AddResponseContent("[]");

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();

            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            await table.PullAsync(null, table.Take(51).Skip(3));

            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 6);
            Assert.AreEqual(store.TableMap["stringId_test_table"]["abc"].Value<string>("String"), "Hey");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["def"].Value<string>("String"), "How");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["ghi"].Value<string>("String"), "Are");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["jkl"].Value<string>("String"), "You");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["mno"].Value<string>("String"), "Mr");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["pqr"].Value<string>("String"), "X");

            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=3&$top=50&__includeDeleted=true"),
                                        mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=5&$top=49&__includeDeleted=true"),
                                        "http://localhost:31475/tables/Green?$top=1&$select=Text%2CDone%2CId&$skip=2",
                                        mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=9&$top=45&__includeDeleted=true"));
        }
        public async Task ReadAsyncWithIntIdTypeAndNoIdProjection()
        {
            TestHttpHandler hijack = new TestHttpHandler();
            hijack.SetResponseContent("[{\"String\":\"Hey\"}]");

            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

            IMobileServiceTable<LongIdType> table = service.GetTable<LongIdType>();

            var items = await table.Select(s => new { Id = s.Id, Message = s.String }).ToListAsync();
            Uri expectedUri = new Uri(mobileAppUriValidator.GetTableUri("LongIdType?$select=id,String"));

            Assert.AreEqual(1, items.Count());
            Assert.AreEqual(0L, items[0].Id);
            Assert.AreEqual("Hey", items[0].Message);
            Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
        }
        public async Task RefreshAsyncWithIntIdTypeAndIntIdItem()
        {
            long[] testIdData = IdTestData.ValidIntIds;

            foreach (long testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":" + testId + ",\"String\":\"Hey\"}]");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<LongIdType> table = service.GetTable<LongIdType>();

                LongIdType item = new LongIdType() { Id = testId, String = "what?" };
                await table.RefreshAsync(item);

                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("LongIdType?$filter=(id eq {0}L)"), testId));

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task ReadAsyncWithIntIdTypeAndOrderByDescending()
        {
            long[] testIdData = IdTestData.ValidIntIds.Concat(
                                IdTestData.InvalidIntIds).ToArray();

            foreach (long testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("[{\"id\":\"" + testId + "\",\"String\":\"Hey\"}]");

                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<LongIdType> table = service.GetTable<LongIdType>();

                var items = await table.OrderByDescending(s => s.Id).ToListAsync();
                Uri expectedUri = new Uri(mobileAppUriValidator.GetTableUri("LongIdType?$orderby=id desc"));

                Assert.AreEqual(1, items.Count());
                Assert.AreEqual(testId, items[0].Id);
                Assert.AreEqual("Hey", items[0].String);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task UpdateAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds.ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                hijack.OnSendingRequest = async request =>
                {
                    string requestContent = await request.Content.ReadAsStringAsync();
                    JObject itemAsJObject = JObject.Parse(requestContent);
                    Assert.AreEqual(testId, (string)itemAsJObject["id"]);
                    Assert.AreEqual("what?", (string)itemAsJObject["String"]);
                    string idForUri = Uri.EscapeDataString(testId);
                    Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("StringIdType/{0}"), idForUri));
                    Assert.AreEqual(request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
                    return request;
                };

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.UpdateAsync(item);

                Assert.AreEqual(testId, item.Id);
                Assert.AreEqual("Hey", item.String);
            }
        }
        public async Task ReadAsyncWithStringIdFilter()
        {
            string[] testIdData = IdTestData.ValidStringIds.Concat(
                                  IdTestData.EmptyStringIds).Concat(
                                  IdTestData.InvalidStringIds).ToArray();

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();

                // Make the testId JSON safe
                string jsonTestId = testId.Replace("\\", "\\\\").Replace("\"", "\\\"");

                hijack.SetResponseContent("[{\"id\":\"" + jsonTestId + "\",\"String\":\"Hey\"}]");

                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable table = service.GetTable("someTable");

                string idForOdataQuery = Uri.EscapeDataString(testId.Replace("'", "''"));
                JToken results = await table.ReadAsync(string.Format("$filter=id eq '{0}'", idForOdataQuery));
                JToken[] items = results.ToArray();
                JObject item0 = items[0] as JObject;

                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("someTable?$filter=id eq '{0}'"), idForOdataQuery));

                Assert.AreEqual(1, items.Count());
                Assert.AreEqual(testId, (string)items[0]["id"]);
                Assert.AreEqual("Hey", (string)items[0]["String"]);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task DeleteAsyncWithStringIdTypeAndStringIdItem()
        {
            string[] testIdData = IdTestData.ValidStringIds;

            foreach (string testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":\"" + testId + "\",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable<StringIdType> table = service.GetTable<StringIdType>();

                hijack.OnSendingRequest = request =>
                {
                    Assert.IsNull(request.Content);
                    string idForUri = Uri.EscapeDataString(testId);
                    Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("StringIdType/{0}"), idForUri));
                    Assert.AreEqual(request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
                    return new TaskFactory<HttpRequestMessage>().StartNew(() => request);
                };

                StringIdType item = new StringIdType() { Id = testId, String = "what?" };
                await table.DeleteAsync(item);

                Assert.AreEqual(null, item.Id);
                Assert.AreEqual("what?", item.String);
            }
        }
        public async Task LookupAsyncWithIntIdParameter()
        {
            long[] testIdData = IdTestData.ValidIntIds;

            foreach (long testId in testIdData)
            {
                TestHttpHandler hijack = new TestHttpHandler();
                hijack.SetResponseContent("{\"id\":" + testId.ToString() + ",\"String\":\"Hey\"}");
                IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
                MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);

                IMobileServiceTable table = service.GetTable("someTable");

                JToken item = await table.LookupAsync(testId);

                Uri expectedUri = new Uri(string.Format(mobileAppUriValidator.GetTableUri("someTable/{0}"), testId));

                Assert.AreEqual(testId, (long)item["id"]);
                Assert.AreEqual("Hey", (string)item["String"]);
                Assert.AreEqual(hijack.Request.RequestUri.AbsoluteUri, expectedUri.AbsoluteUri);
            }
        }
        public async Task PullAsync_FollowsNextLinks()
        {
            var hijack = new TestHttpHandler();
            hijack.AddResponseContent("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"How\"}]"); // first page
            hijack.Responses[0].Headers.Add("Link", "http://localhost:31475/tables/Green?$top=1&$select=Text%2CDone%2CId&$skip=2; rel=next");
            hijack.AddResponseContent("[{\"id\":\"ghi\",\"String\":\"Are\"},{\"id\":\"jkl\",\"String\":\"You\"}]"); // second page
            hijack.AddResponseContent("[]"); // end of the list

            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            MobileAppUriValidator mobileAppUriValidator = new MobileAppUriValidator(service);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable<ToDoWithStringId> table = service.GetSyncTable<ToDoWithStringId>();

            Assert.IsFalse(store.TableMap.ContainsKey("stringId_test_table"));

            await table.PullAsync(null, null);

            Assert.AreEqual(store.TableMap["stringId_test_table"].Count, 4);
            Assert.AreEqual(store.TableMap["stringId_test_table"]["abc"].Value<string>("String"), "Hey");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["def"].Value<string>("String"), "How");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["ghi"].Value<string>("String"), "Are");
            Assert.AreEqual(store.TableMap["stringId_test_table"]["jkl"].Value<string>("String"), "You");

            AssertEx.MatchUris(hijack.Requests, mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=0&$top=50&__includeDeleted=true"),
                                        "http://localhost:31475/tables/Green?$top=1&$select=Text%2CDone%2CId&$skip=2",
                                        mobileAppUriValidator.GetTableUri("stringId_test_table?$skip=4&$top=50&__includeDeleted=true"));
        }