xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1/*
2 *
3 * Copyright 2019 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19#import <XCTest/XCTest.h>
20
21NSTimeInterval const kWaitTime = 30;
22int const kNumIterations = 1;
23
24@interface GrpcIosTestUITests : XCTestCase
25@end
26
27@implementation GrpcIosTestUITests {
28  XCUIApplication *testApp;
29  XCUIApplication *settingsApp;
30}
31
32- (void)setUp {
33  self.continueAfterFailure = NO;
34  [[[XCUIApplication alloc] init] launch];
35  testApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.grpc.GrpcIosTest"];
36  [testApp activate];
37  // Reset RPC counter
38  [self pressButton:@"Reset counter"];
39
40  settingsApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.Preferences"];
41  [settingsApp activate];
42  [NSThread sleepForTimeInterval:1];
43  // Go back to the first page of Settings.
44  XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch;
45  while (backButton.exists && backButton.isHittable) {
46    NSLog(@"Tapping back button");
47    [backButton tap];
48  }
49  XCTAssert([settingsApp.navigationBars[@"Settings"] waitForExistenceWithTimeout:kWaitTime]);
50  NSLog(@"Turning off airplane mode");
51  // Turn off airplane mode
52  [self setAirplaneMode:NO];
53
54  // Turn on wifi
55  NSLog(@"Turning on wifi");
56  [self setWifi:YES];
57}
58
59- (void)tearDown {
60}
61
62- (void)doUnaryCall {
63  [testApp activate];
64  [self pressButton:@"Unary call"];
65}
66
67- (void)do10UnaryCalls {
68  [testApp activate];
69  [self pressButton:@"10 Unary calls"];
70}
71
72- (void)pressButton:(NSString *)name {
73  // Wait for button to be visible
74  while (![testApp.buttons[name] exists] || ![testApp.buttons[name] isHittable]) {
75    [NSThread sleepForTimeInterval:1];
76  }
77  // Wait until all events in run loop have been processed
78  while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource)
79    ;
80
81  NSLog(@"Pressing button: %@", name);
82  [testApp.buttons[name] tap];
83}
84
85- (void)expectCallSuccess {
86  XCTAssert([testApp.staticTexts[@"Call done"] waitForExistenceWithTimeout:kWaitTime]);
87}
88
89- (void)expectCallFailed {
90  XCTAssert([testApp.staticTexts[@"Call failed"] waitForExistenceWithTimeout:kWaitTime]);
91}
92
93- (void)expectCallSuccessOrFailed {
94  NSDate *startTime = [NSDate date];
95  while (![testApp.staticTexts[@"Call done"] exists] &&
96         ![testApp.staticTexts[@"Call failed"] exists]) {
97    XCTAssertLessThan([[NSDate date] timeIntervalSinceDate:startTime], kWaitTime);
98    [NSThread sleepForTimeInterval:1];
99  }
100}
101
102- (void)setAirplaneMode:(BOOL)to {
103  [settingsApp activate];
104  XCUIElement *mySwitch = settingsApp.tables.element.cells.switches[@"Airplane Mode"];
105  BOOL from = [(NSString *)mySwitch.value boolValue];
106  NSLog(@"Setting airplane from: %d to: %d", from, to);
107  if (from != to) {
108    [mySwitch tap];
109    // wait for network change to finish
110    [NSThread sleepForTimeInterval:5];
111  }
112  XCTAssert([(NSString *)mySwitch.value boolValue] == to);
113}
114- (void)setWifi:(BOOL)to {
115  [settingsApp activate];
116  [settingsApp.tables.element.cells.staticTexts[@"Wi-Fi"] tap];
117  XCUIElement *wifiSwitch = settingsApp.tables.cells.switches[@"Wi-Fi"];
118  BOOL from = [(NSString *)wifiSwitch.value boolValue];
119  NSLog(@"Setting wifi from: %d to: %d", from, to);
120  if (from != to) {
121    [wifiSwitch tap];
122    // wait for wifi networks to be detected
123    [NSThread sleepForTimeInterval:10];
124  }
125  // Go back to the first page of Settings.
126  XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch;
127  [backButton tap];
128}
129
130- (int)getRandomNumberBetween:(int)min max:(int)max {
131  return min + arc4random_uniform((max - min + 1));
132}
133
134- (void)testBackgroundBeforeCall {
135  NSLog(@"%s", __func__);
136  // Open test app
137  [testApp activate];
138  // Send test app to background
139  [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
140
141  // Wait a bit
142  int sleepTime = [self getRandomNumberBetween:5 max:10];
143  NSLog(@"Sleeping for %d seconds", sleepTime);
144  [NSThread sleepForTimeInterval:sleepTime];
145
146  // Bring test app to foreground and make a unary call. Call should succeed
147  [self doUnaryCall];
148  [self expectCallSuccess];
149}
150
151- (void)testBackgroundDuringStreamingCall {
152  NSLog(@"%s", __func__);
153  // Open test app and start a streaming call
154  [testApp activate];
155  [self pressButton:@"Start streaming call"];
156
157  // Send test app to background
158  [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
159
160  // Wait a bit
161  int sleepTime = [self getRandomNumberBetween:5 max:10];
162  NSLog(@"Sleeping for %d seconds", sleepTime);
163  [NSThread sleepForTimeInterval:sleepTime];
164
165  // Bring test app to foreground and make a streaming call. Call should succeed.
166  [testApp activate];
167  [self pressButton:@"Send Message"];
168  [self pressButton:@"Stop streaming call"];
169  [self expectCallSuccess];
170}
171
172- (void)testCallAfterNetworkFlap {
173  NSLog(@"%s", __func__);
174  // Open test app and make a unary call. Channel to server should be open after this.
175  [self doUnaryCall];
176  [self expectCallSuccess];
177
178  // Toggle airplane mode on and off
179  [self setAirplaneMode:YES];
180  [self setAirplaneMode:NO];
181
182  // Bring test app to foreground and make a unary call. The call should succeed
183  [self doUnaryCall];
184  [self expectCallSuccess];
185}
186
187- (void)testCallWhileNetworkDown {
188  NSLog(@"%s", __func__);
189  // Open test app and make a unary call. Channel to server should be open after this.
190  [self doUnaryCall];
191  [self expectCallSuccess];
192
193  // Turn on airplane mode
194  [self setAirplaneMode:YES];
195  // Turn off wifi
196  [self setWifi:NO];
197
198  // Unary call should fail
199  [self doUnaryCall];
200  [self expectCallFailed];
201
202  // Turn off airplane mode
203  [self setAirplaneMode:NO];
204  // Turn on wifi
205  [self setWifi:YES];
206
207  // Unary call should succeed
208  [self doUnaryCall];
209  [self expectCallSuccess];
210}
211
212- (void)testSwitchApp {
213  NSLog(@"%s", __func__);
214  // Open test app and make a unary call. Channel to server should be open after this.
215  [self doUnaryCall];
216  [self expectCallSuccess];
217
218  // Send test app to background
219  [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome];
220
221  // Open stocks app
222  XCUIApplication *stocksApp =
223      [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.stocks"];
224  [stocksApp activate];
225  // Ensure that stocks app is running in the foreground
226  XCTAssert([stocksApp waitForState:XCUIApplicationStateRunningForeground timeout:5]);
227  // Wait a bit
228  int sleepTime = [self getRandomNumberBetween:5 max:10];
229  NSLog(@"Sleeping for %d seconds", sleepTime);
230  [NSThread sleepForTimeInterval:sleepTime];
231  [stocksApp terminate];
232
233  // Make another unary call
234  [self doUnaryCall];
235  [self expectCallSuccess];
236}
237
238- (void)testNetworkFlapDuringStreamingCall {
239  NSLog(@"%s", __func__);
240  // Open test app and make a unary call. Channel to server should be open after this.
241  [self doUnaryCall];
242  [self expectCallSuccess];
243  // Start streaming call and send a message
244  [self pressButton:@"Start streaming call"];
245  [self pressButton:@"Send Message"];
246
247  // Toggle network on and off
248  [self setAirplaneMode:YES];
249  [self setWifi:NO];
250  [self setAirplaneMode:NO];
251  [self setWifi:YES];
252
253  [testApp activate];
254  [self pressButton:@"Stop streaming call"];
255  // The call will fail if the stream gets a read error, else the call will succeed.
256  [self expectCallSuccessOrFailed];
257
258  // Make another unary call, it should succeed
259  [self doUnaryCall];
260  [self expectCallSuccess];
261}
262
263- (void)testConcurrentCalls {
264  NSLog(@"%s", __func__);
265
266  // Press button to start 10 unary calls
267  [self do10UnaryCalls];
268
269  // Toggle airplane mode on and off
270  [self setAirplaneMode:YES];
271  [self setAirplaneMode:NO];
272
273  // 10 calls should have completed
274  [testApp activate];
275  XCTAssert([testApp.staticTexts[@"Calls completed: 10"] waitForExistenceWithTimeout:kWaitTime]);
276}
277
278- (void)invokeTest {
279  for (int i = 0; i < kNumIterations; i++) {
280    [super invokeTest];
281  }
282}
283
284- (void)testUnaryCallTurnOffWifi {
285  NSLog(@"%s", __func__);
286  // Open test app and make a unary call. Channel to server should be open after this.
287  [self doUnaryCall];
288  [self expectCallSuccess];
289
290  // Turn off wifi
291  [self setWifi:NO];
292
293  // Phone should switch to cellular connection, call should succeed
294  [self doUnaryCall];
295  [self expectCallSuccess];
296
297  // Turn on wifi
298  [self setWifi:YES];
299
300  // Call should succeed after turning wifi back on
301  [self doUnaryCall];
302  [self expectCallSuccess];
303}
304
305- (void)testStreamingCallTurnOffWifi {
306  NSLog(@"%s", __func__);
307  // Open test app and make a unary call. Channel to server should be open after this.
308  [self doUnaryCall];
309  [self expectCallSuccess];
310
311  // Start streaming call and send a message
312  [self pressButton:@"Start streaming call"];
313  [self pressButton:@"Send Message"];
314
315  // Turn off wifi
316  [self setWifi:NO];
317
318  // Phone should switch to cellular connection, this results in the call failing
319  [testApp activate];
320  [self pressButton:@"Stop streaming call"];
321  [self expectCallFailed];
322
323  // Turn on wifi
324  [self setWifi:YES];
325
326  // Call should succeed after turning wifi back on
327  [self doUnaryCall];
328  [self expectCallSuccess];
329}
330
331@end
332