FIRStorageIntegrationTests.m 31 KB

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