StorageMetadataTests.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 actualURL = StorageGetDownloadURLTask.downloadURLFromMetadataDictionary(metaDict,
  108. rootReference)
  109. XCTAssertNil(actualURL)
  110. }
  111. func testInitializeDownloadURLFromToken() {
  112. let metaDict = [
  113. "bucket": "bucket",
  114. "downloadTokens": "12345,ignored",
  115. "name": "path/to/object",
  116. ] as [String: String]
  117. let rootReference = rootReference()
  118. let escapedPath = StorageUtils.GCSEscapedString(metaDict["name"]!)
  119. let expectedURL =
  120. "https://firebasestorage.googleapis.com:443/v0/b/bucket/o/\(escapedPath)?alt=media&token=12345"
  121. let actualURL = StorageGetDownloadURLTask.downloadURLFromMetadataDictionary(metaDict,
  122. rootReference)
  123. XCTAssertEqual(actualURL?.absoluteString, expectedURL)
  124. }
  125. // Regression test for #10370
  126. func testInitializeDownloadURLFromTokenWithEmptyMetadata() {
  127. let metaDict = [
  128. "bucket": "bucket",
  129. "downloadTokens": "12345,ignored",
  130. "name": "path/to/object",
  131. "metadata": {},
  132. ] as [String: Any]
  133. let rootReference = rootReference()
  134. let escapedPath = StorageUtils.GCSEscapedString("path/to/object")
  135. let expectedURL =
  136. "https://firebasestorage.googleapis.com:443/v0/b/bucket/o/\(escapedPath)?alt=media&token=12345"
  137. let actualURL = StorageGetDownloadURLTask.downloadURLFromMetadataDictionary(metaDict,
  138. rootReference)
  139. XCTAssertEqual(actualURL?.absoluteString, expectedURL)
  140. }
  141. func testInitializeMetadataWithFile() {
  142. let metaDict = ["bucket": "bucket", "name": "/path/to/file"]
  143. let metadata = StorageMetadata(dictionary: metaDict)
  144. metadata.fileType = .file
  145. XCTAssertTrue(metadata.isFile)
  146. XCTAssertFalse(metadata.isFolder)
  147. }
  148. func testInitializeMetadataWithFolder() {
  149. let metaDict = ["bucket": "bucket", "name": "/path/to/folder"]
  150. let metadata = StorageMetadata(dictionary: metaDict)
  151. metadata.fileType = .folder
  152. XCTAssertFalse(metadata.isFile)
  153. XCTAssertTrue(metadata.isFolder)
  154. }
  155. func testReflexiveMetadataEquality() {
  156. let metaDict = ["bucket": "bucket", "name": "/path/to/file"]
  157. let metadata0 = StorageMetadata(dictionary: metaDict)
  158. let metadata1 = metadata0
  159. XCTAssertEqual(metadata0, metadata1)
  160. }
  161. func testNonsenseMetadataEquality() {
  162. let metaDict = [
  163. "bucket": "bucket",
  164. "name": "path/to/object",
  165. ] as [String: String]
  166. let metadata0 = StorageMetadata(dictionary: metaDict)
  167. XCTAssertNotEqual(metadata0, StorageMetadata())
  168. }
  169. func testMetadataEquality() {
  170. let metaDict = [
  171. "bucket": "bucket",
  172. "name": "/path/to/file",
  173. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  174. ]
  175. let metadata0 = StorageMetadata(dictionary: metaDict)
  176. let metadata1 = StorageMetadata(dictionary: metaDict)
  177. XCTAssertEqual(metadata0, metadata1)
  178. }
  179. func testMetadataMd5Inequality() {
  180. let metaDict0 = ["md5Hash": "d41d8cd98f00b204e9800998ecf8427e"]
  181. let metaDict1 = ["md5Hash": "d41d8cd98f00b204e9800998ecf8427f"]
  182. let metadata0 = StorageMetadata(dictionary: metaDict0)
  183. let metadata1 = StorageMetadata(dictionary: metaDict1)
  184. XCTAssertNotEqual(metadata0, metadata1)
  185. }
  186. func testMetadataCopy() {
  187. let metaDict = [
  188. "bucket": "bucket",
  189. "name": "/path/to/file",
  190. "md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
  191. ]
  192. let metadata0 = StorageMetadata(dictionary: metaDict)
  193. let metadata1 = metadata0.copy() as? StorageMetadata
  194. // Verify that copied object has a new reference.
  195. XCTAssertFalse(metadata0 === metadata1)
  196. XCTAssertEqual(metadata0, metadata1)
  197. }
  198. func testUpdatedMetadata() {
  199. let oldMetadata = [
  200. "contentLanguage": "old",
  201. "metadata": ["foo": "old", "bar": "old"],
  202. ] as [String: AnyHashable]
  203. let metadata = StorageMetadata(dictionary: oldMetadata)
  204. metadata.contentLanguage = "new"
  205. metadata.customMetadata = ["foo": "new", "bar": "old"]
  206. let update = metadata.updatedMetadata()
  207. let expectedUpdate = [
  208. "contentLanguage": "new",
  209. "metadata": ["foo": "new"],
  210. "bucket": "",
  211. ] as [String: AnyHashable]
  212. XCTAssertEqual(update, expectedUpdate)
  213. }
  214. func testUpdatedMetadataWithEmptyUpdate() {
  215. let oldMetadata = [
  216. "contentLanguage": "old",
  217. "metadata": ["foo": "old", "bar": "old"],
  218. ] as [String: AnyHashable]
  219. let metadata = StorageMetadata(dictionary: oldMetadata)
  220. let update = metadata.updatedMetadata()
  221. XCTAssertEqual(update, ["bucket": ""])
  222. }
  223. func testUpdatedMetadataWithDelete() {
  224. let oldMetadata = [
  225. "contentLanguage": "old",
  226. "metadata": ["foo": "old", "bar": "old"],
  227. ] as [String: AnyHashable]
  228. let metadata = StorageMetadata(dictionary: oldMetadata)
  229. metadata.contentLanguage = nil
  230. metadata.customMetadata = ["foo": "old"]
  231. let update = metadata.updatedMetadata()
  232. let expected = ["bucket": "",
  233. "contentLanguage": NSNull(),
  234. "metadata": ["bar": NSNull()]] as [String: AnyHashable]
  235. XCTAssertEqual(update, expected)
  236. }
  237. func testMetadataHashEquality() {
  238. let metaDict = [
  239. "bucket": "bucket",
  240. "name": "path/to/object",
  241. ] as [String: String]
  242. let metadata0 = StorageMetadata(dictionary: metaDict)
  243. let metadata1 = StorageMetadata(dictionary: metaDict)
  244. XCTAssertFalse(metadata0 === metadata1)
  245. XCTAssertTrue(metadata0 == metadata1)
  246. XCTAssertEqual(metadata0.hash, metadata1.hash)
  247. }
  248. func testZuluTimeOffset() {
  249. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108Z"]
  250. let metadata = StorageMetadata(dictionary: metaDict)
  251. XCTAssertNotNil(metadata)
  252. }
  253. func testZuluZeroTimeOffset() {
  254. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108+0000"]
  255. let metadata = StorageMetadata(dictionary: metaDict)
  256. XCTAssertNotNil(metadata)
  257. }
  258. func testGoogleStandardTimeOffset() {
  259. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108-0700"]
  260. let metadata = StorageMetadata(dictionary: metaDict)
  261. XCTAssertNotNil(metadata)
  262. }
  263. func testUnspecifiedTimeOffset() {
  264. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108-0000"]
  265. let metadata = StorageMetadata(dictionary: metaDict)
  266. XCTAssertNotNil(metadata)
  267. }
  268. func testNoTimeOffset() {
  269. let metaDict = ["timeCreated": "1992-08-07T17:22:53.108"]
  270. let metadata = StorageMetadata(dictionary: metaDict)
  271. XCTAssertNotNil(metadata)
  272. }
  273. }