Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1535)

Unified Diff: webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm

Issue 2815823002: Add unit test class for RTCCameraVideoCapturer. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/sdk/objc/Framework/Classes/RTCCameraVideoCapturer.m ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
diff --git a/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm b/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
new file mode 100644
index 0000000000000000000000000000000000000000..ac5eefcbc294f69c253bb731fb6b32e21f0c02ca
--- /dev/null
+++ b/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <OCMock/OCMock.h>
+#import <UIKit/UIKit.h>
+
+#include "webrtc/base/gunit.h"
+
+#import <WebRTC/RTCCameraVideoCapturer.h>
+#import <WebRTC/RTCDispatcher.h>
+#import <WebRTC/RTCVideoFrame.h>
+
+@interface RTCCameraVideoCapturer (Testing)<AVCaptureVideoDataOutputSampleBufferDelegate>
+@property(nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput;
+@property(nonatomic, strong) AVCaptureDevice *currentDevice;
+@property(nonatomic, strong) dispatch_queue_t frameQueue;
+@property(nonatomic, assign) RTCVideoRotation rotation;
+// Will the session be running once all asynchronous operations have been completed?
+@property(nonatomic, assign) BOOL willBeRunning;
+
+- (BOOL)setupCaptureSession;
+- (void)setupVideoDataOutput;
+- (void)updateOrientation:(UIDeviceOrientation)orientation;
+- (BOOL)tryStartCaptureWithDevice:(AVCaptureDevice *)device
+ format:(AVCaptureDeviceFormat *)format
+ fps:(int)fps;
+@end
+
+@interface RTCCameraVideoCapturerTests : NSObject
+@property(nonatomic, strong) id delegateMock;
+@property(nonatomic, strong) id deviceMock;
+@property(nonatomic, strong) id dispatchQueueMock;
+@property(nonatomic, strong) RTCCameraVideoCapturer *capturer;
+@end
+
+@implementation RTCCameraVideoCapturerTests
+@synthesize delegateMock = _delegateMock;
+@synthesize capturer = _capturer;
+@synthesize deviceMock = _deviceMock;
+@synthesize dispatchQueueMock = _dispatchQueueMock;
+
+- (void)setup {
+ self.delegateMock = OCMProtocolMock(@protocol(RTCVideoCapturerDelegate));
+ self.capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:self.delegateMock];
+ // Needed when testing async methods so we don't dispatch for real.
+ self.dispatchQueueMock = [self createDispatcherMock];
+ self.deviceMock = [self createDeviceMock];
+}
+
+- (void)tearDown {
+ [self.delegateMock stopMocking];
+ [self.deviceMock stopMocking];
+ [self.dispatchQueueMock stopMocking];
+ self.delegateMock = nil;
+ self.deviceMock = nil;
+ self.dispatchQueueMock = nil;
+ self.capturer = nil;
+}
+
+#pragma mark - utils
+
+- (id)createDispatcherMock {
+ id dispatcherMock = OCMClassMock([RTCDispatcher class]);
+ [[[dispatcherMock stub] ignoringNonObjectArgs] dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
+ block:^(void){
+
+ }];
+ return dispatcherMock;
+}
+
+- (id)createDeviceMock {
+ return OCMClassMock([AVCaptureDevice class]);
+}
+
+#pragma mark - test cases
+
+- (void)testSetupSession {
magjed_webrtc 2017/04/13 11:13:06 This test is good
+ AVCaptureSession *session = self.capturer.captureSession;
+ EXPECT_TRUE(session != nil);
+ EXPECT_EQ(session.sessionPreset, AVCaptureSessionPresetInputPriority);
+ EXPECT_EQ(session.usesApplicationAudioSession, NO);
+ EXPECT_EQ(session.outputs.count, 1u);
+ AVCaptureOutput *sessionOutput = session.outputs[0];
+ 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
+}
+
+// Test that setup session will assert when called twice
+- (void)testSetupSessionSecondCall {
+ // TODO(denicija): Replace this whole block with XCTAssertThrows after migrating to XCTest.
+ BOOL asserts = NO;
+ @try {
+ // when
+ [self.capturer setupCaptureSession];
magjed_webrtc 2017/04/13 11:13:06 You can't test this directly since it's an interna
+ } @catch (NSException *exception) {
+ asserts = YES;
+ }
+
+ // then
+ EXPECT_TRUE(asserts);
+}
+
+- (void)testSetupSessionOutput {
+ 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.
+
+ EXPECT_TRUE(videoOutput.videoSettings != nil);
+ EXPECT_EQ(videoOutput.alwaysDiscardsLateVideoFrames, NO);
+ EXPECT_EQ(videoOutput.sampleBufferDelegate, self.capturer);
+ EXPECT_EQ(videoOutput.sampleBufferCallbackQueue, self.capturer.frameQueue);
+}
+
+- (void)testSetupSessionOutputSecondCall {
magjed_webrtc 2017/04/13 11:13:06 Same here, we can't test this directly.
+ // TODO(denicija): Replace this whole block with XCTAssertThrows after migrating to XCTest.
+ BOOL asserts = NO;
+ @try {
+ // when
+ [self.capturer setupVideoDataOutput];
+ } @catch (NSException *exception) {
+ asserts = YES;
+ }
+ // then
+ EXPECT_TRUE(asserts);
+}
+
+// Test that start/stop mechanism dosen't fire unnecesarilly.
+- (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'
+ EXPECT_TRUE(!self.capturer.willBeRunning);
+
+ // given
+ self.capturer = nil;
+ self.capturer = [[RTCCameraVideoCapturer alloc] init];
+ // when
+ [self.capturer startCaptureWithDevice:self.deviceMock format:[AVCaptureDeviceFormat new] fps:30];
+ [self.capturer stopCapture];
+ // then
+ EXPECT_TRUE(!self.capturer.willBeRunning);
+}
+
+// Test that start/stop mechanism check works.
+- (void)testWillBeRunningFlagIsTrue {
+ // when
+ [self.capturer startCaptureWithDevice:self.deviceMock format:[AVCaptureDeviceFormat new] fps:30];
+ // then
+ EXPECT_TRUE(self.capturer.willBeRunning);
+}
+
+- (void)testSupportedFormatsForDevice {
magjed_webrtc 2017/04/13 11:13:06 This test is good.
+ // given
+ id validFormat1 = OCMClassMock([AVCaptureDeviceFormat class]);
+ CMVideoFormatDescriptionRef format;
+ CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8PlanarFullRange, 123, 456, nil,
+ &format);
+ OCMStub([validFormat1 formatDescription]).andReturn(format);
+
+ id validFormat2 = OCMClassMock([AVCaptureDeviceFormat class]);
+ CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, 123, 456,
+ nil, &format);
+ OCMStub([validFormat2 formatDescription]).andReturn(format);
+
+ id invalidFormat = OCMClassMock([AVCaptureDeviceFormat class]);
+ CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_422YpCbCr8_yuvs, 123, 456, nil, &format);
+ OCMStub([invalidFormat formatDescription]).andReturn(format);
+
+ NSArray *formats = @[ validFormat1, validFormat2, invalidFormat ];
+ OCMStub([self.deviceMock formats]).andReturn(formats);
+
+ // when
+ NSArray *supportedFormats = [RTCCameraVideoCapturer supportedFormatsForDevice:self.deviceMock];
+
+ // then
+ EXPECT_EQ(supportedFormats.count, 2u);
+ EXPECT_TRUE([supportedFormats containsObject:validFormat1]);
+ EXPECT_TRUE([supportedFormats containsObject:validFormat2]);
+ // cleanup
+ [validFormat1 stopMocking];
+ [validFormat2 stopMocking];
+ [invalidFormat stopMocking];
+ validFormat1 = nil;
+ validFormat2 = nil;
+ invalidFormat = nil;
+}
+
+- (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
+ // given
+ OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(NO);
+ // when
+ BOOL success = [self.capturer tryStartCaptureWithDevice:self.deviceMock format:nil fps:20];
+
+ // then
+ EXPECT_EQ(self.capturer.currentDevice, self.deviceMock);
+ EXPECT_TRUE(!success);
+ EXPECT_TRUE(!self.capturer.captureSession.isRunning);
+
+ // given
+ [self.deviceMock stopMocking];
+ self.deviceMock = [self createDeviceMock];
+ OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(YES);
+ // when
+ success = [self.capturer tryStartCaptureWithDevice:self.deviceMock format:nil fps:20];
+ // then
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(self.capturer.captureSession.isRunning);
+}
+
+- (void)testDelegateCallbackNotCalledWhenInvalidBuffer {
+ // given
+ CMSampleBufferRef sampleBuffer = nullptr;
+ [[self.delegateMock reject] capturer:[OCMArg any] didCaptureVideoFrame:[OCMArg any]];
+
+ // when
+ [self.capturer captureOutput:self.capturer.videoDataOutput
+ didOutputSampleBuffer:sampleBuffer
+ fromConnection:nil];
+
+ // then
+ [self.delegateMock verify];
+}
+
+- (void)testDelegateCallbackWithValidBuffer {
+ // TODO(denicija): Add this test case after creating util class for easy cmsamplebuffer mocking.
+ // It will probably be needed when adding unit tests for RTCVideoFrame.
+}
+
+- (void)testUpdateOrientationFrontCamera {
+ self.capturer.currentDevice = self.deviceMock;
+ OCMStub([(AVCaptureDevice *)self.deviceMock position]).andReturn(AVCaptureDevicePositionFront);
+ // Portrait
+ [self.capturer updateOrientation:UIDeviceOrientationPortrait];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_90);
+
+ // Left
+ [self.capturer updateOrientation:UIDeviceOrientationLandscapeLeft];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_180);
+
+ // Upside down
+ [self.capturer updateOrientation:UIDeviceOrientationPortraitUpsideDown];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_270);
+
+ // Right
+ [self.capturer updateOrientation:UIDeviceOrientationLandscapeRight];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_0);
+}
+
+- (void)testUpdateOrientationBackCamera {
+ self.capturer.currentDevice = self.deviceMock;
+ OCMStub([(AVCaptureDevice *)self.deviceMock position]).andReturn(AVCaptureDevicePositionBack);
+ // Portrait
+ [self.capturer updateOrientation:UIDeviceOrientationPortrait];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_90);
+
+ // Left
+ [self.capturer updateOrientation:UIDeviceOrientationLandscapeLeft];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_0);
+
+ // Upside down
+ [self.capturer updateOrientation:UIDeviceOrientationPortraitUpsideDown];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_270);
+
+ // Right
+ [self.capturer updateOrientation:UIDeviceOrientationLandscapeRight];
+ EXPECT_EQ(self.capturer.rotation, RTCVideoRotation_180);
+}
+@end
+
+TEST(RTCCameraVideoCapturerTests, SetupSession) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testSetupSession];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, SetupSessionSecondCall) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testSetupSessionSecondCall];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, SetupSessionOutput) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testSetupSessionOutput];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, SetupSessionOutputSecondCall) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testSetupSessionOutputSecondCall];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, WillBeRunningFlagIsFalse) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testWillBeRunningFlagIsFalse];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, WillBeRunningFlagIsTrue) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testWillBeRunningFlagIsTrue];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, SupportedFormatsForDevice) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testSupportedFormatsForDevice];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, StartCapture) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testStartCapture];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, DelegateCallbackNotCalledWhenInvalidBuffer) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testDelegateCallbackNotCalledWhenInvalidBuffer];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, UpdateOrientationFrontCamera) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testUpdateOrientationFrontCamera];
+ [test tearDown];
+}
+
+TEST(RTCCameraVideoCapturerTests, UpdateOrientationBackCamera) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testUpdateOrientationBackCamera];
+ [test tearDown];
+}
« no previous file with comments | « webrtc/sdk/objc/Framework/Classes/RTCCameraVideoCapturer.m ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698