Skip to content

Commit

Permalink
针对没有签名信息的block的单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
SilverFruity committed Mar 8, 2021
1 parent a16eb93 commit 32b9818
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 69 deletions.
5 changes: 2 additions & 3 deletions OCRunner/ORCoreImp/ORCoreImp.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){
//针对系统传入的block,检查一次签名,如果没有,将在结构体中添加签名信息.
if (argValue.isObject && argValue.isBlockValue && NSBlockHasSignature(argValue.objectValue) == NO) {
ORTypeVarPair *blockdecl = methodImp.declare.parameterTypes[i - 2];
ORFuncVariable *blockSig = (ORFuncVariable *)blockdecl.var;
if ([blockSig isKindOfClass:[ORFuncVariable class]]) {
if ([blockdecl.var isKindOfClass:[ORFuncVariable class]]) {
NSBlockSetSignature(argValue.objectValue, blockdecl.blockSignature);
}
}
Expand Down Expand Up @@ -59,7 +58,7 @@ void methodIMP(ffi_cif *cfi,void *ret,void **args, void*userdata){
void blockInter(ffi_cif *cfi,void *ret,void **args, void*userdata){
struct MFSimulateBlock *block = *(void **)args[0];
MFBlock *mangoBlock = (__bridge MFBlock *)(block->wrapper);
NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:[MFBlock typeEncodingForBlock:mangoBlock.ocBlock]];
NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:NSBlockGetSignature(mangoBlock.ocBlock)];
NSMutableArray<MFValue *> *argValues = [NSMutableArray array];
for (NSUInteger i = 1; i < cfi->nargs; i++) {
MFValue *argValue = [[MFValue alloc] initTypeEncode:[sig getArgumentTypeAtIndex:i] pointer:args[i]];
Expand Down
8 changes: 4 additions & 4 deletions OCRunner/RunEnv/MFBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ struct MFGOSimulateBlockDescriptor {
const char *signature;
};
};
const char *NSBlockGetSignature(id block);
BOOL NSBlockHasSignature(id block);
void NSBlockSetSignature(id block, const char *typeencode);
void *simulateNSBlock(const char* typeEncoding, void *imp, void *userdata);

@class ORTypeVarPair;
@interface MFBlock : NSObject
Expand All @@ -59,9 +63,5 @@ struct MFGOSimulateBlockDescriptor {
@property (strong, nonatomic) ORFunctionImp *func;
@property (strong, nonatomic) NSMutableArray <ORTypeVarPair *>*paramTypes;
@property (strong, nonatomic) ORTypeVarPair *retType;

- (id)ocBlock;
+ (const char *)typeEncodingForBlock:(id)block;
@end
BOOL NSBlockHasSignature(id block);
void NSBlockSetSignature(id block, const char *typeencode);
126 changes: 72 additions & 54 deletions OCRunner/RunEnv/MFBlock.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,49 @@
void copy_helper(struct MFSimulateBlock *dst, struct MFSimulateBlock *src)
{
// do not copy anything is this funcion! just retain if need.
CFRetain(dst->wrapper);
if (dst->wrapper) {
CFRetain(dst->wrapper);
}
}

void dispose_helper(struct MFSimulateBlock *src)
{
free((void *)src->descriptor->signature);
CFRelease(src->wrapper);
if (src->descriptor->signature) {
free((void *)src->descriptor->signature);
}
if (src->descriptor) {
free(src->descriptor);
}
if (src->wrapper) {
CFRelease(src->wrapper);
}
}


@implementation MFBlock{
BOOL _generatedPtr;
void *_blockPtr;
or_ffi_result *_ffi_result;
struct MFGOSimulateBlockDescriptor *_descriptor;
void *simulateNSBlock(const char* typeEncoding, void *imp, void *userdata){
struct MFGOSimulateBlockDescriptor descriptor = {
0,
sizeof(struct MFSimulateBlock),
(void (*)(void *dst, const void *src))copy_helper,
(void (*)(const void *src))dispose_helper,
typeEncoding
};
struct MFGOSimulateBlockDescriptor *_descriptor = malloc(sizeof(struct MFGOSimulateBlockDescriptor));
memcpy(_descriptor, &descriptor, sizeof(struct MFGOSimulateBlockDescriptor));
struct MFSimulateBlock simulateBlock = {
&_NSConcreteStackBlock,
(BLOCK_HAS_COPY_DISPOSE | BLOCK_CREATED_FROM_MFGO),
0,
imp,
_descriptor,
userdata
};
if (typeEncoding != NULL) {
simulateBlock.flags |= BLOCK_HAS_SIGNATURE;
}
return Block_copy(&simulateBlock);
}

+ (const char *)typeEncodingForBlock:(id)block{
const char *NSBlockGetSignature(id block){
struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block;
int flags = blockRef->flags;

if (flags & BLOCK_HAS_SIGNATURE) {
void *signatureLocation = blockRef->descriptor;
signatureLocation += sizeof(unsigned long int);
Expand All @@ -52,7 +74,39 @@ + (const char *)typeEncodingForBlock:(id)block{
}
return NULL;
}
BOOL NSBlockHasSignature(id block){
struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block;
int flags = blockRef->flags;
return flags & BLOCK_HAS_SIGNATURE;
}
void NSBlockSetSignature(id block, const char *typeencode){
struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block;
void *signatureLocation = blockRef->descriptor;
signatureLocation += sizeof(unsigned long int);
signatureLocation += sizeof(unsigned long int);
int flags = blockRef->flags;
if (flags & BLOCK_HAS_COPY_DISPOSE) {
signatureLocation += sizeof(void(*)(void *dst, void *src));
signatureLocation += sizeof(void (*)(void *src));
}
char *copied = strdup(typeencode);
*(char **)signatureLocation = copied;
blockRef->flags |= BLOCK_HAS_SIGNATURE;
}

@implementation MFBlock{
void *_blockPtr;
or_ffi_result *_ffi_result;
}
- (instancetype)init
{
self = [super init];
if (self) {
_blockPtr = NULL;
_ffi_result = NULL;
}
return self;
}
- (id)ocBlock{
return [self blockPtr];
}
Expand All @@ -62,60 +116,24 @@ - (void)setParamTypes:(NSMutableArray<ORTypeVarPair *> *)paramTypes{
_paramTypes = types;
}
- (void *)blockPtr{
if (_generatedPtr) {
if (_blockPtr != NULL) {
return _blockPtr;
}
const char *typeEncoding = self.retType.typeEncode;
for (ORTypeVarPair *param in self.paramTypes) {
const char *paramTypeEncoding = param.typeEncode;
typeEncoding = mf_str_append(typeEncoding, paramTypeEncoding);
}
_generatedPtr = YES;
struct MFGOSimulateBlockDescriptor descriptor = {
0,
sizeof(struct MFSimulateBlock),
(void (*)(void *dst, const void *src))copy_helper,
(void (*)(const void *src))dispose_helper,
typeEncoding
};
_ffi_result = register_function(&blockInter, self.paramTypes, self.retType);
_descriptor = malloc(sizeof(struct MFGOSimulateBlockDescriptor));
memcpy(_descriptor, &descriptor, sizeof(struct MFGOSimulateBlockDescriptor));
struct MFSimulateBlock simulateBlock = {
&_NSConcreteStackBlock,
(BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_SIGNATURE | BLOCK_CREATED_FROM_MFGO),
0,
_ffi_result->function_imp,
_descriptor,
(__bridge void*)self
};
_blockPtr = Block_copy(&simulateBlock);
_blockPtr = simulateNSBlock(typeEncoding, _ffi_result->function_imp, (__bridge void *)self);
return _blockPtr;
}

-(void)dealloc{
free(_descriptor);
or_ffi_result_free(_ffi_result);
if (_ffi_result != NULL) {
or_ffi_result_free(_ffi_result);
}
return;
}

@end
BOOL NSBlockHasSignature(id block){
struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block;
int flags = blockRef->flags;
return flags & BLOCK_HAS_SIGNATURE;
}
void NSBlockSetSignature(id block, const char *typeencode){
struct MFSimulateBlock *blockRef = (__bridge struct MFSimulateBlock *)block;
void *signatureLocation = blockRef->descriptor;
signatureLocation += sizeof(unsigned long int);
signatureLocation += sizeof(unsigned long int);
int flags = blockRef->flags;
if (flags & BLOCK_HAS_COPY_DISPOSE) {
signatureLocation += sizeof(void(*)(void *dst, void *src));
signatureLocation += sizeof(void (*)(void *src));
}
char *copied = strdup(typeencode);
*(char **)signatureLocation = copied;
blockRef->flags |= BLOCK_HAS_SIGNATURE;
}
2 changes: 1 addition & 1 deletion OCRunner/RunnerClasses+Execute.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void ORDebugFrameStackPop(void){
#endif

static MFValue * invoke_MFBlockValue(MFValue *blockValue, NSArray *args){
const char *blockTypeEncoding = [MFBlock typeEncodingForBlock:blockValue.objectValue];
const char *blockTypeEncoding = NSBlockGetSignature(blockValue.objectValue);
NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:blockTypeEncoding];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setTarget:blockValue.objectValue];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
codeCoverageEnabled = "YES">
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "EE98996A24658DA600ACF2C1"
BlueprintIdentifier = "28290063C01D00B7961A2F43D82294F6"
BuildableName = "OCRunner.framework"
BlueprintName = "OCRunner"
ReferencedContainer = "container:../OCRunner.xcodeproj">
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
<Testables>
Expand Down
20 changes: 18 additions & 2 deletions OCRunnerTests/ORTestWithObjc.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#import "ORRecoverClass.h"
#import <objc/message.h>
#import "ORWeakPropertyAndIvar.h"
#import "ORTestReplaceClass.h"
@interface ORTestWithObjc : XCTestCase
@property (nonatomic, strong)MFScopeChain *currentScope;
@property (nonatomic, strong)MFScopeChain *topScope;
Expand Down Expand Up @@ -622,8 +623,23 @@ - (void)testArgumentWithTypeDefBlock{
MFValue *h = [[MFScopeChain topScope] recursiveGetValueWithIdentifier:@"result"];
XCTAssert([h.objectValue isEqual:@"123321"]);
}


int signatureBlockPtr(id object, int b){
return b * 2;
}
- (void)testNoSignatureBlock{
NSString *source = @"\
@implementation ORTestReplaceClass\
- (int)testNoSignatureBlock:(int(^)(int))arg{\
return arg(10);\
}\
@end\
";
AST *ast = [OCParser parseSource:source];
[ORInterpreter excuteNodes:ast.nodes];
id block = (__bridge id)simulateNSBlock(NULL, &signatureBlockPtr, NULL);
int result = [[ORTestReplaceClass new] testNoSignatureBlock: block];
XCTAssert(result == 20);
}
- (void)testOCRecursiveFunctionPerformanceExample {
[self measureBlock:^{
fibonaccia(20);
Expand Down
1 change: 1 addition & 0 deletions OCRunnerTests/TestClass/ORTestReplaceClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSInteger)testOriginalMethod;
- (NSInteger)testAddGlobalVar;
- (NSDictionary *(^)(void))testMethodParameterListAndReturnValueWithString:(NSString *)str block:(NSString *(^)(NSString *))block;
- (int)testNoSignatureBlock:(int(^)(int))arg;
@end

NS_ASSUME_NONNULL_END
4 changes: 3 additions & 1 deletion OCRunnerTests/TestClass/ORTestReplaceClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ - (NSInteger)testAddGlobalVar{
- (NSDictionary* (^)(void))testMethodParameterListAndReturnValueWithString:(NSString *)str block:(NSString *(^)(NSString *))block{
return nil;
}

- (int)testNoSignatureBlock:(int(^)(int))arg{
return 0;
}
@end

0 comments on commit 32b9818

Please sign in to comment.