FIRNetworkTest.m 41 KB

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