PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/AudioSequenceBuilderDemoTests/AudioSequenceBuilderDemoTests.m

https://github.com/dmojdehi/AudioSequenceBuilder
Objective C | 289 lines | 175 code | 44 blank | 70 comment | 25 complexity | 50806942ef62413c3c01010f910c51ab MD5 | raw file
  1. //
  2. // AudioSequenceBuilderDemoTests.m
  3. // AudioSequenceBuilderDemoTests
  4. //
  5. // Created by David Mojdehi on 9/8/11.
  6. // Copyright 2011 Mindful Bear Apps. All rights reserved.
  7. //
  8. #import "AudioSequenceBuilderDemoTests.h"
  9. #import "AudioSequenceBuilder.h"
  10. #import <AVFoundation/AVFoundation.h>
  11. #import "DDXMLDocument.h"
  12. @interface NSMutableDictionary(NSMultiDictionary)
  13. -(NSArray*)objectsForKey:(id)aKey;
  14. - (void)addObject:(id)anObject forKey:(id)aKey;
  15. @end
  16. @implementation NSMutableDictionary(NSMultiDictionary)
  17. -(NSArray*)objectsForKey:(id)aKey
  18. {
  19. NSMutableArray *existingArray = [self objectForKey:aKey];
  20. // no existing values? add the value array
  21. return existingArray;
  22. }
  23. - (void)addObject:(id)anObject forKey:(id)aKey
  24. {
  25. NSMutableArray *existingArray = [self objectForKey:aKey];
  26. // no existing values? add the value array
  27. if(!existingArray)
  28. {
  29. existingArray = [[NSMutableArray alloc]init];
  30. [self setObject:existingArray forKey:aKey];
  31. }
  32. [existingArray addObject:anObject];
  33. }
  34. @end
  35. @interface AudioSequenceBuilderDemoTests(Internal)
  36. -(void)performTestingForXml:(NSString *)filename;
  37. @end
  38. @implementation AudioSequenceBuilderDemoTests
  39. - (void)setUp
  40. {
  41. [super setUp];
  42. // Set-up code here.
  43. [SenTestCase testCaseWithSelector:@selector(foobar)];
  44. }
  45. - (void)tearDown
  46. {
  47. // Tear-down code here.
  48. [super tearDown];
  49. }
  50. //- (void)testExample
  51. //{
  52. // STFail(@"Unit tests are not implemented yet in AudioSequenceBuilderDemoTests");
  53. //}
  54. -(void)foobar
  55. {
  56. }
  57. #define ISCLOSETO(a,b) ((a >= b *0.99) && (a<= b*1.01))
  58. //-(void)testAudioSimpleLooping
  59. //{
  60. //
  61. //#if 0
  62. // // these tests fail currently
  63. // NSArray *xmlFilesToTest = [NSArray arrayWithObjects:
  64. // @"testNestedDurations",
  65. // @"testParDurations",
  66. // nil];
  67. //#else
  68. // NSArray *xmlFilesToTest = @[
  69. // @"testSimpleLoop",
  70. // @"testSimpleLoopNested",
  71. // //@"testNestedDurations",
  72. // @"testNestedDurations2",
  73. // @"testNestedDurations3",
  74. // @"testNestedDurationsMore",
  75. // //@"testParDurations",
  76. // @"testSimpleSequence",
  77. // @"testTracksSimple",
  78. // @"testTracksComplex1"
  79. // ];
  80. //#endif
  81. // for(NSString *filename in xmlFilesToTest)
  82. // {
  83. // [self performTestingForXml:filename];
  84. // }
  85. //
  86. //
  87. //
  88. //}
  89. -(void)testSimpleLoop
  90. {
  91. [self performTestingForXml:@"testSimpleLoop"];
  92. }
  93. -(void)testSimpleLoopNested
  94. {
  95. [self performTestingForXml:@"testSimpleLoopNested"];
  96. }
  97. -(void)testNestedDurations2
  98. {
  99. [self performTestingForXml:@"testNestedDurations2"];
  100. }
  101. -(void)testNestedDurations3
  102. {
  103. [self performTestingForXml:@"testNestedDurations3"];
  104. }
  105. -(void)testNestedDurationsMore
  106. {
  107. [self performTestingForXml:@"testNestedDurationsMore"];
  108. }
  109. -(void)testSimpleSequence
  110. {
  111. [self performTestingForXml:@"testSimpleSequence"];
  112. }
  113. -(void)testTracksSimple
  114. {
  115. [self performTestingForXml:@"testTracksSimple"];
  116. }
  117. -(void)testTracksComplex1
  118. {
  119. [self performTestingForXml:@"testTracksComplex1"];
  120. }
  121. -(void)performTestingForXml:(NSString *)filename
  122. {
  123. NSURL *docUrl = [[NSBundle mainBundle] URLForResource:filename withExtension:@"xml"];
  124. //NSURL *docUrl = [[NSBundle mainBundle] URLForResource:@"testSimpleLoop" withExtension:@"xml"];
  125. NSLog(@"------------------------------------------------------------------------------------------------------");
  126. NSLog(@"Testing file: %@.xml", filename);
  127. AudioSequenceBuilder *builder = [[AudioSequenceBuilder alloc] init ];
  128. [builder loadDocument:docUrl];
  129. //[builder loadFromXmlString:@"<root><seq duration=\"10:00.0\"><sound file=\"BG_Reflective_Peace\" loopToFitParent=\"simple\" /></seq></root>"];
  130. AVPlayer *player = [builder buildPlayer];
  131. // we expect the following
  132. // fish out the <tests> element
  133. NSError *err = nil;
  134. // find all children of <test> elems
  135. NSArray *testElems = [builder.document nodesForXPath:@"//test/*" error:&err];
  136. //NSArray *testElem = [builder.document nodesForXPath:@"//test" error:&err];
  137. // run the tests (but wait for the player to finish loading)
  138. dispatch_group_t waitGroup = dispatch_group_create();
  139. // manually indiate that something has started
  140. dispatch_group_enter(waitGroup);
  141. [player addObserver:self forKeyPath:@"status" options:0 context:waitGroup];
  142. // run for awhile until the player has finished loading
  143. bool done = false;
  144. do {
  145. // process events for a bit
  146. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
  147. //dispatch_group_wait returns 0 when the group is done
  148. done = dispatch_group_wait(waitGroup, 0.01) == 0;
  149. } while (!done);
  150. dispatch_release(waitGroup);
  151. // now, run the tests!
  152. NSMutableDictionary *segmentsByName = [[NSMutableDictionary alloc] init];
  153. // verify it built what we expected
  154. AVPlayerItem *playerItem = player.currentItem;
  155. AVAsset *playerAsset = playerItem.asset;
  156. AVComposition *playerAssetAsComposition = (AVComposition*)playerAsset;
  157. NSArray *tracks = playerAssetAsComposition.tracks;
  158. int totalSegments = 0;
  159. for(AVCompositionTrack *track in tracks)
  160. {
  161. //CMTimeRange timeRange = track.timeRange;
  162. NSArray *segments = track.segments;
  163. for(AVCompositionTrackSegment *segment in segments)
  164. {
  165. NSURL *sourceUrl = segment.sourceURL;
  166. CMTimeMapping timeMapping = segment.timeMapping;
  167. double timeSrcStart = CMTimeGetSeconds(timeMapping.source.start);
  168. double timeSrcDuration = CMTimeGetSeconds(timeMapping.source.duration);
  169. double timeTargetStart = CMTimeGetSeconds(timeMapping.target.start);
  170. double timeTargetDuration = CMTimeGetSeconds(timeMapping.target.duration);
  171. NSLog(@"Segment %@, src time:%.2f dur:%.2f, target time:%.2f, dur:%.2f", [sourceUrl absoluteString], timeSrcStart, timeSrcDuration, timeTargetStart,timeTargetDuration);
  172. totalSegments ++;
  173. // add the filename to the array
  174. NSString *path = sourceUrl.path;
  175. NSString *filename = [[path stringByDeletingPathExtension] lastPathComponent];
  176. [segmentsByName addObject:segment forKey:filename];
  177. }
  178. }
  179. // now go through the test cases, validating each of them
  180. for(DDXMLElement *testCase in testElems)
  181. {
  182. if([testCase.name compare:@"totalSegments" options:NSCaseInsensitiveSearch] == 0)
  183. {
  184. // get the amount to compare
  185. int expectedCount = [[[testCase attributeForName:@"count"] stringValue] intValue];
  186. if(expectedCount != totalSegments)
  187. STFail(@"Test: <totalSegments> failed. Expected count was %d, the actual count was %d", expectedCount, totalSegments);
  188. }
  189. else if([testCase.name compare:@"totalTracks" options:NSCaseInsensitiveSearch] == 0)
  190. {
  191. // get the amount to compare
  192. int expectedCount = [[[testCase attributeForName:@"count"] stringValue] intValue];
  193. if(expectedCount != [tracks count])
  194. STFail(@"Test: <totalTracks> failed. Expected count was %d, the actual count was %d", expectedCount, [tracks count]);
  195. }
  196. else if([testCase.name compare:@"segment" options:NSCaseInsensitiveSearch] == 0)
  197. {
  198. NSString *filename = [[testCase attributeForName:@"file"] stringValue];
  199. NSArray *filenameInstances = [segmentsByName objectsForKey:filename];
  200. //file="BG_Reflective_Peace" targetTime="90.96" targetDuration
  201. if([testCase attributeForName:@"targetTime"])
  202. {
  203. double targetTime = [AudioSequenceBuilder parseTimecode:[[testCase attributeForName:@"targetTime"] stringValue] ];
  204. __block bool found = false;
  205. // test the target time of the file (we look for *any* instance of the file with that value)
  206. [filenameInstances enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  207. AVCompositionTrackSegment *segment = (AVCompositionTrackSegment *)obj;
  208. // if
  209. CMTimeMapping timeMapping = segment.timeMapping;
  210. //double timeSrcStart = CMTimeGetSeconds(timeMapping.source.start);
  211. //double timeSrcDuration = CMTimeGetSeconds(timeMapping.source.duration);
  212. double timeTargetStart = CMTimeGetSeconds(timeMapping.target.start);
  213. double timeTargetDuration = CMTimeGetSeconds(timeMapping.target.duration);
  214. if(ISCLOSETO(timeTargetStart,targetTime))
  215. {
  216. // check this time & duration!
  217. if([testCase attributeForName:@"targetDuration"])
  218. {
  219. double targetDuration = [AudioSequenceBuilder parseTimecode:[[testCase attributeForName:@"targetDuration"] stringValue]];
  220. if(!ISCLOSETO(timeTargetDuration, targetDuration))
  221. STFail(@"Test: <segment> failed -- duration was wrong. The duration was %.2f, but %.2f was expected. (In file %@, time %.2f) ", timeTargetDuration, targetDuration, filename, targetTime );
  222. }
  223. found = true;
  224. *stop = YES;
  225. }
  226. }];
  227. if(!found)
  228. {
  229. STFail(@"Test: <segment> failed, line %d. TargetTime of %.2f wasn't found. (the file %@ was found in %d places) ", 0/*testCase.line*/, targetTime, filename, [filenameInstances count]);
  230. }
  231. }
  232. }
  233. }
  234. NSLog(@" end testing file: %@.xml", filename);
  235. NSLog(@"------------------------------------------------------------------------------------------------------");
  236. }
  237. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
  238. {
  239. if([object isKindOfClass:[AVPlayer class]])
  240. {
  241. dispatch_group_t waitGroup = context;
  242. dispatch_group_leave(waitGroup);
  243. }
  244. }
  245. @end