diff --git a/tools-webrtc/ios/tests/common_tests.json b/tools-webrtc/ios/tests/common_tests.json index 30d557f953..c85db66894 100644 --- a/tools-webrtc/ios/tests/common_tests.json +++ b/tools-webrtc/ios/tests/common_tests.json @@ -1,5 +1,9 @@ { "tests": [ + { + "app": "apprtcmobile_tests", + "xctest": true + }, { "app": "audio_decoder_unittests" }, diff --git a/webrtc/examples/BUILD.gn b/webrtc/examples/BUILD.gn index 59842fc524..1eca3171de 100644 --- a/webrtc/examples/BUILD.gn +++ b/webrtc/examples/BUILD.gn @@ -433,32 +433,38 @@ if (is_ios || (is_mac && target_cpu != "x86")) { } if (rtc_include_tests) { - config("rtc_apprtcmobile_config") { - defines = [ "GTEST_RELATIVE_PATH" ] - } - - rtc_test("apprtcmobile_tests") { - include_dirs = [ "objc/AppRTCMobile/ios" ] - deps = [ - ":AppRTCMobile_lib", - ":apprtc_signaling", - "//testing/gtest", - "//third_party/ocmock", - ] - - sources = [ - "objc/AppRTCMobile/tests/ARDAppClientTest.mm", - "objc/AppRTCMobile/tests/ARDSettingsModelTests.mm", - ] - - if (is_ios) { - info_plist = "objc/AppRTCMobile/ios/Info.plist" + # TODO(kthelgason): compile xctests on mac when chromium supports it. + if (is_ios) { + rtc_source_set("apprtcmobile_test_sources") { + include_dirs = [ + "objc/AppRTCMobile", + "objc/AppRTCMobile/ios", + ] + testonly = true + sources = [ + "objc/AppRTCMobile/tests/ARDAppClient_xctest.mm", + "objc/AppRTCMobile/tests/ARDSDPUtils_xctest.mm", + "objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm", + ] + public_deps = [ + ":AppRTCMobile_ios_frameworks", + ":AppRTCMobile_lib", + "//build/config/ios:xctest", + "//third_party/ocmock", + ] + configs += [ "//build/config/compiler:enable_arc" ] } - configs += [ - ":rtc_apprtcmobile_config", - "//build/config/compiler:enable_arc", - ] + rtc_ios_xctest_test("apprtcmobile_tests") { + info_plist = "objc/AppRTCMobile/ios/Info.plist" + sources = [ + "objc/AppRTCMobile/ios/main.m", + ] + deps = [ + ":apprtcmobile_test_sources", + ] + ldflags = [ "-all_load" ] + } } } } diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClientTest.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm similarity index 63% rename from webrtc/examples/objc/AppRTCMobile/tests/ARDAppClientTest.mm rename to webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm index b206925420..c2cd9e3368 100644 --- a/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClientTest.mm +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDAppClient_xctest.mm @@ -11,108 +11,19 @@ #import #import #import +#import -#include "webrtc/base/gunit.h" #include "webrtc/base/ssladapter.h" #import "WebRTC/RTCMediaConstraints.h" #import "WebRTC/RTCPeerConnectionFactory.h" -#import "WebRTC/RTCSessionDescription.h" #import "ARDAppClient+Internal.h" #import "ARDJoinResponse+Internal.h" #import "ARDMessageResponse+Internal.h" #import "ARDSDPUtils.h" -static NSString *kARDAppClientTestsDomain = @"org.webrtc.ARDAppClientTests"; -static NSInteger kARDAppClientTestsExpectationTimeoutError = 100; - -// These classes mimic XCTest APIs, to make eventual conversion to XCTest -// easier. Conversion will happen once XCTest is supported well on build bots. -@interface ARDTestExpectation : NSObject - -@property(nonatomic, readonly) NSString *description; -@property(nonatomic, readonly) BOOL isFulfilled; - -- (instancetype)initWithDescription:(NSString *)description; -- (void)fulfill; - -@end - -@implementation ARDTestExpectation - -@synthesize description = _description; -@synthesize isFulfilled = _isFulfilled; - -- (instancetype)initWithDescription:(NSString *)description { - if (self = [super init]) { - _description = description; - } - return self; -} - -- (void)fulfill { - _isFulfilled = YES; -} - -@end - -@interface ARDTestCase : NSObject - -- (ARDTestExpectation *)expectationWithDescription:(NSString *)description; -- (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout - handler:(void (^)(NSError *error))handler; - -@end - -@implementation ARDTestCase { - NSMutableArray *_expectations; -} - -- (instancetype)init { - if (self = [super init]) { - _expectations = [NSMutableArray array]; - } - return self; -} - -- (ARDTestExpectation *)expectationWithDescription:(NSString *)description { - ARDTestExpectation *expectation = - [[ARDTestExpectation alloc] initWithDescription:description]; - [_expectations addObject:expectation]; - return expectation; -} - -- (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout - handler:(void (^)(NSError *error))handler { - CFTimeInterval startTime = CACurrentMediaTime(); - NSError *error = nil; - while (![self areExpectationsFulfilled]) { - CFTimeInterval duration = CACurrentMediaTime() - startTime; - if (duration > timeout) { - error = [NSError errorWithDomain:kARDAppClientTestsDomain - code:kARDAppClientTestsExpectationTimeoutError - userInfo:@{}]; - break; - } - [[NSRunLoop currentRunLoop] - runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; - } - handler(error); -} - -- (BOOL)areExpectationsFulfilled { - for (ARDTestExpectation *expectation in _expectations) { - if (!expectation.isFulfilled) { - return NO; - } - } - return YES; -} - -@end - -@interface ARDAppClientTest : ARDTestCase +@interface ARDAppClientTest : XCTestCase @end @implementation ARDAppClientTest @@ -255,9 +166,9 @@ static NSInteger kARDAppClientTestsExpectationTimeoutError = 100; NSString *callerId = @"testCallerId"; NSString *answererId = @"testAnswererId"; - ARDTestExpectation *callerConnectionExpectation = + XCTestExpectation *callerConnectionExpectation = [self expectationWithDescription:@"Caller PC connected."]; - ARDTestExpectation *answererConnectionExpectation = + XCTestExpectation *answererConnectionExpectation = [self expectationWithDescription:@"Answerer PC connected."]; caller = [self createAppClientForRoomId:roomId @@ -309,7 +220,7 @@ static NSInteger kARDAppClientTestsExpectationTimeoutError = 100; shouldUseLevelControl:NO]; [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) { if (error) { - EXPECT_TRUE(0); + XCTFail(@"Expectation failed with error %@.", error); } }]; } @@ -317,23 +228,22 @@ static NSInteger kARDAppClientTestsExpectationTimeoutError = 100; // Test to see that we get a local video connection // Note this will currently pass even when no camera is connected as a local // video track is created regardless (Perhaps there should be a test for that...) +#if !TARGET_IPHONE_SIMULATOR // Expect to fail on simulator due to no camera support - (void)testSessionShouldGetLocalVideoTrackCallback { ARDAppClient *caller = nil; NSString *roomId = @"testRoom"; NSString *callerId = @"testCallerId"; - ARDTestExpectation *localVideoTrackExpectation = + XCTestExpectation *localVideoTrackExpectation = [self expectationWithDescription:@"Caller got local video."]; caller = [self createAppClientForRoomId:roomId clientId:callerId isInitiator:YES messages:[NSArray array] - messageHandler:^(ARDSignalingMessage *message) { - } connectedHandler:^{ - } localVideoTrackHandler:^{ - [localVideoTrackExpectation fulfill]; - }]; + messageHandler:^(ARDSignalingMessage *message) {} + connectedHandler:^{} + localVideoTrackHandler:^{ [localVideoTrackExpectation fulfill]; }]; caller.defaultPeerConnectionConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil optionalConstraints:nil]; @@ -346,112 +256,10 @@ static NSInteger kARDAppClientTestsExpectationTimeoutError = 100; shouldUseLevelControl:NO]; [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) { if (error) { - EXPECT_TRUE(0); + XCTFail("Expectation timed out with error: %@.", error); } }]; } - -@end - -@interface ARDSDPUtilsTest : ARDTestCase -- (void)testPreferVideoCodec:(NSString *)codec - sdp:(NSString *)sdp - expectedSdp:(NSString *)expectedSdp; -@end - -@implementation ARDSDPUtilsTest - -- (void)testPreferVideoCodec:(NSString *)codec - sdp:(NSString *)sdp - expectedSdp:(NSString *)expectedSdp { - RTCSessionDescription* desc = - [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp]; - RTCSessionDescription *outputDesc = - [ARDSDPUtils descriptionForDescription:desc - preferredVideoCodec:codec]; - EXPECT_TRUE([outputDesc.description rangeOfString:expectedSdp].location != - NSNotFound); -} - -@end - -class SignalingTest : public ::testing::Test { - protected: - static void SetUpTestCase() { - rtc::InitializeSSL(); - } - static void TearDownTestCase() { - rtc::CleanupSSL(); - } -}; - -TEST_F(SignalingTest, SessionTest) { - @autoreleasepool { - ARDAppClientTest *test = [[ARDAppClientTest alloc] init]; - [test testSession]; - } -} - -#if !TARGET_IPHONE_SIMULATOR -// Expected fail on iOS Simulator due to no camera support -TEST_F(SignalingTest, SessionLocalVideoCallbackTest) { - @autoreleasepool { - ARDAppClientTest *test = [[ARDAppClientTest alloc] init]; - [test testSessionShouldGetLocalVideoTrackCallback]; - } -} #endif -TEST_F(SignalingTest, SdpH264Test) { - @autoreleasepool { - ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; - NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" - "a=rtpmap:120 H264/90000\n" - "a=rtpmap:97 H264/90000\n"); - NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 97 100 116 117 96\n" - "a=rtpmap:120 H264/90000\n" - "a=rtpmap:97 H264/90000\n"); - [test testPreferVideoCodec:@"H264" - sdp:sdp - expectedSdp:expectedSdp]; - } -} - -TEST_F(SignalingTest, SdpVp8Test) { - @autoreleasepool { - ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; - NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" - "a=rtpmap:116 VP8/90000\n"); - NSString *expectedSdp = @("m=video 9 RTP/SAVPF 116 100 117 96 120 97\n" - "a=rtpmap:116 VP8/90000\n"); - [test testPreferVideoCodec:@"VP8" - sdp:sdp - expectedSdp:expectedSdp]; - } -} - -TEST_F(SignalingTest, SdpNoMLineTest) { - @autoreleasepool { - ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; - NSString *sdp = @("a=rtpmap:116 VP8/90000\n"); - [test testPreferVideoCodec:@"VP8" - sdp:sdp - expectedSdp:sdp]; - } -} - -TEST_F(SignalingTest, SdpMissingCodecTest) { - @autoreleasepool { - ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init]; - NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" - "a=rtpmap:116 VP8/90000\n"); - [test testPreferVideoCodec:@"foo" - sdp:sdp - expectedSdp:sdp]; - } -} - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} +@end diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDSDPUtils_xctest.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDSDPUtils_xctest.mm new file mode 100644 index 0000000000..b58048f0ca --- /dev/null +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDSDPUtils_xctest.mm @@ -0,0 +1,64 @@ +/* + * 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 +#import + +#import "WebRTC/RTCSessionDescription.h" + +#import "ARDSDPUtils.h" + +@interface ARDSDPUtilsTest : XCTestCase +@end + +@implementation ARDSDPUtilsTest + +- (void)testPreferVideoCodecH264 { + NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" + "a=rtpmap:120 H264/90000\n" + "a=rtpmap:97 H264/90000\n"); + NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 97 100 116 117 96\n" + "a=rtpmap:120 H264/90000\n" + "a=rtpmap:97 H264/90000\n"); + [self preferVideoCodec:@"H264" sdp:sdp expected:expectedSdp]; +} + +- (void)testPreferVideoCodecVP8 { + NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" + "a=rtpmap:116 VP8/90000\n"); + NSString *expectedSdp = @("m=video 9 RTP/SAVPF 116 100 117 96 120 97\n" + "a=rtpmap:116 VP8/90000\n"); + [self preferVideoCodec:@"VP8" sdp:sdp expected:expectedSdp]; +} + +- (void)testNoMLine { + NSString *sdp = @("a=rtpmap:116 VP8/90000\n"); + [self preferVideoCodec:@"VP8" sdp:sdp expected:sdp]; +} + +- (void)testMissingCodec { + NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n" + "a=rtpmap:116 VP8/90000\n"); + [self preferVideoCodec:@"foo" sdp:sdp expected:sdp]; +} + +#pragma mark - Helpers + +- (void)preferVideoCodec:(NSString *)codec + sdp:(NSString *)sdp + expected:(NSString *)expectedSdp{ + RTCSessionDescription* desc = + [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp]; + RTCSessionDescription *outputDesc = + [ARDSDPUtils descriptionForDescription:desc + preferredVideoCodec:codec]; + XCTAssertTrue([outputDesc.description rangeOfString:expectedSdp].location != NSNotFound); +} +@end diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm similarity index 51% rename from webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm rename to webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm index 45a10451d2..eee18db69c 100644 --- a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm @@ -10,33 +10,21 @@ #import #import +#import + +#import "WebRTC/RTCMediaConstraints.h" + #import "ARDSettingsModel+Private.h" #import "ARDSettingsStore.h" -#import "WebRTC/RTCMediaConstraints.h" -#include "webrtc/base/gunit.h" -@interface ARDSettingsModelTests : NSObject { +@interface ARDSettingsModelTests : XCTestCase { ARDSettingsModel *_model; } - -- (void)testStoringInavlidConstraintReturnsNo; -- (void)testDefaultMediaFromStore; -- (void)testWidthConstraintFromStore; -- (void)testHeightConstraintFromStore; - @end @implementation ARDSettingsModelTests -- (instancetype)init { - self = [super init]; - if (self) { - _model = [[ARDSettingsModel alloc] init]; - } - return self; -} - - (id)setupMockStoreWithMediaConstraintString:(NSString *)constraintString { id storeMock = [OCMockObject mockForClass:[ARDSettingsStore class]]; [([[storeMock stub] andReturn:constraintString]) videoResolutionConstraints]; @@ -47,113 +35,50 @@ return storeMock; } -- (void)testDefaultMediaFromStore { - // given - id storeMock = [self setupMockStoreWithMediaConstraintString:nil]; +- (void)setUp { + _model = [[ARDSettingsModel alloc] init]; +} +- (void)testDefaultMediaFromStore { + id storeMock = [self setupMockStoreWithMediaConstraintString:nil]; [[storeMock expect] setVideoResolutionConstraints:@"640x480"]; - // when NSString *string = [_model currentVideoResoultionConstraintFromStore]; - // then - EXPECT_TRUE([string isEqualToString:@"640x480"]); + XCTAssertEqualObjects(string, @"640x480"); [storeMock verify]; } -- (void)testStoringInavlidConstraintReturnsNo { - // given - id storeMock = [self setupMockStoreWithMediaConstraintString:@"960x480"]; - - // when - BOOL result = [_model storeVideoResoultionConstraint:@"960x480"]; - - // then - EXPECT_FALSE(result); +- (void)testStoringInvalidConstraintReturnsNo { + __unused id storeMock = [self setupMockStoreWithMediaConstraintString:@"960x480"]; + XCTAssertFalse([_model storeVideoResoultionConstraint:@"960x480"]); } - (void)testWidthConstraintFromStore { - // given [self setupMockStoreWithMediaConstraintString:@"1270x480"]; - - // when NSString *width = [_model currentVideoResolutionWidthFromStore]; - // then - EXPECT_TRUE([width isEqualToString:@"1270"]); + XCTAssertEqualObjects(width, @"1270"); } - (void)testHeightConstraintFromStore { - // given [self setupMockStoreWithMediaConstraintString:@"960x540"]; - // when NSString *height = [_model currentVideoResolutionHeightFromStore]; - // then - EXPECT_TRUE([height isEqualToString:@"540"]); + XCTAssertEqualObjects(height, @"540"); } - (void)testConstraintComponentIsNilWhenInvalidConstraintString { - // given [self setupMockStoreWithMediaConstraintString:@"invalid"]; - - // when NSString *width = [_model currentVideoResolutionWidthFromStore]; - // then - EXPECT_TRUE(width == nil); + XCTAssertNil(width); } - (void)testConstraintsDictionaryIsNilWhenInvalidConstraintString { - // given [self setupMockStoreWithMediaConstraintString:@"invalid"]; - - // when NSDictionary *constraintsDictionary = [_model currentMediaConstraintFromStoreAsRTCDictionary]; - // then - EXPECT_TRUE(constraintsDictionary == nil); + XCTAssertNil(constraintsDictionary); } @end - -class ARDSettingsModelTest : public ::testing::Test { - protected: - ARDSettingsModelTests *test; - ARDSettingsModelTest() { test = [[ARDSettingsModelTests alloc] init]; } -}; - -TEST_F(ARDSettingsModelTest, DefaultMediaFromStore) { - @autoreleasepool { - [test testDefaultMediaFromStore]; - } -} - -TEST_F(ARDSettingsModelTest, StoringInvalidConstraintsReturnsNo) { - @autoreleasepool { - [test testStoringInavlidConstraintReturnsNo]; - } -} - -TEST_F(ARDSettingsModelTest, WidthConstraintFromStore) { - @autoreleasepool { - [test testWidthConstraintFromStore]; - } -} - -TEST_F(ARDSettingsModelTest, HeightConstraintFromStore) { - @autoreleasepool { - [test testHeightConstraintFromStore]; - } -} - -TEST_F(ARDSettingsModelTest, ConstratintIsNil) { - @autoreleasepool { - [test testConstraintComponentIsNilWhenInvalidConstraintString]; - } -} - -TEST_F(ARDSettingsModelTest, DictionaryIsNil) { - @autoreleasepool { - [test testConstraintsDictionaryIsNilWhenInvalidConstraintString]; - } -} diff --git a/webrtc/webrtc.gni b/webrtc/webrtc.gni index e6d746a49e..96975fae9a 100644 --- a/webrtc/webrtc.gni +++ b/webrtc/webrtc.gni @@ -13,6 +13,9 @@ import("//build/config/sanitizers/sanitizers.gni") import("//build/config/ui.gni") import("//build_overrides/build.gni") import("//testing/test.gni") +if (is_ios) { + import("//build/config/ios/rules.gni") +} declare_args() { # Disable this to avoid building the Opus audio codec. @@ -328,3 +331,29 @@ template("rtc_shared_library") { } } } + +if (is_ios) { + set_defaults("rtc_ios_xctest_test") { + configs = rtc_add_configs + suppressed_configs = [] + } + + template("rtc_ios_xctest_test") { + ios_xctest_test(target_name) { + forward_variables_from(invoker, + "*", + [ + "configs", + "public_configs", + "suppressed_configs", + ]) + configs += invoker.configs + configs -= rtc_remove_configs + configs -= invoker.suppressed_configs + public_configs = [ rtc_common_inherited_config ] + if (defined(invoker.public_configs)) { + public_configs += invoker.public_configs + } + } + } +}