An amazing project that generates micro reports from tournament results
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.6 KiB

////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#import "RLMMultiProcessTestCase.h"
@interface RLMMultiProcessTestCase ()
@property (nonatomic) bool isParent;
@property (nonatomic, strong) NSString *testName;
@property (nonatomic, strong) NSString *xctestPath;
@property (nonatomic, strong) NSString *testsPath;
@end
@implementation RLMMultiProcessTestCase
// Override all of the methods for creating a XCTestCase object to capture the current test name
+ (id)testCaseWithInvocation:(NSInvocation *)invocation {
RLMMultiProcessTestCase *testCase = [super testCaseWithInvocation:invocation];
testCase.testName = NSStringFromSelector(invocation.selector);
return testCase;
}
- (id)initWithInvocation:(NSInvocation *)invocation {
self = [super initWithInvocation:invocation];
if (self) {
self.testName = NSStringFromSelector(invocation.selector);
}
return self;
}
+ (id)testCaseWithSelector:(SEL)selector {
RLMMultiProcessTestCase *testCase = [super testCaseWithSelector:selector];
testCase.testName = NSStringFromSelector(selector);
return testCase;
}
- (id)initWithSelector:(SEL)selector {
self = [super initWithSelector:selector];
if (self) {
self.testName = NSStringFromSelector(selector);
}
return self;
}
- (void)setUp {
self.isParent = !getenv("RLMProcessIsChild");
self.xctestPath = [self locateXCTest];
self.testsPath = [NSBundle bundleForClass:[self class]].bundlePath;
if (!self.isParent) {
// For multi-process tests, the child's concept of a default path needs to match the parent.
// RLMRealmConfiguration isn't aware of this, but our test's RLMDefaultRealmURL helper does.
// Use it to reset the default configuration's path so it matches the parent.
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
configuration.fileURL = RLMDefaultRealmURL();
[RLMRealmConfiguration setDefaultConfiguration:configuration];
}
[super setUp];
}
- (void)invokeTest {
CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, ^{
[super invokeTest];
CFRunLoopStop(CFRunLoopGetCurrent());
});
CFRunLoopRun();
}
- (void)deleteFiles {
// Only the parent should delete files in setUp/tearDown
if (self.isParent) {
[super deleteFiles];
}
}
+ (void)preintializeSchema {
// Do nothing so that we can test global schema init in child processes
}
- (NSString *)locateXCTest {
NSString *pathString = [NSProcessInfo processInfo].environment[@"PATH"];
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSString *directory in [pathString componentsSeparatedByString:@":"]) {
NSString *candidatePath = [directory stringByAppendingPathComponent:@"xctest"];
if ([fileManager isExecutableFileAtPath:candidatePath])
return candidatePath;
}
return nil;
}
#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
- (NSTask *)childTask {
NSString *testName = [NSString stringWithFormat:@"%@/%@", self.className, self.testName];
NSMutableDictionary *env = [NSProcessInfo.processInfo.environment mutableCopy];
env[@"RLMProcessIsChild"] = @"true";
env[@"RLMParentProcessBundleID"] = [NSBundle mainBundle].bundleIdentifier;
// Don't inherit the config file in the subprocess, as multiple XCTest
// processes talking to a single Xcode instance doesn't work at all
[env removeObjectForKey:@"XCTestConfigurationFilePath"];
NSTask *task = [[NSTask alloc] init];
task.launchPath = self.xctestPath;
task.arguments = @[@"-XCTest", testName, self.testsPath];
task.environment = env;
task.standardError = nil;
return task;
}
- (int)runChildAndWait {
NSPipe *pipe = [NSPipe pipe];
NSMutableData *buffer = [[NSMutableData alloc] init];
// Filter the output from the child process to reduce xctest noise
pipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle *file) {
[buffer appendData:[file availableData]];
const char *newline;
const char *start = buffer.bytes;
const char *end = start + buffer.length;
while ((newline = memchr(start, '\n', end - start))) {
if (newline < start + 17 ||
(memcmp(start, "Test Suite", 10) && memcmp(start, "Test Case", 9) && memcmp(start, " Executed 1 test", 17))) {
fwrite(start, newline - start + 1, 1, stderr);
}
start = newline + 1;
}
// Remove everything up to the last newline, leaving any data not newline-terminated in the buffer
[buffer replaceBytesInRange:NSMakeRange(0, start - (char *)buffer.bytes) withBytes:0 length:0];
};
NSTask *task = [self childTask];
task.standardError = pipe;
[task launch];
[task waitUntilExit];
return task.terminationStatus;
}
#else
- (NSTask *)childTask {
return nil;
}
- (int)runChildAndWait {
return 1;
}
#endif
@end