// // RKManagedObjectThreadSafeInvocationTest.h // RestKit // // Created by Blake Watters on 5/12/11. // Copyright (c) 2009-2012 RestKit. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #import "RKTestEnvironment.h" #import "RKHuman.h" #import "RKManagedObjectThreadSafeInvocation.h" @interface RKManagedObjectThreadSafeInvocation (Private) - (void)serializeManagedObjectsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths; - (void)deserializeManagedObjectIDsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths; @end @interface RKManagedObjectThreadSafeInvocationTest : RKTestCase { NSMutableDictionary *_dictionary; RKManagedObjectStore *_objectStore; id _results; BOOL _waiting; } @end @implementation RKManagedObjectThreadSafeInvocationTest - (void)testShouldSerializeOneManagedObjectToManagedObjectID { RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.managedObjectStore = managedObjectStore; RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:human forKey:@"human"]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"human"]]; assertThat([dictionary valueForKeyPath:@"human"], is(instanceOf([NSManagedObjectID class]))); } - (void)testShouldSerializeOneManagedObjectWithKeyPathToManagedObjectID { NSString *testKey = @"data.human"; RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.managedObjectStore = managedObjectStore; RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:human forKey:testKey]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:testKey]]; assertThat([dictionary valueForKeyPath:testKey], is(instanceOf([NSManagedObjectID class]))); } - (void)testShouldSerializeCollectionOfManagedObjectsToManagedObjectIDs { RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.managedObjectStore = managedObjectStore; RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; NSArray *humans = [NSArray arrayWithObjects:human1, human2, nil]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:humans forKey:@"humans"]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"humans"]]; assertThat([dictionary valueForKeyPath:@"humans"], is(instanceOf([NSArray class]))); assertThat([[dictionary valueForKeyPath:@"humans"] lastObject], is(instanceOf([NSManagedObjectID class]))); } - (void)testShouldDeserializeOneManagedObjectIDToManagedObject { RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.managedObjectStore = managedObjectStore; RKHuman* human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:[human objectID] forKey:@"human"]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [managedObjectContext performBlockAndWait:^{ managedObjectContext.parentContext = managedObjectStore.primaryManagedObjectContext; }]; RKManagedObjectThreadSafeInvocation* invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; invocation.privateQueueManagedObjectContext = managedObjectContext; invocation.mainQueueManagedObjectContext = managedObjectStore.mainQueueManagedObjectContext; [invocation deserializeManagedObjectIDsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"human"]]; assertThat([dictionary valueForKeyPath:@"human"], is(instanceOf([NSManagedObject class]))); assertThat([[dictionary valueForKeyPath:@"human"] objectID], is(equalTo([human objectID]))); } - (void)testShouldDeserializeCollectionOfManagedObjectIDToManagedObjects { RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.managedObjectStore = managedObjectStore; RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]; NSArray *humanIDs = [NSArray arrayWithObjects:[human1 objectID], [human2 objectID], nil]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:humanIDs forKey:@"humans"]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; invocation.privateQueueManagedObjectContext = managedObjectStore.primaryManagedObjectContext; invocation.mainQueueManagedObjectContext = managedObjectStore.mainQueueManagedObjectContext; [invocation deserializeManagedObjectIDsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"humans"]]; assertThat([dictionary valueForKeyPath:@"humans"], is(instanceOf([NSArray class]))); NSArray *humans = [NSArray arrayWithObjects:human1, human2, nil]; assertThat([dictionary valueForKeyPath:@"humans.objectID"], is(equalTo([humans valueForKey:@"objectID"]))); } - (void)informDelegateWithDictionary:(NSDictionary *)results { assertThatBool([NSThread isMainThread], equalToBool(YES)); assertThat(results, isNot(nilValue())); assertThat(results, isNot(empty())); assertThat([[results objectForKey:@"humans"] lastObject], is(instanceOf([NSManagedObject class]))); _waiting = NO; } - (void)createBackgroundObjects { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; assertThatBool([NSThread isMainThread], equalToBool(NO)); // Assert this is not the main thread // Create a new array of objects in the background RKObjectManager *objectManager = [RKTestFactory objectManager]; RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; objectManager.managedObjectStore = managedObjectStore; NSArray *humans = [NSArray arrayWithObject:[NSEntityDescription entityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.primaryManagedObjectContext]]; _dictionary = [[NSMutableDictionary dictionaryWithObject:humans forKey:@"humans"] retain]; NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; invocation.privateQueueManagedObjectContext = _objectStore.primaryManagedObjectContext; invocation.mainQueueManagedObjectContext = _objectStore.mainQueueManagedObjectContext; [invocation retain]; [invocation setTarget:self]; [invocation setSelector:@selector(informDelegateWithDictionary:)]; [invocation setArgument:&_dictionary atIndex:2]; // NOTE: _cmd and self are 0 and 1 [invocation setManagedObjectKeyPaths:[NSSet setWithObject:@"humans"] forArgument:2]; [invocation invokeOnMainThread]; [pool drain]; } @end