blob: 99004ea51587ce519f5acf0b7c06c0b0a0c2657c [file] [log] [blame]
kthelgason954d9b92017-03-09 03:36:58 -08001/*
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 <Foundation/Foundation.h>
12#import <OCMock/OCMock.h>
13
14#include "webrtc/base/gunit.h"
15
16#include <Metal/RTCMTLNV12Renderer.h>
17#include <WebRTC/RTCMTLVideoView.h>
18
19// Extension of RTCMTLVideoView for testing purposes.
20@interface RTCMTLVideoView (Testing)
kthelgason954d9b92017-03-09 03:36:58 -080021
22+ (BOOL)isMetalAvailable;
23+ (UIView*)createMetalView:(CGRect)frame;
denicijad2088152017-04-28 02:14:54 -070024+ (id<RTCMTLRenderer>)createNV12Renderer;
25+ (id<RTCMTLRenderer>)createI420Renderer;
kthelgason954d9b92017-03-09 03:36:58 -080026- (void)drawInMTKView:(id)view;
27@end
28
29@interface RTCMTLVideoViewTests : NSObject
30@property(nonatomic, strong) id classMock;
31@property(nonatomic, strong) id metalViewMock;
denicijad2088152017-04-28 02:14:54 -070032@property(nonatomic, strong) id rendererNV12Mock;
33@property(nonatomic, strong) id rendererI420Mock;
34@property(nonatomic, strong) id frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080035@end
36
37@implementation RTCMTLVideoViewTests
38
39@synthesize classMock = _classMock;
40@synthesize metalViewMock = _metalViewMock;
denicijad2088152017-04-28 02:14:54 -070041@synthesize rendererNV12Mock = _rendererNV12Mock;
42@synthesize rendererI420Mock = _rendererI420Mock;
43@synthesize frameMock = _frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080044
45- (void)setup {
46 self.classMock = OCMClassMock([RTCMTLVideoView class]);
kthelgason954d9b92017-03-09 03:36:58 -080047}
48
49- (void)tearDown {
50 [self.classMock stopMocking];
denicijad2088152017-04-28 02:14:54 -070051 [self.rendererI420Mock stopMocking];
52 [self.rendererNV12Mock stopMocking];
kthelgason954d9b92017-03-09 03:36:58 -080053 [self.metalViewMock stopMocking];
denicijad2088152017-04-28 02:14:54 -070054 [self.frameMock stopMocking];
kthelgason954d9b92017-03-09 03:36:58 -080055 self.classMock = nil;
denicijad2088152017-04-28 02:14:54 -070056 self.rendererI420Mock = nil;
57 self.rendererNV12Mock = nil;
kthelgason954d9b92017-03-09 03:36:58 -080058 self.metalViewMock = nil;
denicijad2088152017-04-28 02:14:54 -070059 self.frameMock = nil;
kthelgason954d9b92017-03-09 03:36:58 -080060}
61
denicijad2088152017-04-28 02:14:54 -070062- (id)frameMockWithNativeHandle:(BOOL)hasNativeHandle {
63 id frameMock = OCMClassMock([RTCVideoFrame class]);
64 if (hasNativeHandle) {
65 OCMStub([frameMock nativeHandle]).andReturn((CVPixelBufferRef)[OCMArg anyPointer]);
66 } else {
67 OCMStub([frameMock nativeHandle]).andReturn((CVPixelBufferRef) nullptr);
68 }
69 return frameMock;
kthelgason954d9b92017-03-09 03:36:58 -080070}
71
denicijad2088152017-04-28 02:14:54 -070072- (id)rendererMockWithSuccessfulSetup:(BOOL)sucess {
73 id rendererMock = OCMProtocolMock(@protocol(RTCMTLRenderer));
74 OCMStub([rendererMock addRenderingDestination:[OCMArg any]]).andReturn(sucess);
kthelgason954d9b92017-03-09 03:36:58 -080075
denicijad2088152017-04-28 02:14:54 -070076 return rendererMock;
kthelgason954d9b92017-03-09 03:36:58 -080077}
78
denicijad2088152017-04-28 02:14:54 -070079#pragma mark - Test cases
80- (void)testInitAssertsIfMetalUnavailabe {
kthelgason954d9b92017-03-09 03:36:58 -080081 // given
82 OCMStub([self.classMock isMetalAvailable]).andReturn(NO);
kthelgason954d9b92017-03-09 03:36:58 -080083
84 // when
denicijad2088152017-04-28 02:14:54 -070085 BOOL asserts = NO;
86 @try {
87 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero];
88 (void)realView;
89 } @catch (NSException *ex) {
90 asserts = YES;
91 }
kthelgason954d9b92017-03-09 03:36:58 -080092
denicijad2088152017-04-28 02:14:54 -070093 EXPECT_TRUE(asserts);
kthelgason954d9b92017-03-09 03:36:58 -080094}
95
96- (void)testRTCVideoRenderNilFrameCallback {
97 // given
denicijad2088152017-04-28 02:14:54 -070098 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
kthelgason954d9b92017-03-09 03:36:58 -080099 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
denicijad2088152017-04-28 02:14:54 -0700100 self.frameMock = OCMClassMock([RTCVideoFrame class]);
101
102 [[self.frameMock reject] nativeHandle];
103 [[self.classMock reject] createNV12Renderer];
104 [[self.classMock reject] createI420Renderer];
kthelgason954d9b92017-03-09 03:36:58 -0800105
106 // when
107 [realView renderFrame:nil];
kthelgason954d9b92017-03-09 03:36:58 -0800108 [realView drawInMTKView:self.metalViewMock];
109
110 // then
denicijad2088152017-04-28 02:14:54 -0700111 [self.frameMock verify];
112 [self.classMock verify];
113}
114
115- (void)testRTCVideoRenderFrameCallbackI420 {
116 // given
117 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
118 self.rendererI420Mock = [self rendererMockWithSuccessfulSetup:YES];
119 self.frameMock = [self frameMockWithNativeHandle:NO];
120
121 OCMExpect([self.rendererI420Mock drawFrame:self.frameMock]);
122 OCMExpect([self.classMock createI420Renderer]).andReturn(self.rendererI420Mock);
123 [[self.classMock reject] createNV12Renderer];
124
125 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
126
127 // when
128 [realView renderFrame:self.frameMock];
129 [realView drawInMTKView:self.metalViewMock];
130
131 // then
132 [self.rendererI420Mock verify];
133 [self.classMock verify];
134}
135
136- (void)testRTCVideoRenderFrameCallbackNV12 {
137 // given
138 OCMStub([self.classMock isMetalAvailable]).andReturn(YES);
139 self.rendererNV12Mock = [self rendererMockWithSuccessfulSetup:YES];
140 self.frameMock = [self frameMockWithNativeHandle:YES];
141
142 OCMExpect([self.rendererNV12Mock drawFrame:self.frameMock]);
143 OCMExpect([self.classMock createNV12Renderer]).andReturn(self.rendererNV12Mock);
144 [[self.classMock reject] createI420Renderer];
145
146 RTCMTLVideoView *realView = [[RTCMTLVideoView alloc] init];
147
148 // when
149 [realView renderFrame:self.frameMock];
150 [realView drawInMTKView:self.metalViewMock];
151
152 // then
153 [self.rendererNV12Mock verify];
154 [self.classMock verify];
kthelgason954d9b92017-03-09 03:36:58 -0800155}
156@end
157
denicijad2088152017-04-28 02:14:54 -0700158TEST(RTCMTLVideoViewTests, InitAssertsIfMetalUnavailabe) {
kthelgason954d9b92017-03-09 03:36:58 -0800159 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
160 [test setup];
kthelgason954d9b92017-03-09 03:36:58 -0800161
denicijad2088152017-04-28 02:14:54 -0700162 [test testInitAssertsIfMetalUnavailabe];
kthelgason954d9b92017-03-09 03:36:58 -0800163 [test tearDown];
164}
165
166TEST(RTCMTLVideoViewTests, RTCVideoRenderNilFrameCallback) {
167 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
168 [test setup];
169 [test testRTCVideoRenderNilFrameCallback];
170 [test tearDown];
171}
172
denicijad2088152017-04-28 02:14:54 -0700173TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackI420) {
kthelgason954d9b92017-03-09 03:36:58 -0800174 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
175 [test setup];
denicijad2088152017-04-28 02:14:54 -0700176
177 [test testRTCVideoRenderFrameCallbackI420];
178 [test tearDown];
179}
180
181TEST(RTCMTLVideoViewTests, RTCVideoRenderFrameCallbackNV12) {
182 RTCMTLVideoViewTests *test = [[RTCMTLVideoViewTests alloc] init];
183 [test setup];
184
185 [test testRTCVideoRenderFrameCallbackNV12];
kthelgason954d9b92017-03-09 03:36:58 -0800186 [test tearDown];
187}