StorageMetadataTests.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright 2022 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 Foundation
  15. @testable import FirebaseStorage
  16. import GTMSessionFetcherCore
  17. import XCTest
  18. class StorageMetadataTests: StorageTestHelpers {
  19. func testInitializeNoMetadata() {
  20. let metadata = StorageMetadata(dictionary: [:])
  21. XCTAssertNotNil(metadata)
  22. }
  23. func testInitializeFullMetadata() {
  24. let metaDict = [
  25. "bucket": "bucket",
  26. "cacheControl": "max-age=3600, no-cache",
  27. "contentDisposition": "inline",
  28. "contentEncoding": "gzip",
  29. "contentLanguage": "en-us",
  30. "contentType": "application/octet-stream",
  31. "customMetadata": ["foo": ["bar": "baz"]],
  32. "generation": "12345",
  33. "metageneration": "67890",
  34. "name": "path/to/object",
  35. "timeCreated": "1992-08-07T17:22:53.108Z",
  36. "updated": "2016-03-01T20:16:01.673Z",
  37. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  38. "size": 1337,
  39. ] as [String: AnyHashable]
  40. let metadata = StorageMetadata(dictionary: metaDict)
  41. XCTAssertNotNil(metadata)
  42. XCTAssertEqual(metadata.bucket, metaDict["bucket"] as? String)
  43. XCTAssertEqual(metadata.cacheControl, metaDict["cacheControl"] as? String)
  44. XCTAssertEqual(metadata.contentDisposition, metaDict["contentDisposition"] as? String)
  45. XCTAssertEqual(metadata.contentEncoding, metaDict["contentEncoding"] as? String)
  46. XCTAssertEqual(metadata.contentType, metaDict["contentType"] as? String)
  47. XCTAssertEqual(metadata.customMetadata, metaDict["customMetadata"] as? [String: String])
  48. XCTAssertEqual(metadata.md5Hash, metaDict["md5Hash"] as? String)
  49. XCTAssertEqual("\(metadata.generation)", "12345")
  50. XCTAssertEqual("\(metadata.metageneration)", "67890")
  51. XCTAssertEqual(metadata.path, metaDict["name"] as? String)
  52. XCTAssertEqual(StorageMetadata.RFC3339StringFromDate(metadata.timeCreated!),
  53. metaDict["timeCreated"] as? String)
  54. XCTAssertEqual(StorageMetadata.RFC3339StringFromDate(metadata.updated!),
  55. metaDict["updated"] as? String)
  56. XCTAssertEqual(metadata.size, 1337)
  57. }
  58. func testDictionaryRepresentation() {
  59. let metaDict = [
  60. "bucket": "bucket",
  61. "cacheControl": "max-age=3600, no-cache",
  62. "contentDisposition": "inline",
  63. "contentEncoding": "gzip",
  64. "contentLanguage": "en-us",
  65. "contentType": "application/octet-stream",
  66. "customMetadata": ["foo": ["bar": "baz"]],
  67. "generation": "12345",
  68. "metageneration": "67890",
  69. "name": "path/to/object",
  70. "timeCreated": "1992-08-07T17:22:53.108Z",
  71. "updated": "2016-03-01T20:16:01.673Z",
  72. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  73. "size": 1337,
  74. ] as [String: AnyHashable]
  75. let metadata = StorageMetadata(dictionary: metaDict)
  76. let dictRepresentation = metadata.dictionaryRepresentation()
  77. XCTAssertNotNil(dictRepresentation)
  78. XCTAssertEqual(dictRepresentation["bucket"] as? String, metaDict["bucket"] as? String)
  79. XCTAssertEqual(
  80. dictRepresentation["cacheControl"] as? String,
  81. metaDict["cacheControl"] as? String
  82. )
  83. XCTAssertEqual(
  84. dictRepresentation["contentDisposition"] as? String,
  85. metaDict["contentDisposition"] as? String
  86. )
  87. XCTAssertEqual(
  88. dictRepresentation["contentEncoding"] as? String,
  89. metaDict["contentEncoding"] as? String
  90. )
  91. XCTAssertEqual(dictRepresentation["contentType"] as? String, metaDict["contentType"] as? String)
  92. XCTAssertEqual(dictRepresentation["customMetadata"] as? [String: String],
  93. metaDict["customMetadata"] as? [String: String])
  94. XCTAssertEqual(dictRepresentation["md5Hash"] as? String, metaDict["md5Hash"] as? String)
  95. XCTAssertEqual(dictRepresentation["generation"] as? String, "12345")
  96. XCTAssertEqual(dictRepresentation["metageneration"] as? String, "67890")
  97. XCTAssertEqual(dictRepresentation["name"] as? String, metaDict["name"] as? String)
  98. XCTAssertEqual(dictRepresentation["timeCreated"] as? String,
  99. metaDict["timeCreated"] as? String)
  100. XCTAssertEqual(dictRepresentation["updated"] as? String,
  101. metaDict["updated"] as? String)
  102. XCTAssertEqual(dictRepresentation["size"] as? Int64, 1337)
  103. }
  104. func testInitializeEmptyDownloadURL() {
  105. let metaDict = ["bucket": "bucket", "name": "/path/to/object"]
  106. let rootReference = rootReference()
  107. let task = StorageGetDownloadURLTask(reference: rootReference,
  108. fetcherService: GTMSessionFetcherService(),
  109. queue: DispatchQueue.main,
  110. completion: nil)
  111. let actualURL = task.downloadURLFromMetadataDictionary(metaDict)
  112. XCTAssertNil(actualURL)
  113. }
  114. func testInitializeDownloadURLFromToken() {
  115. let metaDict = [
  116. "bucket": "bucket",
  117. "downloadTokens": "12345,ignored",
  118. "name": "path/to/object",
  119. ] as [String: String]
  120. let rootReference = rootReference()
  121. let escapedPath = StorageUtils.GCSEscapedString(metaDict["name"]!)
  122. let expectedURL =
  123. "https://firebasestorage.googleapis.com:443/v0/b/bucket/o/\(escapedPath)?alt=media&token=12345"
  124. let task = StorageGetDownloadURLTask(reference: rootReference,
  125. fetcherService: GTMSessionFetcherService(),
  126. queue: DispatchQueue.main,
  127. completion: nil)
  128. let actualURL = task.downloadURLFromMetadataDictionary(metaDict)
  129. XCTAssertEqual(actualURL?.absoluteString, expectedURL)
  130. }
  131. func testInitializeMetadataWithFile() {
  132. let metaDict = ["bucket": "bucket", "name": "/path/to/file"]
  133. let metadata = StorageMetadata(dictionary: metaDict)
  134. metadata.fileType = .file
  135. XCTAssertTrue(metadata.isFile)
  136. XCTAssertFalse(metadata.isFolder)
  137. }
  138. func testInitializeMetadataWithFolder() {
  139. let metaDict = ["bucket": "bucket", "name": "/path/to/folder"]
  140. let metadata = StorageMetadata(dictionary: metaDict)
  141. metadata.fileType = .folder
  142. XCTAssertFalse(metadata.isFile)
  143. XCTAssertTrue(metadata.isFolder)
  144. }
  145. func testReflexiveMetadataEquality() {
  146. let metaDict = ["bucket": "bucket", "name": "/path/to/file"]
  147. let metadata0 = StorageMetadata(dictionary: metaDict)
  148. let metadata1 = metadata0
  149. XCTAssertEqual(metadata0, metadata1)
  150. }
  151. func testNonsenseMetadataEquality() {
  152. let metaDict = [
  153. "bucket": "bucket",
  154. "name": "path/to/object",
  155. ] as [String: String]
  156. let metadata0 = StorageMetadata(dictionary: metaDict)
  157. XCTAssertNotEqual(metadata0, StorageMetadata())
  158. }
  159. func testMetadataEquality() {
  160. let metaDict = [
  161. "bucket": "bucket",
  162. "name": "/path/to/file",
  163. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  164. ]
  165. let metadata0 = StorageMetadata(dictionary: metaDict)
  166. let metadata1 = StorageMetadata(dictionary: metaDict)
  167. XCTAssertEqual(metadata0, metadata1)
  168. }
  169. func testMetadataMd5Inequality() {
  170. let metaDict0 = ["md5Hash": "d41d8cd98f00b204e9800998ecf8427e"]
  171. let metaDict1 = ["md5Hash": "d41d8cd98f00b204e9800998ecf8427f"]
  172. let metadata0 = StorageMetadata(dictionary: metaDict0)
  173. let metadata1 = StorageMetadata(dictionary: metaDict1)
  174. XCTAssertNotEqual(metadata0, metadata1)
  175. }
  176. func testMetadataCopy() {
  177. let metaDict = [
  178. "bucket": "bucket",
  179. "name": "/path/to/file",
  180. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  181. ]
  182. let metadata0 = StorageMetadata(dictionary: metaDict)
  183. let metadata1 = metadata0.copy() as? StorageMetadata
  184. // Verify that copied object has a new reference.
  185. XCTAssertFalse(metadata0 === metadata1)
  186. XCTAssertEqual(metadata0, metadata1)
  187. }
  188. func testUpdatedMetadata() {
  189. let oldMetadata = [
  190. "contentLanguage": "old",
  191. "metadata": ["foo": "old", "bar": "old"],
  192. ] as [String: AnyHashable]
  193. let metadata = StorageMetadata(dictionary: oldMetadata)
  194. metadata.contentLanguage = "new"
  195. metadata.customMetadata = ["foo": "new", "bar": "old"]
  196. let update = metadata.updatedMetadata()
  197. let expectedUpdate = [
  198. "contentLanguage": "new",
  199. "metadata": ["foo": "new"],
  200. "bucket": "",
  201. ] as [String: AnyHashable]
  202. XCTAssertEqual(update, expectedUpdate)
  203. }
  204. func testUpdatedMetadataWithEmptyUpdate() {
  205. let oldMetadata = [
  206. "contentLanguage": "old",
  207. "metadata": ["foo": "old", "bar": "old"],
  208. ] as [String: AnyHashable]
  209. let metadata = StorageMetadata(dictionary: oldMetadata)
  210. let update = metadata.updatedMetadata()
  211. XCTAssertEqual(update, ["bucket": ""])
  212. }
  213. func testUpdatedMetadataWithDelete() {
  214. let oldMetadata = [
  215. "contentLanguage": "old",
  216. "metadata": ["foo": "old", "bar": "old"],
  217. ] as [String: AnyHashable]
  218. let metadata = StorageMetadata(dictionary: oldMetadata)
  219. metadata.contentLanguage = nil
  220. metadata.customMetadata = ["foo": "old"]
  221. let update = metadata.updatedMetadata()
  222. let expected = ["bucket": "",
  223. "contentLanguage": NSNull(),
  224. "metadata": ["bar": NSNull()]] as [String: AnyHashable]
  225. XCTAssertEqual(update, expected)
  226. }
  227. func testMetadataHashEquality() {
  228. let metaDict = [
  229. "bucket": "bucket",
  230. "name": "path/to/object",
  231. ] as [String: String]
  232. let metadata0 = StorageMetadata(dictionary: metaDict)
  233. let metadata1 = StorageMetadata(dictionary: metaDict)
  234. XCTAssertFalse(metadata0 === metadata1)
  235. XCTAssertTrue(metadata0 == metadata1)
  236. XCTAssertEqual(metadata0.hash, metadata1.hash)
  237. }
  238. func testZuluTimeOffset() {
  239. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108Z"]
  240. let metadata = StorageMetadata(dictionary: metaDict)
  241. XCTAssertNotNil(metadata)
  242. }
  243. func testZuluZeroTimeOffset() {
  244. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108+0000"]
  245. let metadata = StorageMetadata(dictionary: metaDict)
  246. XCTAssertNotNil(metadata)
  247. }
  248. func testGoogleStandardTimeOffset() {
  249. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108-0700"]
  250. let metadata = StorageMetadata(dictionary: metaDict)
  251. XCTAssertNotNil(metadata)
  252. }
  253. func testUnspecifiedTimeOffset() {
  254. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108-0000"]
  255. let metadata = StorageMetadata(dictionary: metaDict)
  256. XCTAssertNotNil(metadata)
  257. }
  258. func testNoTimeOffset() {
  259. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108"]
  260. let metadata = StorageMetadata(dictionary: metaDict)
  261. XCTAssertNotNil(metadata)
  262. }
  263. }