OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 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 <Foundation/Foundation.h> | |
12 #import <OCMock/OCMock.h> | |
13 #include "avfoundationformatmapper.h" | |
14 #include "webrtc/base/gunit.h" | |
15 | |
16 static NSString * const kMediaSubtypeKey = @"subtype"; | |
17 static NSString * const kMinFrameRateKey = @"min_framerate"; | |
18 static NSString * const kMaxFrameRateKey = @"max_framerate"; | |
19 | |
20 // Width and height don't play any role so lets use predefined values throughout | |
21 // the tests. | |
22 static const int kFormatWidth = 789; | |
23 static const int kFormatHeight = 987; | |
24 | |
25 // Hardcoded framrate to be used throughout the tests. | |
26 static const int kFramerate = 30; | |
27 | |
28 | |
29 NSArray<AVCaptureDeviceFormat*>* GetEligibleDeviceFormats( | |
30 const AVCaptureDevice* device, | |
31 int supportedFps); | |
32 AVCaptureDeviceFormat* GetDeviceFormatForVideoFormat( | |
33 const AVCaptureDevice* device, | |
34 const cricket::VideoFormat& videoFormat); | |
35 | |
36 | |
37 // Mock class for AVCaptureDeviceFormat. | |
38 // Custom implementation needed because OCMock cannot handle the | |
39 // CMVideoDescriptionRef mocking. | |
40 @interface AVCaptureDeviceFormatMock : NSObject { | |
41 CMVideoFormatDescriptionRef _format; | |
42 OCMockObject *_rangeMock; | |
43 } | |
44 | |
45 // The dictionaries are in the following format. | |
46 // @{@"subtype":@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
47 // @"min_framerate":@0, | |
48 // @"max_framerate":@30} | |
49 | |
50 - (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary; | |
51 @end | |
52 | |
53 @implementation AVCaptureDeviceFormatMock | |
54 | |
55 - (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary { | |
56 if (self = [super init]) { | |
57 NSNumber *subtype = [mockDataDictionary objectForKey:kMediaSubtypeKey]; | |
magjed_webrtc
2016/11/28 12:21:23
What's the benefit of sending these arguments in a
daniela-webrtc
2016/11/29 12:05:55
Done.
| |
58 NSNumber *minFramerate = [mockDataDictionary objectForKey:kMinFrameRateKey]; | |
59 NSNumber *maxFramerate = [mockDataDictionary objectForKey:kMaxFrameRateKey]; | |
60 | |
61 | |
62 CMVideoFormatDescriptionCreate(nil, subtype.intValue, kFormatWidth, | |
63 kFormatHeight, nil, &_format); | |
64 // We can use OCMock for the range. | |
65 _rangeMock = [OCMockObject mockForClass:[AVFrameRateRange class]]; | |
66 [[[_rangeMock stub] andReturnValue:@(minFramerate.floatValue)] minFrameRate] ; | |
67 [[[_rangeMock stub] andReturnValue:@(maxFramerate.floatValue)] maxFrameRate] ; | |
68 } | |
69 | |
70 return self; | |
71 } | |
72 | |
73 - (void)dealloc { | |
74 if (_rangeMock != nil) { | |
75 [_rangeMock dealloc]; | |
76 _rangeMock = nil; | |
77 } | |
78 if (_format != nil) { | |
79 CFRelease(_format); | |
80 _format = nil; | |
81 } | |
82 [super dealloc]; | |
83 } | |
84 | |
85 // Redefinition of AVCaptureDevice methods we want to mock. | |
86 - (CMVideoFormatDescriptionRef)formatDescription { | |
87 return _format; | |
88 } | |
89 | |
90 - (NSArray *)videoSupportedFrameRateRanges { | |
91 return @[_rangeMock]; | |
92 } | |
93 | |
94 @end | |
95 | |
96 class AVFormatMapperTest : public ::testing::Test { | |
97 protected: | |
98 void testEligibleWithValidFormats() { | |
magjed_webrtc
2016/11/28 12:21:23
It looks like you can make the unittests more simp
daniela-webrtc
2016/11/29 12:05:55
Done.
magjed_webrtc
2016/11/29 13:34:01
It's not done. What I mean is that if we want to u
| |
99 // given | |
100 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
101 | |
102 // Valid media subtype, valid framerate | |
103 AVCaptureDeviceFormatMock* mockOne = | |
104 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
105 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
106 kMinFrameRateKey : @(0), | |
107 kMaxFrameRateKey : @(60) | |
108 }]; | |
109 // Valid media subtype, valid framerate | |
110 AVCaptureDeviceFormatMock* mockTwo = | |
111 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
112 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange), | |
113 kMinFrameRateKey : @(0), | |
114 kMaxFrameRateKey : @(30) | |
115 }]; | |
116 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
117 | |
118 // when | |
119 NSArray* result = GetEligibleDeviceFormats(mockDevice, kFramerate); | |
120 | |
121 // then | |
122 EXPECT_TRUE(result.count == 2); | |
magjed_webrtc
2016/11/28 12:21:23
EXPECT_EQ(2, result.count); Same for other places.
daniela-webrtc
2016/11/29 12:05:55
Done.
| |
123 } | |
124 | |
125 void testEligibleWithInvalidFramerateFormats() { | |
126 // given | |
127 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
128 | |
129 // Valid media subtype, invalid framerate | |
130 AVCaptureDeviceFormatMock* mockOne = | |
131 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
132 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
133 kMinFrameRateKey : @(0), | |
134 kMaxFrameRateKey : @(20) | |
135 }]; | |
136 | |
137 // Valid media subtype, valid framerate | |
138 AVCaptureDeviceFormatMock* mockTwo = | |
139 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
140 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
141 kMinFrameRateKey : @(0), | |
142 kMaxFrameRateKey : @(30) | |
143 }]; | |
144 | |
145 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
146 | |
147 // when | |
148 NSArray* result = GetEligibleDeviceFormats(mockDevice, kFramerate); | |
149 | |
150 // then | |
151 EXPECT_TRUE(result.count == 1); | |
152 EXPECT_TRUE([result[0] isEqual:mockTwo]); | |
153 } | |
154 | |
155 void testEligibleWithInvalidFormats() { | |
156 // given | |
157 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
158 | |
159 // Invalid media subtype, valid framerate | |
160 AVCaptureDeviceFormatMock* mockOne = | |
161 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
162 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8Planar), | |
163 kMinFrameRateKey : @(0), | |
164 kMaxFrameRateKey : @(30) | |
165 }]; | |
166 | |
167 // Valid media subtype, valid framerate | |
168 AVCaptureDeviceFormatMock* mockTwo = | |
169 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
170 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
171 kMinFrameRateKey : @(0), | |
172 kMaxFrameRateKey : @(30) | |
173 }]; | |
174 | |
175 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
176 | |
177 // when | |
178 NSArray* result = GetEligibleDeviceFormats(mockDevice, kFramerate); | |
179 | |
180 // then | |
181 EXPECT_TRUE(result.count == 1); | |
182 EXPECT_TRUE([result[0] isEqual:mockTwo]); | |
183 } | |
184 | |
185 void testSuportedCricketFormats() { | |
186 // given | |
187 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
188 | |
189 // valid media subtype, valid framerate | |
190 AVCaptureDeviceFormatMock* mockOne = | |
191 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
192 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
193 kMinFrameRateKey : @(0), | |
194 kMaxFrameRateKey : @(30) | |
195 }]; | |
196 | |
197 [[[mockDevice stub] andReturn:@[ mockOne ]] formats]; | |
198 | |
199 cricket::VideoFormat expectedFormat = cricket::VideoFormat( | |
200 kFormatWidth, kFormatHeight, | |
201 cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12); | |
202 | |
203 // when | |
204 std::set<cricket::VideoFormat> result = | |
205 webrtc::GetSupportedVideoFormatsForDevice(mockDevice); | |
206 | |
207 // then | |
208 EXPECT_EQ(result.size(), 1); | |
magjed_webrtc
2016/11/28 12:21:23
You need to flip the order of the arguments, i.e.
daniela-webrtc
2016/11/29 12:05:55
Done.
| |
209 | |
210 // make sure the set has the expected format | |
211 auto it = result.find(expectedFormat); | |
212 EXPECT_TRUE(it != result.end()); | |
magjed_webrtc
2016/11/28 12:21:23
Do this instead: EXPECT_EQ(1u, result.count(expect
daniela-webrtc
2016/11/29 12:05:55
Done.
magjed_webrtc
2016/11/29 13:34:01
Actually, since you only have one element, it migh
| |
213 } | |
214 | |
215 void testAVFormatForCricketFormat() { | |
216 // given | |
217 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
218 | |
219 // valid media subtype, valid framerate | |
220 AVCaptureDeviceFormatMock* mockOne = | |
221 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
222 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange), | |
223 kMinFrameRateKey : @(0), | |
224 kMaxFrameRateKey : @(30) | |
225 }]; | |
226 | |
227 // valid media subtype, valid framerate. | |
228 // This media subtype should be the preffered one. | |
229 AVCaptureDeviceFormatMock* mockTwo = | |
230 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
231 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
232 kMinFrameRateKey : @(0), | |
233 kMaxFrameRateKey : @(30) | |
234 }]; | |
235 | |
236 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
237 | |
238 cricket::VideoFormat inputFormat = cricket::VideoFormat( | |
239 kFormatWidth, kFormatHeight, | |
240 cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12); | |
241 | |
242 // when | |
243 id resultFormat = GetDeviceFormatForVideoFormat(mockDevice, inputFormat); | |
244 | |
245 // then | |
246 EXPECT_TRUE([resultFormat isEqual:mockTwo]); | |
magjed_webrtc
2016/11/28 12:21:23
So EXPECT_EQ doesn't work here?
daniela-webrtc
2016/11/29 12:05:55
Done.
| |
247 } | |
248 | |
249 void testSetFormatWhenDeviceCannotLock() { | |
250 // given | |
251 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
252 [[[mockDevice stub] andReturnValue:@(NO)] | |
253 lockForConfiguration:[OCMArg setTo:nil]]; | |
254 | |
255 [[[mockDevice stub] andReturn:@[]] formats]; | |
256 | |
257 // when | |
258 bool resultFormat = webrtc::SetFormatForCaptureDevice( | |
259 mockDevice, nil, cricket::VideoFormat()); | |
260 | |
261 // then | |
262 EXPECT_FALSE(resultFormat); | |
263 } | |
264 | |
265 void testSetFormatWhenFormatIsIncompatible() { | |
266 // given | |
267 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
268 [[[mockDevice stub] andReturn:@[]] formats]; | |
269 [[[mockDevice stub] andReturnValue:@(YES)] | |
270 lockForConfiguration:[OCMArg setTo:nil]]; | |
271 | |
272 NSException* exception = | |
273 [NSException exceptionWithName:@"Test exception" | |
274 reason:@"Raised from unit tests" | |
275 userInfo:nil]; | |
276 [[[mockDevice stub] andThrow:exception] setActiveFormat:[OCMArg any]]; | |
277 [[mockDevice expect] unlockForConfiguration]; | |
278 | |
279 // when | |
280 bool resultFormat = webrtc::SetFormatForCaptureDevice( | |
281 mockDevice, nil, cricket::VideoFormat()); | |
282 | |
283 // then | |
284 EXPECT_FALSE(resultFormat); | |
285 [mockDevice verify]; | |
286 } | |
287 }; | |
288 | |
289 TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithValidFormats) { | |
290 testEligibleWithValidFormats(); | |
magjed_webrtc
2016/11/28 12:21:23
Inline these functions instead, unless you have so
magjed_webrtc
2016/11/29 13:34:01
I still want this done. You don't need the fixture
daniela-webrtc
2016/11/29 16:13:57
Sorry, I missed this one :/ It's changed now
| |
291 } | |
292 | |
293 TEST_F(AVFormatMapperTest, | |
294 EligibleFormatsPerDeviceWithInvalidFramerateFormats) { | |
295 testEligibleWithInvalidFramerateFormats(); | |
296 } | |
297 | |
298 TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithInvalidFormats) { | |
299 testEligibleWithInvalidFormats(); | |
300 } | |
301 | |
302 TEST_F(AVFormatMapperTest, SuportedCricketFormats) { | |
303 testSuportedCricketFormats(); | |
304 } | |
305 | |
306 TEST_F(AVFormatMapperTest, AVFormatForCricketFormat) { | |
307 testAVFormatForCricketFormat(); | |
308 } | |
309 | |
310 TEST_F(AVFormatMapperTest, SetFormatWhenDeviceCannotLock) { | |
311 testSetFormatWhenDeviceCannotLock(); | |
312 } | |
313 | |
314 TEST_F(AVFormatMapperTest, SetFormatWhenFormatIsIncompatible) { | |
315 testSetFormatWhenFormatIsIncompatible(); | |
316 } | |
OLD | NEW |