FIRStorageIntegrationTests.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. // Copyright 2017 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 <FirebaseAuth/FirebaseAuth.h>
  15. #import <FirebaseStorage/FirebaseStorage.h>
  16. #import <XCTest/XCTest.h>
  17. #import <FirebaseCore/FIRApp.h>
  18. #import <FirebaseCore/FIROptions.h>
  19. #import "Credentials.h"
  20. NSTimeInterval kFIRStorageIntegrationTestTimeout = 60;
  21. /**
  22. * Firebase Storage Integration tests
  23. *
  24. * To run these tests, you need to define the following access rights:
  25. *
  26. rules_version = '2';
  27. service firebase.storage {
  28. match /b/{bucket}/o {
  29. match /ios {
  30. match /public/{allPaths=**} {
  31. allow write: if request.auth != null;
  32. allow read: if true;
  33. }
  34. match /private/{allPaths=**} {
  35. allow read, write: if false;
  36. }
  37. }
  38. }
  39. }
  40. *
  41. * You also need to enable email/password sign in and add a test user in your
  42. * Firebase Authentication settings. Your account credentials need to match
  43. * the credentials defined in `kTestUser` and `kTestPassword`.
  44. *
  45. * You can define these access rights in the Firebase Console of your project.
  46. */
  47. NSString *const kTestUser = KUSER_NAME;
  48. NSString *const kTestPassword = KPASSWORD;
  49. @interface FIRStorageIntegrationTests : XCTestCase
  50. @property(strong, nonatomic) FIRApp *app;
  51. @property(strong, nonatomic) FIRAuth *auth;
  52. @property(strong, nonatomic) FIRStorage *storage;
  53. @end
  54. @implementation FIRStorageIntegrationTests
  55. + (void)setUp {
  56. [FIRApp configure];
  57. }
  58. - (void)setUp {
  59. [super setUp];
  60. self.app = [FIRApp defaultApp];
  61. self.auth = [FIRAuth authWithApp:self.app];
  62. self.storage = [FIRStorage storageForApp:self.app];
  63. static dispatch_once_t once;
  64. dispatch_once(&once, ^{
  65. XCTestExpectation *signInExpectation = [self expectationWithDescription:@"signIn"];
  66. [self.auth signInWithEmail:kTestUser
  67. password:kTestPassword
  68. completion:^(FIRAuthDataResult *result, NSError *error) {
  69. XCTAssertNil(error);
  70. [signInExpectation fulfill];
  71. }];
  72. [self waitForExpectations];
  73. XCTestExpectation *setUpExpectation = [self expectationWithDescription:@"setUp"];
  74. NSArray<NSString *> *largeFiles = @[ @"ios/public/1mb" ];
  75. NSArray<NSString *> *emptyFiles = @[
  76. @"ios/public/empty", @"ios/public/list/a", @"ios/public/list/b", @"ios/public/list/prefix/c"
  77. ];
  78. setUpExpectation.expectedFulfillmentCount = largeFiles.count + emptyFiles.count;
  79. NSString *filePath = [[NSBundle mainBundle] pathForResource:@"1mb" ofType:@"dat"];
  80. if (filePath == nil) {
  81. // Use bundleForClass to allow 1mb.dat to be in the test target's bundle.
  82. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  83. filePath = [bundle pathForResource:@"1mb" ofType:@"dat"];
  84. }
  85. NSData *data = [NSData dataWithContentsOfFile:filePath];
  86. XCTAssertNotNil(data, "Could not load bundled file");
  87. for (NSString *largeFile in largeFiles) {
  88. FIRStorageReference *file = [[FIRStorage storage].reference child:largeFile];
  89. [file putData:data
  90. metadata:nil
  91. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  92. XCTAssertNil(error);
  93. [setUpExpectation fulfill];
  94. }];
  95. }
  96. for (NSString *emptyFile in emptyFiles) {
  97. FIRStorageReference *file = [[FIRStorage storage].reference child:emptyFile];
  98. [file putData:[NSData data]
  99. metadata:nil
  100. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  101. XCTAssertNil(error);
  102. [setUpExpectation fulfill];
  103. }];
  104. }
  105. [self waitForExpectations];
  106. });
  107. }
  108. - (void)tearDown {
  109. self.app = nil;
  110. self.storage = nil;
  111. [super tearDown];
  112. }
  113. - (void)testName {
  114. NSString *aGSURI = [NSString
  115. stringWithFormat:@"gs://%@.appspot.com/path/to", [[FIRApp defaultApp] options].projectID];
  116. FIRStorageReference *ref = [self.storage referenceForURL:aGSURI];
  117. XCTAssertEqualObjects(ref.description, aGSURI);
  118. }
  119. - (void)testGetMetadata {
  120. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetMetadata"];
  121. FIRStorageReference *ref = [self.storage.reference child:@"ios/public/1mb"];
  122. [ref metadataWithCompletion:^(FIRStorageMetadata *metadata, NSError *error) {
  123. XCTAssertNotNil(metadata, "Metadata should not be nil");
  124. XCTAssertNil(error, "Error should be nil");
  125. [expectation fulfill];
  126. }];
  127. [self waitForExpectations];
  128. }
  129. - (void)testDelete {
  130. XCTestExpectation *expectation = [self expectationWithDescription:@"testDelete"];
  131. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/fileToDelete"];
  132. NSData *data = [@"Delete me!!!!!!!" dataUsingEncoding:NSUTF8StringEncoding];
  133. [ref putData:data
  134. metadata:nil
  135. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  136. XCTAssertNotNil(metadata, "Metadata should not be nil");
  137. XCTAssertNil(error, "Error should be nil");
  138. [ref deleteWithCompletion:^(NSError *error) {
  139. XCTAssertNil(error, "Error should be nil");
  140. [expectation fulfill];
  141. }];
  142. }];
  143. [self waitForExpectations];
  144. }
  145. - (void)testDeleteWithNilCompletion {
  146. XCTestExpectation *expectation = [self expectationWithDescription:@"testDeleteWithNilCompletion"];
  147. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/fileToDelete"];
  148. NSData *data = [@"Delete me!!!!!!!" dataUsingEncoding:NSUTF8StringEncoding];
  149. [ref putData:data
  150. metadata:nil
  151. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  152. XCTAssertNotNil(metadata, "Metadata should not be nil");
  153. XCTAssertNil(error, "Error should be nil");
  154. [ref deleteWithCompletion:nil];
  155. [expectation fulfill];
  156. }];
  157. [self waitForExpectations];
  158. }
  159. - (void)testPutDataSpecialCharacter {
  160. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutDataSpecialCharacter"];
  161. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/-._~!$'()*,=:@&+;"];
  162. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  163. [ref putData:data
  164. metadata:nil
  165. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  166. XCTAssertNotNil(metadata, "Metadata should not be nil");
  167. XCTAssertNil(error, "Error should be nil");
  168. [expectation fulfill];
  169. }];
  170. [self waitForExpectations];
  171. }
  172. - (void)testPutDataInBackgroundQueue {
  173. XCTestExpectation *expectation =
  174. [self expectationWithDescription:@"testPutDataInBackgroundQueue"];
  175. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/testBytesUpload"];
  176. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  177. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  178. [ref putData:data
  179. metadata:nil
  180. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  181. XCTAssertNotNil(metadata, "Metadata should not be nil");
  182. XCTAssertNil(error, "Error should be nil");
  183. [expectation fulfill];
  184. }];
  185. });
  186. [self waitForExpectations];
  187. }
  188. - (void)testPutDataWithEmptyData {
  189. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutDataWithEmptyData"];
  190. FIRStorageReference *ref =
  191. [self.storage referenceWithPath:@"ios/public/testUnauthenticatedSimplePutEmptyData"];
  192. NSData *data = [[NSData alloc] init];
  193. [ref putData:data
  194. metadata:nil
  195. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  196. XCTAssertNotNil(metadata, "Metadata should not be nil");
  197. XCTAssertNil(error, "Error should be nil");
  198. [expectation fulfill];
  199. }];
  200. [self waitForExpectations];
  201. }
  202. - (void)testPutData {
  203. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutData"];
  204. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/private/secretfile.txt"];
  205. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  206. [ref putData:data
  207. metadata:nil
  208. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  209. XCTAssertNil(metadata, "Metadata should be nil");
  210. XCTAssertNotNil(error, "Error should not be nil");
  211. XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthorized);
  212. [expectation fulfill];
  213. }];
  214. [self waitForExpectations];
  215. }
  216. - (void)testPutFile {
  217. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutFile"];
  218. FIRStorageReference *ref =
  219. [self.storage referenceWithPath:@"ios/public/testUnauthenticatedSimplePutFile"];
  220. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  221. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  222. NSURL *fileURL =
  223. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  224. [data writeToURL:fileURL atomically:YES];
  225. FIRStorageUploadTask *task = [ref putFile:fileURL
  226. metadata:nil
  227. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  228. XCTAssertNotNil(metadata, "Metadata should not be nil");
  229. XCTAssertNil(error, "Error should be nil");
  230. }];
  231. __block long uploadedBytes = -1;
  232. [task observeStatus:FIRStorageTaskStatusSuccess
  233. handler:^(FIRStorageTaskSnapshot *snapshot) {
  234. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  235. [expectation fulfill];
  236. }];
  237. [task observeStatus:FIRStorageTaskStatusProgress
  238. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  239. XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
  240. [[snapshot description] containsString:@"State: Resume"]);
  241. NSProgress *progress = snapshot.progress;
  242. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, uploadedBytes);
  243. uploadedBytes = (long)progress.completedUnitCount;
  244. }];
  245. [self waitForExpectations];
  246. }
  247. - (void)testPutFileWithSpecialCharacters {
  248. XCTestExpectation *expectation =
  249. [self expectationWithDescription:@"testPutFileWithSpecialCharacters"];
  250. NSString *fileName = @"hello&+@_ .txt";
  251. FIRStorageReference *ref =
  252. [self.storage referenceWithPath:[@"ios/public/" stringByAppendingString:fileName]];
  253. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  254. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  255. NSURL *fileURL = [tmpDirURL URLByAppendingPathComponent:fileName];
  256. [data writeToURL:fileURL atomically:YES];
  257. [ref putFile:fileURL
  258. metadata:nil
  259. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  260. XCTAssertNotNil(metadata, "Metadata should not be nil");
  261. XCTAssertNil(error, "Error should be nil");
  262. XCTAssertEqualObjects(fileName, metadata.name);
  263. FIRStorageReference *download =
  264. [self.storage referenceWithPath:[@"ios/public/" stringByAppendingString:fileName]];
  265. [download metadataWithCompletion:^(FIRStorageMetadata *metadata, NSError *error) {
  266. XCTAssertNotNil(metadata, "Metadata should not be nil");
  267. XCTAssertNil(error, "Error should be nil");
  268. XCTAssertEqualObjects(fileName, metadata.name);
  269. [expectation fulfill];
  270. }];
  271. }];
  272. [self waitForExpectations];
  273. }
  274. - (void)testPutDataNoMetadata {
  275. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutDataNoMetadata"];
  276. FIRStorageReference *ref =
  277. [self.storage referenceWithPath:@"ios/public/testUnauthenticatedSimplePutDataNoMetadata"];
  278. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  279. [ref putData:data
  280. metadata:nil
  281. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  282. XCTAssertNotNil(metadata, "Metadata should not be nil");
  283. XCTAssertNil(error, "Error should be nil");
  284. [expectation fulfill];
  285. }];
  286. [self waitForExpectations];
  287. }
  288. - (void)testPutFileNoMetadata {
  289. XCTestExpectation *expectation = [self expectationWithDescription:@"testPutFileNoMetadata"];
  290. FIRStorageReference *ref =
  291. [self.storage referenceWithPath:@"ios/public/testUnauthenticatedSimplePutFileNoMetadata"];
  292. NSData *data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
  293. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  294. NSURL *fileURL =
  295. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  296. [data writeToURL:fileURL atomically:YES];
  297. [ref putFile:fileURL
  298. metadata:nil
  299. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  300. XCTAssertNotNil(metadata, "Metadata should not be nil");
  301. XCTAssertNil(error, "Error should be nil");
  302. [expectation fulfill];
  303. }];
  304. [self waitForExpectations];
  305. }
  306. - (void)testGetData {
  307. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetData"];
  308. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  309. [ref dataWithMaxSize:1 * 1024 * 1024
  310. completion:^(NSData *data, NSError *error) {
  311. XCTAssertNotNil(data, "Data should not be nil");
  312. XCTAssertNil(error, "Error should be nil");
  313. [expectation fulfill];
  314. }];
  315. [self waitForExpectations];
  316. }
  317. - (void)testGetDataInBackgroundQueue {
  318. XCTestExpectation *expectation =
  319. [self expectationWithDescription:@"testGetDataInBackgroundQueue"];
  320. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  321. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  322. [ref dataWithMaxSize:1 * 1024 * 1024
  323. completion:^(NSData *data, NSError *error) {
  324. XCTAssertNotNil(data, "Data should not be nil");
  325. XCTAssertNil(error, "Error should be nil");
  326. [expectation fulfill];
  327. }];
  328. });
  329. [self waitForExpectations];
  330. }
  331. - (void)testGetDataWithCustomCallbackQueue {
  332. XCTestExpectation *expectation =
  333. [self expectationWithDescription:@"testUnauthenticatedGetDataInCustomCallbackQueue"];
  334. NSString *callbackQueueLabelString = @"customCallbackQueue";
  335. const char *callbackQueueLabel = [callbackQueueLabelString UTF8String];
  336. const void *callbackQueueKey = callbackQueueLabel;
  337. dispatch_queue_t callbackQueue = dispatch_queue_create(callbackQueueLabel, NULL);
  338. dispatch_queue_set_specific(callbackQueue, callbackQueueKey, (void *)callbackQueueKey, NULL);
  339. _storage.callbackQueue = callbackQueue;
  340. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  341. [ref dataWithMaxSize:1 * 1024 * 1024
  342. completion:^(NSData *data, NSError *error) {
  343. XCTAssertNotNil(data, "Data should not be nil");
  344. XCTAssertNil(error, "Error should be nil");
  345. char *currentQueueLabel = dispatch_get_specific(callbackQueueKey);
  346. NSString *currentQueueLabelString = [NSString stringWithUTF8String:currentQueueLabel];
  347. XCTAssertEqualObjects(currentQueueLabelString, callbackQueueLabelString);
  348. [expectation fulfill];
  349. // Reset the callbackQueue to default (main queue).
  350. self.storage.callbackQueue = dispatch_get_main_queue();
  351. dispatch_queue_set_specific(callbackQueue, callbackQueueKey, NULL, NULL);
  352. }];
  353. [self waitForExpectations];
  354. }
  355. - (void)testGetDataTooSmall {
  356. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetDataTooSmall"];
  357. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  358. /// Only allow 1kB size, which is smaller than our file
  359. [ref dataWithMaxSize:1 * 1024
  360. completion:^(NSData *data, NSError *error) {
  361. XCTAssertNil(data);
  362. XCTAssertEqual(error.code, FIRStorageErrorCodeDownloadSizeExceeded);
  363. [expectation fulfill];
  364. }];
  365. [self waitForExpectations];
  366. }
  367. - (void)testGetDownloadURL {
  368. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetDownloadURL"];
  369. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  370. // Download URL format is
  371. // "https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{path}?alt=media&token={token}"
  372. NSString *downloadURLPattern =
  373. @"^https:\\/\\/firebasestorage.googleapis.com\\/v0\\/b\\/[^\\/]*\\/o\\/"
  374. @"ios%2Fpublic%2F1mb\\?alt=media&token=[a-z0-9-]*$";
  375. [ref downloadURLWithCompletion:^(NSURL *downloadURL, NSError *error) {
  376. XCTAssertNil(error);
  377. NSRegularExpression *testRegex =
  378. [NSRegularExpression regularExpressionWithPattern:downloadURLPattern options:0 error:nil];
  379. NSString *urlString = [downloadURL absoluteString];
  380. XCTAssertEqual([testRegex numberOfMatchesInString:urlString
  381. options:0
  382. range:NSMakeRange(0, [urlString length])],
  383. 1);
  384. [expectation fulfill];
  385. }];
  386. [self waitForExpectations];
  387. }
  388. - (void)testGetFile {
  389. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetFile"];
  390. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/helloworld"];
  391. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  392. NSURL *fileURL =
  393. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  394. [ref putData:[@"Hello World" dataUsingEncoding:NSUTF8StringEncoding]
  395. metadata:nil
  396. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  397. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  398. [task observeStatus:FIRStorageTaskStatusSuccess
  399. handler:^(FIRStorageTaskSnapshot *snapshot) {
  400. NSString *data = [NSString stringWithContentsOfURL:fileURL
  401. encoding:NSUTF8StringEncoding
  402. error:NULL];
  403. NSString *expectedData = @"Hello World";
  404. XCTAssertEqualObjects(data, expectedData);
  405. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  406. [expectation fulfill];
  407. }];
  408. [task observeStatus:FIRStorageTaskStatusProgress
  409. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  410. NSProgress *progress = snapshot.progress;
  411. NSLog(@"%lld of %lld", progress.completedUnitCount, progress.totalUnitCount);
  412. }];
  413. [task observeStatus:FIRStorageTaskStatusFailure
  414. handler:^(FIRStorageTaskSnapshot *snapshot) {
  415. XCTAssertNil(snapshot.error);
  416. }];
  417. }];
  418. [self waitForExpectations];
  419. }
  420. - (void)testCancelDownload {
  421. XCTestExpectation *expectation = [self expectationWithDescription:@"testCancelDownload"];
  422. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  423. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  424. NSURL *fileURL =
  425. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"dat"];
  426. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  427. [task observeStatus:FIRStorageTaskStatusFailure
  428. handler:^(FIRStorageTaskSnapshot *snapshot) {
  429. XCTAssertTrue([[snapshot description] containsString:@"State: Failed"]);
  430. [expectation fulfill];
  431. }];
  432. [task observeStatus:FIRStorageTaskStatusProgress
  433. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  434. [task cancel];
  435. }];
  436. [self waitForExpectations];
  437. }
  438. - (void)assertMetadata:(FIRStorageMetadata *)actualMetadata
  439. contentType:(NSString *)expectedContentType
  440. customMetadata:(NSDictionary *)expectedCustomMetadata {
  441. XCTAssertEqualObjects(actualMetadata.cacheControl, @"cache-control");
  442. XCTAssertEqualObjects(actualMetadata.contentDisposition, @"content-disposition");
  443. XCTAssertEqualObjects(actualMetadata.contentEncoding, @"gzip");
  444. XCTAssertEqualObjects(actualMetadata.contentLanguage, @"de");
  445. XCTAssertEqualObjects(actualMetadata.contentType, expectedContentType);
  446. XCTAssertTrue([actualMetadata.md5Hash length] == 24);
  447. for (NSString *key in expectedCustomMetadata) {
  448. XCTAssertEqualObjects([actualMetadata.customMetadata objectForKey:key],
  449. [expectedCustomMetadata objectForKey:key]);
  450. }
  451. }
  452. - (void)assertMetadataNil:(FIRStorageMetadata *)actualMetadata {
  453. XCTAssertNil(actualMetadata.cacheControl);
  454. XCTAssertNil(actualMetadata.contentDisposition);
  455. XCTAssertEqualObjects(actualMetadata.contentEncoding, @"identity");
  456. XCTAssertNil(actualMetadata.contentLanguage);
  457. XCTAssertNil(actualMetadata.contentType);
  458. XCTAssertTrue([actualMetadata.md5Hash length] == 24);
  459. XCTAssertNil(actualMetadata.customMetadata);
  460. }
  461. - (void)testUpdateMetadata {
  462. XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateMetadata"];
  463. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  464. // Update all available metadata
  465. FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] init];
  466. metadata.cacheControl = @"cache-control";
  467. metadata.contentDisposition = @"content-disposition";
  468. metadata.contentEncoding = @"gzip";
  469. metadata.contentLanguage = @"de";
  470. metadata.contentType = @"content-type-a";
  471. metadata.customMetadata = @{@"a" : @"b"};
  472. [ref updateMetadata:metadata
  473. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  474. XCTAssertNil(error);
  475. [self assertMetadata:updatedMetadata
  476. contentType:@"content-type-a"
  477. customMetadata:@{@"a" : @"b"}];
  478. // Update a subset of the metadata using the existing object.
  479. FIRStorageMetadata *metadata = updatedMetadata;
  480. metadata.contentType = @"content-type-b";
  481. metadata.customMetadata = @{@"a" : @"b", @"c" : @"d"};
  482. [ref updateMetadata:metadata
  483. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  484. XCTAssertNil(error);
  485. [self assertMetadata:updatedMetadata
  486. contentType:@"content-type-b"
  487. customMetadata:@{@"a" : @"b", @"c" : @"d"}];
  488. // Clear all metadata.
  489. FIRStorageMetadata *metadata = updatedMetadata;
  490. metadata.cacheControl = nil;
  491. metadata.contentDisposition = nil;
  492. metadata.contentEncoding = nil;
  493. metadata.contentLanguage = nil;
  494. metadata.contentType = nil;
  495. metadata.customMetadata = [NSDictionary dictionary];
  496. [ref updateMetadata:metadata
  497. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  498. XCTAssertNil(error);
  499. [self assertMetadataNil:updatedMetadata];
  500. [expectation fulfill];
  501. }];
  502. }];
  503. }];
  504. [self waitForExpectations];
  505. }
  506. - (void)testResumeGetFile {
  507. XCTestExpectation *expectation = [self expectationWithDescription:@"testResumeGetFile"];
  508. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  509. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  510. NSURL *fileURL =
  511. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  512. __block long resumeAtBytes = 256 * 1024;
  513. __block long downloadedBytes = 0;
  514. __block double computationResult = 0;
  515. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  516. [task observeStatus:FIRStorageTaskStatusSuccess
  517. handler:^(FIRStorageTaskSnapshot *snapshot) {
  518. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  519. [expectation fulfill];
  520. }];
  521. [task observeStatus:FIRStorageTaskStatusProgress
  522. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  523. XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
  524. [[snapshot description] containsString:@"State: Resume"]);
  525. NSProgress *progress = snapshot.progress;
  526. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
  527. downloadedBytes = (long)progress.completedUnitCount;
  528. if (progress.completedUnitCount > resumeAtBytes) {
  529. // Making sure the main run loop is busy.
  530. for (int i = 0; i < 500; ++i) {
  531. dispatch_async(dispatch_get_main_queue(), ^{
  532. computationResult = sqrt(INT_MAX - i);
  533. });
  534. }
  535. NSLog(@"Pausing");
  536. [task pause];
  537. resumeAtBytes = INT_MAX;
  538. }
  539. }];
  540. [task observeStatus:FIRStorageTaskStatusPause
  541. handler:^(FIRStorageTaskSnapshot *snapshot) {
  542. XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
  543. NSLog(@"Resuming");
  544. [task resume];
  545. }];
  546. [self waitForExpectations];
  547. XCTAssertEqual(INT_MAX, resumeAtBytes);
  548. XCTAssertEqualWithAccuracy(sqrt(INT_MAX - 499), computationResult, 0.1);
  549. }
  550. - (void)testResumeGetFileInBackgroundQueue {
  551. XCTestExpectation *expectation =
  552. [self expectationWithDescription:@"testResumeGetFileInBackgroundQueue"];
  553. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  554. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  555. NSURL *fileURL =
  556. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  557. __block long resumeAtBytes = 256 * 1024;
  558. __block long downloadedBytes = 0;
  559. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  560. [task observeStatus:FIRStorageTaskStatusSuccess
  561. handler:^(FIRStorageTaskSnapshot *snapshot) {
  562. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  563. [expectation fulfill];
  564. }];
  565. [task observeStatus:FIRStorageTaskStatusProgress
  566. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  567. XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
  568. [[snapshot description] containsString:@"State: Resume"]);
  569. NSProgress *progress = snapshot.progress;
  570. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
  571. downloadedBytes = (long)progress.completedUnitCount;
  572. if (progress.completedUnitCount > resumeAtBytes) {
  573. NSLog(@"Pausing");
  574. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  575. [task pause];
  576. });
  577. resumeAtBytes = INT_MAX;
  578. }
  579. }];
  580. [task observeStatus:FIRStorageTaskStatusPause
  581. handler:^(FIRStorageTaskSnapshot *snapshot) {
  582. XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
  583. NSLog(@"Resuming");
  584. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  585. [task resume];
  586. });
  587. }];
  588. [self waitForExpectations];
  589. XCTAssertEqual(INT_MAX, resumeAtBytes);
  590. }
  591. - (void)testPagedListFiles {
  592. XCTestExpectation *expectation = [self expectationWithDescription:@"testPagedListFiles"];
  593. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/list"];
  594. [ref listWithMaxResults:2
  595. completion:^(FIRStorageListResult *_Nullable listResult, NSError *_Nullable error) {
  596. XCTAssertNotNil(listResult);
  597. XCTAssertNil(error);
  598. XCTAssertEqualObjects(listResult.items, (@[ [ref child:@"a"], [ref child:@"b"] ]));
  599. XCTAssertEqualObjects(listResult.prefixes, @[]);
  600. XCTAssertNotNil(listResult.pageToken);
  601. [ref listWithMaxResults:2
  602. pageToken:listResult.pageToken
  603. completion:^(FIRStorageListResult *_Nullable listResult,
  604. NSError *_Nullable error) {
  605. XCTAssertNotNil(listResult);
  606. XCTAssertNil(error);
  607. XCTAssertEqualObjects(listResult.items, @[]);
  608. XCTAssertEqualObjects(listResult.prefixes,
  609. @[ [ref child:@"prefix"] ]);
  610. XCTAssertNil(listResult.pageToken);
  611. [expectation fulfill];
  612. }];
  613. }];
  614. [self waitForExpectations];
  615. }
  616. - (void)testListAllFiles {
  617. XCTestExpectation *expectation = [self expectationWithDescription:@"testPagedListFiles"];
  618. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/list"];
  619. [ref listAllWithCompletion:^(FIRStorageListResult *_Nullable listResult,
  620. NSError *_Nullable error) {
  621. XCTAssertNotNil(listResult);
  622. XCTAssertNil(error);
  623. XCTAssertEqualObjects(listResult.items, (@[ [ref child:@"a"], [ref child:@"b"] ]));
  624. XCTAssertEqualObjects(listResult.prefixes, @[ [ref child:@"prefix"] ]);
  625. XCTAssertNil(listResult.pageToken);
  626. [expectation fulfill];
  627. }];
  628. [self waitForExpectations];
  629. }
  630. - (void)waitForExpectations {
  631. [self waitForExpectationsWithTimeout:kFIRStorageIntegrationTestTimeout
  632. handler:^(NSError *_Nullable error) {
  633. if (error) {
  634. NSLog(@"%@", error);
  635. }
  636. }];
  637. }
  638. @end