FIRStorageIntegrationTests.m 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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)testGetDataTooSmall {
  332. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetDataTooSmall"];
  333. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  334. /// Only allow 1kB size, which is smaller than our file
  335. [ref dataWithMaxSize:1 * 1024
  336. completion:^(NSData *data, NSError *error) {
  337. XCTAssertNil(data);
  338. XCTAssertEqual(error.code, FIRStorageErrorCodeDownloadSizeExceeded);
  339. [expectation fulfill];
  340. }];
  341. [self waitForExpectations];
  342. }
  343. - (void)testGetDownloadURL {
  344. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetDownloadURL"];
  345. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  346. // Download URL format is
  347. // "https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{path}?alt=media&token={token}"
  348. NSString *downloadURLPattern =
  349. @"^https:\\/\\/firebasestorage.googleapis.com\\/v0\\/b\\/[^\\/]*\\/o\\/"
  350. @"ios%2Fpublic%2F1mb\\?alt=media&token=[a-z0-9-]*$";
  351. [ref downloadURLWithCompletion:^(NSURL *downloadURL, NSError *error) {
  352. XCTAssertNil(error);
  353. NSRegularExpression *testRegex =
  354. [NSRegularExpression regularExpressionWithPattern:downloadURLPattern options:0 error:nil];
  355. NSString *urlString = [downloadURL absoluteString];
  356. XCTAssertEqual([testRegex numberOfMatchesInString:urlString
  357. options:0
  358. range:NSMakeRange(0, [urlString length])],
  359. 1);
  360. [expectation fulfill];
  361. }];
  362. [self waitForExpectations];
  363. }
  364. - (void)testGetFile {
  365. XCTestExpectation *expectation = [self expectationWithDescription:@"testGetFile"];
  366. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/helloworld"];
  367. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  368. NSURL *fileURL =
  369. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  370. [ref putData:[@"Hello World" dataUsingEncoding:NSUTF8StringEncoding]
  371. metadata:nil
  372. completion:^(FIRStorageMetadata *metadata, NSError *error) {
  373. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  374. [task observeStatus:FIRStorageTaskStatusSuccess
  375. handler:^(FIRStorageTaskSnapshot *snapshot) {
  376. NSString *data = [NSString stringWithContentsOfURL:fileURL
  377. encoding:NSUTF8StringEncoding
  378. error:NULL];
  379. NSString *expectedData = @"Hello World";
  380. XCTAssertEqualObjects(data, expectedData);
  381. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  382. [expectation fulfill];
  383. }];
  384. [task observeStatus:FIRStorageTaskStatusProgress
  385. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  386. NSProgress *progress = snapshot.progress;
  387. NSLog(@"%lld of %lld", progress.completedUnitCount, progress.totalUnitCount);
  388. }];
  389. [task observeStatus:FIRStorageTaskStatusFailure
  390. handler:^(FIRStorageTaskSnapshot *snapshot) {
  391. XCTAssertNil(snapshot.error);
  392. }];
  393. }];
  394. [self waitForExpectations];
  395. }
  396. - (void)testCancelDownload {
  397. XCTestExpectation *expectation = [self expectationWithDescription:@"testCancelDownload"];
  398. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  399. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  400. NSURL *fileURL =
  401. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"dat"];
  402. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  403. [task observeStatus:FIRStorageTaskStatusFailure
  404. handler:^(FIRStorageTaskSnapshot *snapshot) {
  405. XCTAssertTrue([[snapshot description] containsString:@"State: Failed"]);
  406. [expectation fulfill];
  407. }];
  408. [task observeStatus:FIRStorageTaskStatusProgress
  409. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  410. [task cancel];
  411. }];
  412. [self waitForExpectations];
  413. }
  414. - (void)assertMetadata:(FIRStorageMetadata *)actualMetadata
  415. contentType:(NSString *)expectedContentType
  416. customMetadata:(NSDictionary *)expectedCustomMetadata {
  417. XCTAssertEqualObjects(actualMetadata.cacheControl, @"cache-control");
  418. XCTAssertEqualObjects(actualMetadata.contentDisposition, @"content-disposition");
  419. XCTAssertEqualObjects(actualMetadata.contentEncoding, @"gzip");
  420. XCTAssertEqualObjects(actualMetadata.contentLanguage, @"de");
  421. XCTAssertEqualObjects(actualMetadata.contentType, expectedContentType);
  422. XCTAssertTrue([actualMetadata.md5Hash length] == 24);
  423. for (NSString *key in expectedCustomMetadata) {
  424. XCTAssertEqualObjects([actualMetadata.customMetadata objectForKey:key],
  425. [expectedCustomMetadata objectForKey:key]);
  426. }
  427. }
  428. - (void)assertMetadataNil:(FIRStorageMetadata *)actualMetadata {
  429. XCTAssertNil(actualMetadata.cacheControl);
  430. XCTAssertNil(actualMetadata.contentDisposition);
  431. XCTAssertEqualObjects(actualMetadata.contentEncoding, @"identity");
  432. XCTAssertNil(actualMetadata.contentLanguage);
  433. XCTAssertNil(actualMetadata.contentType);
  434. XCTAssertTrue([actualMetadata.md5Hash length] == 24);
  435. XCTAssertNil(actualMetadata.customMetadata);
  436. }
  437. - (void)testUpdateMetadata {
  438. XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateMetadata"];
  439. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  440. // Update all available metadata
  441. FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] init];
  442. metadata.cacheControl = @"cache-control";
  443. metadata.contentDisposition = @"content-disposition";
  444. metadata.contentEncoding = @"gzip";
  445. metadata.contentLanguage = @"de";
  446. metadata.contentType = @"content-type-a";
  447. metadata.customMetadata = @{@"a" : @"b"};
  448. [ref updateMetadata:metadata
  449. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  450. XCTAssertNil(error);
  451. [self assertMetadata:updatedMetadata
  452. contentType:@"content-type-a"
  453. customMetadata:@{@"a" : @"b"}];
  454. // Update a subset of the metadata using the existing object.
  455. FIRStorageMetadata *metadata = updatedMetadata;
  456. metadata.contentType = @"content-type-b";
  457. metadata.customMetadata = @{@"a" : @"b", @"c" : @"d"};
  458. [ref updateMetadata:metadata
  459. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  460. XCTAssertNil(error);
  461. [self assertMetadata:updatedMetadata
  462. contentType:@"content-type-b"
  463. customMetadata:@{@"a" : @"b", @"c" : @"d"}];
  464. // Clear all metadata.
  465. FIRStorageMetadata *metadata = updatedMetadata;
  466. metadata.cacheControl = nil;
  467. metadata.contentDisposition = nil;
  468. metadata.contentEncoding = nil;
  469. metadata.contentLanguage = nil;
  470. metadata.contentType = nil;
  471. metadata.customMetadata = [NSDictionary dictionary];
  472. [ref updateMetadata:metadata
  473. completion:^(FIRStorageMetadata *updatedMetadata, NSError *error) {
  474. XCTAssertNil(error);
  475. [self assertMetadataNil:updatedMetadata];
  476. [expectation fulfill];
  477. }];
  478. }];
  479. }];
  480. [self waitForExpectations];
  481. }
  482. - (void)testResumeGetFile {
  483. XCTestExpectation *expectation = [self expectationWithDescription:@"testResumeGetFile"];
  484. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  485. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  486. NSURL *fileURL =
  487. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  488. __block long resumeAtBytes = 256 * 1024;
  489. __block long downloadedBytes = 0;
  490. __block double computationResult = 0;
  491. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  492. [task observeStatus:FIRStorageTaskStatusSuccess
  493. handler:^(FIRStorageTaskSnapshot *snapshot) {
  494. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  495. [expectation fulfill];
  496. }];
  497. [task observeStatus:FIRStorageTaskStatusProgress
  498. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  499. XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
  500. [[snapshot description] containsString:@"State: Resume"]);
  501. NSProgress *progress = snapshot.progress;
  502. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
  503. downloadedBytes = (long)progress.completedUnitCount;
  504. if (progress.completedUnitCount > resumeAtBytes) {
  505. // Making sure the main run loop is busy.
  506. for (int i = 0; i < 500; ++i) {
  507. dispatch_async(dispatch_get_main_queue(), ^{
  508. computationResult = sqrt(INT_MAX - i);
  509. });
  510. }
  511. NSLog(@"Pausing");
  512. [task pause];
  513. resumeAtBytes = INT_MAX;
  514. }
  515. }];
  516. [task observeStatus:FIRStorageTaskStatusPause
  517. handler:^(FIRStorageTaskSnapshot *snapshot) {
  518. XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
  519. NSLog(@"Resuming");
  520. [task resume];
  521. }];
  522. [self waitForExpectations];
  523. XCTAssertEqual(INT_MAX, resumeAtBytes);
  524. XCTAssertEqualWithAccuracy(sqrt(INT_MAX - 499), computationResult, 0.1);
  525. }
  526. - (void)testResumeGetFileInBackgroundQueue {
  527. XCTestExpectation *expectation =
  528. [self expectationWithDescription:@"testResumeGetFileInBackgroundQueue"];
  529. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
  530. NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
  531. NSURL *fileURL =
  532. [[tmpDirURL URLByAppendingPathComponent:@"hello"] URLByAppendingPathExtension:@"txt"];
  533. __block long resumeAtBytes = 256 * 1024;
  534. __block long downloadedBytes = 0;
  535. FIRStorageDownloadTask *task = [ref writeToFile:fileURL];
  536. [task observeStatus:FIRStorageTaskStatusSuccess
  537. handler:^(FIRStorageTaskSnapshot *snapshot) {
  538. XCTAssertEqualObjects([snapshot description], @"<State: Success>");
  539. [expectation fulfill];
  540. }];
  541. [task observeStatus:FIRStorageTaskStatusProgress
  542. handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) {
  543. XCTAssertTrue([[snapshot description] containsString:@"State: Progress"] ||
  544. [[snapshot description] containsString:@"State: Resume"]);
  545. NSProgress *progress = snapshot.progress;
  546. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, downloadedBytes);
  547. downloadedBytes = (long)progress.completedUnitCount;
  548. if (progress.completedUnitCount > resumeAtBytes) {
  549. NSLog(@"Pausing");
  550. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  551. [task pause];
  552. });
  553. resumeAtBytes = INT_MAX;
  554. }
  555. }];
  556. [task observeStatus:FIRStorageTaskStatusPause
  557. handler:^(FIRStorageTaskSnapshot *snapshot) {
  558. XCTAssertEqualObjects([snapshot description], @"<State: Paused>");
  559. NSLog(@"Resuming");
  560. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  561. [task resume];
  562. });
  563. }];
  564. [self waitForExpectations];
  565. XCTAssertEqual(INT_MAX, resumeAtBytes);
  566. }
  567. - (void)testPagedListFiles {
  568. XCTestExpectation *expectation = [self expectationWithDescription:@"testPagedListFiles"];
  569. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/list"];
  570. [ref listWithMaxResults:2
  571. completion:^(FIRStorageListResult *_Nullable listResult, NSError *_Nullable error) {
  572. XCTAssertNotNil(listResult);
  573. XCTAssertNil(error);
  574. XCTAssertEqualObjects(listResult.items, (@[ [ref child:@"a"], [ref child:@"b"] ]));
  575. XCTAssertEqualObjects(listResult.prefixes, @[]);
  576. XCTAssertNotNil(listResult.pageToken);
  577. [ref listWithMaxResults:2
  578. pageToken:listResult.pageToken
  579. completion:^(FIRStorageListResult *_Nullable listResult,
  580. NSError *_Nullable error) {
  581. XCTAssertNotNil(listResult);
  582. XCTAssertNil(error);
  583. XCTAssertEqualObjects(listResult.items, @[]);
  584. XCTAssertEqualObjects(listResult.prefixes,
  585. @[ [ref child:@"prefix"] ]);
  586. XCTAssertNil(listResult.pageToken);
  587. [expectation fulfill];
  588. }];
  589. }];
  590. [self waitForExpectations];
  591. }
  592. - (void)testListAllFiles {
  593. XCTestExpectation *expectation = [self expectationWithDescription:@"testPagedListFiles"];
  594. FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/list"];
  595. [ref listAllWithCompletion:^(FIRStorageListResult *_Nullable listResult,
  596. NSError *_Nullable error) {
  597. XCTAssertNotNil(listResult);
  598. XCTAssertNil(error);
  599. XCTAssertEqualObjects(listResult.items, (@[ [ref child:@"a"], [ref child:@"b"] ]));
  600. XCTAssertEqualObjects(listResult.prefixes, @[ [ref child:@"prefix"] ]);
  601. XCTAssertNil(listResult.pageToken);
  602. [expectation fulfill];
  603. }];
  604. [self waitForExpectations];
  605. }
  606. - (void)waitForExpectations {
  607. [self waitForExpectationsWithTimeout:kFIRStorageIntegrationTestTimeout
  608. handler:^(NSError *_Nullable error) {
  609. if (error) {
  610. NSLog(@"%@", error);
  611. }
  612. }];
  613. }
  614. @end