1781 lines
64 KiB
Objective-C
1781 lines
64 KiB
Objective-C
#import <XCTest/XCTest.h>
|
|
|
|
#import "YapDatabase.h"
|
|
#import "YapDatabaseAutoView.h"
|
|
#import "YapDatabaseFilteredView.h"
|
|
|
|
#import <CocoaLumberjack/CocoaLumberjack.h>
|
|
#import <CocoaLumberjack/DDTTYLogger.h>
|
|
|
|
@interface TestYapDatabaseFilteredView : XCTestCase
|
|
@end
|
|
|
|
@implementation TestYapDatabaseFilteredView
|
|
|
|
- (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)test_badInit
|
|
{
|
|
dispatch_block_t exceptionBlock = ^{
|
|
|
|
(void)[[YapDatabaseFilteredView alloc] init];
|
|
};
|
|
|
|
XCTAssertThrows(exceptionBlock(), @"Should have thrown an exception");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)test_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _test_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)test_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _test_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_test_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
NSString *order_initialVersionTag = @"1";
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:order_initialVersionTag
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSString *versionTag = [[transaction ext:@"order"] versionTag];
|
|
XCTAssert([versionTag isEqualToString:order_initialVersionTag], @"Bad versionTag");
|
|
}];
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
NSString *filter_initialVersionTag = @"1";
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering
|
|
versionTag:filter_initialVersionTag];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSString *versionTag = [[transaction ext:@"filter"] versionTag];
|
|
XCTAssert([versionTag isEqualToString:filter_initialVersionTag], @"Bad versionTag");
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){
|
|
|
|
XCTAssertNil([transaction ext:@"non-existent-view"], @"Expected nil");
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected view extension");
|
|
XCTAssertNotNil([transaction ext:@"filter"], @"Expected filteredView extension");
|
|
|
|
[transaction setObject:[NSNull null] forKey:@"keyX" inCollection:nil];
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"key%d", i];
|
|
|
|
[transaction setObject:@(i) forKey:key inCollection:nil];
|
|
}
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == 50, @"Bad count in filter. Expected 50, got %d", (int)filterCount);
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == 50, @"Bad count in filter. Expected 50, got %d", (int)filterCount);
|
|
}];
|
|
|
|
connection1 = nil;
|
|
connection2 = nil;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)test_skipInitialPopulationView_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
options.skipInitialViewPopulation = YES;
|
|
|
|
[self _testSkipInitialPopulationView_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)test_skipInitialPopulationView_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
options.skipInitialViewPopulation = YES;
|
|
|
|
[self _testSkipInitialPopulationView_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)test_notskipInitialPopulationView_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
options.skipInitialViewPopulation = NO;
|
|
|
|
[self _testSkipInitialPopulationView_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)test_notskipInitialPopulationView_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
options.skipInitialViewPopulation = NO;
|
|
|
|
[self _testSkipInitialPopulationView_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testSkipInitialPopulationView_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
NSString *order_initialVersionTag = @"1";
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:order_initialVersionTag
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSString *versionTag = [[transaction ext:@"order"] versionTag];
|
|
XCTAssert([versionTag isEqualToString:order_initialVersionTag], @"Bad versionTag");
|
|
}];
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
NSString *filter_initialVersionTag = @"1";
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering
|
|
versionTag:filter_initialVersionTag
|
|
options:options];
|
|
|
|
// Without registering the view,
|
|
// add a bunch of keys to the database.
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"key%d", i];
|
|
|
|
[transaction setObject:@(i) forKey:key inCollection:nil];
|
|
}
|
|
}];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
if (options.skipInitialViewPopulation) {
|
|
XCTAssertTrue(orderCount == 0, @"Bad count in view. Expected 0, got %d", (int)orderCount);
|
|
} else {
|
|
XCTAssertTrue(orderCount == 50, @"Bad count in view. Expected 0, got %d", (int)orderCount);
|
|
}
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
if (options.skipInitialViewPopulation) {
|
|
XCTAssertTrue(orderCount == 0, @"Bad count in view. Expected 0, got %d", (int)orderCount);
|
|
} else {
|
|
XCTAssertTrue(orderCount == 50, @"Bad count in view. Expected 0, got %d", (int)orderCount);
|
|
}
|
|
}];
|
|
|
|
connection1 = nil;
|
|
connection2 = nil;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testScratch_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testScratch_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testScratch_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testScratch_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testScratch_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected view extension");
|
|
XCTAssertNil([transaction ext:@"filter"], @"Expected filteredView extension");
|
|
|
|
[transaction setObject:[NSNull null] forKey:@"keyX" inCollection:nil];
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"key%d", i];
|
|
|
|
[transaction setObject:@(i) forKey:key inCollection:nil];
|
|
}
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
}];
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected view extension");
|
|
XCTAssertNotNil([transaction ext:@"filter"], @"Expected filteredView extension");
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == 50, @"Bad count in filter. Expected 50, got %d", (int)filterCount);
|
|
}];
|
|
|
|
connection1 = nil;
|
|
connection2 = nil;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testRepopulate_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testRepopulate_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testRepopulate_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testRepopulate_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testRepopulate_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering
|
|
versionTag:@"even"];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){
|
|
|
|
XCTAssertNil([transaction ext:@"non-existent-view"], @"Expected nil");
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected view extension");
|
|
XCTAssertNotNil([transaction ext:@"filter"], @"Expected filteredView extension");
|
|
|
|
[transaction setObject:[NSNull null] forKey:@"keyX" inCollection:nil];
|
|
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"key%d", i];
|
|
|
|
[transaction setObject:@(i) forKey:key inCollection:nil];
|
|
}
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == 50, @"Bad count in filter. Expected 50, got %d", (int)filterCount);
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == 50, @"Bad count in filter. Expected 50, got %d", (int)filterCount);
|
|
}];
|
|
|
|
//
|
|
// Now update the filterBlock
|
|
//
|
|
|
|
filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
int num = [(NSNumber *)object intValue];
|
|
|
|
if ((num % 2 == 0) || (num % 5 == 0))
|
|
return YES; // even OR divisable by 5
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction ext:@"filter"] setFiltering:filtering
|
|
versionTag:@"even+5"];
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == (50 + 10), @"Bad count in filter. Expected 60, got %d", (int)filterCount);
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
|
|
NSUInteger orderCount = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
NSUInteger filterCount = [[transaction ext:@"filter"] numberOfItemsInGroup:@""];
|
|
|
|
XCTAssertTrue(orderCount == 100, @"Bad count in view. Expected 100, got %d", (int)orderCount);
|
|
XCTAssertTrue(filterCount == (50 + 10), @"Bad count in filter. Expected 60, got %d", (int)filterCount);
|
|
}];
|
|
|
|
connection1 = nil;
|
|
connection2 = nil;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testUnregistration_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testUnregistration_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testUnregistration_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testUnregistration_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testUnregistration_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
// Make sure the extensions are visible
|
|
|
|
[connection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected YapDatabaseViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
}];
|
|
|
|
// Now unregister the view, and make sure it automatically unregisters the filteredView too.
|
|
|
|
[database unregisterExtensionWithName:@"order"];
|
|
|
|
[connection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNil([transaction ext:@"order"], @"Expected nil");
|
|
XCTAssertNil([transaction ext:@"filter"], @"Expected nil");
|
|
}];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testDoubleUnregistration_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testDoubleUnregistration_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testDoubleUnregistration_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testDoubleUnregistration_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testDoubleUnregistration_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView1 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering1];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView1 withName:@"filter1"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView1 extension");
|
|
|
|
YapDatabaseViewFiltering *filtering2 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] < 100)
|
|
return YES; // even && within range
|
|
else
|
|
return NO; // odd || out of range
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView2 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"filter1"
|
|
filtering:filtering2];
|
|
|
|
BOOL registerResult3 = [database registerExtension:filteredView2 withName:@"filter2"];
|
|
XCTAssertTrue(registerResult3, @"Failure registering filteredView2 extension");
|
|
|
|
// Make sure the extensions are visible
|
|
|
|
[connection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected YapDatabaseViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter1"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter2"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
}];
|
|
|
|
// Now unregister the view, and make sure it automatically unregisters both filteredViews too.
|
|
|
|
[database unregisterExtensionWithName:@"order"];
|
|
|
|
[connection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNil([transaction ext:@"order"], @"Expected nil");
|
|
XCTAssertNil([transaction ext:@"filter1"], @"Expected nil");
|
|
XCTAssertNil([transaction ext:@"filter2"], @"Expected nil");
|
|
}];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testDoubleDependencyPlusChangeFilterBlock_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testDoubleDependencyPlusChangeFilterBlock_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testDoubleDependencyPlusChangeFilterBlock_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testDoubleDependencyPlusChangeFilterBlock_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testDoubleDependencyPlusChangeFilterBlock_withPath:(NSString *)databasePath
|
|
options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView1 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering1
|
|
versionTag:@"1"];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView1 withName:@"filter1"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView1 extension");
|
|
|
|
YapDatabaseViewFiltering *filtering2 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] < 100)
|
|
return YES; // within range
|
|
else
|
|
return NO; // out of range
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView2 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"filter1"
|
|
filtering:filtering2
|
|
versionTag:@"1"];
|
|
|
|
BOOL registerResult3 = [database registerExtension:filteredView2 withName:@"filter2"];
|
|
XCTAssertTrue(registerResult3, @"Failure registering filteredView2 extension");
|
|
|
|
// Make sure the extensions are visible
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected YapDatabaseViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter1"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter2"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
}];
|
|
|
|
// Now add a bunch of numbers to the views
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
for (int i = 0; i < 200; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"%d", i];
|
|
NSNumber *number = @(i);
|
|
|
|
[transaction setObject:number forKey:key inCollection:nil];
|
|
}
|
|
}];
|
|
|
|
// Make sure the views are working correctly
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
}];
|
|
|
|
// Now update the filteringBlock, and make sure the dependent filteredView is also updated properly
|
|
|
|
filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return YES; // odd <<---- changed
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction ext:@"filter1"] setFiltering:filtering1 versionTag:@"2"];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
}];
|
|
|
|
// Now update the filteringBlock (again), and make sure the dependent filteredView is also updated properly
|
|
|
|
filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return NO; // even <<---- changed
|
|
else
|
|
return YES; // odd
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction ext:@"filter1"] setFiltering:filtering1 versionTag:@"3"];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
}];
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testDoubleDependencyPlusChangeGroupingBlock_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testDoubleDependencyPlusChangeGroupingBlock_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testDoubleDependencyPlusChangeGroupingBlock_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testDoubleDependencyPlusChangeGroupingBlock_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testDoubleDependencyPlusChangeGroupingBlock_withPath:(NSString *)databasePath
|
|
options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withObjectBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return @""; // even
|
|
else
|
|
return nil; // odd
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"1"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] < 100)
|
|
return YES; // within range
|
|
else
|
|
return NO; // out of range
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView1 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering1
|
|
versionTag:@"1"];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView1 withName:@"filter1"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView1 extension");
|
|
|
|
YapDatabaseViewFiltering *filtering2 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] < 50)
|
|
return YES; // within range
|
|
else
|
|
return NO; // out of range
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView2 =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"filter1"
|
|
filtering:filtering2
|
|
versionTag:@"1"];
|
|
|
|
BOOL registerResult3 = [database registerExtension:filteredView2 withName:@"filter2"];
|
|
XCTAssertTrue(registerResult3, @"Failure registering filteredView2 extension");
|
|
|
|
// Make sure the extensions are visible
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
XCTAssertNotNil([transaction ext:@"order"], @"Expected YapDatabaseViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter1"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
XCTAssertNotNil([transaction ext:@"filter2"], @"Expected YapDatabaseFilteredViewTransaction");
|
|
}];
|
|
|
|
// Now add a bunch of numbers to the views
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
for (int i = 0; i < 200; i++)
|
|
{
|
|
NSString *key = [NSString stringWithFormat:@"%d", i];
|
|
NSNumber *number = @(i);
|
|
|
|
[transaction setObject:number forKey:key inCollection:nil];
|
|
}
|
|
}];
|
|
|
|
// Make sure the views are working correctly
|
|
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 25, @"");
|
|
|
|
// [[transaction ext:@"filter1"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter1: key: %@", key);
|
|
// }];
|
|
//
|
|
// [[transaction ext:@"filter2"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter2: key: %@", key);
|
|
// }];
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 25, @"");
|
|
}];
|
|
|
|
// NSLog(@"===========================================================================================");
|
|
|
|
// Now update the groupingBlock, and make sure the dependent filteredView's are also updated properly
|
|
|
|
grouping = [YapDatabaseViewGrouping withObjectBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return @""; // even
|
|
else
|
|
return @""; // odd <<----- changed
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction ext:@"order"] setGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"2"];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
|
|
// [[transaction ext:@"filter1"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter1: key: %@", key);
|
|
// }];
|
|
//
|
|
// [[transaction ext:@"filter2"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter2: key: %@", key);
|
|
// }];
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 200, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
}];
|
|
|
|
// NSLog(@"===========================================================================================");
|
|
|
|
// Now update the groupingBlock (again), and make sure the dependent filteredView's are also updated properly
|
|
|
|
grouping = [YapDatabaseViewGrouping withObjectBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return nil; // even <<----- changed
|
|
else
|
|
return @""; // odd
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction ext:@"order"] setGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"3"];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 25, @"");
|
|
|
|
// [[transaction ext:@"filter1"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter1: key: %@", key);
|
|
// }];
|
|
//
|
|
// [[transaction ext:@"filter2"] enumerateKeysInGroup:@""
|
|
// usingBlock:^(NSString *collection, NSString *key, NSUInteger index, BOOL *stop)
|
|
// {
|
|
// NSLog(@"filter2: key: %@", key);
|
|
// }];
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"order"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 100, @"");
|
|
|
|
count = [[transaction ext:@"filter1"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 50, @"");
|
|
|
|
count = [[transaction ext:@"filter2"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 25, @"");
|
|
}];
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (void)testEmptyFilterMappings_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testEmptyFilterMappings_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testEmptyFilterMappings_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testEmptyFilterMappings_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testEmptyFilterMappings_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
YapDatabaseConnection *connection3 = [database newConnection];
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
if ([key isEqualToString:@"keyX"]) // Exclude keyX from view
|
|
return nil;
|
|
else
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"0"
|
|
options:options];
|
|
|
|
BOOL registerResult1 = [database registerExtension:view withName:@"order"];
|
|
XCTAssertTrue(registerResult1, @"Failure registering view extension");
|
|
|
|
YapDatabaseViewFiltering *filtering1 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"order"
|
|
filtering:filtering1
|
|
versionTag:@"0"];
|
|
|
|
BOOL registerResult2 = [database registerExtension:filteredView withName:@"filter"];
|
|
XCTAssertTrue(registerResult2, @"Failure registering filteredView extension");
|
|
|
|
|
|
YapDatabaseViewMappings *mappings =
|
|
[[YapDatabaseViewMappings alloc] initWithGroups:@[@""] view:@"filter"];
|
|
|
|
[connection1 beginLongLivedReadTransaction];
|
|
[connection1 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
[mappings updateWithTransaction:transaction];
|
|
}];
|
|
|
|
__block int notificationCount = 0;
|
|
id observer =
|
|
[[NSNotificationCenter defaultCenter] addObserverForName:YapDatabaseModifiedNotification
|
|
object:database
|
|
queue:[NSOperationQueue mainQueue]
|
|
usingBlock:^(NSNotification *note)
|
|
{
|
|
notificationCount++;
|
|
}];
|
|
|
|
NSTimeInterval timeout = 1.0; // Number of seconds before giving up
|
|
NSTimeInterval idle = 0.01; // Number of seconds to pause within loop
|
|
BOOL timedOut = NO;
|
|
NSDate *timeoutDate = nil;
|
|
|
|
// --- Flush NSNotification queue. There are pending notifications from the extension registrations.
|
|
|
|
timedOut = NO;
|
|
timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
|
|
while (!timedOut) {
|
|
NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:tick];
|
|
timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
|
|
}
|
|
|
|
// --- Try setting a regular filter
|
|
|
|
[connection3 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction extension:@"filter"] setFiltering:filtering1 versionTag:@"1"];
|
|
}];
|
|
|
|
notificationCount = 0;
|
|
|
|
timedOut = NO;
|
|
timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
|
|
while (!timedOut) {
|
|
NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:tick];
|
|
timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
|
|
}
|
|
|
|
XCTAssertEqual(notificationCount, 1, @"Expected notification (%d notifications)", notificationCount);
|
|
|
|
// --- Try setting an empty filter
|
|
|
|
YapDatabaseViewFiltering *filtering2 = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection, NSString *key, id object)
|
|
{
|
|
return NO;
|
|
}];
|
|
|
|
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction extension:@"filter"] setFiltering:filtering2
|
|
versionTag:@"2"];
|
|
}];
|
|
|
|
notificationCount = 0;
|
|
|
|
timedOut = NO;
|
|
timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
|
|
while (!timedOut) {
|
|
NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:tick];
|
|
timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
|
|
}
|
|
|
|
XCTAssertEqual(notificationCount, 1, @"Expected notification (%d notifications)", notificationCount);
|
|
|
|
// --- Try setting a regular filter
|
|
|
|
[connection3 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction extension:@"filter"] setFiltering:filtering1 versionTag:@"3"];
|
|
}];
|
|
|
|
notificationCount = 0;
|
|
|
|
timedOut = NO;
|
|
timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
|
|
while (!timedOut) {
|
|
NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:tick];
|
|
timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
|
|
}
|
|
|
|
XCTAssertEqual(notificationCount, 1, @"Expected notification (%d notifications)", notificationCount);
|
|
|
|
// --- Try setting an empty filter
|
|
|
|
[connection2 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[[transaction extension:@"filter"] setFiltering:filtering2
|
|
versionTag:@"emptytag"];
|
|
}];
|
|
|
|
notificationCount = 0;
|
|
|
|
timedOut = NO;
|
|
timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
|
|
while (!timedOut) {
|
|
NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
|
|
[[NSRunLoop currentRunLoop] runUntilDate:tick];
|
|
timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
|
|
}
|
|
|
|
XCTAssertEqual(notificationCount, 1, @"Expected notification (%d notifications)", notificationCount);
|
|
|
|
// ---
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:observer];
|
|
|
|
[database unregisterExtensionWithName:@"order"];
|
|
// The @"filter" extension will get automatically unregistered with order (b/c of dependency)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark -
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* https://github.com/yapstudios/YapDatabase/issues/186
|
|
**/
|
|
|
|
- (void)testIssue186_persistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = YES;
|
|
|
|
[self _testIssue186_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)testIssue186_nonPersistent
|
|
{
|
|
NSString *databasePath = [self databasePath:NSStringFromSelector(_cmd)];
|
|
|
|
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
|
options.isPersistent = NO;
|
|
|
|
[self _testIssue186_withPath:databasePath options:options];
|
|
}
|
|
|
|
- (void)_testIssue186_withPath:(NSString *)databasePath options:(YapDatabaseViewOptions *)options
|
|
{
|
|
BOOL registerResult;
|
|
|
|
[[NSFileManager defaultManager] removeItemAtPath:databasePath error:NULL];
|
|
YapDatabase *database = [[YapDatabase alloc] initWithPath:databasePath];
|
|
|
|
XCTAssertNotNil(database, @"Oops");
|
|
|
|
YapDatabaseConnection *connection1 = [database newConnection];
|
|
YapDatabaseConnection *connection2 = [database newConnection];
|
|
|
|
{ // Create "view-object"
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withObjectBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
NSParameterAssert(obj1 != nil);
|
|
NSParameterAssert(obj2 != nil);
|
|
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"0"
|
|
options:options];
|
|
|
|
registerResult = [database registerExtension:view withName:@"view-object"];
|
|
XCTAssertTrue(registerResult, @"Failure registering view extension");
|
|
}
|
|
|
|
{ // Create "view-metadata"
|
|
|
|
YapDatabaseViewGrouping *grouping = [YapDatabaseViewGrouping withKeyBlock:
|
|
^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key)
|
|
{
|
|
return @"";
|
|
}];
|
|
|
|
YapDatabaseViewSorting *sorting = [YapDatabaseViewSorting withMetadataBlock:
|
|
^(YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection1, NSString *key1, id obj1,
|
|
NSString *collection2, NSString *key2, id obj2)
|
|
{
|
|
NSParameterAssert(obj1 != nil);
|
|
NSParameterAssert(obj2 != nil);
|
|
|
|
__unsafe_unretained NSNumber *number1 = (NSNumber *)obj1;
|
|
__unsafe_unretained NSNumber *number2 = (NSNumber *)obj2;
|
|
|
|
return [number1 compare:number2];
|
|
}];
|
|
|
|
YapDatabaseAutoView *view =
|
|
[[YapDatabaseAutoView alloc] initWithGrouping:grouping
|
|
sorting:sorting
|
|
versionTag:@"0"
|
|
options:options];
|
|
|
|
registerResult = [database registerExtension:view withName:@"view-metadata"];
|
|
XCTAssertTrue(registerResult, @"Failure registering view extension");
|
|
}
|
|
|
|
{ // Create "filter-object-even"
|
|
|
|
YapDatabaseViewFiltering *filtering = [YapDatabaseViewFiltering withObjectBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection, NSString *key, id object)
|
|
{
|
|
NSParameterAssert(object != nil);
|
|
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)object;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return YES; // even
|
|
else
|
|
return NO; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *filteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"view-object"
|
|
filtering:filtering
|
|
versionTag:@"0"];
|
|
|
|
registerResult = [database registerExtension:filteredView withName:@"filter-object-even"];
|
|
XCTAssertTrue(registerResult, @"Failure registering filteredView extension");
|
|
}
|
|
|
|
{ // Create "filter-metadata-odd"
|
|
|
|
YapDatabaseViewFiltering *oddFiltering = [YapDatabaseViewFiltering withMetadataBlock:
|
|
^BOOL (YapDatabaseReadTransaction *transaction, NSString *group,
|
|
NSString *collection, NSString *key, id metadata)
|
|
{
|
|
NSParameterAssert(metadata != nil);
|
|
|
|
__unsafe_unretained NSNumber *number = (NSNumber *)metadata;
|
|
|
|
if ([number intValue] % 2 == 0)
|
|
return NO; // even
|
|
else
|
|
return YES; // odd
|
|
}];
|
|
|
|
YapDatabaseFilteredView *oddFilteredView =
|
|
[[YapDatabaseFilteredView alloc] initWithParentViewName:@"view-metadata"
|
|
filtering:oddFiltering
|
|
versionTag:@"0"];
|
|
|
|
registerResult = [database registerExtension:oddFilteredView withName:@"filter-metadata-odd"];
|
|
XCTAssertTrue(registerResult, @"Failure registering filteredView extension");
|
|
}
|
|
|
|
// Add a couple items
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[transaction setObject:@(0) forKey:@"even-even" inCollection:nil withMetadata:@(0)];
|
|
[transaction setObject:@(0) forKey:@"even-odd" inCollection:nil withMetadata:@(1)];
|
|
[transaction setObject:@(1) forKey:@"odd-even" inCollection:nil withMetadata:@(0)];
|
|
[transaction setObject:@(1) forKey:@"odd-odd" inCollection:nil withMetadata:@(1)];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"filter-object-even"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
|
|
count = [[transaction ext:@"filter-metadata-odd"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"filter-object-even"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
|
|
count = [[transaction ext:@"filter-metadata-odd"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
}];
|
|
|
|
[connection1 readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[transaction replaceObject:@(2) forKey:@"even-even" inCollection:nil];
|
|
[transaction replaceObject:@(2) forKey:@"even-odd" inCollection:nil];
|
|
[transaction replaceObject:@(3) forKey:@"odd-even" inCollection:nil];
|
|
[transaction replaceObject:@(3) forKey:@"odd-odd" inCollection:nil];
|
|
|
|
[transaction replaceMetadata:@(2) forKey:@"even-even" inCollection:nil];
|
|
[transaction replaceMetadata:@(3) forKey:@"even-odd" inCollection:nil];
|
|
[transaction replaceMetadata:@(2) forKey:@"odd-even" inCollection:nil];
|
|
[transaction replaceMetadata:@(3) forKey:@"odd-odd" inCollection:nil];
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"filter-object-even"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
|
|
count = [[transaction ext:@"filter-metadata-odd"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
}];
|
|
|
|
[connection2 readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
NSUInteger count;
|
|
|
|
count = [[transaction ext:@"filter-object-even"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
|
|
count = [[transaction ext:@"filter-metadata-odd"] numberOfItemsInGroup:@""];
|
|
XCTAssertTrue(count == 2, @"");
|
|
}];
|
|
}
|
|
|
|
@end
|