-
Notifications
You must be signed in to change notification settings - Fork 1
/
DPTestCase.m
79 lines (68 loc) · 2.73 KB
/
DPTestCase.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//
// ---------------------------------------
// < Copyright © 2019 Showmax. MIT License >
// ---------------------------------------
// \
// \
// \ >()_
// (__)__ _
#import "DPTestCase.h"
#import <objc/runtime.h>
@interface _DPSelectorWrapper ()
@property(nonatomic, assign) SEL selector;
@end
@implementation _DPSelectorWrapper
- (instancetype)initWithSelector:(SEL)selector {
self = [super init];
_selector = selector;
return self;
}
@end
@implementation _DPTestCase
+ (NSArray<NSInvocation *> *)testInvocations {
NSMutableArray<NSInvocation *> *invocations = [self prefixInvocations];
NSArray<_DPSelectorWrapper *> *wrappers = [self _dp_testMethodSelectors];
for (_DPSelectorWrapper *wrapper in wrappers) {
SEL selector = wrapper.selector;
NSMethodSignature *signature = [self instanceMethodSignatureForSelector: selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
[invocations addObject: invocation];
}
return invocations;
}
+ (NSMutableArray<NSInvocation *> *)prefixInvocations {
uint count;
Method * methods = class_copyMethodList(self, &count);
NSMutableArray<NSInvocation *> *invocations = [NSMutableArray array];
for (uint i = 0; i < count; i++) {
Method method = methods[i];
SEL selector = method_getName(method);
NSArray *nameParts = [[NSString stringWithCString: sel_getName(selector)
encoding: NSUTF8StringEncoding] componentsSeparatedByString: @"_"];
if (nameParts.count < 2) { continue; }
IMP imp = method_getImplementation(method);
void (*callableImp)(id) = (void (*)(id))imp;
id newImpBlock = [self _impForMethodWithPrefix: nameParts[0]
currentImpl: ^(XCTestCase *test){ callableImp(test); }];
if (!newImpBlock) { continue; }
IMP newImp = imp_implementationWithBlock(newImpBlock);
method_setImplementation(method, newImp);
NSMethodSignature *signature = [self instanceMethodSignatureForSelector: selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
[invocations addObject: invocation];
}
free(methods);
return invocations;
}
+ (void (^)(XCTestCase *))_impForMethodWithPrefix:(NSString *)prefix currentImpl:(void (^)(XCTestCase *))imp {
if ([prefix isEqualToString: @"test"]) {
return imp;
}
return NULL;
}
+ (NSArray<_DPSelectorWrapper *> *)_dp_testMethodSelectors {
return @[];
}
@end