YapDatabase/Testing/UnitTesting/TestYapDatabaseRelationship.m

1283 lines
57 KiB
Objective-C

#import <XCTest/XCTest.h>
#import "YapDatabase.h"
#import "YapDatabaseRelationship.h"
#import "TestNodes.h"
#import "DDLog.h"
#import "DDTTYLogger.h"
@interface TestYapDatabaseRelationship : XCTestCase
@end
@implementation TestYapDatabaseRelationship
- (NSString *)databasePath:(NSString *)suffix
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
NSString *databaseName = [NSString stringWithFormat:@"%@-%@.sqlite", THIS_FILE, suffix];
return [baseDir stringByAppendingPathComponent:databaseName];
}
- (void)setUp
{
[super setUp];
[DDLog removeAllLoggers];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
}
- (void)tearDown
{
[DDLog flushLog];
[super tearDown];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)testProtocol_Standard
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
Node_Standard *n1 = [[Node_Standard alloc] init];
Node_Standard *n2 = [[Node_Standard alloc] init];
Node_Standard *n3 = [[Node_Standard alloc] init];
n1.childKeys = @[ n2.key, n3.key ];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting the children
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n2.key inCollection:nil];
[transaction removeObjectForKey:n3.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Re-add the children and edges
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Re-add the children
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
// Reset the parent (so it re-adds the edges)
[transaction replaceObject:n1 forKey:n1.key inCollection:nil];
// Check that the edges are back
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting the parent
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n1.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"child"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
XCTAssertNil([transaction objectForKey:n2.key inCollection:nil], @"Oops");
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
// Now test adding an edge and deleting it within the same transaction
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
[transaction removeObjectForKey:n1.key inCollection:nil];
[[transaction ext:@"relationship"] flush];
XCTAssertNil([transaction objectForKey:n2.key inCollection:nil], @"Oops");
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
// Re-add everything
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
}];
// Update n1, and remove its children, which should delete n2 & n3
n1.childKeys = nil;
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
}];
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
XCTAssertNil([transaction objectForKey:n2.key inCollection:nil], @"Oops");
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
}
- (void)testProtocol_Inverse
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
Node_Inverse *n1 = [[Node_Inverse alloc] init];
Node_Inverse *n2 = [[Node_Inverse alloc] init];
Node_Inverse *n3 = [[Node_Inverse alloc] init];
n2.parentKey = n1.key;
n3.parentKey = n1.key;
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n2.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n2.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting 1 of the children.
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n2.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n2.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n2.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"parent"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting the parent.
// This should also delete the second child (due to the nodeDeleteRules).
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n1.key inCollection:nil];
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
XCTAssertNil([transaction objectForKey:n2.key inCollection:nil], @"Oops");
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
}
- (void)testProtocol_RetainCount
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
Node_RetainCount *n1 = [[Node_RetainCount alloc] init];
Node_RetainCount *n2 = [[Node_RetainCount alloc] init];
Node_RetainCount *n3 = [[Node_RetainCount alloc] init];
// Node1 & Node2 will both retain Node3.
//
// Node1 -> Node3
// Node2 -> Node3
n1.retainedKey = n3.key;
n2.retainedKey = n3.key;
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting 1 of the retainers.
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n1.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n2.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" destinationKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained" sourceKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n1.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retained"
sourceKey:n2.key
collection:nil
destinationKey:n3.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting the second/last retainer.
// This should also delete n3 (as no more nodes are retaining it).
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n2.key inCollection:nil];
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
}
- (void)testProtocol_InverseRetainCount
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
Node_InverseRetainCount *n1 = [[Node_InverseRetainCount alloc] init];
Node_InverseRetainCount *n2 = [[Node_InverseRetainCount alloc] init];
Node_InverseRetainCount *n3 = [[Node_InverseRetainCount alloc] init];
// Node1 & Node2 will both retain Node3.
// But the edges are being created in reverse.
//
// Node3 -> Node1
// Node3 -> Node2
n3.retainerKeys = @[ n1.key, n2.key ];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting both of the retainers.
// This should delete n3, because no nodes are left to retain it.
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n1.key inCollection:nil];
[transaction removeObjectForKey:n2.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Reset all the nodes
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Re-add the children
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
// Check that the edges are back
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 2, @"Bad edgeCount. expected(2) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Test deleting just one of the retainers.
// This should not delete n3, as n2 is still retaining it.
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n1.key inCollection:nil];
NSUInteger edgeCount;
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" sourceKey:n3.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n1.key collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(0) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer" destinationKey:n2.key collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n1.key
collection:nil];
XCTAssertTrue(edgeCount == 0, @"Bad edgeCount. expected(0) != %d", (int)edgeCount);
edgeCount = [[transaction ext:@"relationship"] edgeCountWithName:@"retainer"
sourceKey:n3.key
collection:nil
destinationKey:n2.key
collection:nil];
XCTAssertTrue(edgeCount == 1, @"Bad edgeCount. expected(1) != %d", (int)edgeCount);
}];
// Now delete the last retainer (n2).
// This should delete n3 as there are no other nodes retaining it.
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:n2.key inCollection:nil];
}];
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
// Now test adding the edges and deleting them within the same transaction
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:n1 forKey:n1.key inCollection:nil];
[transaction setObject:n2 forKey:n2.key inCollection:nil];
[transaction setObject:n3 forKey:n3.key inCollection:nil];
[transaction removeObjectForKey:n1.key inCollection:nil];
[transaction removeObjectForKey:n2.key inCollection:nil];
[[transaction ext:@"relationship"] flush];
XCTAssertNil([transaction objectForKey:n3.key inCollection:nil], @"Oops");
}];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)testManual_1
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
NSString *key1 = @"key1";
NSString *key2 = @"key2";
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:key1 forKey:key1 inCollection:nil];
[transaction setObject:key2 forKey:key2 inCollection:nil];
YapDatabaseRelationshipEdge *edge =
[YapDatabaseRelationshipEdge edgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted];
[[transaction ext:@"relationship"] addEdge:edge];
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:key1 inCollection:nil];
[[transaction ext:@"relationship"] flush];
XCTAssertNil([transaction objectForKey:key2 inCollection:nil], @"Oops");
}];
}
- (void)testManual_2
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
NSString *key1 = @"key1";
NSString *key2 = @"key2";
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:key1 forKey:key1 inCollection:nil];
[transaction setObject:key2 forKey:key2 inCollection:nil];
YapDatabaseRelationshipEdge *edge =
[YapDatabaseRelationshipEdge edgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted];
[[transaction ext:@"relationship"] addEdge:edge];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:key1 forKey:key1 inCollection:nil];
[transaction setObject:key2 forKey:key2 inCollection:nil];
YapDatabaseRelationshipEdge *edge =
[YapDatabaseRelationshipEdge edgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted];
[[transaction ext:@"relationship"] addEdge:edge];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Test removing an edge
[[transaction ext:@"relationship"] removeEdgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
withProcessing:YDB_SourceNodeDeleted];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
// The edge's nodeDeleteRules (YDB_DeleteDestinationIfSourceDeleted),
// plus the processing rules (YDB_SourceNodeDeleted),
// should have resulted in the destination node being deleted.
id obj1 = [transaction objectForKey:key1 inCollection:nil];
XCTAssertNotNil(obj1, @"Relationship incorrectly deleted sourceNode");
id obj2 = [transaction objectForKey:key2 inCollection:nil];
XCTAssertNil(obj2, @"Relationship extension didn't properly delete destinationNode");
}];
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Test removing an edge that doesn't exist in the database.
// Make sure it doesn't do anything funky.
[[transaction ext:@"relationship"] removeEdgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
withProcessing:YDB_SourceNodeDeleted];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
}];
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
id obj1 = [transaction objectForKey:key1 inCollection:nil];
XCTAssertNotNil(obj1, @"Relationship incorrectly deleted sourceNode");
id obj2 = [transaction objectForKey:key2 inCollection:nil];
XCTAssertNil(obj2, @"Relationship extension didn't properly delete destinationNode");
}];
}
- (void)testManual_3
{
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
XCTAssertNotNil(database, @"Oops");
YapDatabaseConnection *connection1 = [database newConnection];
YapDatabaseConnection *connection2 = [database newConnection];
YapDatabaseRelationship *relationship = [[YapDatabaseRelationship alloc] init];
BOOL registered = [database registerExtension:relationship withName:@"relationship"];
XCTAssertTrue(registered, @"Error registering extension");
NSString *key1 = @"key1";
NSString *key2 = @"key2";
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:key1 forKey:key1 inCollection:nil];
[transaction setObject:key2 forKey:key2 inCollection:nil];
}];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Test creating an edge in a separate transaction from when the nodes are created
YapDatabaseRelationshipEdge *edge =
[YapDatabaseRelationshipEdge edgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted];
[[transaction ext:@"relationship"] addEdge:edge];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 1, @"Oops");
}];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Test deleting an edge without any processing rules
[[transaction ext:@"relationship"] removeEdgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
withProcessing:YDB_EdgeDeleted];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
}];
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
// The processing rules (YDB_EdgeDeleted),
// should * NOT * have resulted in the destination node being deleted.
id obj1 = [transaction objectForKey:key1 inCollection:nil];
XCTAssertNotNil(obj1, @"Relationship incorrectly deleted sourceNode");
id obj2 = [transaction objectForKey:key2 inCollection:nil];
XCTAssertNotNil(obj2, @"Relationship incorrectly deleted destinationNode");
}];
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Re-create the edge (with different nodeDeleteRules)
YapDatabaseRelationshipEdge *edge =
[YapDatabaseRelationshipEdge edgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
nodeDeleteRules:YDB_DeleteSourceIfDestinationDeleted];
[[transaction ext:@"relationship"] addEdge:edge];
}];
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// Test deleting an edge
[[transaction ext:@"relationship"] removeEdgeWithName:@"child"
sourceKey:key1
collection:nil
destinationKey:key2
collection:nil
withProcessing:YDB_DestinationNodeDeleted];
NSUInteger count;
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child"];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" sourceKey:key1 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
count = [[transaction ext:@"relationship"] edgeCountWithName:@"child" destinationKey:key2 collection:nil];
XCTAssertTrue(count == 0, @"Oops");
}];
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
// The edge's nodeDeleteRules (YDB_DeleteSourceIfDestinationDeleted),
// plus the processing rules (YDB_DestinationNodeDeleted),
// should have resulted in the source node being deleted.
id obj1 = [transaction objectForKey:key1 inCollection:nil];
XCTAssertNil(obj1, @"Relationship extension should have deleted sourceNode");
id obj2 = [transaction objectForKey:key2 inCollection:nil];
XCTAssertNotNil(obj2, @"Relationship extension improperly deleted destinationNode");
}];
}
@end