RLMTestCase.m 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2014 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "RLMTestCase.h"
  19. #import "RLMRealmConfiguration_Private.h"
  20. #import <Realm/RLMRealm_Private.h>
  21. #import <Realm/RLMSchema_Private.h>
  22. #import <Realm/RLMRealmConfiguration_Private.h>
  23. static NSString *parentProcessBundleIdentifier()
  24. {
  25. static BOOL hasInitializedIdentifier;
  26. static NSString *identifier;
  27. if (!hasInitializedIdentifier) {
  28. identifier = [NSProcessInfo processInfo].environment[@"RLMParentProcessBundleID"];
  29. hasInitializedIdentifier = YES;
  30. }
  31. return identifier;
  32. }
  33. NSURL *RLMDefaultRealmURL() {
  34. return [NSURL fileURLWithPath:RLMRealmPathForFileAndBundleIdentifier(@"default.realm", parentProcessBundleIdentifier())];
  35. }
  36. NSURL *RLMTestRealmURL() {
  37. return [NSURL fileURLWithPath:RLMRealmPathForFileAndBundleIdentifier(@"test.realm", parentProcessBundleIdentifier())];
  38. }
  39. static void deleteOrThrow(NSURL *fileURL) {
  40. NSError *error;
  41. if (![[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error]) {
  42. if (error.code != NSFileNoSuchFileError) {
  43. @throw [NSException exceptionWithName:@"RLMTestException"
  44. reason:[@"Unable to delete realm: " stringByAppendingString:error.description]
  45. userInfo:nil];
  46. }
  47. }
  48. }
  49. NSData *RLMGenerateKey() {
  50. uint8_t buffer[64];
  51. (void)SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
  52. return [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
  53. }
  54. static BOOL encryptTests() {
  55. static BOOL encryptAll = NO;
  56. static dispatch_once_t onceToken;
  57. dispatch_once(&onceToken, ^{
  58. if (getenv("REALM_ENCRYPT_ALL")) {
  59. encryptAll = YES;
  60. }
  61. });
  62. return encryptAll;
  63. }
  64. @implementation RLMTestCase {
  65. dispatch_queue_t _bgQueue;
  66. }
  67. + (void)setUp {
  68. [super setUp];
  69. #if DEBUG || !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
  70. // Disable actually syncing anything to the disk to greatly speed up the
  71. // tests, but only when not running on device because it can't be
  72. // re-enabled and we need it enabled for performance tests
  73. RLMDisableSyncToDisk();
  74. #endif
  75. if (!getenv("RLMProcessIsChild")) {
  76. [self preinitializeSchema];
  77. // Clean up any potentially lingering Realm files from previous runs
  78. [NSFileManager.defaultManager removeItemAtPath:RLMRealmPathForFile(@"") error:nil];
  79. }
  80. // Ensure the documents directory exists as it sometimes doesn't after
  81. // resetting the simulator
  82. [NSFileManager.defaultManager createDirectoryAtURL:RLMDefaultRealmURL().URLByDeletingLastPathComponent
  83. withIntermediateDirectories:YES attributes:nil error:nil];
  84. }
  85. // This ensures the shared schema is initialized outside of of a test case,
  86. // so if an exception is thrown, it will kill the test process rather than
  87. // allowing hundreds of test cases to fail in strange ways
  88. // This is overridden by RLMMultiProcessTestCase to support testing the schema init
  89. + (void)preinitializeSchema {
  90. [RLMSchema sharedSchema];
  91. }
  92. - (void)deleteFiles {
  93. // Clear cache
  94. [self resetRealmState];
  95. // Delete Realm files
  96. [self deleteRealmFileAtURL:RLMDefaultRealmURL()];
  97. [self deleteRealmFileAtURL:RLMTestRealmURL()];
  98. }
  99. - (void)resetRealmState {
  100. [RLMRealm resetRealmState];
  101. }
  102. - (void)deleteRealmFileAtURL:(NSURL *)fileURL
  103. {
  104. deleteOrThrow(fileURL);
  105. deleteOrThrow([fileURL URLByAppendingPathExtension:@"lock"]);
  106. deleteOrThrow([fileURL URLByAppendingPathExtension:@"note"]);
  107. }
  108. - (void)invokeTest {
  109. @autoreleasepool {
  110. [self deleteFiles];
  111. if (encryptTests()) {
  112. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  113. configuration.encryptionKey = RLMGenerateKey();
  114. }
  115. }
  116. @autoreleasepool {
  117. [super invokeTest];
  118. }
  119. @autoreleasepool {
  120. if (_bgQueue) {
  121. dispatch_sync(_bgQueue, ^{});
  122. _bgQueue = nil;
  123. }
  124. [self deleteFiles];
  125. }
  126. }
  127. - (RLMRealm *)realmWithTestPath
  128. {
  129. return [RLMRealm realmWithURL:RLMTestRealmURL()];
  130. }
  131. - (RLMRealm *)realmWithTestPathAndSchema:(RLMSchema *)schema {
  132. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  133. configuration.fileURL = RLMTestRealmURL();
  134. if (schema)
  135. configuration.customSchema = schema;
  136. else
  137. configuration.dynamic = true;
  138. return [RLMRealm realmWithConfiguration:configuration error:nil];
  139. }
  140. - (RLMRealm *)inMemoryRealmWithIdentifier:(NSString *)identifier {
  141. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  142. configuration.inMemoryIdentifier = identifier;
  143. return [RLMRealm realmWithConfiguration:configuration error:nil];
  144. }
  145. - (RLMRealm *)readOnlyRealmWithURL:(NSURL *)fileURL error:(NSError **)error {
  146. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  147. configuration.fileURL = fileURL;
  148. configuration.readOnly = true;
  149. return [RLMRealm realmWithConfiguration:configuration error:error];
  150. }
  151. - (void)waitForNotification:(NSString *)expectedNote realm:(RLMRealm *)realm block:(dispatch_block_t)block {
  152. XCTestExpectation *notificationFired = [self expectationWithDescription:@"notification fired"];
  153. __block RLMNotificationToken *token = [realm addNotificationBlock:^(NSString *note, RLMRealm *realm) {
  154. XCTAssertNotNil(note, @"Note should not be nil");
  155. XCTAssertNotNil(realm, @"Realm should not be nil");
  156. if (note == expectedNote) { // Check pointer equality to ensure we're using the interned string constant
  157. [notificationFired fulfill];
  158. [token invalidate];
  159. }
  160. }];
  161. dispatch_queue_t queue = dispatch_queue_create("background", 0);
  162. dispatch_async(queue, ^{
  163. @autoreleasepool {
  164. block();
  165. }
  166. });
  167. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  168. // wait for queue to finish
  169. dispatch_sync(queue, ^{});
  170. }
  171. - (void)dispatchAsync:(dispatch_block_t)block {
  172. if (!_bgQueue) {
  173. _bgQueue = dispatch_queue_create("test background queue", 0);
  174. }
  175. dispatch_async(_bgQueue, ^{
  176. @autoreleasepool {
  177. block();
  178. }
  179. });
  180. }
  181. - (void)dispatchAsyncAndWait:(dispatch_block_t)block {
  182. [self dispatchAsync:block];
  183. dispatch_sync(_bgQueue, ^{});
  184. }
  185. - (id)nonLiteralNil
  186. {
  187. return nil;
  188. }
  189. @end