From c23339b2f9d715d01df22daa828c14b338d10c0c Mon Sep 17 00:00:00 2001 From: Stephen Drew Date: Wed, 14 Oct 2015 12:06:00 -0500 Subject: [PATCH 1/2] Avoid assertion in allDocsQuery:options: when a docId isn't found. When using `allDocsQuery:options:` with an array of docIds, a missing document will cause an 'Invalid parameter not satisfying: properties' assertion in `[TD_Body initWithProperties:]`. --- Classes/common/CDTDatastore.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Classes/common/CDTDatastore.m b/Classes/common/CDTDatastore.m index abf6d983b..2d039302f 100644 --- a/Classes/common/CDTDatastore.m +++ b/Classes/common/CDTDatastore.m @@ -350,6 +350,12 @@ - (NSArray *)allDocsQuery:(NSArray *)docIds options:(TDQueryOptions *)queryOptio NSString *docId = row[@"id"]; NSString *revId = row[@"value"][@"rev"]; + + // If a document isn't found, docId and revId will be null, and row will + // contain an @"error" key. + if (docId == nil && revId == nil && [row[@"error"] isEqualToString:@"not_found"]) { + continue; + } // deleted field only present in deleted documents, but to be safe we use // the fact that (BOOL)[nil -boolValue] is false From 2e0a78e13bb7d09f9707ce6e356c7b04ac461532 Mon Sep 17 00:00:00 2001 From: Stephen Drew Date: Mon, 19 Oct 2015 17:07:11 -0500 Subject: [PATCH 2/2] Added getDocumentsWithIds: test for non-existent docIds --- Tests/Tests/CDTDatastoreQueryTests.m | 7 +++++ Tests/Tests/DatastoreCRUD.m | 38 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Tests/Tests/CDTDatastoreQueryTests.m b/Tests/Tests/CDTDatastoreQueryTests.m index f89fe11d0..2515b077f 100644 --- a/Tests/Tests/CDTDatastoreQueryTests.m +++ b/Tests/Tests/CDTDatastoreQueryTests.m @@ -89,6 +89,13 @@ expect(results).toNot.beNil(); expect([results.documentIds count]).to.equal(3); }); + + it(@"can find documents and ignore non-existent documents", ^{ + NSDictionary *query = @{ @"_id" : @{ @"$in" : @[@"mike12", @"mike34", @"mike72", @"mike-not-found"] } }; + CDTQResultSet *results = [ds find:query]; + expect(results).toNot.beNil(); + expect([results.documentIds count]).to.equal(3); + }); it(@" can delete an index", ^{ [ds ensureIndexed:@[ @"name", @"address" ] withName:@"basic"]; diff --git a/Tests/Tests/DatastoreCRUD.m b/Tests/Tests/DatastoreCRUD.m index a5ed60a57..32d268236 100644 --- a/Tests/Tests/DatastoreCRUD.m +++ b/Tests/Tests/DatastoreCRUD.m @@ -614,6 +614,44 @@ -(void)testGetDocumentsWithIds } } +-(void)testGetDocumentsWithIds_NonExistentDocument +{ + NSError *error; + NSMutableArray *docIds = [NSMutableArray arrayWithCapacity:20]; + + for (int i = 0; i < 200; i++) { + error = nil; + CDTDocumentRevision *rev = [CDTDocumentRevision revision]; + rev.body = [@{@"hello":@"world",@"index":[NSNumber numberWithInt:i]} mutableCopy]; + CDTDocumentRevision *ob = [self.datastore createDocumentFromRevision:rev error:&error]; + XCTAssertNil(error, @"Error creating document"); + + NSString *docId = ob.docId; + [docIds addObject:docId]; + } + + NSArray *retrivedDocIds = @[docIds[5], docIds[7], docIds[12], docIds[170], @"i_do_not_exist"]; + NSArray *obs = [self.datastore getDocumentsWithIds:retrivedDocIds]; + XCTAssertNotNil(obs, @"Error getting documents"); + + XCTAssertEqual([obs count], 4, @"Unexpected number of documents"); + + int ob_index = 0; + for (NSNumber *index in @[@5, @7, @12, @170]) { + NSString *docId = [docIds objectAtIndex:[index intValue]]; + CDTDocumentRevision *retrieved = [obs objectAtIndex:ob_index]; + + XCTAssertNotNil(retrieved, @"retrieved object was nil"); + XCTAssertEqualObjects(retrieved.docId, docId, @"Object retrieved from database has wrong docid"); + const NSUInteger expected_count = 2; + XCTAssertEqual(retrieved.body.count, expected_count, @"Object from database has != 2 keys"); + XCTAssertEqualObjects(retrieved.body[@"hello"], @"world", @"Object from database has wrong data"); + XCTAssertEqualObjects(retrieved.body[@"index"], index, @"Object from database has wrong data"); + + ob_index++; + } +} + -(void)testGetNonExistingDocument { NSError *error;