Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 <OCMock/OCMock.h> | |
| 12 #import <UIKit/UIKit.h> | |
| 13 | |
| 14 #include "webrtc/base/gunit.h" | |
| 15 | |
| 16 #import <WebRTC/RTCCameraVideoCapturer.h> | |
| 17 #import <WebRTC/RTCDispatcher.h> | |
| 18 #import <WebRTC/RTCVideoFrame.h> | |
| 19 | |
| 20 @interface RTCCameraVideoCapturer (Testing)<AVCaptureVideoDataOutputSampleBuffer Delegate> | |
| 21 @property(nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput; | |
| 22 @property(nonatomic, strong) AVCaptureDevice *currentDevice; | |
| 23 @property(nonatomic, strong) dispatch_queue_t frameQueue; | |
| 24 @property(nonatomic, assign) RTCVideoRotation rotation; | |
| 25 // Will the session be running once all asynchronous operations have been comple ted? | |
| 26 @property(nonatomic, assign) BOOL willBeRunning; | |
| 27 | |
| 28 - (BOOL)setupCaptureSession; | |
| 29 - (void)setupVideoDataOutput; | |
| 30 - (void)updateOrientation:(UIDeviceOrientation)orientation; | |
| 31 - (BOOL)tryStartCaptureWithDevice:(AVCaptureDevice *)device | |
| 32 format:(AVCaptureDeviceFormat *)format | |
| 33 fps:(int)fps; | |
| 34 @end | |
| 35 | |
| 36 @interface RTCCameraVideoCapturerTests : NSObject | |
| 37 @property(nonatomic, strong) id delegateMock; | |
| 38 @property(nonatomic, strong) id deviceMock; | |
| 39 @property(nonatomic, strong) id dispatchQueueMock; | |
| 40 @property(nonatomic, strong) RTCCameraVideoCapturer *capturer; | |
| 41 @end | |
| 42 | |
| 43 @implementation RTCCameraVideoCapturerTests | |
| 44 @synthesize delegateMock = _delegateMock; | |
| 45 @synthesize capturer = _capturer; | |
| 46 @synthesize deviceMock = _deviceMock; | |
| 47 @synthesize dispatchQueueMock = _dispatchQueueMock; | |
| 48 | |
| 49 - (void)setup { | |
| 50 self.delegateMock = OCMProtocolMock(@protocol(RTCVideoCapturerDelegate)); | |
| 51 self.capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:self.delegate Mock]; | |
| 52 // Needed when testing async methods so we don't dispatch for real. | |
| 53 self.dispatchQueueMock = [self createDispatcherMock]; | |
| 54 self.deviceMock = [self createDeviceMock]; | |
| 55 } | |
| 56 | |
| 57 - (void)tearDown { | |
| 58 [self.delegateMock stopMocking]; | |
| 59 [self.deviceMock stopMocking]; | |
| 60 [self.dispatchQueueMock stopMocking]; | |
| 61 self.delegateMock = nil; | |
| 62 self.deviceMock = nil; | |
| 63 self.dispatchQueueMock = nil; | |
| 64 self.capturer = nil; | |
| 65 } | |
| 66 | |
| 67 #pragma mark - utils | |
| 68 | |
| 69 - (id)createDispatcherMock { | |
| 70 id dispatcherMock = OCMClassMock([RTCDispatcher class]); | |
| 71 [[[dispatcherMock stub] ignoringNonObjectArgs] dispatchAsyncOnType:RTCDispatch erTypeCaptureSession | |
| 72 block:^(void){ | |
| 73 | |
| 74 }]; | |
| 75 return dispatcherMock; | |
| 76 } | |
| 77 | |
| 78 - (id)createDeviceMock { | |
| 79 return OCMClassMock([AVCaptureDevice class]); | |
| 80 } | |
| 81 | |
| 82 #pragma mark - test cases | |
| 83 | |
| 84 - (void)testSetupSession { | |
|
magjed_webrtc
2017/04/13 11:13:06
This test is good
| |
| 85 AVCaptureSession *session = self.capturer.captureSession; | |
| 86 EXPECT_TRUE(session != nil); | |
| 87 EXPECT_EQ(session.sessionPreset, AVCaptureSessionPresetInputPriority); | |
| 88 EXPECT_EQ(session.usesApplicationAudioSession, NO); | |
| 89 EXPECT_EQ(session.outputs.count, 1u); | |
| 90 AVCaptureOutput *sessionOutput = session.outputs[0]; | |
| 91 EXPECT_EQ(sessionOutput, self.capturer.videoDataOutput); | |
|
magjed_webrtc
2017/04/13 11:13:06
except that we can't make this check since it's an
| |
| 92 } | |
| 93 | |
| 94 // Test that setup session will assert when called twice | |
| 95 - (void)testSetupSessionSecondCall { | |
| 96 // TODO(denicija): Replace this whole block with XCTAssertThrows after migrati ng to XCTest. | |
| 97 BOOL asserts = NO; | |
| 98 @try { | |
| 99 // when | |
| 100 [self.capturer setupCaptureSession]; | |
|
magjed_webrtc
2017/04/13 11:13:06
You can't test this directly since it's an interna
| |
| 101 } @catch (NSException *exception) { | |
| 102 asserts = YES; | |
| 103 } | |
| 104 | |
| 105 // then | |
| 106 EXPECT_TRUE(asserts); | |
| 107 } | |
| 108 | |
| 109 - (void)testSetupSessionOutput { | |
| 110 AVCaptureVideoDataOutput *videoOutput = self.capturer.videoDataOutput; | |
|
magjed_webrtc
2017/04/13 11:13:06
Is it possible to extract this object through the
daniela-webrtc
2017/04/26 11:43:38
Done.
| |
| 111 | |
| 112 EXPECT_TRUE(videoOutput.videoSettings != nil); | |
| 113 EXPECT_EQ(videoOutput.alwaysDiscardsLateVideoFrames, NO); | |
| 114 EXPECT_EQ(videoOutput.sampleBufferDelegate, self.capturer); | |
| 115 EXPECT_EQ(videoOutput.sampleBufferCallbackQueue, self.capturer.frameQueue); | |
| 116 } | |
| 117 | |
| 118 - (void)testSetupSessionOutputSecondCall { | |
|
magjed_webrtc
2017/04/13 11:13:06
Same here, we can't test this directly.
| |
| 119 // TODO(denicija): Replace this whole block with XCTAssertThrows after migrati ng to XCTest. | |
| 120 BOOL asserts = NO; | |
| 121 @try { | |
| 122 // when | |
| 123 [self.capturer setupVideoDataOutput]; | |
| 124 } @catch (NSException *exception) { | |
| 125 asserts = YES; | |
| 126 } | |
| 127 // then | |
| 128 EXPECT_TRUE(asserts); | |
| 129 } | |
| 130 | |
| 131 // Test that start/stop mechanism dosen't fire unnecesarilly. | |
| 132 - (void)testWillBeRunningFlagIsFalse { | |
|
magjed_webrtc
2017/04/13 11:13:06
We have to change this test to check e.g. that we
daniela-webrtc
2017/04/26 11:43:38
This test case intends to test that dealloc doesn'
| |
| 133 EXPECT_TRUE(!self.capturer.willBeRunning); | |
| 134 | |
| 135 // given | |
| 136 self.capturer = nil; | |
| 137 self.capturer = [[RTCCameraVideoCapturer alloc] init]; | |
| 138 // when | |
| 139 [self.capturer startCaptureWithDevice:self.deviceMock format:[AVCaptureDeviceF ormat new] fps:30]; | |
| 140 [self.capturer stopCapture]; | |
| 141 // then | |
| 142 EXPECT_TRUE(!self.capturer.willBeRunning); | |
| 143 } | |
| 144 | |
| 145 // Test that start/stop mechanism check works. | |
| 146 - (void)testWillBeRunningFlagIsTrue { | |
| 147 // when | |
| 148 [self.capturer startCaptureWithDevice:self.deviceMock format:[AVCaptureDeviceF ormat new] fps:30]; | |
| 149 // then | |
| 150 EXPECT_TRUE(self.capturer.willBeRunning); | |
| 151 } | |
| 152 | |
| 153 - (void)testSupportedFormatsForDevice { | |
|
magjed_webrtc
2017/04/13 11:13:06
This test is good.
| |
| 154 // given | |
| 155 id validFormat1 = OCMClassMock([AVCaptureDeviceFormat class]); | |
| 156 CMVideoFormatDescriptionRef format; | |
| 157 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8PlanarFullRan ge, 123, 456, nil, | |
| 158 &format); | |
| 159 OCMStub([validFormat1 formatDescription]).andReturn(format); | |
| 160 | |
| 161 id validFormat2 = OCMClassMock([AVCaptureDeviceFormat class]); | |
| 162 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8BiPlanarVideo Range, 123, 456, | |
| 163 nil, &format); | |
| 164 OCMStub([validFormat2 formatDescription]).andReturn(format); | |
| 165 | |
| 166 id invalidFormat = OCMClassMock([AVCaptureDeviceFormat class]); | |
| 167 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_422YpCbCr8_yuvs, 123, 4 56, nil, &format); | |
| 168 OCMStub([invalidFormat formatDescription]).andReturn(format); | |
| 169 | |
| 170 NSArray *formats = @[ validFormat1, validFormat2, invalidFormat ]; | |
| 171 OCMStub([self.deviceMock formats]).andReturn(formats); | |
| 172 | |
| 173 // when | |
| 174 NSArray *supportedFormats = [RTCCameraVideoCapturer supportedFormatsForDevice: self.deviceMock]; | |
| 175 | |
| 176 // then | |
| 177 EXPECT_EQ(supportedFormats.count, 2u); | |
| 178 EXPECT_TRUE([supportedFormats containsObject:validFormat1]); | |
| 179 EXPECT_TRUE([supportedFormats containsObject:validFormat2]); | |
| 180 // cleanup | |
| 181 [validFormat1 stopMocking]; | |
| 182 [validFormat2 stopMocking]; | |
| 183 [invalidFormat stopMocking]; | |
| 184 validFormat1 = nil; | |
| 185 validFormat2 = nil; | |
| 186 invalidFormat = nil; | |
| 187 } | |
| 188 | |
| 189 - (void)testStartCapture { | |
|
magjed_webrtc
2017/04/13 11:13:06
This test is interesting, but if we want to proper
daniela-webrtc
2017/04/26 11:43:38
If we want to change the API we should do that as
magjed_webrtc
2017/04/26 14:12:08
Ok, let's keep the API intact and not support pass
| |
| 190 // given | |
| 191 OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(N O); | |
| 192 // when | |
| 193 BOOL success = [self.capturer tryStartCaptureWithDevice:self.deviceMock format :nil fps:20]; | |
| 194 | |
| 195 // then | |
| 196 EXPECT_EQ(self.capturer.currentDevice, self.deviceMock); | |
| 197 EXPECT_TRUE(!success); | |
| 198 EXPECT_TRUE(!self.capturer.captureSession.isRunning); | |
| 199 | |
| 200 // given | |
| 201 [self.deviceMock stopMocking]; | |
| 202 self.deviceMock = [self createDeviceMock]; | |
| 203 OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(Y ES); | |
| 204 // when | |
| 205 success = [self.capturer tryStartCaptureWithDevice:self.deviceMock format:nil fps:20]; | |
| 206 // then | |
| 207 EXPECT_TRUE(success); | |
| 208 EXPECT_TRUE(self.capturer.captureSession.isRunning); | |
| 209 } | |
| 210 | |
| 211 - (void)testDelegateCallbackNotCalledWhenInvalidBuffer { | |
| 212 // given | |
| 213 CMSampleBufferRef sampleBuffer = nullptr; | |
| 214 [[self.delegateMock reject] capturer:[OCMArg any] didCaptureVideoFrame:[OCMArg any]]; | |
| 215 | |
| 216 // when | |
| 217 [self.capturer captureOutput:self.capturer.videoDataOutput | |
| 218 didOutputSampleBuffer:sampleBuffer | |
| 219 fromConnection:nil]; | |
| 220 | |
| 221 // then | |
| 222 [self.delegateMock verify]; | |
| 223 } | |
| 224 | |
| 225 - (void)testDelegateCallbackWithValidBuffer { | |
| 226 // TODO(denicija): Add this test case after creating util class for easy cmsam plebuffer mocking. | |
| 227 // It will probably be needed when adding unit tests for RTCVideoFrame. | |
| 228 } | |
| 229 | |
| 230 - (void)testUpdateOrientationFrontCamera { | |
| 231 self.capturer.currentDevice = self.deviceMock; | |
| 232 OCMStub([(AVCaptureDevice *)self.deviceMock position]).andReturn(AVCaptureDevi cePositionFront); | |
| 233 // Portrait | |
| 234 [self.capturer updateOrientation:UIDeviceOrientationPortrait]; | |
| 235 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_90); | |
| 236 | |
| 237 // Left | |
| 238 [self.capturer updateOrientation:UIDeviceOrientationLandscapeLeft]; | |
| 239 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_180); | |
| 240 | |
| 241 // Upside down | |
| 242 [self.capturer updateOrientation:UIDeviceOrientationPortraitUpsideDown]; | |
| 243 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_270); | |
| 244 | |
| 245 // Right | |
| 246 [self.capturer updateOrientation:UIDeviceOrientationLandscapeRight]; | |
| 247 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_0); | |
| 248 } | |
| 249 | |
| 250 - (void)testUpdateOrientationBackCamera { | |
| 251 self.capturer.currentDevice = self.deviceMock; | |
| 252 OCMStub([(AVCaptureDevice *)self.deviceMock position]).andReturn(AVCaptureDevi cePositionBack); | |
| 253 // Portrait | |
| 254 [self.capturer updateOrientation:UIDeviceOrientationPortrait]; | |
| 255 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_90); | |
| 256 | |
| 257 // Left | |
| 258 [self.capturer updateOrientation:UIDeviceOrientationLandscapeLeft]; | |
| 259 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_0); | |
| 260 | |
| 261 // Upside down | |
| 262 [self.capturer updateOrientation:UIDeviceOrientationPortraitUpsideDown]; | |
| 263 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_270); | |
| 264 | |
| 265 // Right | |
| 266 [self.capturer updateOrientation:UIDeviceOrientationLandscapeRight]; | |
| 267 EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_180); | |
| 268 } | |
| 269 @end | |
| 270 | |
| 271 TEST(RTCCameraVideoCapturerTests, SetupSession) { | |
| 272 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 273 [test setup]; | |
| 274 [test testSetupSession]; | |
| 275 [test tearDown]; | |
| 276 } | |
| 277 | |
| 278 TEST(RTCCameraVideoCapturerTests, SetupSessionSecondCall) { | |
| 279 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 280 [test setup]; | |
| 281 [test testSetupSessionSecondCall]; | |
| 282 [test tearDown]; | |
| 283 } | |
| 284 | |
| 285 TEST(RTCCameraVideoCapturerTests, SetupSessionOutput) { | |
| 286 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 287 [test setup]; | |
| 288 [test testSetupSessionOutput]; | |
| 289 [test tearDown]; | |
| 290 } | |
| 291 | |
| 292 TEST(RTCCameraVideoCapturerTests, SetupSessionOutputSecondCall) { | |
| 293 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 294 [test setup]; | |
| 295 [test testSetupSessionOutputSecondCall]; | |
| 296 [test tearDown]; | |
| 297 } | |
| 298 | |
| 299 TEST(RTCCameraVideoCapturerTests, WillBeRunningFlagIsFalse) { | |
| 300 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 301 [test setup]; | |
| 302 [test testWillBeRunningFlagIsFalse]; | |
| 303 [test tearDown]; | |
| 304 } | |
| 305 | |
| 306 TEST(RTCCameraVideoCapturerTests, WillBeRunningFlagIsTrue) { | |
| 307 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 308 [test setup]; | |
| 309 [test testWillBeRunningFlagIsTrue]; | |
| 310 [test tearDown]; | |
| 311 } | |
| 312 | |
| 313 TEST(RTCCameraVideoCapturerTests, SupportedFormatsForDevice) { | |
| 314 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 315 [test setup]; | |
| 316 [test testSupportedFormatsForDevice]; | |
| 317 [test tearDown]; | |
| 318 } | |
| 319 | |
| 320 TEST(RTCCameraVideoCapturerTests, StartCapture) { | |
| 321 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 322 [test setup]; | |
| 323 [test testStartCapture]; | |
| 324 [test tearDown]; | |
| 325 } | |
| 326 | |
| 327 TEST(RTCCameraVideoCapturerTests, DelegateCallbackNotCalledWhenInvalidBuffer) { | |
| 328 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 329 [test setup]; | |
| 330 [test testDelegateCallbackNotCalledWhenInvalidBuffer]; | |
| 331 [test tearDown]; | |
| 332 } | |
| 333 | |
| 334 TEST(RTCCameraVideoCapturerTests, UpdateOrientationFrontCamera) { | |
| 335 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 336 [test setup]; | |
| 337 [test testUpdateOrientationFrontCamera]; | |
| 338 [test tearDown]; | |
| 339 } | |
| 340 | |
| 341 TEST(RTCCameraVideoCapturerTests, UpdateOrientationBackCamera) { | |
| 342 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init] ; | |
| 343 [test setup]; | |
| 344 [test testUpdateOrientationBackCamera]; | |
| 345 [test tearDown]; | |
| 346 } | |
| OLD | NEW |