blob: a75b632214874f7091006ef1fd1502a0d1fa2653 [file] [log] [blame]
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <XCTest/XCTest.h>
NSTimeInterval const kWaitTime = 30;
int const kNumIterations = 1;
@interface GrpcIosTestUITests : XCTestCase
@end
@implementation GrpcIosTestUITests {
XCUIApplication *testApp;
XCUIApplication *settingsApp;
}
- (void)setUp {
self.continueAfterFailure = NO;
[[[XCUIApplication alloc] init] launch];
testApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.grpc.GrpcIosTest"];
[testApp activate];
// Reset RPC counter
[self pressButton:@"Reset counter"];
settingsApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.Preferences"];
[settingsApp activate];
[NSThread sleepForTimeInterval:1];
// Go back to the first page of Settings.
XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch;
while (backButton.exists && backButton.isHittable) {
NSLog(@"Tapping back button");
[backButton tap];
}
XCTAssert([settingsApp.navigationBars[@"Settings"] waitForExistenceWithTimeout:kWaitTime]);
NSLog(@"Turning off airplane mode");
// Turn off airplane mode
[self setAirplaneMode:NO];
// Turn on wifi
NSLog(@"Turning on wifi");
[self setWifi:YES];
}
- (void)tearDown {
}
- (void)doUnaryCall {
[testApp activate];
[self pressButton:@"Unary call"];
}
- (void)do10UnaryCalls {
[testApp activate];
[self pressButton:@"10 Unary calls"];
}
- (void)pressButton:(NSString *)name {
// Wait for button to be visible
while (![testApp.buttons[name] exists] || ![testApp.buttons[name] isHittable]) {
[NSThread sleepForTimeInterval:1];
}
// Wait until all events in run loop have been processed
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource)
;
NSLog(@"Pressing button: %@", name);
[testApp.buttons[name] tap];
}
- (void)expectCallSuccess {
XCTAssert([testApp.staticTexts[@"Call done"] waitForExistenceWithTimeout:kWaitTime]);
}
- (void)expectCallFailed {
XCTAssert([testApp.staticTexts[@"Call failed"] waitForExistenceWithTimeout:kWaitTime]);
}
- (void)expectCallSuccessOrFailed {
NSDate *startTime = [NSDate date];
while (![testApp.staticTexts[@"Call done"] exists] &&
![testApp.staticTexts[@"Call failed"] exists]) {
XCTAssertLessThan([[NSDate date] timeIntervalSinceDate:startTime], kWaitTime);
[NSThread sleepForTimeInterval:1];
}
}
- (void)setAirplaneMode:(BOOL)to {
[settingsApp activate];
XCUIElement *mySwitch = settingsApp.tables.element.cells.switches[@"Airplane Mode"];
BOOL from = [(NSString *)mySwitch.value boolValue];
NSLog(@"Setting airplane from: %d to: %d", from, to);
if (from != to) {
[mySwitch tap];
// wait for network change to finish
[NSThread sleepForTimeInterval:5];
}
XCTAssert([(NSString *)mySwitch.value boolValue] == to);
}
- (void)setWifi:(BOOL)to {
[settingsApp activate];
[settingsApp.tables.element.cells.staticTexts[@"Wi-Fi"] tap];
XCUIElement *wifiSwitch = settingsApp.tables.cells.switches[@"Wi-Fi"];
BOOL from = [(NSString *)wifiSwitch.value boolValue];
NSLog(@"Setting wifi from: %d to: %d", from, to);
if (from != to) {
[wifiSwitch tap];
// wait for wifi networks to be detected
[NSThread sleepForTimeInterval:10];
}
// Go back to the first page of Settings.
XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch;
[backButton tap];
}
- (int)getRandomNumberBetween:(int)min max:(int)max {
return min + arc4random_uniform((max - min + 1));
}
- (void)testBackgroundBeforeCall {
NSLog(@"%s", __func__);
// Open test app
[testApp activate];
// Send test app to background
[XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
// Wait a bit
int sleepTime = [self getRandomNumberBetween:5 max:10];
NSLog(@"Sleeping for %d seconds", sleepTime);
[NSThread sleepForTimeInterval:sleepTime];
// Bring test app to foreground and make a unary call. Call should succeed
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testBackgroundDuringStreamingCall {
NSLog(@"%s", __func__);
// Open test app and start a streaming call
[testApp activate];
[self pressButton:@"Start streaming call"];
// Send test app to background
[XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
// Wait a bit
int sleepTime = [self getRandomNumberBetween:5 max:10];
NSLog(@"Sleeping for %d seconds", sleepTime);
[NSThread sleepForTimeInterval:sleepTime];
// Bring test app to foreground and make a streaming call. Call should succeed.
[testApp activate];
[self pressButton:@"Send Message"];
[self pressButton:@"Stop streaming call"];
[self expectCallSuccess];
}
- (void)testCallAfterNetworkFlap {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Toggle airplane mode on and off
[self setAirplaneMode:YES];
[self setAirplaneMode:NO];
// Bring test app to foreground and make a unary call. The call should succeed
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testCallWhileNetworkDown {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Turn on airplane mode
[self setAirplaneMode:YES];
// Turn off wifi
[self setWifi:NO];
// Unary call should fail
[self doUnaryCall];
[self expectCallFailed];
// Turn off airplane mode
[self setAirplaneMode:NO];
// Turn on wifi
[self setWifi:YES];
// Unary call should succeed
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testSwitchApp {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Send test app to background
[XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
// Open stocks app
XCUIApplication *stocksApp =
[[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.stocks"];
[stocksApp activate];
// Ensure that stocks app is running in the foreground
XCTAssert([stocksApp waitForState:XCUIApplicationStateRunningForeground timeout:5]);
// Wait a bit
int sleepTime = [self getRandomNumberBetween:5 max:10];
NSLog(@"Sleeping for %d seconds", sleepTime);
[NSThread sleepForTimeInterval:sleepTime];
[stocksApp terminate];
// Make another unary call
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testNetworkFlapDuringStreamingCall {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Start streaming call and send a message
[self pressButton:@"Start streaming call"];
[self pressButton:@"Send Message"];
// Toggle network on and off
[self setAirplaneMode:YES];
[self setWifi:NO];
[self setAirplaneMode:NO];
[self setWifi:YES];
[testApp activate];
[self pressButton:@"Stop streaming call"];
// The call will fail if the stream gets a read error, else the call will succeed.
[self expectCallSuccessOrFailed];
// Make another unary call, it should succeed
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testConcurrentCalls {
NSLog(@"%s", __func__);
// Press button to start 10 unary calls
[self do10UnaryCalls];
// Toggle airplane mode on and off
[self setAirplaneMode:YES];
[self setAirplaneMode:NO];
// 10 calls should have completed
[testApp activate];
XCTAssert([testApp.staticTexts[@"Calls completed: 10"] waitForExistenceWithTimeout:kWaitTime]);
}
- (void)invokeTest {
for (int i = 0; i < kNumIterations; i++) {
[super invokeTest];
}
}
- (void)testUnaryCallTurnOffWifi {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Turn off wifi
[self setWifi:NO];
// Phone should switch to cellular connection, call should succeed
[self doUnaryCall];
[self expectCallSuccess];
// Turn on wifi
[self setWifi:YES];
// Call should succeed after turning wifi back on
[self doUnaryCall];
[self expectCallSuccess];
}
- (void)testStreamingCallTurnOffWifi {
NSLog(@"%s", __func__);
// Open test app and make a unary call. Channel to server should be open after this.
[self doUnaryCall];
[self expectCallSuccess];
// Start streaming call and send a message
[self pressButton:@"Start streaming call"];
[self pressButton:@"Send Message"];
// Turn off wifi
[self setWifi:NO];
// Phone should switch to cellular connection, this results in the call failing
[testApp activate];
[self pressButton:@"Stop streaming call"];
[self expectCallFailed];
// Turn on wifi
[self setWifi:YES];
// Call should succeed after turning wifi back on
[self doUnaryCall];
[self expectCallSuccess];
}
@end