GULNetworkTest.m 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. // Copyright 2018 Google
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "GoogleUtilities/Tests/Unit/Network/third_party/GTMHTTPServer.h"
  15. #import <XCTest/XCTest.h>
  16. #import "OCMock.h"
  17. #if !TARGET_OS_MACCATALYST
  18. // These tests are flaky on Catalyst. One of the tests typically fails.
  19. #import "GoogleUtilities/NSData+zlib/Public/GoogleUtilities/GULNSData+zlib.h"
  20. #import "GoogleUtilities/Network/Public/GoogleUtilities/GULNetwork.h"
  21. #import "GoogleUtilities/Reachability/Public/GoogleUtilities/GULReachabilityChecker.h"
  22. @interface GULNetwork ()
  23. - (void)reachability:(GULReachabilityChecker *)reachability
  24. statusChanged:(GULReachabilityStatus)status;
  25. @end
  26. @interface GULNetworkURLSession ()
  27. - (void)maybeRemoveTempFilesAtURL:(NSURL *)tempFile expiringTime:(NSTimeInterval)expiringTime;
  28. @end
  29. @interface GULNetworkTest : XCTestCase <GULNetworkReachabilityDelegate>
  30. @end
  31. @implementation GULNetworkTest {
  32. dispatch_queue_t _backgroundQueue;
  33. GULNetwork *_network;
  34. /// Fake Server.
  35. GTMHTTPServer *_httpServer;
  36. GTMHTTPRequestMessage *_request;
  37. int _statusCode;
  38. // For network reachability test.
  39. BOOL _fakeNetworkIsReachable;
  40. BOOL _currentNetworkStatus;
  41. GULReachabilityStatus _fakeReachabilityStatus;
  42. }
  43. #pragma mark - Setup and teardown
  44. - (void)setUp {
  45. [super setUp];
  46. _fakeNetworkIsReachable = YES;
  47. _statusCode = 200;
  48. _request = nil;
  49. _httpServer = [[GTMHTTPServer alloc] initWithDelegate:self];
  50. // Start the server.
  51. NSError *error = nil;
  52. XCTAssertTrue([_httpServer start:&error], @"Failed to start HTTP server: %@", error);
  53. _network = [[GULNetwork alloc] init];
  54. _backgroundQueue = dispatch_queue_create("Test queue", DISPATCH_QUEUE_SERIAL);
  55. _request = nil;
  56. }
  57. - (void)tearDown {
  58. _network = nil;
  59. _backgroundQueue = nil;
  60. _request = nil;
  61. [_httpServer stop];
  62. _httpServer = nil;
  63. [super tearDown];
  64. }
  65. #pragma mark - Test reachability
  66. - (void)testReachability {
  67. _network.reachabilityDelegate = self;
  68. id reachability = [_network valueForKey:@"_reachability"];
  69. XCTAssertNotNil(reachability);
  70. id reachabilityMock = OCMPartialMock(reachability);
  71. [[[reachabilityMock stub] andCall:@selector(reachabilityStatus)
  72. onObject:self] reachabilityStatus];
  73. // Fake scenario with connectivity.
  74. _fakeNetworkIsReachable = YES;
  75. _fakeReachabilityStatus = kGULReachabilityViaWifi;
  76. [_network reachability:reachabilityMock statusChanged:[reachabilityMock reachabilityStatus]];
  77. XCTAssertTrue([_network isNetworkConnected]);
  78. XCTAssertEqual(_currentNetworkStatus, _fakeNetworkIsReachable);
  79. // Fake scenario without connectivity.
  80. _fakeNetworkIsReachable = NO;
  81. _fakeReachabilityStatus = kGULReachabilityNotReachable;
  82. [_network reachability:reachabilityMock statusChanged:[reachabilityMock reachabilityStatus]];
  83. XCTAssertFalse([_network isNetworkConnected]);
  84. XCTAssertEqual(_currentNetworkStatus, _fakeNetworkIsReachable);
  85. [reachabilityMock stopMocking];
  86. reachabilityMock = nil;
  87. }
  88. #pragma mark - Test POST Foreground
  89. - (void)testSessionNetwork_POST_foreground {
  90. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  91. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  92. NSURL *url =
  93. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  94. _statusCode = 200;
  95. [_network postURL:url
  96. payload:uncompressedData
  97. queue:_backgroundQueue
  98. usingBackgroundSession:NO
  99. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  100. XCTAssertNotNil(data);
  101. NSString *responseBody = [[NSString alloc] initWithData:data
  102. encoding:NSUTF8StringEncoding];
  103. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  104. [self verifyResponse:response error:error];
  105. [self verifyRequest];
  106. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  107. [expectation fulfill];
  108. }];
  109. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  110. // Wait a little bit so the server has enough time to respond.
  111. [self waitForExpectationsWithTimeout:10
  112. handler:^(NSError *error) {
  113. if (error) {
  114. XCTFail(@"Timeout Error: %@", error);
  115. }
  116. }];
  117. }
  118. - (void)testSessionNetworkShouldReturnError_POST_foreground {
  119. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  120. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  121. NSURL *url =
  122. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  123. _statusCode = 500;
  124. [_network postURL:url
  125. payload:uncompressedData
  126. queue:_backgroundQueue
  127. usingBackgroundSession:NO
  128. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  129. XCTAssertEqual(((NSHTTPURLResponse *)response).statusCode, 500);
  130. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  131. [expectation fulfill];
  132. }];
  133. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  134. // Wait a little bit so the server has enough time to respond.
  135. [self waitForExpectationsWithTimeout:10
  136. handler:^(NSError *error) {
  137. if (error) {
  138. XCTFail(@"Timeout Error: %@", error);
  139. }
  140. }];
  141. }
  142. - (void)testNilURLNSURLSession_POST_foreground {
  143. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  144. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  145. _statusCode = 200;
  146. [_network postURL:nil
  147. payload:uncompressedData
  148. queue:_backgroundQueue
  149. usingBackgroundSession:NO
  150. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  151. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  152. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  153. [expectation fulfill];
  154. }];
  155. [self waitForExpectationsWithTimeout:10
  156. handler:^(NSError *error) {
  157. if (error) {
  158. XCTFail(@"Timeout Error: %@", error);
  159. }
  160. }];
  161. }
  162. - (void)testEmptyURLNSURLSession_POST_foreground {
  163. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  164. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  165. _statusCode = 200;
  166. [_network postURL:[NSURL URLWithString:@""]
  167. payload:uncompressedData
  168. queue:_backgroundQueue
  169. usingBackgroundSession:NO
  170. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  171. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  172. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  173. [expectation fulfill];
  174. }];
  175. [self waitForExpectationsWithTimeout:10
  176. handler:^(NSError *error) {
  177. if (error) {
  178. XCTFail(@"Timeout Error: %@", error);
  179. }
  180. }];
  181. }
  182. - (void)testEmptyPayloadNSURLSession_POST_foreground {
  183. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  184. NSData *uncompressedData = [[NSData alloc] init];
  185. NSURL *url =
  186. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  187. _statusCode = 200;
  188. [_network postURL:url
  189. payload:uncompressedData
  190. queue:_backgroundQueue
  191. usingBackgroundSession:NO
  192. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  193. XCTAssertNil(error);
  194. XCTAssertNotNil(self->_request);
  195. XCTAssertEqualObjects([self->_request.URL absoluteString], [url absoluteString]);
  196. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  197. [expectation fulfill];
  198. }];
  199. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  200. [self waitForExpectationsWithTimeout:10
  201. handler:^(NSError *error) {
  202. if (error) {
  203. XCTFail(@"Timeout Error: %@", error);
  204. }
  205. }];
  206. }
  207. - (void)testNilQueueNSURLSession_POST_foreground {
  208. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  209. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  210. NSURL *url =
  211. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/1", _httpServer.port]];
  212. _statusCode = 200;
  213. [_network postURL:url
  214. payload:uncompressedData
  215. queue:nil
  216. usingBackgroundSession:NO
  217. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  218. [self verifyResponse:response error:error];
  219. [self verifyRequest];
  220. [expectation fulfill];
  221. }];
  222. // Wait a little bit so the server has enough time to respond.
  223. [self waitForExpectationsWithTimeout:10
  224. handler:^(NSError *error) {
  225. if (error) {
  226. XCTFail(@"Timeout Error: %@", error);
  227. }
  228. }];
  229. }
  230. - (void)testHasRequestPendingNSURLSession_POST_foreground {
  231. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  232. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  233. NSURL *url =
  234. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/hasRequestPending",
  235. _httpServer.port]];
  236. _statusCode = 200;
  237. [_network postURL:url
  238. payload:uncompressedData
  239. queue:_backgroundQueue
  240. usingBackgroundSession:NO
  241. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  242. [self verifyResponse:response error:error];
  243. [self verifyRequest];
  244. XCTAssertFalse(self->_network.hasUploadInProgress,
  245. @"hasUploadInProgress must be false");
  246. [expectation fulfill];
  247. }];
  248. XCTAssertTrue(self->_network.hasUploadInProgress, @"hasUploadInProgress must be true");
  249. // Wait a little bit so the server has enough time to respond.
  250. [self waitForExpectationsWithTimeout:10
  251. handler:^(NSError *error) {
  252. if (error) {
  253. XCTFail(@"Timeout Error: %@", error);
  254. }
  255. }];
  256. }
  257. #pragma mark - Test POST Background
  258. - (void)testSessionNetwork_POST_background {
  259. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  260. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  261. NSURL *url =
  262. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  263. _statusCode = 200;
  264. [_network postURL:url
  265. payload:uncompressedData
  266. queue:_backgroundQueue
  267. usingBackgroundSession:YES
  268. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  269. XCTAssertNotNil(data);
  270. NSString *responseBody = [[NSString alloc] initWithData:data
  271. encoding:NSUTF8StringEncoding];
  272. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  273. [self verifyResponse:response error:error];
  274. [self verifyRequest];
  275. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  276. [expectation fulfill];
  277. }];
  278. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  279. // Wait a little bit so the server has enough time to respond.
  280. [self waitForExpectationsWithTimeout:10
  281. handler:^(NSError *error) {
  282. if (error) {
  283. XCTFail(@"Timeout Error: %@", error);
  284. }
  285. }];
  286. }
  287. - (void)testSessionNetworkShouldReturnError_POST_background {
  288. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  289. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  290. NSURL *url =
  291. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  292. _statusCode = 500;
  293. [_network postURL:url
  294. payload:uncompressedData
  295. queue:_backgroundQueue
  296. usingBackgroundSession:YES
  297. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  298. XCTAssertEqual(((NSHTTPURLResponse *)response).statusCode, 500);
  299. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  300. [expectation fulfill];
  301. }];
  302. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  303. // Wait a little bit so the server has enough time to respond.
  304. [self waitForExpectationsWithTimeout:10
  305. handler:^(NSError *error) {
  306. if (error) {
  307. XCTFail(@"Timeout Error: %@", error);
  308. }
  309. }];
  310. }
  311. - (void)testNilURLNSURLSession_POST_background {
  312. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  313. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  314. _statusCode = 200;
  315. [_network postURL:nil
  316. payload:uncompressedData
  317. queue:_backgroundQueue
  318. usingBackgroundSession:YES
  319. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  320. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  321. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  322. [expectation fulfill];
  323. }];
  324. [self waitForExpectationsWithTimeout:10
  325. handler:^(NSError *error) {
  326. if (error) {
  327. XCTFail(@"Timeout Error: %@", error);
  328. }
  329. }];
  330. }
  331. - (void)testEmptyURLNSURLSession_POST_background {
  332. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  333. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  334. _statusCode = 200;
  335. [_network postURL:[NSURL URLWithString:@""]
  336. payload:uncompressedData
  337. queue:_backgroundQueue
  338. usingBackgroundSession:YES
  339. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  340. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  341. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  342. [expectation fulfill];
  343. }];
  344. [self waitForExpectationsWithTimeout:10
  345. handler:^(NSError *error) {
  346. if (error) {
  347. XCTFail(@"Timeout Error: %@", error);
  348. }
  349. }];
  350. }
  351. - (void)testEmptyPayloadNSURLSession_POST_background {
  352. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  353. NSData *uncompressedData = [[NSData alloc] init];
  354. NSURL *url =
  355. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  356. _statusCode = 200;
  357. [_network postURL:url
  358. payload:uncompressedData
  359. queue:_backgroundQueue
  360. usingBackgroundSession:YES
  361. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  362. XCTAssertNil(error);
  363. XCTAssertNotNil(self->_request);
  364. XCTAssertEqualObjects([self->_request.URL absoluteString], [url absoluteString]);
  365. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  366. [expectation fulfill];
  367. }];
  368. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  369. [self waitForExpectationsWithTimeout:10
  370. handler:^(NSError *error) {
  371. if (error) {
  372. XCTFail(@"Timeout Error: %@", error);
  373. }
  374. }];
  375. }
  376. - (void)testNilQueueNSURLSession_POST_background {
  377. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  378. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  379. NSURL *url =
  380. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/1", _httpServer.port]];
  381. _statusCode = 200;
  382. [_network postURL:url
  383. payload:uncompressedData
  384. queue:nil
  385. usingBackgroundSession:YES
  386. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  387. [self verifyResponse:response error:error];
  388. [self verifyRequest];
  389. [expectation fulfill];
  390. }];
  391. // Wait a little bit so the server has enough time to respond.
  392. [self waitForExpectationsWithTimeout:10
  393. handler:^(NSError *error) {
  394. if (error) {
  395. XCTFail(@"Timeout Error: %@", error);
  396. }
  397. }];
  398. }
  399. - (void)testHasRequestPendingNSURLSession_POST_background {
  400. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  401. NSData *uncompressedData = [@"Google" dataUsingEncoding:NSUTF8StringEncoding];
  402. NSURL *url =
  403. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/hasRequestPending",
  404. _httpServer.port]];
  405. _statusCode = 200;
  406. [_network postURL:url
  407. payload:uncompressedData
  408. queue:_backgroundQueue
  409. usingBackgroundSession:YES
  410. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  411. [self verifyResponse:response error:error];
  412. [self verifyRequest];
  413. XCTAssertFalse(self->_network.hasUploadInProgress,
  414. @"hasUploadInProgress must be false");
  415. [expectation fulfill];
  416. }];
  417. XCTAssertTrue(self->_network.hasUploadInProgress, @"hasUploadInProgress must be true");
  418. // Wait a little bit so the server has enough time to respond.
  419. [self waitForExpectationsWithTimeout:10
  420. handler:^(NSError *error) {
  421. if (error) {
  422. XCTFail(@"Timeout Error: %@", error);
  423. }
  424. }];
  425. }
  426. #pragma mark - GET Methods Foreground
  427. - (void)testSessionNetworkAsync_GET_foreground {
  428. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  429. NSURL *url =
  430. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  431. _statusCode = 200;
  432. [_network getURL:url
  433. headers:nil
  434. queue:_backgroundQueue
  435. usingBackgroundSession:NO
  436. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  437. XCTAssertNotNil(data);
  438. NSString *responseBody = [[NSString alloc] initWithData:data
  439. encoding:NSUTF8StringEncoding];
  440. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  441. XCTAssertNil(error);
  442. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  443. [expectation fulfill];
  444. }];
  445. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  446. // Wait a little bit so the server has enough time to respond.
  447. [self waitForExpectationsWithTimeout:10
  448. handler:^(NSError *error) {
  449. if (error) {
  450. XCTFail(@"Timeout Error: %@", error);
  451. }
  452. }];
  453. }
  454. - (void)testSessionNetworkShouldReturnError_GET_foreground {
  455. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  456. NSURL *url =
  457. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  458. _statusCode = 500;
  459. [_network getURL:url
  460. headers:nil
  461. queue:_backgroundQueue
  462. usingBackgroundSession:NO
  463. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  464. XCTAssertEqual(((NSHTTPURLResponse *)response).statusCode, 500);
  465. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  466. [expectation fulfill];
  467. }];
  468. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  469. // Wait a little bit so the server has enough time to respond.
  470. [self waitForExpectationsWithTimeout:10
  471. handler:^(NSError *error) {
  472. if (error) {
  473. XCTFail(@"Timeout Error: %@", error);
  474. }
  475. }];
  476. }
  477. - (void)testNilURLNSURLSession_GET_foreground {
  478. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  479. _statusCode = 200;
  480. [_network getURL:nil
  481. headers:nil
  482. queue:_backgroundQueue
  483. usingBackgroundSession:NO
  484. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  485. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  486. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  487. [expectation fulfill];
  488. }];
  489. [self waitForExpectationsWithTimeout:10
  490. handler:^(NSError *error) {
  491. if (error) {
  492. XCTFail(@"Timeout Error: %@", error);
  493. }
  494. }];
  495. }
  496. - (void)testEmptyURLNSURLSession_GET_foreground {
  497. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  498. _statusCode = 200;
  499. [_network getURL:[NSURL URLWithString:@""]
  500. headers:nil
  501. queue:_backgroundQueue
  502. usingBackgroundSession:NO
  503. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  504. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  505. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  506. [expectation fulfill];
  507. }];
  508. [self waitForExpectationsWithTimeout:10
  509. handler:^(NSError *error) {
  510. if (error) {
  511. XCTFail(@"Timeout Error: %@", error);
  512. }
  513. }];
  514. }
  515. - (void)testNilQueueNSURLSession_GET_foreground {
  516. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  517. NSURL *url =
  518. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/1", _httpServer.port]];
  519. _statusCode = 200;
  520. [_network getURL:url
  521. headers:nil
  522. queue:nil
  523. usingBackgroundSession:NO
  524. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  525. XCTAssertNotNil(data);
  526. NSString *responseBody = [[NSString alloc] initWithData:data
  527. encoding:NSUTF8StringEncoding];
  528. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  529. XCTAssertNil(error);
  530. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  531. [expectation fulfill];
  532. }];
  533. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  534. // Wait a little bit so the server has enough time to respond.
  535. [self waitForExpectationsWithTimeout:10
  536. handler:^(NSError *error) {
  537. if (error) {
  538. XCTFail(@"Timeout Error: %@", error);
  539. }
  540. }];
  541. }
  542. - (void)testHasRequestPendingNSURLSession_GET_foreground {
  543. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  544. NSURL *url =
  545. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/hasRequestPending",
  546. _httpServer.port]];
  547. _statusCode = 200;
  548. [_network getURL:url
  549. headers:nil
  550. queue:_backgroundQueue
  551. usingBackgroundSession:NO
  552. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  553. XCTAssertNotNil(data);
  554. NSString *responseBody = [[NSString alloc] initWithData:data
  555. encoding:NSUTF8StringEncoding];
  556. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  557. XCTAssertNil(error);
  558. XCTAssertFalse(self->_network.hasUploadInProgress,
  559. @"hasUploadInProgress must be false");
  560. [expectation fulfill];
  561. }];
  562. XCTAssertTrue(self->_network.hasUploadInProgress, @"hasUploadInProgress must be true");
  563. // Wait a little bit so the server has enough time to respond.
  564. [self waitForExpectationsWithTimeout:10
  565. handler:^(NSError *error) {
  566. if (error) {
  567. XCTFail(@"Timeout Error: %@", error);
  568. }
  569. }];
  570. }
  571. - (void)testHeaders_foreground {
  572. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  573. NSURL *url =
  574. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  575. _statusCode = 200;
  576. NSDictionary *headers = @{@"Version" : @"123"};
  577. [_network getURL:url
  578. headers:headers
  579. queue:_backgroundQueue
  580. usingBackgroundSession:NO
  581. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  582. XCTAssertNotNil(data);
  583. NSString *responseBody = [[NSString alloc] initWithData:data
  584. encoding:NSUTF8StringEncoding];
  585. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  586. XCTAssertNil(error);
  587. NSString *version = [self->_request.allHeaderFieldValues valueForKey:@"Version"];
  588. XCTAssertEqualObjects(version, @"123");
  589. [expectation fulfill];
  590. }];
  591. // Wait a little bit so the server has enough time to respond.
  592. [self waitForExpectationsWithTimeout:10
  593. handler:^(NSError *error) {
  594. if (error) {
  595. XCTFail(@"Timeout Error: %@", error);
  596. }
  597. }];
  598. }
  599. #pragma mark - GET Methods Background
  600. - (void)testSessionNetworkAsync_GET_background {
  601. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  602. NSURL *url =
  603. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/2", _httpServer.port]];
  604. _statusCode = 200;
  605. [_network getURL:url
  606. headers:nil
  607. queue:_backgroundQueue
  608. usingBackgroundSession:YES
  609. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  610. XCTAssertNotNil(data);
  611. NSString *responseBody = [[NSString alloc] initWithData:data
  612. encoding:NSUTF8StringEncoding];
  613. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  614. XCTAssertNil(error);
  615. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  616. [expectation fulfill];
  617. }];
  618. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  619. // Wait a little bit so the server has enough time to respond.
  620. [self waitForExpectationsWithTimeout:10
  621. handler:^(NSError *error) {
  622. if (error) {
  623. XCTFail(@"Timeout Error: %@", error);
  624. }
  625. }];
  626. }
  627. - (void)testSessionNetworkShouldReturnError_GET_background {
  628. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  629. NSURL *url =
  630. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  631. _statusCode = 500;
  632. [_network getURL:url
  633. headers:nil
  634. queue:_backgroundQueue
  635. usingBackgroundSession:YES
  636. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  637. XCTAssertEqual(((NSHTTPURLResponse *)response).statusCode, 500);
  638. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  639. [expectation fulfill];
  640. }];
  641. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  642. // Wait a little bit so the server has enough time to respond.
  643. [self waitForExpectationsWithTimeout:10
  644. handler:^(NSError *error) {
  645. if (error) {
  646. XCTFail(@"Timeout Error: %@", error);
  647. }
  648. }];
  649. }
  650. - (void)testNilURLNSURLSession_GET_background {
  651. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  652. _statusCode = 200;
  653. [_network getURL:nil
  654. headers:nil
  655. queue:_backgroundQueue
  656. usingBackgroundSession:YES
  657. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  658. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  659. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  660. [expectation fulfill];
  661. }];
  662. [self waitForExpectationsWithTimeout:10
  663. handler:^(NSError *error) {
  664. if (error) {
  665. XCTFail(@"Timeout Error: %@", error);
  666. }
  667. }];
  668. }
  669. - (void)testEmptyURLNSURLSession_GET_background {
  670. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  671. _statusCode = 200;
  672. [_network getURL:[NSURL URLWithString:@""]
  673. headers:nil
  674. queue:_backgroundQueue
  675. usingBackgroundSession:YES
  676. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  677. XCTAssertEqual(error.code, GULErrorCodeNetworkInvalidURL);
  678. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  679. [expectation fulfill];
  680. }];
  681. [self waitForExpectationsWithTimeout:10
  682. handler:^(NSError *error) {
  683. if (error) {
  684. XCTFail(@"Timeout Error: %@", error);
  685. }
  686. }];
  687. }
  688. - (void)testNilQueueNSURLSession_GET_background {
  689. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  690. NSURL *url =
  691. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/1", _httpServer.port]];
  692. _statusCode = 200;
  693. [_network getURL:url
  694. headers:nil
  695. queue:nil
  696. usingBackgroundSession:YES
  697. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  698. XCTAssertNotNil(data);
  699. NSString *responseBody = [[NSString alloc] initWithData:data
  700. encoding:NSUTF8StringEncoding];
  701. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  702. XCTAssertNil(error);
  703. XCTAssertFalse(self->_network.hasUploadInProgress, "There must be no pending request");
  704. [expectation fulfill];
  705. }];
  706. XCTAssertTrue(self->_network.hasUploadInProgress, "There must be a pending request");
  707. // Wait a little bit so the server has enough time to respond.
  708. [self waitForExpectationsWithTimeout:10
  709. handler:^(NSError *error) {
  710. if (error) {
  711. XCTFail(@"Timeout Error: %@", error);
  712. }
  713. }];
  714. }
  715. - (void)testHasRequestPendingNSURLSession_GET_background {
  716. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  717. NSURL *url =
  718. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/hasRequestPending",
  719. _httpServer.port]];
  720. _statusCode = 200;
  721. [_network getURL:url
  722. headers:nil
  723. queue:_backgroundQueue
  724. usingBackgroundSession:YES
  725. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  726. XCTAssertNotNil(data);
  727. NSString *responseBody = [[NSString alloc] initWithData:data
  728. encoding:NSUTF8StringEncoding];
  729. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  730. XCTAssertNil(error);
  731. XCTAssertFalse(self->_network.hasUploadInProgress,
  732. @"hasUploadInProgress must be false");
  733. [expectation fulfill];
  734. }];
  735. XCTAssertTrue(self->_network.hasUploadInProgress, @"hasUploadInProgress must be true");
  736. // Wait a little bit so the server has enough time to respond.
  737. [self waitForExpectationsWithTimeout:10
  738. handler:^(NSError *error) {
  739. if (error) {
  740. XCTFail(@"Timeout Error: %@", error);
  741. }
  742. }];
  743. }
  744. - (void)testHeaders_background {
  745. XCTestExpectation *expectation = [self expectationWithDescription:@"Expect block is called"];
  746. NSURL *url =
  747. [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:%d/3", _httpServer.port]];
  748. _statusCode = 200;
  749. NSDictionary *headers = @{@"Version" : @"123"};
  750. [_network getURL:url
  751. headers:headers
  752. queue:_backgroundQueue
  753. usingBackgroundSession:YES
  754. completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
  755. XCTAssertNotNil(data);
  756. NSString *responseBody = [[NSString alloc] initWithData:data
  757. encoding:NSUTF8StringEncoding];
  758. XCTAssertEqualObjects(responseBody, @"<html><body>Hello, World!</body></html>");
  759. XCTAssertNil(error);
  760. NSString *version = [self->_request.allHeaderFieldValues valueForKey:@"Version"];
  761. XCTAssertEqualObjects(version, @"123");
  762. [expectation fulfill];
  763. }];
  764. // Wait a little bit so the server has enough time to respond.
  765. [self waitForExpectationsWithTimeout:10
  766. handler:^(NSError *error) {
  767. if (error) {
  768. XCTFail(@"Timeout Error: %@", error);
  769. }
  770. }];
  771. }
  772. #pragma mark - Test clean up files
  773. - (void)testRemoveExpiredFiles {
  774. NSError *writeError = nil;
  775. NSFileManager *fileManager = [NSFileManager defaultManager];
  776. GULNetworkURLSession *session = [[GULNetworkURLSession alloc]
  777. initWithNetworkLoggerDelegate:(id<GULNetworkLoggerDelegate>)_network];
  778. #if TARGET_OS_TV
  779. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  780. #else
  781. NSArray *paths =
  782. NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
  783. #endif
  784. NSString *applicationSupportDirectory = paths.firstObject;
  785. NSArray *tempPathComponents = @[
  786. applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory,
  787. @"GULNetworkTemporaryDirectory"
  788. ];
  789. NSURL *folderURL = [NSURL fileURLWithPathComponents:tempPathComponents];
  790. [fileManager createDirectoryAtURL:folderURL
  791. withIntermediateDirectories:YES
  792. attributes:nil
  793. error:&writeError];
  794. NSURL *tempFile1 = [folderURL URLByAppendingPathComponent:@"FIRUpload_temp_123"];
  795. [self createTempFileAtURL:tempFile1];
  796. NSURL *tempFile2 = [folderURL URLByAppendingPathComponent:@"FIRUpload_temp_456"];
  797. [self createTempFileAtURL:tempFile2];
  798. XCTAssertTrue([fileManager fileExistsAtPath:tempFile1.path]);
  799. XCTAssertTrue([fileManager fileExistsAtPath:tempFile2.path]);
  800. NSDate *now =
  801. [[NSDate date] dateByAddingTimeInterval:1]; // Start mocking the clock to avoid flakiness.
  802. id mockDate = OCMStrictClassMock([NSDate class]);
  803. [[[mockDate stub] andReturn:now] date];
  804. // The file should not be removed since it is not expired yet.
  805. [session maybeRemoveTempFilesAtURL:folderURL expiringTime:20];
  806. XCTAssertTrue([fileManager fileExistsAtPath:tempFile1.path]);
  807. XCTAssertTrue([fileManager fileExistsAtPath:tempFile2.path]);
  808. [mockDate stopMocking];
  809. mockDate = nil;
  810. now = [[NSDate date] dateByAddingTimeInterval:100]; // Move forward in time 100s.
  811. mockDate = OCMStrictClassMock([NSDate class]);
  812. [[[mockDate stub] andReturn:now] date];
  813. [session maybeRemoveTempFilesAtURL:folderURL expiringTime:20];
  814. XCTAssertFalse([fileManager fileExistsAtPath:tempFile1.path]);
  815. XCTAssertFalse([fileManager fileExistsAtPath:tempFile2.path]);
  816. [mockDate stopMocking];
  817. mockDate = nil;
  818. }
  819. #pragma mark - Internal Methods
  820. - (void)createTempFileAtURL:(NSURL *)fileURL {
  821. // Create a dictionary and write it to file.
  822. NSDictionary *someContent = @{@"object" : @"key"};
  823. [someContent writeToURL:fileURL atomically:YES];
  824. }
  825. - (void)verifyResponse:(NSHTTPURLResponse *)response error:(NSError *)error {
  826. XCTAssertNil(error, @"Error is not expected");
  827. XCTAssertNotNil(response, @"Error is not expected");
  828. }
  829. - (void)verifyRequest {
  830. XCTAssertNotNil(_request, @"Request cannot be nil");
  831. // Test whether the request is compressed correctly.
  832. NSData *requestBody = [_request body];
  833. NSData *decompressedRequestData = [NSData gul_dataByInflatingGzippedData:requestBody error:NULL];
  834. NSString *requestString = [[NSString alloc] initWithData:decompressedRequestData
  835. encoding:NSUTF8StringEncoding];
  836. XCTAssertEqualObjects(requestString, @"Google", @"Request is not compressed correctly.");
  837. // The request has to be a POST.
  838. XCTAssertEqualObjects([_request method], @"POST", @"Request method has to be POST");
  839. // Content length has to be set correctly.
  840. NSString *contentLength = [_request.allHeaderFieldValues valueForKey:@"Content-Length"];
  841. XCTAssertEqualObjects(contentLength, @"26", @"Content Length is incorrect");
  842. NSString *contentEncoding = [_request.allHeaderFieldValues valueForKey:@"Content-Encoding"];
  843. XCTAssertEqualObjects(contentEncoding, @"gzip", @"Content Encoding is incorrect");
  844. }
  845. #pragma mark - Helper Methods
  846. - (GTMHTTPResponseMessage *)httpServer:(GTMHTTPServer *)server
  847. handleRequest:(GTMHTTPRequestMessage *)request {
  848. _request = request;
  849. NSData *html =
  850. [@"<html><body>Hello, World!</body></html>" dataUsingEncoding:NSUTF8StringEncoding];
  851. return [GTMHTTPResponseMessage responseWithBody:html
  852. contentType:@"text/html; charset=UTF-8"
  853. statusCode:_statusCode];
  854. }
  855. - (BOOL)isReachable {
  856. return _fakeNetworkIsReachable;
  857. }
  858. - (GULReachabilityStatus)reachabilityStatus {
  859. return _fakeReachabilityStatus;
  860. }
  861. #pragma mark - FIRReachabilityDelegate
  862. - (void)reachabilityDidChange {
  863. _currentNetworkStatus = _fakeNetworkIsReachable;
  864. }
  865. @end
  866. #endif // TARGET_OS_MACCATALYST