StorageIntegration.swift 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Copyright 2020 Google LLC
  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
  15. import FirebaseCore
  16. import FirebaseStorage
  17. import XCTest
  18. /**
  19. * Firebase Storage Integration tests
  20. *
  21. * To run these tests, you need to define the following access rights:
  22. *
  23. rules_version = '2';
  24. service firebase.storage {
  25. match /b/{bucket}/o {
  26. match /{directChild=*} {
  27. allow read: if request.auth != null;
  28. }
  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. class StorageResultTests: StorageIntegrationCommon {
  42. func testGetMetadata() {
  43. let expectation = self.expectation(description: "testGetMetadata")
  44. let ref = storage.reference().child("ios/public/1mb")
  45. ref.getMetadata { result in
  46. self.assertResultSuccess(result)
  47. expectation.fulfill()
  48. }
  49. waitForExpectations()
  50. }
  51. func testUpdateMetadata() {
  52. let expectation = self.expectation(description: #function)
  53. let meta = StorageMetadata()
  54. meta.contentType = "lol/custom"
  55. meta.customMetadata = ["lol": "custom metadata is neat",
  56. "ちかてつ": "🚇",
  57. "shinkansen": "新幹線"]
  58. let ref = storage.reference(withPath: "ios/public/1mb")
  59. ref.updateMetadata(meta) { result in
  60. switch result {
  61. case let .success(metadata):
  62. XCTAssertEqual(meta.contentType, metadata.contentType)
  63. XCTAssertEqual(meta.customMetadata!["lol"], metadata.customMetadata!["lol"])
  64. XCTAssertEqual(meta.customMetadata!["ちかてつ"], metadata.customMetadata!["ちかてつ"])
  65. XCTAssertEqual(meta.customMetadata!["shinkansen"],
  66. metadata.customMetadata!["shinkansen"])
  67. case let .failure(error):
  68. XCTFail("Unexpected error \(error) from updateMetadata")
  69. }
  70. expectation.fulfill()
  71. }
  72. waitForExpectations()
  73. }
  74. func testDelete() throws {
  75. let expectation = self.expectation(description: #function)
  76. let ref = storage.reference(withPath: "ios/public/fileToDelete")
  77. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  78. ref.putData(data) { result in
  79. self.assertResultSuccess(result)
  80. ref.delete { error in
  81. XCTAssertNil(error, "Error should be nil")
  82. // Next delete should fail and verify the first delete succeeded.
  83. ref.delete { error in
  84. do {
  85. let nsError = try XCTUnwrap(error as? NSError)
  86. XCTAssertEqual(nsError.code, StorageErrorCode.objectNotFound.rawValue)
  87. XCTAssertEqual(
  88. nsError.localizedDescription,
  89. "Object ios/public/fileToDelete does not exist."
  90. )
  91. let userInfo = try XCTUnwrap(nsError.userInfo)
  92. let object = try XCTUnwrap(userInfo["object"] as? String)
  93. XCTAssertEqual(object, "ios/public/fileToDelete")
  94. let responseErrorCode = try XCTUnwrap(userInfo["ResponseErrorCode"] as? Int)
  95. XCTAssertEqual(responseErrorCode, 404)
  96. let responseErrorDomain = try XCTUnwrap(userInfo["ResponseErrorDomain"] as? String)
  97. XCTAssertEqual(responseErrorDomain, "com.google.HTTPStatus")
  98. let bucket = try XCTUnwrap(userInfo["bucket"] as? String)
  99. XCTAssertEqual(bucket, "ios-opensource-samples.appspot.com")
  100. expectation.fulfill()
  101. } catch {
  102. XCTFail("Unexpected unwrap failure")
  103. }
  104. }
  105. }
  106. }
  107. waitForExpectations()
  108. }
  109. func testDeleteWithNilCompletion() throws {
  110. let expectation = self.expectation(description: #function)
  111. let ref = storage.reference(withPath: "ios/public/fileToDelete")
  112. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  113. ref.putData(data) { result in
  114. self.assertResultSuccess(result)
  115. ref.delete(completion: nil)
  116. expectation.fulfill()
  117. }
  118. waitForExpectations()
  119. }
  120. func testSimplePutData() throws {
  121. let expectation = self.expectation(description: #function)
  122. let ref = storage.reference(withPath: "ios/public/testBytesUpload")
  123. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  124. ref.putData(data) { result in
  125. self.assertResultSuccess(result)
  126. expectation.fulfill()
  127. }
  128. waitForExpectations()
  129. }
  130. func testSimplePutSpecialCharacter() throws {
  131. let expectation = self.expectation(description: #function)
  132. let ref = storage.reference(withPath: "ios/public/-._~!$'()*,=:@&+;")
  133. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  134. ref.putData(data) { result in
  135. self.assertResultSuccess(result)
  136. expectation.fulfill()
  137. }
  138. waitForExpectations()
  139. }
  140. func testSimplePutDataInBackgroundQueue() throws {
  141. let expectation = self.expectation(description: #function)
  142. let ref = storage.reference(withPath: "ios/public/testBytesUpload")
  143. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  144. DispatchQueue.global(qos: .background).async {
  145. ref.putData(data) { result in
  146. self.assertResultSuccess(result)
  147. expectation.fulfill()
  148. }
  149. }
  150. waitForExpectations()
  151. }
  152. func testSimplePutEmptyData() {
  153. let expectation = self.expectation(description: #function)
  154. let ref = storage.reference(withPath: "ios/public/testSimplePutEmptyData")
  155. let data = Data()
  156. ref.putData(data) { result in
  157. self.assertResultSuccess(result)
  158. expectation.fulfill()
  159. }
  160. waitForExpectations()
  161. }
  162. func testSimplePutDataUnauthorized() throws {
  163. let expectation = self.expectation(description: #function)
  164. let file = "ios/private/secretfile.txt"
  165. let ref = storage.reference(withPath: file)
  166. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  167. ref.putData(data) { result in
  168. switch result {
  169. case .success:
  170. XCTFail("Unexpected success from unauthorized putData")
  171. case let .failure(error as StorageError):
  172. switch error {
  173. case let .unauthorized(bucket, object):
  174. XCTAssertEqual(bucket, "ios-opensource-samples.appspot.com")
  175. XCTAssertEqual(object, file)
  176. expectation.fulfill()
  177. default:
  178. XCTFail("Failed with unexpected error: \(error)")
  179. }
  180. case let .failure(error):
  181. XCTFail("Failed with unexpected error: \(error)")
  182. }
  183. }
  184. waitForExpectations()
  185. }
  186. func testSimplePutDataUnauthorizedThrow() throws {
  187. let expectation = self.expectation(description: #function)
  188. let ref = storage.reference(withPath: "ios/private/secretfile.txt")
  189. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  190. ref.putData(data) { result in
  191. do {
  192. try _ = result.get() // .failure will throw
  193. } catch {
  194. expectation.fulfill()
  195. return
  196. }
  197. XCTFail("Unexpected success from unauthorized putData")
  198. expectation.fulfill()
  199. }
  200. waitForExpectations()
  201. }
  202. func testSimplePutFile() throws {
  203. let expectation = self.expectation(description: #function)
  204. let putFileExpectation = self.expectation(description: "putFile")
  205. let ref = storage.reference(withPath: "ios/public/testSimplePutFile")
  206. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  207. let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory())
  208. let fileURL = tmpDirURL.appendingPathComponent("hello.txt")
  209. try data.write(to: fileURL, options: .atomicWrite)
  210. let task = ref.putFile(from: fileURL) { result in
  211. self.assertResultSuccess(result)
  212. putFileExpectation.fulfill()
  213. }
  214. task.observe(StorageTaskStatus.success) { snapshot in
  215. XCTAssertEqual(snapshot.description, "<State: Success>")
  216. expectation.fulfill()
  217. }
  218. var uploadedBytes: Int64 = -1
  219. task.observe(StorageTaskStatus.progress) { snapshot in
  220. XCTAssertTrue(snapshot.description.starts(with: "<State: Progress") ||
  221. snapshot.description.starts(with: "<State: Resume"))
  222. guard let progress = snapshot.progress else {
  223. XCTFail("Failed to get snapshot.progress")
  224. return
  225. }
  226. XCTAssertGreaterThanOrEqual(progress.completedUnitCount, uploadedBytes)
  227. uploadedBytes = progress.completedUnitCount
  228. }
  229. waitForExpectations()
  230. }
  231. func testAttemptToUploadDirectoryShouldFail() throws {
  232. // This `.numbers` file is actually a directory.
  233. let fileName = "HomeImprovement.numbers"
  234. let expectation = self.expectation(description: #function)
  235. let bundle = Bundle(for: StorageIntegrationCommon.self)
  236. let fileURL = try XCTUnwrap(bundle.url(forResource: fileName, withExtension: ""),
  237. "Failed to get filePath")
  238. let ref = storage.reference(withPath: "ios/public/" + fileName)
  239. ref.putFile(from: fileURL) { result in
  240. self.assertResultFailure(result)
  241. expectation.fulfill()
  242. }
  243. waitForExpectations()
  244. }
  245. func testPutFileWithSpecialCharacters() throws {
  246. let expectation = self.expectation(description: #function)
  247. let fileName = "hello&+@_ .txt"
  248. let ref = storage.reference(withPath: "ios/public/" + fileName)
  249. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  250. let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory())
  251. let fileURL = tmpDirURL.appendingPathComponent("hello.txt")
  252. try data.write(to: fileURL, options: .atomicWrite)
  253. ref.putFile(from: fileURL) { result in
  254. switch result {
  255. case let .success(metadata):
  256. XCTAssertEqual(fileName, metadata.name)
  257. ref.getMetadata { result in
  258. self.assertResultSuccess(result)
  259. }
  260. case let .failure(error):
  261. XCTFail("Unexpected error \(error) from putFile")
  262. }
  263. expectation.fulfill()
  264. }
  265. waitForExpectations()
  266. }
  267. func testSimplePutDataNoMetadata() throws {
  268. let expectation = self.expectation(description: #function)
  269. let ref = storage.reference(withPath: "ios/public/testSimplePutDataNoMetadata")
  270. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  271. ref.putData(data) { result in
  272. self.assertResultSuccess(result)
  273. expectation.fulfill()
  274. }
  275. waitForExpectations()
  276. }
  277. func testSimplePutFileNoMetadata() throws {
  278. let expectation = self.expectation(description: #function)
  279. let fileName = "hello&+@_ .txt"
  280. let ref = storage.reference(withPath: "ios/public/" + fileName)
  281. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  282. let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory())
  283. let fileURL = tmpDirURL.appendingPathComponent("hello.txt")
  284. try data.write(to: fileURL, options: .atomicWrite)
  285. ref.putFile(from: fileURL) { result in
  286. self.assertResultSuccess(result)
  287. expectation.fulfill()
  288. }
  289. waitForExpectations()
  290. }
  291. func testSimpleGetData() {
  292. let expectation = self.expectation(description: #function)
  293. let ref = storage.reference(withPath: "ios/public/1mb")
  294. ref.getData(maxSize: 1024 * 1024) { result in
  295. self.assertResultSuccess(result)
  296. expectation.fulfill()
  297. }
  298. waitForExpectations()
  299. }
  300. func testSimpleGetDataInBackgroundQueue() {
  301. let expectation = self.expectation(description: #function)
  302. let ref = storage.reference(withPath: "ios/public/1mb")
  303. DispatchQueue.global(qos: .background).async {
  304. ref.getData(maxSize: 1024 * 1024) { result in
  305. self.assertResultSuccess(result)
  306. expectation.fulfill()
  307. }
  308. }
  309. waitForExpectations()
  310. }
  311. func testSimpleGetDataWithCustomCallbackQueue() {
  312. let expectation = self.expectation(description: #function)
  313. let callbackQueueLabel = "customCallbackQueue"
  314. let callbackQueueKey = DispatchSpecificKey<String>()
  315. let callbackQueue = DispatchQueue(label: callbackQueueLabel)
  316. callbackQueue.setSpecific(key: callbackQueueKey, value: callbackQueueLabel)
  317. storage.callbackQueue = callbackQueue
  318. let ref = storage.reference(withPath: "ios/public/1mb")
  319. ref.getData(maxSize: 1024 * 1024) { result in
  320. self.assertResultSuccess(result)
  321. XCTAssertFalse(Thread.isMainThread)
  322. let currentQueueLabel = DispatchQueue.getSpecific(key: callbackQueueKey)
  323. XCTAssertEqual(currentQueueLabel, callbackQueueLabel)
  324. expectation.fulfill()
  325. // Reset the callbackQueue to default (main queue).
  326. self.storage.callbackQueue = DispatchQueue.main
  327. callbackQueue.setSpecific(key: callbackQueueKey, value: nil)
  328. }
  329. waitForExpectations()
  330. }
  331. func testSimpleGetDataTooSmall() {
  332. let expectation = self.expectation(description: #function)
  333. let ref = storage.reference(withPath: "ios/public/1mb")
  334. let maxSize: Int64 = 1024
  335. ref.getData(maxSize: maxSize) { result in
  336. switch result {
  337. case .success:
  338. XCTFail("Unexpected success from getData too small")
  339. case let .failure(error as StorageError):
  340. switch error {
  341. case let .downloadSizeExceeded(total, max):
  342. XCTAssertEqual(total, 1_048_576)
  343. XCTAssertEqual(max, maxSize)
  344. default:
  345. XCTFail("Failed with unexpected error: \(error)")
  346. }
  347. case let .failure(error):
  348. XCTFail("Failed with unexpected error: \(error)")
  349. }
  350. expectation.fulfill()
  351. }
  352. waitForExpectations()
  353. }
  354. func testSimpleGetDownloadURL() {
  355. let expectation = self.expectation(description: #function)
  356. let ref = storage.reference(withPath: "ios/public/1mb")
  357. // Download URL format is
  358. // "https://firebasestorage.googleapis.com:443/v0/b/{bucket}/o/{path}?alt=media&token={token}"
  359. let downloadURLPattern =
  360. "^https:\\/\\/firebasestorage.googleapis.com:443\\/v0\\/b\\/[^\\/]*\\/o\\/" +
  361. "ios%2Fpublic%2F1mb\\?alt=media&token=[a-z0-9-]*$"
  362. ref.downloadURL { result in
  363. switch result {
  364. case let .success(downloadURL):
  365. do {
  366. let testRegex = try NSRegularExpression(pattern: downloadURLPattern)
  367. let urlString = downloadURL.absoluteString
  368. XCTAssertEqual(testRegex.numberOfMatches(in: urlString,
  369. range: NSRange(location: 0,
  370. length: urlString.count)), 1)
  371. } catch {
  372. XCTFail("Throw in downloadURL completion block")
  373. }
  374. case let .failure(error):
  375. XCTFail("Unexpected error \(error) from downloadURL")
  376. }
  377. expectation.fulfill()
  378. }
  379. waitForExpectations()
  380. }
  381. func testSimpleGetFile() throws {
  382. let expectation = self.expectation(description: #function)
  383. let ref = storage.reference(withPath: "ios/public/helloworld")
  384. let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory())
  385. let fileURL = tmpDirURL.appendingPathComponent("hello.txt")
  386. let data = try XCTUnwrap("Hello Swift World".data(using: .utf8), "Data construction failed")
  387. ref.putData(data) { result in
  388. switch result {
  389. case .success:
  390. let task = ref.write(toFile: fileURL)
  391. task.observe(StorageTaskStatus.success) { snapshot in
  392. do {
  393. let stringData = try String(contentsOf: fileURL, encoding: .utf8)
  394. XCTAssertEqual(stringData, "Hello Swift World")
  395. XCTAssertEqual(snapshot.description, "<State: Success>")
  396. } catch {
  397. XCTFail("Error processing success snapshot")
  398. }
  399. expectation.fulfill()
  400. }
  401. task.observe(StorageTaskStatus.progress) { snapshot in
  402. XCTAssertNil(snapshot.error, "Error should be nil")
  403. guard let progress = snapshot.progress else {
  404. XCTFail("Missing progress")
  405. return
  406. }
  407. print("\(progress.completedUnitCount) of \(progress.totalUnitCount)")
  408. }
  409. task.observe(StorageTaskStatus.failure) { snapshot in
  410. XCTAssertNil(snapshot.error, "Error should be nil")
  411. }
  412. case let .failure(error):
  413. XCTFail("Unexpected error \(error) from putData")
  414. expectation.fulfill()
  415. }
  416. }
  417. waitForExpectations()
  418. }
  419. private func assertMetadata(actualMetadata: StorageMetadata,
  420. expectedContentType: String,
  421. expectedCustomMetadata: [String: String]) {
  422. XCTAssertEqual(actualMetadata.cacheControl, "cache-control")
  423. XCTAssertEqual(actualMetadata.contentDisposition, "content-disposition")
  424. XCTAssertEqual(actualMetadata.contentEncoding, "gzip")
  425. XCTAssertEqual(actualMetadata.contentLanguage, "de")
  426. XCTAssertEqual(actualMetadata.contentType, expectedContentType)
  427. XCTAssertEqual(actualMetadata.md5Hash?.count, 24)
  428. for (key, value) in expectedCustomMetadata {
  429. XCTAssertEqual(actualMetadata.customMetadata![key], value)
  430. }
  431. }
  432. private func assertMetadataNil(actualMetadata: StorageMetadata) {
  433. XCTAssertNil(actualMetadata.cacheControl)
  434. XCTAssertNil(actualMetadata.contentDisposition)
  435. XCTAssertEqual(actualMetadata.contentEncoding, "identity")
  436. XCTAssertNil(actualMetadata.contentLanguage)
  437. XCTAssertNil(actualMetadata.contentType)
  438. XCTAssertEqual(actualMetadata.md5Hash?.count, 24)
  439. XCTAssertNil(actualMetadata.customMetadata)
  440. }
  441. func testUpdateMetadata2() {
  442. let expectation = self.expectation(description: #function)
  443. let ref = storage.reference(withPath: "ios/public/1mb")
  444. let metadata = StorageMetadata()
  445. metadata.cacheControl = "cache-control"
  446. metadata.contentDisposition = "content-disposition"
  447. metadata.contentEncoding = "gzip"
  448. metadata.contentLanguage = "de"
  449. metadata.contentType = "content-type-a"
  450. metadata.customMetadata = ["a": "b"]
  451. ref.updateMetadata(metadata) { updatedMetadata, error in
  452. XCTAssertNil(error, "Error should be nil")
  453. guard let updatedMetadata = updatedMetadata else {
  454. XCTFail("Metadata is nil")
  455. expectation.fulfill()
  456. return
  457. }
  458. self.assertMetadata(actualMetadata: updatedMetadata,
  459. expectedContentType: "content-type-a",
  460. expectedCustomMetadata: ["a": "b"])
  461. let metadata = updatedMetadata
  462. metadata.contentType = "content-type-b"
  463. metadata.customMetadata = ["a": "b", "c": "d"]
  464. ref.updateMetadata(metadata) { result in
  465. switch result {
  466. case let .success(updatedMetadata):
  467. self.assertMetadata(actualMetadata: updatedMetadata,
  468. expectedContentType: "content-type-b",
  469. expectedCustomMetadata: ["a": "b", "c": "d"])
  470. metadata.cacheControl = nil
  471. metadata.contentDisposition = nil
  472. metadata.contentEncoding = nil
  473. metadata.contentLanguage = nil
  474. metadata.contentType = nil
  475. metadata.customMetadata = nil
  476. ref.updateMetadata(metadata) { result in
  477. self.assertResultSuccess(result)
  478. expectation.fulfill()
  479. }
  480. case let .failure(error):
  481. XCTFail("Unexpected error \(error) from updateMetadata")
  482. expectation.fulfill()
  483. }
  484. }
  485. }
  486. waitForExpectations()
  487. }
  488. func testPagedListFiles() {
  489. let expectation = self.expectation(description: #function)
  490. let ref = storage.reference(withPath: "ios/public/list")
  491. ref.list(maxResults: 2) { result in
  492. switch result {
  493. case let .success(listResult):
  494. XCTAssertEqual(listResult.items, [ref.child("a"), ref.child("b")])
  495. XCTAssertEqual(listResult.prefixes, [])
  496. guard let pageToken = listResult.pageToken else {
  497. XCTFail("pageToken should not be nil")
  498. expectation.fulfill()
  499. return
  500. }
  501. ref.list(maxResults: 2, pageToken: pageToken) { result in
  502. switch result {
  503. case let .success(listResult):
  504. XCTAssertEqual(listResult.items, [])
  505. XCTAssertEqual(listResult.prefixes, [ref.child("prefix")])
  506. XCTAssertNil(listResult.pageToken, "pageToken should be nil")
  507. case let .failure(error):
  508. XCTFail("Unexpected error \(error) from list")
  509. }
  510. expectation.fulfill()
  511. }
  512. case let .failure(error):
  513. XCTFail("Unexpected error \(error) from list")
  514. expectation.fulfill()
  515. }
  516. }
  517. waitForExpectations()
  518. }
  519. func testPagedListFilesTooManyError() {
  520. let expectation = self.expectation(description: #function)
  521. let ref = storage.reference(withPath: "ios/public/list")
  522. ref.list(maxResults: 22222) { result in
  523. switch result {
  524. case .success:
  525. XCTFail("Unexpected success from list")
  526. case let .failure(error as StorageError):
  527. switch error {
  528. case let .invalidArgument(message):
  529. XCTAssertEqual(message, "Argument 'maxResults' must be between 1 and 1000 inclusive.")
  530. default:
  531. XCTFail("Failed with unexpected error: \(error)")
  532. }
  533. case let .failure(error):
  534. XCTFail("Failed with unexpected error: \(error)")
  535. }
  536. expectation.fulfill()
  537. }
  538. waitForExpectations()
  539. }
  540. func testListAllFiles() {
  541. let expectation = self.expectation(description: #function)
  542. let ref = storage.reference(withPath: "ios/public/list")
  543. ref.listAll { result in
  544. switch result {
  545. case let .success(listResult):
  546. XCTAssertEqual(listResult.items, [ref.child("a"), ref.child("b")])
  547. XCTAssertEqual(listResult.prefixes, [ref.child("prefix")])
  548. XCTAssertNil(listResult.pageToken, "pageToken should be nil")
  549. case let .failure(error):
  550. XCTFail("Unexpected error \(error) from list")
  551. }
  552. expectation.fulfill()
  553. }
  554. waitForExpectations()
  555. }
  556. private func waitForExpectations() {
  557. let kFIRStorageIntegrationTestTimeout = 100.0
  558. waitForExpectations(timeout: kFIRStorageIntegrationTestTimeout,
  559. handler: { error in
  560. if let error = error {
  561. print(error)
  562. }
  563. })
  564. }
  565. private func assertResultSuccess<T>(_ result: Result<T, Error>,
  566. file: StaticString = #file, line: UInt = #line) {
  567. switch result {
  568. case let .success(value):
  569. XCTAssertNotNil(value, file: file, line: line)
  570. case let .failure(error):
  571. XCTFail("Unexpected error \(error)")
  572. }
  573. }
  574. private func assertResultFailure<T>(_ result: Result<T, Error>,
  575. file: StaticString = #file, line: UInt = #line) {
  576. switch result {
  577. case let .success(value):
  578. XCTFail("Unexpected success with value: \(value)")
  579. case let .failure(error):
  580. XCTAssertNotNil(error, file: file, line: line)
  581. }
  582. }
  583. }