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

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

Issue 2526813002: Add unit tests for avfoundation format mapper functions and fix wrong implementation. (Closed)
Patch Set: Created 4 years, 1 month 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
Index: webrtc/sdk/objc/Framework/UnitTests/avformatmappertests.mm
diff --git a/webrtc/sdk/objc/Framework/UnitTests/avformatmappertests.mm b/webrtc/sdk/objc/Framework/UnitTests/avformatmappertests.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6e3295005ccd4f79d50829cd9ec9a360c4184eea
--- /dev/null
+++ b/webrtc/sdk/objc/Framework/UnitTests/avformatmappertests.mm
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2016 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 <Foundation/Foundation.h>
+#import <OCMock/OCMock.h>
+#include "avfoundationformatmapper.h"
+#include "webrtc/base/gunit.h"
+
+static NSString * const kMediaSubtypeKey = @"subtype";
+static NSString * const kMinFrameRateKey = @"min_framerate";
+static NSString * const kMaxFrameRateKey = @"max_framerate";
+
+// Widht and height don't play any role so lets use predefined values troughout
magjed_webrtc 2016/11/24 13:42:59 nit: Spelling: Width and throughout
daniela-webrtc 2016/11/25 08:58:15 Done.
+// the tests.
+static const int kFormatWidth = 789;
+static const int kFormatHeight = 987;
+
+// Hardcoded framrate to be used troughout the tests.
magjed_webrtc 2016/11/24 13:42:59 nit: spelling: throughout
daniela-webrtc 2016/11/25 08:58:15 Done.
+static const int kFramerate = 30;
+
+namespace webrtc {
+NSArray<AVCaptureDeviceFormat*>* GetEligibleDeviceFormats(
magjed_webrtc 2016/11/24 13:42:59 Are you testing some implementation helper functio
daniela-webrtc 2016/11/25 08:58:15 Yes it's an implementation helper function. I want
magjed_webrtc 2016/11/28 12:21:23 I see. I'm sorry, but you have to stick to testing
+ const AVCaptureDevice* device,
+ int supportedFps);
+AVCaptureDeviceFormat* GetDeviceFormatForVideoFormat(
+ const AVCaptureDevice* device,
+ const cricket::VideoFormat& videoFormat);
+}
+
+// Mock class for AVCaptureDeviceFormat.
+// Custom implementation needed because OCMock cannot handle the
+// CMVideoDescriptionRef mocking.
+@interface AVCaptureDeviceFormatMock : NSObject {
+ CMVideoFormatDescriptionRef _format;
+ OCMockObject *_rangeMock;
+}
+
+// The dictionaries are in the following format.
+// @{@"subtype":@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+// @"min_framerate":@0,
+// @"max_framerate":@30}
+
+- (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary;
+@end
+
+@implementation AVCaptureDeviceFormatMock
+
+- (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary {
+ if (self = [super init]) {
+ NSNumber *subtype = [mockDataDictionary objectForKey:kMediaSubtypeKey];
+ NSNumber *minFramerate = [mockDataDictionary objectForKey:kMinFrameRateKey];
+ NSNumber *maxFramerate = [mockDataDictionary objectForKey:kMaxFrameRateKey];
+
+
+ CMVideoFormatDescriptionCreate(nil, subtype.intValue, kFormatWidth,
+ kFormatHeight, nil, &_format);
+ // We can use OCMock for the range.
+ _rangeMock = [OCMockObject mockForClass:[AVFrameRateRange class]];
+ [[[_rangeMock stub] andReturnValue:@(minFramerate.floatValue)] minFrameRate];
+ [[[_rangeMock stub] andReturnValue:@(maxFramerate.floatValue)] maxFrameRate];
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ if (_rangeMock != nil) {
+ [_rangeMock dealloc];
+ _rangeMock = nil;
+ }
+ if (_format != nil) {
+ CFRelease(_format);
+ _format = nil;
+ }
+ [super dealloc];
+}
+
+// Redefinition of AVCaptureDevice methods we want to mock.
+- (CMVideoFormatDescriptionRef)formatDescription {
+ return _format;
+}
+
+- (NSArray *)videoSupportedFrameRateRanges {
+ return @[_rangeMock];
+}
+
+@end
+
+class AVFormatMapperTest : public ::testing::Test {
+ protected:
+ void testEligibleWithValidFormats() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+
+ // Valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockOne =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+ // Valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockTwo =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+ [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats];
+
+ // when
+ NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate);
+
+ // then
+ EXPECT_TRUE(result.count == 2);
+ }
+
+ void testEligibleWithInvalidFramerateFormats() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+
+ // Valid media subtype, invalid framerate
+ AVCaptureDeviceFormatMock* mockOne =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(35)
+ }];
+
+ // Valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockTwo =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(30)
+ }];
+
+ [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats];
+
+ // when
+ NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate);
+
+ // then
+ EXPECT_TRUE(result.count == 1);
+ EXPECT_TRUE([result[0] isEqual:mockTwo]);
+ }
+
+ void testEligibleWithInvalidFormats() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+
+ // Invalid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockOne =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8Planar),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+
+ // Valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockTwo =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+
+ [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats];
+
+ // when
+ NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate);
+
+ // then
+ EXPECT_TRUE(result.count == 1);
+ EXPECT_TRUE([result[0] isEqual:mockTwo]);
+ }
+
+ void testSuportedCricketFormats() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+
+ // valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockOne =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+
+ [[[mockDevice stub] andReturn:@[ mockOne ]] formats];
+
+ cricket::VideoFormat expectedFormat = cricket::VideoFormat(
+ kFormatWidth, kFormatHeight,
+ cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12);
+
+ // when
+ std::set<cricket::VideoFormat> result =
+ webrtc::GetSupportedVideoFormatsForDevice(mockDevice);
+
+ // then
+ EXPECT_EQ(result.size(), 1);
+
+ // make sure the set has the expected format
+ auto it = result.find(expectedFormat);
+ EXPECT_TRUE(it != result.end());
+ }
+
+ void testAVFormatForCricketFormat() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+
+ // valid media subtype, valid framerate
+ AVCaptureDeviceFormatMock* mockOne =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+
+ // valid media subtype, valid framerate.
+ // This media subtype should be the preffered one.
+ AVCaptureDeviceFormatMock* mockTwo =
+ [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{
+ kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
+ kMinFrameRateKey : @(0),
+ kMaxFrameRateKey : @(20)
+ }];
+
+ [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats];
+
+ cricket::VideoFormat inputFormat = cricket::VideoFormat(
+ kFormatWidth, kFormatHeight,
+ cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12);
+
+ // when
+ id resultFormat =
+ webrtc::GetDeviceFormatForVideoFormat(mockDevice, inputFormat);
+
+ // then
+ EXPECT_TRUE([resultFormat isEqual:mockTwo]);
+ }
+
+ void testSetFormatWhenDeviceCannotLock() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+ [[[mockDevice stub] andReturnValue:@(NO)]
+ lockForConfiguration:[OCMArg setTo:nil]];
+
+ [[[mockDevice stub] andReturn:@[]] formats];
+
+ // when
+ bool resultFormat = webrtc::SetFormatForCaptureDevice(
+ mockDevice, nil, cricket::VideoFormat());
+
+ // then
+ EXPECT_FALSE(resultFormat);
+ }
+
+ void testSetFormatWhenFormatIsIncompatible() {
+ // given
+ id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]];
+ [[[mockDevice stub] andReturn:@[]] formats];
+ [[[mockDevice stub] andReturnValue:@(YES)]
+ lockForConfiguration:[OCMArg setTo:nil]];
+
+ NSException* exception =
+ [NSException exceptionWithName:@"Test exception"
+ reason:@"Raised from unit tests"
+ userInfo:nil];
+ [[[mockDevice stub] andThrow:exception] setActiveFormat:[OCMArg any]];
+ [[mockDevice expect] unlockForConfiguration];
+
+ // when
+ bool resultFormat = webrtc::SetFormatForCaptureDevice(
+ mockDevice, nil, cricket::VideoFormat());
+
+ // then
+ EXPECT_FALSE(resultFormat);
+ [mockDevice verify];
+ }
+};
+
+TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithValidFormats) {
+ testEligibleWithValidFormats();
+}
+
+TEST_F(AVFormatMapperTest,
+ EligibleFormatsPerDeviceWithInvalidFramerateFormats) {
+ testEligibleWithInvalidFramerateFormats();
+}
+
+TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithInvalidFormats) {
+ testEligibleWithInvalidFormats();
+}
+
+TEST_F(AVFormatMapperTest, SuportedCricketFormats) {
+ testSuportedCricketFormats();
+}
+
+TEST_F(AVFormatMapperTest, AVFormatForCricketFormat) {
+ testAVFormatForCricketFormat();
+}
+
+TEST_F(AVFormatMapperTest, SetFormatWhenDeviceCannotLock) {
+ testSetFormatWhenDeviceCannotLock();
+}
+
+TEST_F(AVFormatMapperTest, SetFormatWhenFormatIsIncompatible) {
+ testSetFormatWhenFormatIsIncompatible();
+}

Powered by Google App Engine
This is Rietveld 408576698