Commit f564901c authored by Guillaume BIENKOWSKI's avatar Guillaume BIENKOWSKI

Add media streamer unit tests for Xcode, this allows to launch it from the command line

parent fb9bda89
//
// DTObjectBlockExecutor.h
// DTFoundation
//
// Created by Oliver Drobnik on 12.02.13.
// Copyright (c) 2013 Cocoanetics. All rights reserved.
//
/**
This class is used by [NSObject addDeallocBlock:] to execute blocks on dealloc
*/
#import <Foundation/Foundation.h>
@interface DTObjectBlockExecutor : NSObject
/**
Convenience method to create a block executor with a deallocation block
@param block The block to execute when the created receiver is being deallocated
*/
+ (id)blockExecutorWithDeallocBlock:(void(^)())block;
/**
Block to execute when dealloc of the receiver is called
*/
@property (nonatomic, copy) void (^deallocBlock)();
@end
//
// DTObjectBlockExecutor.m
// DTFoundation
//
// Created by Oliver Drobnik on 12.02.13.
// Copyright (c) 2013 Cocoanetics. All rights reserved.
//
#import "DTObjectBlockExecutor.h"
@implementation DTObjectBlockExecutor
+ (id)blockExecutorWithDeallocBlock:(void(^)())block
{
DTObjectBlockExecutor *executor = [[DTObjectBlockExecutor alloc] init];
executor.deallocBlock = block; // copy
return executor;
}
- (void)dealloc
{
if (_deallocBlock)
{
_deallocBlock();
_deallocBlock = nil;
}
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.belledonne-communications.tester.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
//
// NSObject+DTRuntime.h
// DTFoundation
//
// Created by Oliver Drobnik on 4/25/12.
// Copyright (c) 2012 Cocoanetics. All rights reserved.
//
/**
Methods to dynamically modify objects at runtime
*/
@interface NSObject (DTRuntime)
/**-------------------------------------------------------------------------------------
@name Blocks
---------------------------------------------------------------------------------------
*/
/**
Adds a block to be executed as soon as the receiver's memory is deallocated
@param block The block to execute when the receiver is being deallocated
*/
- (void)addDeallocBlock:(void(^)())block;
/**
Adds a new instance method to a class. All instances of this class will have this method.
The block captures `self` in the calling context. To allow access to the instance from within the block it is passed as parameter to the block.
@param selectorName The name of the method.
@param block The block to execute for the instance method, a pointer to the instance is passed as the only parameter.
@returns `YES` if the operation was successful
*/
+ (BOOL)addInstanceMethodWithSelectorName:(NSString *)selectorName block:(void(^)(id))block;
/**-------------------------------------------------------------------------------------
@name Method Swizzling
---------------------------------------------------------------------------------------
*/
/**
Exchanges two method implementations. After the call methods to the first selector will now go to the second one and vice versa.
@param selector The first method
@param otherSelector The second method
*/
+ (void)swizzleMethod:(SEL)selector withMethod:(SEL)otherSelector;
/**
Exchanges two class method implementations. After the call methods to the first selector will now go to the second one and vice versa.
@param selector The first method
@param otherSelector The second method
*/
+ (void)swizzleClassMethod:(SEL)selector withMethod:(SEL)otherSelector;
@end
//
// NSObject_DTRuntime.h
// DTFoundation
//
// Created by Oliver Drobnik on 4/25/12.
// Copyright (c) 2012 Cocoanetics. All rights reserved.
//
#import <objc/runtime.h>
#import "DTObjectBlockExecutor.h"
@implementation NSObject (DTRuntime)
static char DTRuntimeDeallocBlocks;
#pragma mark - Blocks
- (void)addDeallocBlock:(void(^)())block
{
// don't accept NULL block
NSParameterAssert(block);
NSMutableArray *deallocBlocks = objc_getAssociatedObject(self, &DTRuntimeDeallocBlocks);
// add array of dealloc blocks if not existing yet
if (!deallocBlocks)
{
deallocBlocks = [[NSMutableArray alloc] init];
objc_setAssociatedObject(self, &DTRuntimeDeallocBlocks, deallocBlocks, OBJC_ASSOCIATION_RETAIN);
}
DTObjectBlockExecutor *executor = [DTObjectBlockExecutor blockExecutorWithDeallocBlock:block];
[deallocBlocks addObject:executor];
}
+ (BOOL)addInstanceMethodWithSelectorName:(NSString *)selectorName block:(void(^)(id))block
{
// don't accept nil name
NSParameterAssert(selectorName);
// don't accept NULL block
NSParameterAssert(block);
// See http://stackoverflow.com/questions/6357663/casting-a-block-to-a-void-for-dynamic-class-method-resolution
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_7
void *impBlockForIMP = (void *)objc_unretainedPointer(block);
#else
id impBlockForIMP = (__bridge id)objc_unretainedPointer(block);
#endif
IMP myIMP = imp_implementationWithBlock(impBlockForIMP);
SEL selector = NSSelectorFromString(selectorName);
return class_addMethod(self, selector, myIMP, "v@:");
}
#pragma mark - Method Swizzling
+ (void)swizzleMethod:(SEL)selector withMethod:(SEL)otherSelector
{
// my own class is being targetted
Class c = [self class];
// get the methods from the selectors
Method originalMethod = class_getInstanceMethod(c, selector);
Method otherMethod = class_getInstanceMethod(c, otherSelector);
if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod)))
{
class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
method_exchangeImplementations(originalMethod, otherMethod);
}
}
+ (void)swizzleClassMethod:(SEL)selector withMethod:(SEL)otherSelector
{
// my own class is being targetted
Class c = [self class];
// get the methods from the selectors
Method originalMethod = class_getClassMethod(c, selector);
Method otherMethod = class_getClassMethod(c, otherSelector);
// if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod)))
// {
// class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
// }
// else
// {
method_exchangeImplementations(originalMethod, otherMethod);
// }
}
@end
//
// mediastream_tester_Tests.m
// mediastream-tester Tests
//
// Created by guillaume on 21/11/2014.
//
//
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "NSObject+DTRuntime.h"
#include "mediastreamer2_tester.h"
@interface mediastream_tester_Tests : XCTestCase
@property (nonatomic,retain) NSString* bundlePath;
@property (nonatomic,retain) NSString* documentPath;
@property (nonatomic,retain) NSString* staticImagePath;
@end
@implementation mediastream_tester_Tests
+ (NSArray*)skippedSuites {
NSArray* skipped_suites = @[];
return skipped_suites;
}
+ (void)initialize {
mediastreamer2_tester_init();
int count = mediastreamer2_tester_nb_test_suites();
for (int i=0; i<count; i++) {
const char* suite = mediastreamer2_tester_test_suite_name(i);
int test_count = mediastreamer2_tester_nb_tests(suite);
for( int k = 0; k<test_count; k++){
const char* test =mediastreamer2_tester_test_name(suite, k);
NSString* sSuite = [NSString stringWithUTF8String:suite];
NSString* sTest = [NSString stringWithUTF8String:test];
if( [[mediastream_tester_Tests skippedSuites] containsObject:sSuite] ) continue;
// prepend test_ so that it gets found by introspection
NSString* safesTest = [sTest stringByReplacingOccurrencesOfString:@" " withString:@"_"];
NSString* safesSuite = [sSuite stringByReplacingOccurrencesOfString:@" " withString:@"_"];
NSString *selectorName = [NSString stringWithFormat:@"test_%@__%@", safesSuite, safesTest];
[mediastream_tester_Tests addInstanceMethodWithSelectorName:selectorName block:^(mediastream_tester_Tests* myself) {
[myself testForSuite:sSuite andTest:sTest];
}];
}
}
}
- (void)setUp {
[super setUp];
self.bundlePath = [[NSBundle mainBundle] bundlePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentPath = [paths objectAtIndex:0];
self.staticImagePath = [[self.bundlePath stringByAppendingString:@"/"] stringByAppendingString:@"nowebcamCIF.jpg"];
NSLog(@"Bundle path: %@", self.bundlePath);
NSLog(@"Document path: %@", self.documentPath);
mediastreamer2_tester_set_file_root( [self.bundlePath UTF8String] );
mediastreamer2_tester_set_writable_dir( [self.documentPath UTF8String] );
ms_static_image_set_default_image( [self.staticImagePath UTF8String]);
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testForSuite:(NSString*)suite andTest:(NSString*)test
{
NSLog(@"Launching test %@ from suite %@", test, suite);
XCTAssertFalse(mediastreamer2_tester_run_tests([suite UTF8String], [test UTF8String]), @"Suite '%@' / Test '%@' failed", suite, test);
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment