FIRNetworkTest.m 41 KB

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