{"action":"created","comment":{"url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/comments/31056498","id":31056498,"diff_hunk":"@@ -1082,9 +1083,348 @@ -(void) testPushNetworkTimeoutWithErroredOps\n     XCTAssertEqual(filteredClient.syncContext.pendingOperationsCount, 3);\n }\n \n+// Tests cancellation of the push operation at various stages of a push workflow.\n+// - Verifies that a push following a cancelled push operation works as expected\n+// - Verifies that cancelling a push operation finishes the push NSOperation regardless of the cancellation point\n+// - Verifies that the expected number of items are pushed to the server\n+-(void) testPushCancellability\n+{\n+    XCTAssertEqual([self performPushWithCancellationPoint:0 serverResponseCode:@200], 0, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:1 serverResponseCode:@200], 0, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:2 serverResponseCode:@200], 1, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:3 serverResponseCode:@200], 0, \"Push cancellation failed\");\n+\n+    XCTAssertEqual([self performPushWithCancellationPoint:0 serverResponseCode:@500], 0, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:1 serverResponseCode:@500], 0, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:2 serverResponseCode:@500], 0, \"Push cancellation failed\");\n+    XCTAssertEqual([self performPushWithCancellationPoint:3 serverResponseCode:@500], 0, \"Push cancellation failed\");\n+}\n+\n+// Performs push and cancels it at the specified cancellation point.\n+// - Verifies that a push operation following a cancelled push operation works as expected\n+// - Verifies that cancelling a push finishes the push NSOperation regardless of the cancellation point\n+// - Verifies that the expected number of items are pushed to the server\n+// - Returns the number of items pushed to the server.\n+-(int) performPushWithCancellationPoint:(int) requestedCancellationPoint serverResponseCode:(NSNumber *)serverResponseCode\n+{\n+    // Initialization\n+    MSMultiRequestTestFilter *filter = [MSMultiRequestTestFilter testFilterWithStatusCodes:@[serverResponseCode] data:@[@\"{\\\"id\\\": \\\"id1\\\", \\\"text\\\":\\\"server\\\"}\"] appendEmptyRequest:YES];\n+    MSClient *filteredClient = [client clientWithFilter:filter];\n+    MSSyncTable *todoTable = [filteredClient syncTableWithName:TodoTableNoVersion];\n+\n+    // Start with a clean slate\n+    [[todoTable forcePurgeWithCompletion:^(NSError *error) {\n+        XCTAssertNil(error, @\"error should have been nil.\");\n+    }] waitUntilFinished];\n+\n+    __block NSOperation *pushOperation;\n+\n+    // Define filters\n+    ((MSTestFilter *)filter.testFilters[0]).onInspectRequest = ^(NSURLRequest *request) {\n+\n+        // Cancellation point 0\n+        if (requestedCancellationPoint == 0)\n+            [pushOperation cancel];\n+        \n+        return request;\n+    };\n+    \n+    ((MSTestFilter *)filter.testFilters[0]).onInspectResponseData = ^(NSURLRequest *request, NSData *data) {\n+\n+        // Cancellation point 1\n+        if (requestedCancellationPoint == 1)\n+            [pushOperation cancel];\n+        \n+        return data;\n+    };\n+    \n+    // Perform an insert\n+    XCTestExpectation *insertExpectation = [self expectationWithDescription:@\"insert expectation\"];\n+    [todoTable insert:@{ @\"id\" : @\"id1\", @\"text\" : @\"client\" } completion:^(NSDictionary *item, NSError *error) {\n+        [insertExpectation fulfill];\n+    }];\n+    \n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+    \n+    // Perform a push\n+    pushOperation = [filteredClient.syncContext pushWithCompletion:^(NSError *error) {\n+        \n+        // Cancellation point 2\n+        if (requestedCancellationPoint == 2)\n+            [pushOperation cancel];\n+    }];\n+    \n+    // Cancellation point 3\n+    if (requestedCancellationPoint == 3)\n+        [pushOperation cancel];\n+\n+    [self verifyFinished:pushOperation];\n+\n+    int synchronizedItemCount = [self synchronizedItemCount];\n+\n+    // Perform another insert\n+    insertExpectation = [self expectationWithDescription:@\"insert expectation\"];\n+    [todoTable insert:@{ @\"id\" : @\"id2\", @\"text\" : @\"client\" } completion:^(NSDictionary *item, NSError *error) {\n+        [insertExpectation fulfill];\n+    }];\n+    \n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+\n+    XCTAssertEqual([self performVanillaPush], 2, \"Expected all inserted items to have been pushed to the server by now\");\n+\n+    return synchronizedItemCount;\n+}\n+\n+// Performs a push operation and returns the count of all client items pushed so far\n+-(int) performVanillaPush\n+{\n+    // Define a filter that returns an appropriate server response for the requested item\n+    MSTestFilter *filter = [MSTestFilter new];\n+    MSClient *filteredClient = [client clientWithFilter:filter];\n+\n+    filter.ignoreNextFilter = YES;\n+    filter.onInspectResponseData = ^(NSURLRequest *request, NSData *data) {\n+        NSError *error = nil;\n+        \n+        NSDictionary *item = [filteredClient.serializer itemFromData:request.HTTPBody withOriginalItem:nil ensureDictionary:YES orError:&error];\n+        XCTAssertNil(error);\n+        \n+        NSString *responseString = [NSString stringWithFormat:@\"{\\\"id\\\": \\\"%@\\\", \\\"text\\\":\\\"server\\\"}\", item[@\"id\"]];\n+        NSData *pushResponse = [responseString dataUsingEncoding:NSUTF8StringEncoding];\n+\n+        return pushResponse;\n+    };\n+\n+    // Perform push\n+    XCTestExpectation *pushExpectation = [self expectationWithDescription:@\"push expectation\"];\n+    [filteredClient.syncContext pushWithCompletion:^(NSError *error) {\n+        XCTAssertNil(error, \"Expected successful push\");\n+        [pushExpectation fulfill];\n+    }];\n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+    \n+    return [self synchronizedItemCount];\n+}\n+\n+// Returns the number of synchronized items, i.e. items that are present on the server as well as the client.\n+// An item is synchronized if it was successfully pushed to the server from the client OR\n+// if it was successfully pulled from the server to the client.\n+-(int) synchronizedItemCount\n+{\n+    // Initialization\n+    MSSyncTable *todoTable = [client syncTableWithName:TodoTableNoVersion];\n+    MSQuery *query = [[MSQuery alloc] initWithSyncTable:todoTable];\n+\n+    // Number synchronized items\n+    __block int numSynchronizedItems = 0;\n+\n+    XCTestExpectation *readExpectation = [self expectationWithDescription:@\"read expectation\"];\n+\n+    // Read from the table\n+    [client.syncContext readWithQuery:query completion:^(MSQueryResult *result, NSError *error) {\n+        \n+        // Count the number of synchronized items\n+        for (NSDictionary* item in result.items) {\n+            if ([item[@\"text\"] isEqualToString:@\"server\"]) {\n+                ++numSynchronizedItems;\n+            }\n+        }\n+\n+        [readExpectation fulfill];\n+    }];\n+    \n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+    \n+    return numSynchronizedItems;\n+}\n+\n+// Verify that the specified NSOperation has finished\n+-(void) verifyFinished:(NSOperation *)operation\n+{\n+    XCTestExpectation *completionExpectation = [self expectationWithDescription:@\"Completion expectation\"];\n+    \n+    // Define an operation and make it dependent on blockingOperation\n+    NSOperation *dependentOperation = [NSBlockOperation blockOperationWithBlock:^{\n+        [completionExpectation fulfill];\n+    }];\n+\n+    // Add the dependentOperation to the queue after configuring dependencies\n+    [dependentOperation addDependency:operation];\n+    [[NSOperationQueue new] addOperation:dependentOperation];\n+    \n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+}\n \n #pragma mark Pull Tests\n \n+// Tests cancellation of the pull operation at various stages of the pull workflow\n+// - Verifies that a pull operation following a cancelled pull operation works as expected\n+// - Verifies that cancelling a pull operation finishes the pull NSOperation regardless of the cancellation point\n+// - Verifies that the expected number of items are pulled from the server\n+-(void) testPullCancellability\n+{\n+    XCTAssertEqual([self performPullWithCancellationPoint:0 serverPushResponseCode:@200 serverPullResponseCode:@200], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:1 serverPushResponseCode:@200 serverPullResponseCode:@200], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:2 serverPushResponseCode:@200 serverPullResponseCode:@200], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:3 serverPushResponseCode:@200 serverPullResponseCode:@200], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:4 serverPushResponseCode:@200 serverPullResponseCode:@200], 2, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:5 serverPushResponseCode:@200 serverPullResponseCode:@200], 1, \"Pull cancellation failed\");\n+   \n+    XCTAssertEqual([self performPullWithCancellationPoint:0 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:1 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:2 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:3 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:4 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:5 serverPushResponseCode:@200 serverPullResponseCode:@500], 1, \"Pull cancellation failed\");\n+    \n+    XCTAssertEqual([self performPullWithCancellationPoint:0 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:1 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:2 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:3 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:4 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:5 serverPushResponseCode:@500 serverPullResponseCode:@200], 0, \"Pull cancellation failed\");\n+    \n+    XCTAssertEqual([self performPullWithCancellationPoint:0 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:1 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:2 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:3 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:4 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    XCTAssertEqual([self performPullWithCancellationPoint:5 serverPushResponseCode:@500 serverPullResponseCode:@500], 0, \"Pull cancellation failed\");\n+    \n+    [self performPullWithCancellationPoint:0 serverPushResponseCode:@500 serverPullResponseCode:@200];\n+}\n+\n+// Performs pull and cancels it at the specified cancellation point.\n+// - Verifies that a pull operation following a cancelled pull operation works as expected\n+// - Verifies that cancelling a pull operation finishes the pull NSOperation regardless of the cancellation point\n+// - Verifies that the expected number of items are pull from the server\n+// - Returns the number of items pulled from the server.\n+-(int) performPullWithCancellationPoint:(int) requestedCancellationPoint serverPushResponseCode:(NSNumber *)serverPushResponseCode serverPullResponseCode:(NSNumber *)serverPullResponseCode\n+{\n+    // Initialization\n+    NSString *serverPushData = @\"{\\\"id\\\": \\\"id1\\\", \\\"text\\\":\\\"server\\\"}\";\n+    NSString *serverPullData = @\"[{\\\"id\\\": \\\"id1\\\", \\\"text\\\":\\\"server\\\"}, {\\\"id\\\": \\\"id2\\\", \\\"text\\\":\\\"server\\\"}]\";\n+    MSMultiRequestTestFilter *filter = [MSMultiRequestTestFilter testFilterWithStatusCodes:@[serverPushResponseCode, serverPullResponseCode] data:@[serverPushData, serverPullData] appendEmptyRequest:YES];\n+    MSClient *filteredClient = [client clientWithFilter:filter];\n+    MSSyncTable *todoTable = [filteredClient syncTableWithName:TodoTableNoVersion];\n+    MSQuery *query = [[MSQuery alloc] initWithSyncTable:todoTable];\n+    \n+    // Start with a clean slate\n+    [[todoTable forcePurgeWithCompletion:^(NSError *error) {\n+        XCTAssertNil(error, @\"error should have been nil.\");\n+    }] waitUntilFinished];\n+    \n+    __block NSOperation *pullOperation;\n+    \n+    // Define filters\n+    ((MSTestFilter *)filter.testFilters[0]).onInspectRequest = ^(NSURLRequest *request) {\n+        \n+        // Cancellation point 0\n+        if (requestedCancellationPoint == 0)\n+            [pullOperation cancel];\n+        \n+        return request;\n+    };\n+    \n+    ((MSTestFilter *)filter.testFilters[0]).onInspectResponseData = ^(NSURLRequest *request, NSData *data) {\n+        \n+        // Cancellation point 1\n+        if (requestedCancellationPoint == 1)\n+            [pullOperation cancel];\n+        \n+        return data;\n+    };\n+    \n+    ((MSTestFilter *)filter.testFilters[1]).onInspectRequest = ^(NSURLRequest *request) {\n+        \n+        // Cancellation point 2\n+        if (requestedCancellationPoint == 2)\n+            [pullOperation cancel];\n+        \n+        return request;\n+    };\n+    \n+    ((MSTestFilter *)filter.testFilters[1]).onInspectResponseData = ^(NSURLRequest *request, NSData *data) {\n+        \n+        // Cancellation point 3\n+        if (requestedCancellationPoint == 3)\n+            [pullOperation cancel];\n+        \n+        return data;\n+    };\n+    \n+    // Insert an item\n+    XCTestExpectation *insertExpectation = [self expectationWithDescription:@\"insert expectation\"];\n+    [todoTable insert:@{ @\"id\" : @\"id1\", @\"text\" : @\"client\" } completion:^(NSDictionary *item, NSError *error) {\n+        [insertExpectation fulfill];\n+    }];\n+    \n+    [self waitForExpectationsWithTimeout:10 handler:nil];\n+    \n+    // Perform a pull\n+    pullOperation = [filteredClient.syncContext pullWithQuery:query queryId:nil completion:^(NSError *error) {\n+\n+        // Cancellation point 4\n+        if (requestedCancellationPoint == 4)\n+            [pullOperation cancel];\n+    }];\n+\n+    // Cancellation point 5\n+    if (requestedCancellationPoint == 5)\n+        [pullOperation cancel];\n+\n+    [self verifyFinished:pullOperation];\n+    \n+    int synchronizedItemCount = [self synchronizedItemCount];\n+    \n+    XCTAssertEqual([self performVanillaPull], 3, \"Expected all server items to have been pulled to the client by now\");\n+    \n+    return synchronizedItemCount;\n+}\n+\n+// Performs a pull operation and returns the count of all the server items pulled so far\n+-(int) performVanillaPull\n+{\n+    // Initialization\n+    MSTestFilter *filter = [MSTestFilter new];\n+    MSClient *filteredClient = [client clientWithFilter:filter];\n+    MSSyncTable *todoTable = [filteredClient syncTableWithName:TodoTableNoVersion];\n+    MSQuery *query = [[MSQuery alloc] initWithSyncTable:todoTable];\n+\n+    __block bool isFirstPullRequest = true;\n+    filter.ignoreNextFilter = YES;\n+    filter.onInspectResponseData = ^(NSURLRequest *request, NSData *data) {\n+\n+        NSDictionary *item = [filteredClient.serializer itemFromData:request.HTTPBody withOriginalItem:nil ensureDictionary:YES orError:nil];\n+        \n+        NSString *responseString;\n+        if (item != nil) // This means it is a push request","path":"sdk/iOS/test/MSSyncTableTests.m","position":327,"original_position":327,"commit_id":"144069fa24e07dc7c18b258eadc7eacc8973232c","original_commit_id":"144069fa24e07dc7c18b258eadc7eacc8973232c","user":{"login":"phvannor","id":3979343,"avatar_url":"https://avatars.githubusercontent.com/u/3979343?v=3","gravatar_id":"","url":"https://api.github.com/users/phvannor","html_url":"https://github.com/phvannor","followers_url":"https://api.github.com/users/phvannor/followers","following_url":"https://api.github.com/users/phvannor/following{/other_user}","gists_url":"https://api.github.com/users/phvannor/gists{/gist_id}","starred_url":"https://api.github.com/users/phvannor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phvannor/subscriptions","organizations_url":"https://api.github.com/users/phvannor/orgs","repos_url":"https://api.github.com/users/phvannor/repos","events_url":"https://api.github.com/users/phvannor/events{/privacy}","received_events_url":"https://api.github.com/users/phvannor/received_events","type":"User","site_admin":false},"body":"This is why the multirequest filter exists, to let the filter handle returning responses/etc. ","created_at":"2015-05-26T17:12:03Z","updated_at":"2015-05-26T17:12:03Z","html_url":"https://github.com/Azure/azure-mobile-services/pull/714#discussion_r31056498","pull_request_url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714","_links":{"self":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/comments/31056498"},"html":{"href":"https://github.com/Azure/azure-mobile-services/pull/714#discussion_r31056498"},"pull_request":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714"}}},"pull_request":{"url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714","id":36174183,"html_url":"https://github.com/Azure/azure-mobile-services/pull/714","diff_url":"https://github.com/Azure/azure-mobile-services/pull/714.diff","patch_url":"https://github.com/Azure/azure-mobile-services/pull/714.patch","issue_url":"https://api.github.com/repos/Azure/azure-mobile-services/issues/714","number":714,"state":"open","locked":false,"title":"Push/Pull cancellability UTs","user":{"login":"shrishrirang","id":11167859,"avatar_url":"https://avatars.githubusercontent.com/u/11167859?v=3","gravatar_id":"","url":"https://api.github.com/users/shrishrirang","html_url":"https://github.com/shrishrirang","followers_url":"https://api.github.com/users/shrishrirang/followers","following_url":"https://api.github.com/users/shrishrirang/following{/other_user}","gists_url":"https://api.github.com/users/shrishrirang/gists{/gist_id}","starred_url":"https://api.github.com/users/shrishrirang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shrishrirang/subscriptions","organizations_url":"https://api.github.com/users/shrishrirang/orgs","repos_url":"https://api.github.com/users/shrishrirang/repos","events_url":"https://api.github.com/users/shrishrirang/events{/privacy}","received_events_url":"https://api.github.com/users/shrishrirang/received_events","type":"User","site_admin":false},"body":"- Added UTs to test cancellability of push and pull operations at various execution points\r\n- Removed UT testPullResultingInErrorAllowsDependentOperationsToComplete as completion of push/pull operation is covered by the newly added UTs","created_at":"2015-05-26T07:00:30Z","updated_at":"2015-05-26T17:12:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1961faa01e48b36e517a6d3f2458ba342323ff48","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714/commits","review_comments_url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714/comments","review_comment_url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Azure/azure-mobile-services/issues/714/comments","statuses_url":"https://api.github.com/repos/Azure/azure-mobile-services/statuses/144069fa24e07dc7c18b258eadc7eacc8973232c","head":{"label":"shrishrirang:dev-nsop-review","ref":"dev-nsop-review","sha":"144069fa24e07dc7c18b258eadc7eacc8973232c","user":{"login":"shrishrirang","id":11167859,"avatar_url":"https://avatars.githubusercontent.com/u/11167859?v=3","gravatar_id":"","url":"https://api.github.com/users/shrishrirang","html_url":"https://github.com/shrishrirang","followers_url":"https://api.github.com/users/shrishrirang/followers","following_url":"https://api.github.com/users/shrishrirang/following{/other_user}","gists_url":"https://api.github.com/users/shrishrirang/gists{/gist_id}","starred_url":"https://api.github.com/users/shrishrirang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shrishrirang/subscriptions","organizations_url":"https://api.github.com/users/shrishrirang/orgs","repos_url":"https://api.github.com/users/shrishrirang/repos","events_url":"https://api.github.com/users/shrishrirang/events{/privacy}","received_events_url":"https://api.github.com/users/shrishrirang/received_events","type":"User","site_admin":false},"repo":{"id":31236672,"name":"azure-mobile-services","full_name":"shrishrirang/azure-mobile-services","owner":{"login":"shrishrirang","id":11167859,"avatar_url":"https://avatars.githubusercontent.com/u/11167859?v=3","gravatar_id":"","url":"https://api.github.com/users/shrishrirang","html_url":"https://github.com/shrishrirang","followers_url":"https://api.github.com/users/shrishrirang/followers","following_url":"https://api.github.com/users/shrishrirang/following{/other_user}","gists_url":"https://api.github.com/users/shrishrirang/gists{/gist_id}","starred_url":"https://api.github.com/users/shrishrirang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shrishrirang/subscriptions","organizations_url":"https://api.github.com/users/shrishrirang/orgs","repos_url":"https://api.github.com/users/shrishrirang/repos","events_url":"https://api.github.com/users/shrishrirang/events{/privacy}","received_events_url":"https://api.github.com/users/shrishrirang/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/shrishrirang/azure-mobile-services","description":"Client SDKs and Samples for Azure Mobile Services","fork":true,"url":"https://api.github.com/repos/shrishrirang/azure-mobile-services","forks_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/forks","keys_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/teams","hooks_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/hooks","issue_events_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/issues/events{/number}","events_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/events","assignees_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/assignees{/user}","branches_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/branches{/branch}","tags_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/tags","blobs_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/git/refs{/sha}","trees_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/statuses/{sha}","languages_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/languages","stargazers_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/stargazers","contributors_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/contributors","subscribers_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/subscribers","subscription_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/subscription","commits_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/commits{/sha}","git_commits_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/git/commits{/sha}","comments_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/comments{/number}","issue_comment_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/issues/comments{/number}","contents_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/contents/{+path}","compare_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/merges","archive_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/downloads","issues_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/issues{/number}","pulls_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/pulls{/number}","milestones_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/milestones{/number}","notifications_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/labels{/name}","releases_url":"https://api.github.com/repos/shrishrirang/azure-mobile-services/releases{/id}","created_at":"2015-02-23T23:59:22Z","updated_at":"2015-02-23T23:59:28Z","pushed_at":"2015-05-26T06:57:05Z","git_url":"git://github.com/shrishrirang/azure-mobile-services.git","ssh_url":"git@github.com:shrishrirang/azure-mobile-services.git","clone_url":"https://github.com/shrishrirang/azure-mobile-services.git","svn_url":"https://github.com/shrishrirang/azure-mobile-services","homepage":"http://azure.microsoft.com/en-us/develop/mobile/","size":31023,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Azure:dev","ref":"dev","sha":"7c37f600caf5c356bf0e15a33b9a288106049958","user":{"login":"Azure","id":6844498,"avatar_url":"https://avatars.githubusercontent.com/u/6844498?v=3","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"repo":{"id":5803673,"name":"azure-mobile-services","full_name":"Azure/azure-mobile-services","owner":{"login":"Azure","id":6844498,"avatar_url":"https://avatars.githubusercontent.com/u/6844498?v=3","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Azure/azure-mobile-services","description":"Client SDKs and Samples for Azure Mobile Services","fork":false,"url":"https://api.github.com/repos/Azure/azure-mobile-services","forks_url":"https://api.github.com/repos/Azure/azure-mobile-services/forks","keys_url":"https://api.github.com/repos/Azure/azure-mobile-services/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Azure/azure-mobile-services/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Azure/azure-mobile-services/teams","hooks_url":"https://api.github.com/repos/Azure/azure-mobile-services/hooks","issue_events_url":"https://api.github.com/repos/Azure/azure-mobile-services/issues/events{/number}","events_url":"https://api.github.com/repos/Azure/azure-mobile-services/events","assignees_url":"https://api.github.com/repos/Azure/azure-mobile-services/assignees{/user}","branches_url":"https://api.github.com/repos/Azure/azure-mobile-services/branches{/branch}","tags_url":"https://api.github.com/repos/Azure/azure-mobile-services/tags","blobs_url":"https://api.github.com/repos/Azure/azure-mobile-services/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Azure/azure-mobile-services/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Azure/azure-mobile-services/git/refs{/sha}","trees_url":"https://api.github.com/repos/Azure/azure-mobile-services/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Azure/azure-mobile-services/statuses/{sha}","languages_url":"https://api.github.com/repos/Azure/azure-mobile-services/languages","stargazers_url":"https://api.github.com/repos/Azure/azure-mobile-services/stargazers","contributors_url":"https://api.github.com/repos/Azure/azure-mobile-services/contributors","subscribers_url":"https://api.github.com/repos/Azure/azure-mobile-services/subscribers","subscription_url":"https://api.github.com/repos/Azure/azure-mobile-services/subscription","commits_url":"https://api.github.com/repos/Azure/azure-mobile-services/commits{/sha}","git_commits_url":"https://api.github.com/repos/Azure/azure-mobile-services/git/commits{/sha}","comments_url":"https://api.github.com/repos/Azure/azure-mobile-services/comments{/number}","issue_comment_url":"https://api.github.com/repos/Azure/azure-mobile-services/issues/comments{/number}","contents_url":"https://api.github.com/repos/Azure/azure-mobile-services/contents/{+path}","compare_url":"https://api.github.com/repos/Azure/azure-mobile-services/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Azure/azure-mobile-services/merges","archive_url":"https://api.github.com/repos/Azure/azure-mobile-services/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Azure/azure-mobile-services/downloads","issues_url":"https://api.github.com/repos/Azure/azure-mobile-services/issues{/number}","pulls_url":"https://api.github.com/repos/Azure/azure-mobile-services/pulls{/number}","milestones_url":"https://api.github.com/repos/Azure/azure-mobile-services/milestones{/number}","notifications_url":"https://api.github.com/repos/Azure/azure-mobile-services/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Azure/azure-mobile-services/labels{/name}","releases_url":"https://api.github.com/repos/Azure/azure-mobile-services/releases{/id}","created_at":"2012-09-14T02:04:52Z","updated_at":"2015-05-26T09:26:08Z","pushed_at":"2015-05-26T07:00:30Z","git_url":"git://github.com/Azure/azure-mobile-services.git","ssh_url":"git@github.com:Azure/azure-mobile-services.git","clone_url":"https://github.com/Azure/azure-mobile-services.git","svn_url":"https://github.com/Azure/azure-mobile-services","homepage":"http://azure.microsoft.com/en-us/develop/mobile/","size":61498,"stargazers_count":377,"watchers_count":377,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":238,"mirror_url":null,"open_issues_count":84,"forks":238,"open_issues":84,"watchers":377,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714"},"html":{"href":"https://github.com/Azure/azure-mobile-services/pull/714"},"issue":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/issues/714"},"comments":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/issues/714/comments"},"review_comments":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714/comments"},"review_comment":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/pulls/714/commits"},"statuses":{"href":"https://api.github.com/repos/Azure/azure-mobile-services/statuses/144069fa24e07dc7c18b258eadc7eacc8973232c"}}}}