Skip to content

Instantly share code, notes, and snippets.

@kolyuchiy
Created February 3, 2016 08:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kolyuchiy/f0c6a4d087e8c0aff264 to your computer and use it in GitHub Desktop.
Save kolyuchiy/f0c6a4d087e8c0aff264 to your computer and use it in GitHub Desktop.
//
// ObjectsSnapshot.m
// MRMail
//
// Created by Nikolay Morev on 02/02/16.
// Copyright © 2016 Mail.Ru. All rights reserved.
//
#import "ObjectsSnapshot.h"
#include <stdio.h>
static NSString * captureStderrWithBlock(void (^block)(void));
static NSString * captureShowPools(void);
static NSString * _objectsSnapshot = nil;
static void * _ignoredPointers[1000] = { NULL };
NSString * MRObjectsSnapshotAndSave(void) {
_objectsSnapshot = captureShowPools();
return _objectsSnapshot;
}
NSString * MRObjectsSnapshotAndCompare(void) {
NSString *snapshot = captureShowPools();
NSArray *before = [_objectsSnapshot componentsSeparatedByString:@"\n"];
NSArray *after = [snapshot componentsSeparatedByString:@"\n"];
NSMutableSet *afterSet = [NSMutableSet setWithArray:after];
[afterSet minusSet:[NSSet setWithArray:before]];
__block BOOL (^predicateBlock)(NSString *, NSDictionary *);
predicateBlock = ^BOOL (NSString *string, NSDictionary *bindings) {
BOOL ignored = ([string containsString:@"releases pending"] ||
[string containsString:@"_XCTestCaseImplementation"] ||
[string containsString:[NSString stringWithFormat:@"%p", _objectsSnapshot]] ||
[string containsString:[NSString stringWithFormat:@"%p", predicateBlock]] ||
[string containsString:@"__NSMallocBlock__"]);
for (int i = 0; i < 1000; i++) {
void *p = _ignoredPointers[i];
if (p == NULL) {
break;
}
ignored = ignored || [string containsString:[NSString stringWithFormat:@"%p", p]];
}
return !ignored;
};
NSArray *diff = [[afterSet allObjects] filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:predicateBlock]];
_ignoredPointers[0] = NULL;
return [diff componentsJoinedByString:@"\n"];
}
static NSString * captureShowPools(void) {
void (^block)(void) = ^{
Class pool = NSClassFromString(@"NSAutoreleasePool");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[pool performSelector:NSSelectorFromString(@"showPools")];
#pragma clang diagnostic pop
};
_ignoredPointers[0] = (__bridge void *)block;
return captureStderrWithBlock(block);
}
static NSString * captureStderrWithBlock(void (^block)(void)) {
FILE *output;
NSString *filePath;
@autoreleasepool {
NSString *directory = NSTemporaryDirectory();
filePath = [directory stringByAppendingPathComponent:@"stdout.log"];
output = fopen([filePath fileSystemRepresentation], "w");
}
int fileno = STDERR_FILENO;
int saved_stdout;
saved_stdout = dup(fileno);
dup2(output->_file, fileno);
_ignoredPointers[1] = (__bridge void *)filePath;
_ignoredPointers[2] = (__bridge void *)block;
_ignoredPointers[3] = NULL;
block();
dup2(saved_stdout, fileno);
close(saved_stdout);
fclose(output);
NSData *data = [[NSData alloc] initWithContentsOfFile:filePath];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return string;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment