GULNetworkTest.m 42 KB

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