You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
7.8 KiB
238 lines
7.8 KiB
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright 2014 Realm Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#import "RLMTestCase.h"
|
|
#import "RLMRealm_Dynamic.h"
|
|
|
|
RLM_ARRAY_TYPE(CircularArrayObject)
|
|
@interface CircularArrayObject : RLMObject
|
|
@property RLM_GENERIC_ARRAY(CircularArrayObject) *array;
|
|
@end
|
|
@implementation CircularArrayObject
|
|
@end
|
|
|
|
@interface LinkTests : RLMTestCase
|
|
@end
|
|
|
|
@implementation LinkTests
|
|
|
|
- (void)makeDogWithName:(NSString *)name owner:(NSString *)ownerName {
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
OwnerObject *owner = [[OwnerObject alloc] init];
|
|
owner.name = ownerName;
|
|
owner.dog = [[DogObject alloc] init];
|
|
owner.dog.dogName = name;
|
|
owner.dog.age = 0;
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:owner];
|
|
[realm commitWriteTransaction];
|
|
}
|
|
|
|
- (void)testBasicLink
|
|
{
|
|
[self makeDogWithName:@"Harvie" owner:@"Tim"];
|
|
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
RLMResults *owners = [OwnerObject objectsInRealm:realm withPredicate:nil];
|
|
RLMResults *dogs = [DogObject objectsInRealm:realm withPredicate:nil];
|
|
XCTAssertEqual(owners.count, 1U);
|
|
XCTAssertEqual(dogs.count, 1U);
|
|
XCTAssertEqualObjects([owners[0] name], @"Tim", @"Tim is named Tim");
|
|
XCTAssertEqualObjects([dogs[0] dogName], @"Harvie", @"Harvie is named Harvie");
|
|
|
|
OwnerObject *tim = owners[0];
|
|
XCTAssertEqualObjects(tim.dog.dogName, @"Harvie", @"Tim's dog should be Harvie");
|
|
}
|
|
|
|
-(void)testBasicLinkWithNil
|
|
{
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
OwnerObject *owner = [[OwnerObject alloc] init];
|
|
owner.name = @"Tim";
|
|
owner.dog = nil;
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:owner];
|
|
[realm commitWriteTransaction];
|
|
|
|
RLMResults *owners = [OwnerObject objectsInRealm:realm withPredicate:nil];
|
|
RLMResults *dogs = [DogObject objectsInRealm:realm withPredicate:nil];
|
|
XCTAssertEqual(owners.count, 1U);
|
|
XCTAssertEqual(dogs.count, 0U);
|
|
XCTAssertEqualObjects([owners[0] name], @"Tim", @"Tim is named Tim");
|
|
|
|
OwnerObject *tim = owners[0];
|
|
XCTAssertEqualObjects(tim.dog, nil, @"Tim does not have a dog");
|
|
}
|
|
|
|
- (void)testMultipleOwnerLink
|
|
{
|
|
[self makeDogWithName:@"Harvie" owner:@"Tim"];
|
|
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
XCTAssertEqual([OwnerObject allObjectsInRealm:realm].count, 1U);
|
|
XCTAssertEqual([DogObject allObjectsInRealm:realm].count, 1U);
|
|
|
|
[realm beginWriteTransaction];
|
|
OwnerObject *fiel = [OwnerObject createInRealm:realm withValue:@[@"Fiel", [NSNull null]]];
|
|
fiel.dog = [DogObject allObjectsInRealm:realm].firstObject;
|
|
[realm commitWriteTransaction];
|
|
|
|
XCTAssertEqual([OwnerObject objectsInRealm:realm withPredicate:nil].count, 2U);
|
|
XCTAssertEqual([DogObject objectsInRealm:realm withPredicate:nil].count, 1U);
|
|
}
|
|
|
|
- (void)testLinkRemoval
|
|
{
|
|
[self makeDogWithName:@"Harvie" owner:@"Tim"];
|
|
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
XCTAssertEqual([OwnerObject objectsInRealm:realm withPredicate:nil].count, 1U);
|
|
XCTAssertEqual([DogObject objectsInRealm:realm withPredicate:nil].count, 1U);
|
|
|
|
DogObject *dog = [DogObject allObjectsInRealm:realm].firstObject;
|
|
OwnerObject *owner = [OwnerObject allObjectsInRealm:realm].firstObject;
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm deleteObject:dog];
|
|
[realm commitWriteTransaction];
|
|
|
|
XCTAssertNil(owner.dog, @"Dog should be nullified when deleted");
|
|
XCTAssertThrows(dog.dogName, @"Dog object should be invalid after being deleted from the realm");
|
|
|
|
// refresh owner and check
|
|
owner = [OwnerObject allObjectsInRealm:realm].firstObject;
|
|
XCTAssertNotNil(owner, @"Should have 1 owner");
|
|
XCTAssertNil(owner.dog, @"Dog should be nullified when deleted");
|
|
XCTAssertEqual([DogObject objectsInRealm:realm withPredicate:nil].count, 0U);
|
|
}
|
|
|
|
- (void)testInvalidLinks
|
|
{
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
LinkToAllTypesObject *linkObject = [[LinkToAllTypesObject alloc] init];
|
|
linkObject.allTypesCol = [[AllTypesObject alloc] init];
|
|
[realm beginWriteTransaction];
|
|
XCTAssertThrows([realm addObject:linkObject], @"dateCol not set on linked object");
|
|
|
|
StringObject *to = [StringObject createInRealm:realm withValue:@[@"testObject"]];
|
|
NSArray *args = @[@"Tim", to];
|
|
XCTAssertThrows([OwnerObject createInRealm:realm withValue:args], @"Inserting wrong object type should throw");
|
|
[realm commitWriteTransaction];
|
|
}
|
|
|
|
- (void)testLinkTooManyRelationships
|
|
{
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
OwnerObject *owner = [[OwnerObject alloc] init];
|
|
owner.name = @"Tim";
|
|
owner.dog = [[DogObject alloc] init];
|
|
owner.dog.dogName = @"Harvie";
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:owner];
|
|
[realm commitWriteTransaction];
|
|
|
|
XCTAssertThrows([OwnerObject objectsInRealm:realm where:@"dog.dogName.first = 'Fifo'"], @"3 levels of relationship");
|
|
}
|
|
|
|
- (void)testBidirectionalRelationship {
|
|
RLMRealm *realm = [RLMRealm defaultRealm];
|
|
|
|
CircleObject *obj0 = [[CircleObject alloc] initWithValue:@[@"a", NSNull.null]];
|
|
CircleObject *obj1 = [[CircleObject alloc] initWithValue:@[@"b", obj0]];
|
|
obj0.next = obj1;
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:obj0];
|
|
[realm addObject:obj1];
|
|
[realm commitWriteTransaction];
|
|
|
|
RLMResults *results = [CircleObject allObjects];
|
|
XCTAssertEqualObjects(@"a", [results[0] data]);
|
|
XCTAssertEqualObjects(@"b", [results[1] data]);
|
|
}
|
|
|
|
- (void)testAddingCircularReferenceDoesNotLeakSourceObjects {
|
|
CircleObject __weak *weakObj0, __weak *weakObj1;
|
|
@autoreleasepool {
|
|
CircleObject *obj0 = [[CircleObject alloc] initWithValue:@[@"a", NSNull.null]];
|
|
CircleObject *obj1 = [[CircleObject alloc] initWithValue:@[@"b", obj0]];
|
|
obj0.next = obj1;
|
|
|
|
weakObj0 = obj0;
|
|
weakObj1 = obj1;
|
|
|
|
RLMRealm *realm = [RLMRealm defaultRealm];
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:obj0];
|
|
obj0.next = nil;
|
|
obj1.next = nil;
|
|
[realm commitWriteTransaction];
|
|
}
|
|
|
|
XCTAssertNil(weakObj0);
|
|
XCTAssertNil(weakObj1);
|
|
}
|
|
|
|
- (void)testAddingCircularReferenceInArrayDoesNotLeakSourceObjects {
|
|
CircularArrayObject __weak *weakObj0, __weak *weakObj1;
|
|
@autoreleasepool {
|
|
CircularArrayObject *obj0 = [[CircularArrayObject alloc] initWithValue:@[@[]]];
|
|
CircularArrayObject *obj1 = [[CircularArrayObject alloc] initWithValue:@[@[obj0]]];
|
|
[obj0.array addObject:obj1];
|
|
|
|
weakObj0 = obj0;
|
|
weakObj1 = obj1;
|
|
|
|
RLMRealm *realm = [RLMRealm defaultRealm];
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:obj0];
|
|
[realm commitWriteTransaction];
|
|
}
|
|
|
|
XCTAssertNil(weakObj0);
|
|
XCTAssertNil(weakObj1);
|
|
}
|
|
|
|
- (void)testCircularLinks {
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
|
|
CircleObject *obj = [[CircleObject alloc] init];
|
|
obj.data = @"a";
|
|
obj.next = obj;
|
|
|
|
[realm beginWriteTransaction];
|
|
[realm addObject:obj];
|
|
obj.next.data = @"b";
|
|
[realm commitWriteTransaction];
|
|
|
|
XCTAssertEqual(1U, [CircleObject allObjectsInRealm:realm].count);
|
|
CircleObject *obj1 = [CircleObject allObjectsInRealm:realm].firstObject;
|
|
XCTAssertEqualObjects(obj1.data, @"b", @"data should be 'b'");
|
|
XCTAssertEqualObjects(obj1.data, obj.next.data, @"objects should be equal");
|
|
}
|
|
|
|
@end
|
|
|
|
|