1/*
2 *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "components/capturer/RTCFileVideoCapturer.h"
12
13#import <XCTest/XCTest.h>
14
15#include "rtc_base/gunit.h"
16
17NSString *const kTestFileName = @"foreman.mp4";
18static const int kTestTimeoutMs = 5 * 1000;  // 5secs.
19
20@interface MockCapturerDelegate : NSObject <RTC_OBJC_TYPE (RTCVideoCapturerDelegate)>
21
22@property(nonatomic, assign) NSInteger capturedFramesCount;
23
24@end
25
26@implementation MockCapturerDelegate
27@synthesize capturedFramesCount = _capturedFramesCount;
28
29- (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer
30    didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
31  self.capturedFramesCount++;
32}
33
34@end
35
36NS_CLASS_AVAILABLE_IOS(10)
37@interface RTCFileVideoCapturerTests : XCTestCase
38
39@property(nonatomic, strong) RTC_OBJC_TYPE(RTCFileVideoCapturer) * capturer;
40@property(nonatomic, strong) MockCapturerDelegate *mockDelegate;
41
42@end
43
44@implementation RTCFileVideoCapturerTests
45@synthesize capturer = _capturer;
46@synthesize mockDelegate = _mockDelegate;
47
48- (void)setUp {
49  self.mockDelegate = [[MockCapturerDelegate alloc] init];
50  self.capturer = [[RTC_OBJC_TYPE(RTCFileVideoCapturer) alloc] initWithDelegate:self.mockDelegate];
51}
52
53- (void)tearDown {
54  self.capturer = nil;
55  self.mockDelegate = nil;
56}
57
58- (void)testCaptureWhenFileNotInBundle {
59  __block BOOL errorOccured = NO;
60
61  RTCFileVideoCapturerErrorBlock errorBlock = ^void(NSError *error) {
62    errorOccured = YES;
63  };
64
65  [self.capturer startCapturingFromFileNamed:@"not_in_bundle.mov" onError:errorBlock];
66  ASSERT_TRUE_WAIT(errorOccured, kTestTimeoutMs);
67}
68
69- (void)testSecondStartCaptureCallFails {
70  __block BOOL secondError = NO;
71
72  RTCFileVideoCapturerErrorBlock firstErrorBlock = ^void(NSError *error) {
73    // This block should never be called.
74    NSLog(@"Error: %@", [error userInfo]);
75    ASSERT_TRUE(false);
76  };
77
78  RTCFileVideoCapturerErrorBlock secondErrorBlock = ^void(NSError *error) {
79    secondError = YES;
80  };
81
82  [self.capturer startCapturingFromFileNamed:kTestFileName onError:firstErrorBlock];
83  [self.capturer startCapturingFromFileNamed:kTestFileName onError:secondErrorBlock];
84
85  ASSERT_TRUE_WAIT(secondError, kTestTimeoutMs);
86}
87
88- (void)testStartStopCapturer {
89#if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
90  if (@available(iOS 10, *)) {
91    [self.capturer startCapturingFromFileNamed:kTestFileName onError:nil];
92
93    __block BOOL done = NO;
94    __block NSInteger capturedFrames = -1;
95    NSInteger capturedFramesAfterStop = -1;
96
97    // We're dispatching the `stopCapture` with delay to ensure the capturer has
98    // had the chance to capture several frames.
99    dispatch_time_t captureDelay = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);  // 2secs.
100    dispatch_after(captureDelay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
101      capturedFrames = self.mockDelegate.capturedFramesCount;
102      [self.capturer stopCapture];
103      done = YES;
104    });
105    WAIT(done, kTestTimeoutMs);
106
107    capturedFramesAfterStop = self.mockDelegate.capturedFramesCount;
108    ASSERT_TRUE(capturedFrames != -1);
109    ASSERT_EQ(capturedFrames, capturedFramesAfterStop);
110  }
111#endif
112}
113
114@end
115