From 26d5cc27d222dcba8fe748ae57c6425ed55cf2d3 Mon Sep 17 00:00:00 2001 From: Pasin Suriyentrakorn Date: Thu, 14 Dec 2023 17:51:08 -0800 Subject: [PATCH] =?UTF-8?q?CBL-5203=20:=20Collection=E2=80=99s=20full=20na?= =?UTF-8?q?me=20accessor=20(#3207)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implemented Collection’s fullName accessor in Objective-C and Swift. * Fixed XCode static analysic warning in CBLCoflict+Internal.h * Fixed XCode static analysic warning in DatabaseTest.m. --- Objective-C/CBLCollection.h | 5 ++- Objective-C/CBLCollection.mm | 19 ++++++----- Objective-C/Internal/CBLCollection+Internal.h | 2 -- .../Replicator/CBLConflict+Internal.h | 4 +-- Objective-C/Tests/CollectionTest.m | 33 +++++++++++++++++++ Objective-C/Tests/DatabaseTest.m | 3 ++ Swift/Collection.swift | 5 ++- Swift/Tests/CollectionTest.swift | 31 +++++++++++++++++ 8 files changed, 87 insertions(+), 15 deletions(-) diff --git a/Objective-C/CBLCollection.h b/Objective-C/CBLCollection.h index 6e2280480..53169d72d 100644 --- a/Objective-C/CBLCollection.h +++ b/Objective-C/CBLCollection.h @@ -70,9 +70,12 @@ extern NSString* const kCBLDefaultCollectionName; */ @interface CBLCollection : NSObject -/** Collection name.*/ +/** Collection's name.*/ @property (readonly, nonatomic) NSString* name; +/** Collection's fully qualified name in the '.' format. */ +@property (readonly, nonatomic) NSString* fullName; + /** The scope of the collection. */ @property (readonly, nonatomic) CBLScope* scope; diff --git a/Objective-C/CBLCollection.mm b/Objective-C/CBLCollection.mm index 76b695c02..601c65279 100644 --- a/Objective-C/CBLCollection.mm +++ b/Objective-C/CBLCollection.mm @@ -98,18 +98,23 @@ - (NSUInteger) hash { return [self.name hash] ^ [self.scope.name hash]; } +- (id) copyWithZone: (nullable NSZone*)zone { + return [[[self class] alloc] initWithDB: _db c4collection: _c4col]; +} + +#pragma mark - Properties + +- (NSString*) fullName { + return $sprintf(@"%@.%@", _scope.name, _name); +} + - (uint64_t) count { CBL_LOCK(_mutex) { _count = c4coll_isValid(_c4col) ? c4coll_getDocumentCount(_c4col) : 0; } - return _count; } -- (id) copyWithZone: (nullable NSZone*)zone { - return [[[self class] alloc] initWithDB: _db c4collection: _c4col]; -} - #pragma mark - Indexable - (BOOL) createIndexWithName: (NSString*)name @@ -496,10 +501,6 @@ - (C4CollectionSpec) c4spec { return { .name = name, .scope = scopeName }; } -- (NSString*) fullName { - return $sprintf(@"%@.%@", _scope.name, _name); -} - - (BOOL) isEqual: (id)object { if (self == object) return YES; diff --git a/Objective-C/Internal/CBLCollection+Internal.h b/Objective-C/Internal/CBLCollection+Internal.h index b8e5768f1..438f0b8a0 100644 --- a/Objective-C/Internal/CBLCollection+Internal.h +++ b/Objective-C/Internal/CBLCollection+Internal.h @@ -47,8 +47,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) C4CollectionSpec c4spec; -@property (nonatomic, readonly) NSString* fullName; - /** This constructor will return CBLCollection for the c4collection. */ - (instancetype) initWithDB: (CBLDatabase*)db c4collection: (C4Collection*)c4collection; diff --git a/Objective-C/Internal/Replicator/CBLConflict+Internal.h b/Objective-C/Internal/Replicator/CBLConflict+Internal.h index 7adaba982..77b026ef7 100644 --- a/Objective-C/Internal/Replicator/CBLConflict+Internal.h +++ b/Objective-C/Internal/Replicator/CBLConflict+Internal.h @@ -25,8 +25,8 @@ NS_ASSUME_NONNULL_BEGIN @interface CBLConflict () - (instancetype) initWithID: (NSString*)documentID - localDocument: (CBLDocument *)localDoc - remoteDocument: (CBLDocument *)remoteDoc; + localDocument: (nullable CBLDocument*)localDoc + remoteDocument: (nullable CBLDocument*)remoteDoc; @end diff --git a/Objective-C/Tests/CollectionTest.m b/Objective-C/Tests/CollectionTest.m index 3e646da42..8713c23f6 100644 --- a/Objective-C/Tests/CollectionTest.m +++ b/Objective-C/Tests/CollectionTest.m @@ -470,6 +470,39 @@ - (void) testScopeNameCaseSensitive { Assert([(@[@"scopeA", @"SCOPEa", kCBLDefaultScopeName]) containsObject: scopes[1].name]); } +#pragma mark - Collection Full Name + +// Spec: https://docs.google.com/document/d/1nUgaCgXIB3lLViudf6Pw6H9nPa_OeYU6uM_9xAd08M0 + +- (void) testCollectionFullName { + NSError* error; + + // 3.1 TestGetFullNameFromDefaultCollection + CBLCollection* col1 = [self.db defaultCollection: &error]; + AssertNotNil(col1); + AssertEqualObjects(col1.fullName, @"_default._default"); + + // 3.2 TestGetFullNameFromNewCollectionInDefaultScope + CBLCollection* col2 = [self.db createCollectionWithName: @"colA" scope: nil error: &error]; + AssertNotNil(col2); + AssertEqualObjects(col2.fullName, @"_default.colA"); + + // 3.3 TestGetFullNameFromNewCollectionInCustomScope + CBLCollection* col3 = [self.db createCollectionWithName: @"colA" scope: @"scopeA" error: &error]; + AssertNotNil(col3); + AssertEqualObjects(col3.fullName, @"scopeA.colA"); + + // 3.4 TestGetFullNameFromExistingCollectionInDefaultScope + CBLCollection* col4 = [self.db collectionWithName: @"colA" scope: nil error: &error]; + AssertNotNil(col4); + AssertEqualObjects(col4.fullName, @"_default.colA"); + + // 3.5 TestGetFullNameFromNewCollectionInCustomScope + CBLCollection* col5 = [self.db collectionWithName: @"colA" scope: @"scopeA" error: &error]; + AssertNotNil(col5); + AssertEqualObjects(col5.fullName, @"scopeA.colA"); +} + #pragma mark - 8.3 Collections and Cross Database Instance - (void) testCreateThenGetCollectionFromDifferentDatabaseInstance { diff --git a/Objective-C/Tests/DatabaseTest.m b/Objective-C/Tests/DatabaseTest.m index 2591f2f2c..643db0784 100644 --- a/Objective-C/Tests/DatabaseTest.m +++ b/Objective-C/Tests/DatabaseTest.m @@ -2592,6 +2592,7 @@ - (void) testCreateCollection { // Create in Custom Scope c = [self.db createCollectionWithName: @"collection2" scope: @"scope1" error: &error]; + AssertNotNil(c); // verify collections = [self.db collections: @"scope1" error: &error]; @@ -2634,7 +2635,9 @@ - (void) testCreateDuplicateCollection { // Create in Custom Scope c1 = [self.db createCollectionWithName: @"collection2" scope: @"scope1" error: &error]; + AssertNotNil(c1); c2 = [self.db createCollectionWithName: @"collection2" scope: @"scope1" error: &error]; + AssertNotNil(c2); // verify no duplicate is created. collections = [self.db collections: @"scope1" error: &error]; diff --git a/Swift/Collection.swift b/Swift/Collection.swift index f252a420c..79469df34 100644 --- a/Swift/Collection.swift +++ b/Swift/Collection.swift @@ -58,9 +58,12 @@ public final class Collection : CollectionChangeObservable, Indexable, Equatable /// The default scope name constant public static let defaultCollectionName: String = kCBLDefaultCollectionName - /// Collection name. + /// Collection's name. public var name: String { impl.name } + /// Collection's fully qualified name in the '.' format. + public var fullName: String { impl.fullName } + /// The scope of the collection. public let scope: Scope diff --git a/Swift/Tests/CollectionTest.swift b/Swift/Tests/CollectionTest.swift index 12e188947..b02fd375b 100644 --- a/Swift/Tests/CollectionTest.swift +++ b/Swift/Tests/CollectionTest.swift @@ -100,6 +100,37 @@ class CollectionTest: CBLTestCase { XCTAssertEqual(scopes[0].name, Scope.defaultScopeName) } + // MARK: Collection Full Name + + // Spec: https://docs.google.com/document/d/1nUgaCgXIB3lLViudf6Pw6H9nPa_OeYU6uM_9xAd08M0 + + func testCollectionFullName() throws { + // 3.1 TestGetFullNameFromDefaultCollection + let col1 = try self.db.defaultCollection() + XCTAssertNotNil(col1) + XCTAssertEqual(col1.fullName, "_default._default") + + // 3.2 TestGetFullNameFromNewCollectionInDefaultScope + let col2 = try self.db.createCollection(name: "colA") + XCTAssertNotNil(col2) + XCTAssertEqual(col2.fullName, "_default.colA") + + // 3.3 TestGetFullNameFromNewCollectionInCustomScope + let col3 = try self.db.createCollection(name: "colA", scope: "scopeA") + XCTAssertNotNil(col3) + XCTAssertEqual(col3.fullName, "scopeA.colA") + + // 3.4 TestGetFullNameFromExistingCollectionInDefaultScope + let col4 = try self.db.collection(name: "colA") + XCTAssertNotNil(col4) + XCTAssertEqual(col4!.fullName, "_default.colA") + + // 3.5 TestGetFullNameFromNewCollectionInCustomScope + let col5 = try self.db.collection(name: "colA", scope: "scopeA") + XCTAssertNotNil(col5) + XCTAssertEqual(col5!.fullName, "scopeA.colA") + } + // MARK: 8.2 Collections func testCreateAndGetCollectionsInDefaultScope() throws {