ParameterEncoderTests.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. //
  2. // ParameterEncoderTests.swift
  3. //
  4. // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. import Alamofire
  25. import XCTest
  26. final class JSONParameterEncoderTests: BaseTestCase {
  27. func testThatDataIsProperlyEncodedAndProperContentTypeIsSet() throws {
  28. // Given
  29. let encoder = JSONParameterEncoder()
  30. let request = URLRequest.makeHTTPBinRequest()
  31. // When
  32. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  33. // Then
  34. XCTAssertEqual(newRequest.httpHeaders["Content-Type"], "application/json")
  35. XCTAssertEqual(newRequest.httpBody?.asString, "{\"property\":\"property\"}")
  36. }
  37. func testThatDataIsProperlyEncodedButContentTypeIsNotSetIfRequestAlreadyHasAContentType() throws {
  38. // Given
  39. let encoder = JSONParameterEncoder()
  40. var request = URLRequest.makeHTTPBinRequest()
  41. request.httpHeaders.update(.contentType("type"))
  42. // When
  43. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  44. // Then
  45. XCTAssertEqual(newRequest.httpHeaders["Content-Type"], "type")
  46. XCTAssertEqual(newRequest.httpBody?.asString, "{\"property\":\"property\"}")
  47. }
  48. func testThatJSONEncoderCanBeCustomized() throws {
  49. // Given
  50. let jsonEncoder = JSONEncoder()
  51. jsonEncoder.outputFormatting = .prettyPrinted
  52. let encoder = JSONParameterEncoder(encoder: jsonEncoder)
  53. let request = URLRequest.makeHTTPBinRequest()
  54. // When
  55. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  56. // Then
  57. let expected = """
  58. {
  59. "property" : "property"
  60. }
  61. """
  62. XCTAssertEqual(newRequest.httpBody?.asString, expected)
  63. }
  64. func testThatJSONEncoderDefaultWorks() throws {
  65. // Given
  66. let encoder = JSONParameterEncoder.default
  67. let request = URLRequest.makeHTTPBinRequest()
  68. // When
  69. let encoded = try encoder.encode(HTTPBinParameters.default, into: request)
  70. // Then
  71. let expected = """
  72. {"property":"property"}
  73. """
  74. XCTAssertEqual(encoded.httpBody?.asString, expected)
  75. }
  76. func testThatJSONEncoderPrettyPrintedPrintsPretty() throws {
  77. // Given
  78. let encoder = JSONParameterEncoder.prettyPrinted
  79. let request = URLRequest.makeHTTPBinRequest()
  80. // When
  81. let encoded = try encoder.encode(HTTPBinParameters.default, into: request)
  82. // Then
  83. let expected = """
  84. {
  85. "property" : "property"
  86. }
  87. """
  88. XCTAssertEqual(encoded.httpBody?.asString, expected)
  89. }
  90. @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
  91. func testTestJSONEncoderSortedKeysHasSortedKeys() throws {
  92. // Given
  93. let encoder = JSONParameterEncoder.sortedKeys
  94. let request = URLRequest.makeHTTPBinRequest()
  95. // When
  96. let encoded = try encoder.encode(["z": "z", "a": "a", "p": "p"], into: request)
  97. // Then
  98. let expected = """
  99. {"a":"a","p":"p","z":"z"}
  100. """
  101. XCTAssertEqual(encoded.httpBody?.asString, expected)
  102. }
  103. }
  104. final class URLEncodedFormParameterEncoderTests: BaseTestCase {
  105. func testThatQueryIsBodyEncodedAndProperContentTypeIsSetForPOSTRequest() throws {
  106. // Given
  107. let encoder = URLEncodedFormParameterEncoder()
  108. let request = URLRequest.makeHTTPBinRequest(method: .post)
  109. // When
  110. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  111. // Then
  112. XCTAssertEqual(newRequest.httpHeaders["Content-Type"], "application/x-www-form-urlencoded; charset=utf-8")
  113. XCTAssertEqual(newRequest.httpBody?.asString, "property=property")
  114. }
  115. func testThatQueryIsBodyEncodedButContentTypeIsNotSetWhenRequestAlreadyHasContentType() throws {
  116. // Given
  117. let encoder = URLEncodedFormParameterEncoder()
  118. var request = URLRequest.makeHTTPBinRequest(method: .post)
  119. request.httpHeaders.update(.contentType("type"))
  120. // When
  121. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  122. // Then
  123. XCTAssertEqual(newRequest.httpHeaders["Content-Type"], "type")
  124. XCTAssertEqual(newRequest.httpBody?.asString, "property=property")
  125. }
  126. func testThatEncoderCanBeCustomized() throws {
  127. // Given
  128. let urlEncoder = URLEncodedFormEncoder(boolEncoding: .literal)
  129. let encoder = URLEncodedFormParameterEncoder(encoder: urlEncoder)
  130. let request = URLRequest.makeHTTPBinRequest()
  131. // When
  132. let newRequest = try encoder.encode(["bool": true], into: request)
  133. // Then
  134. let components = URLComponents(url: newRequest.url!, resolvingAgainstBaseURL: false)
  135. XCTAssertEqual(components?.percentEncodedQuery, "bool=true")
  136. }
  137. func testThatQueryIsInURLWhenDestinationIsURLAndMethodIsPOST() throws {
  138. // Given
  139. let encoder = URLEncodedFormParameterEncoder(destination: .queryString)
  140. let request = URLRequest.makeHTTPBinRequest(method: .post)
  141. // When
  142. let newRequest = try encoder.encode(HTTPBinParameters.default, into: request)
  143. // Then
  144. let components = URLComponents(url: newRequest.url!, resolvingAgainstBaseURL: false)
  145. XCTAssertEqual(components?.percentEncodedQuery, "property=property")
  146. }
  147. }
  148. final class URLEncodedFormEncoderTests: BaseTestCase {
  149. func testEncoderThrowsErrorWhenAttemptingToEncodeNilInKeyedContainer() {
  150. // Given
  151. let encoder = URLEncodedFormEncoder()
  152. let parameters = FailingOptionalStruct(testedContainer: .keyed)
  153. // When
  154. let result = Result<String> { try encoder.encode(parameters) }
  155. // Then
  156. XCTAssertTrue(result.isFailure)
  157. }
  158. func testEncoderThrowsErrorWhenAttemptingToEncodeNilInUnkeyedContainer() {
  159. // Given
  160. let encoder = URLEncodedFormEncoder()
  161. let parameters = FailingOptionalStruct(testedContainer: .unkeyed)
  162. // When
  163. let result = Result<String> { try encoder.encode(parameters) }
  164. // Then
  165. XCTAssertTrue(result.isFailure)
  166. }
  167. func testEncoderCanEncodeDictionary() {
  168. // Given
  169. let encoder = URLEncodedFormEncoder()
  170. let parameters = ["a": "a"]
  171. // When
  172. let result = Result<String> { try encoder.encode(parameters) }
  173. // Then
  174. XCTAssertEqual(result.value, "a=a")
  175. }
  176. func testEncoderCanEncodeDouble() {
  177. // Given
  178. let encoder = URLEncodedFormEncoder()
  179. let parameters = ["a": 1.0]
  180. // When
  181. let result = Result<String> { try encoder.encode(parameters) }
  182. // Then
  183. XCTAssertEqual(result.value, "a=1.0")
  184. }
  185. func testEncoderCanEncodeFloat() {
  186. // Given
  187. let encoder = URLEncodedFormEncoder()
  188. let parameters: [String: Float] = ["a": 1.0]
  189. // When
  190. let result = Result<String> { try encoder.encode(parameters) }
  191. // Then
  192. XCTAssertEqual(result.value, "a=1.0")
  193. }
  194. func testEncoderCanEncodeInt8() {
  195. // Given
  196. let encoder = URLEncodedFormEncoder()
  197. let parameters: [String: Int8] = ["a": 1]
  198. // When
  199. let result = Result<String> { try encoder.encode(parameters) }
  200. // Then
  201. XCTAssertEqual(result.value, "a=1")
  202. }
  203. func testEncoderCanEncodeInt16() {
  204. // Given
  205. let encoder = URLEncodedFormEncoder()
  206. let parameters: [String: Int16] = ["a": 1]
  207. // When
  208. let result = Result<String> { try encoder.encode(parameters) }
  209. // Then
  210. XCTAssertEqual(result.value, "a=1")
  211. }
  212. func testEncoderCanEncodeInt32() {
  213. // Given
  214. let encoder = URLEncodedFormEncoder()
  215. let parameters: [String: Int32] = ["a": 1]
  216. // When
  217. let result = Result<String> { try encoder.encode(parameters) }
  218. // Then
  219. XCTAssertEqual(result.value, "a=1")
  220. }
  221. func testEncoderCanEncodeInt64() {
  222. // Given
  223. let encoder = URLEncodedFormEncoder()
  224. let parameters: [String: Int64] = ["a": 1]
  225. // When
  226. let result = Result<String> { try encoder.encode(parameters) }
  227. // Then
  228. XCTAssertEqual(result.value, "a=1")
  229. }
  230. func testEncoderCanEncodeUInt() {
  231. // Given
  232. let encoder = URLEncodedFormEncoder()
  233. let parameters: [String: UInt] = ["a": 1]
  234. // When
  235. let result = Result<String> { try encoder.encode(parameters) }
  236. // Then
  237. XCTAssertEqual(result.value, "a=1")
  238. }
  239. func testEncoderCanEncodeUInt8() {
  240. // Given
  241. let encoder = URLEncodedFormEncoder()
  242. let parameters: [String: UInt8] = ["a": 1]
  243. // When
  244. let result = Result<String> { try encoder.encode(parameters) }
  245. // Then
  246. XCTAssertEqual(result.value, "a=1")
  247. }
  248. func testEncoderCanEncodeUInt16() {
  249. // Given
  250. let encoder = URLEncodedFormEncoder()
  251. let parameters: [String: UInt16] = ["a": 1]
  252. // When
  253. let result = Result<String> { try encoder.encode(parameters) }
  254. // Then
  255. XCTAssertEqual(result.value, "a=1")
  256. }
  257. func testEncoderCanEncodeUInt32() {
  258. // Given
  259. let encoder = URLEncodedFormEncoder()
  260. let parameters: [String: UInt32] = ["a": 1]
  261. // When
  262. let result = Result<String> { try encoder.encode(parameters) }
  263. // Then
  264. XCTAssertEqual(result.value, "a=1")
  265. }
  266. func testEncoderCanEncodeUInt64() {
  267. // Given
  268. let encoder = URLEncodedFormEncoder()
  269. let parameters: [String: UInt64] = ["a": 1]
  270. // When
  271. let result = Result<String> { try encoder.encode(parameters) }
  272. // Then
  273. XCTAssertEqual(result.value, "a=1")
  274. }
  275. func testThatNestedDictionariesHaveBracketedKeys() {
  276. // Given
  277. let encoder = URLEncodedFormEncoder()
  278. let parameters = ["a": ["b": "b"]]
  279. // When
  280. let result = Result<String> { try encoder.encode(parameters) }
  281. // Then
  282. XCTAssertEqual(result.value, "a%5Bb%5D=b")
  283. }
  284. func testThatEncodableStructCanBeEncoded() {
  285. // Given
  286. let encoder = URLEncodedFormEncoder()
  287. let parameters = EncodableStruct()
  288. // When
  289. let result = Result<String> { try encoder.encode(parameters) }
  290. // Then
  291. let expected = "four%5B%5D=1&four%5B%5D=2&four%5B%5D=3&three=1&one=one&two=2&five%5Ba%5D=a&six%5Ba%5D%5Bb%5D=b&seven%5Ba%5D=a"
  292. XCTAssertEqual(result.value, expected)
  293. }
  294. func testThatManuallyEncodableStructCanBeEncoded() {
  295. // Given
  296. let encoder = URLEncodedFormEncoder()
  297. let parameters = ManuallyEncodableStruct()
  298. // When
  299. let result = Result<String> { try encoder.encode(parameters) }
  300. // Then
  301. let expected = "root%5B%5D%5B%5D=1&root%5B%5D%5B%5D=2&root%5B%5D%5B%5D=3&root%5B%5D%5Ba%5D%5Bstring%5D=string&root%5B%5D%5B%5D%5B%5D=1&root%5B%5D%5B%5D%5B%5D=2&root%5B%5D%5B%5D%5B%5D=3"
  302. XCTAssertEqual(result.value, expected)
  303. }
  304. func testThatEncodableClassWithNoInheritanceCanBeEncoded() {
  305. // Given
  306. let encoder = URLEncodedFormEncoder()
  307. let parameters = EncodableSuperclass()
  308. // When
  309. let result = Result<String> { try encoder.encode(parameters) }
  310. // Then
  311. XCTAssertEqual(result.value, "two=2&one=one&three=1")
  312. }
  313. func testThatEncodableSubclassCanBeEncoded() {
  314. // Given
  315. let encoder = URLEncodedFormEncoder()
  316. let parameters = EncodableSubclass()
  317. // When
  318. let result = Result<String> { try encoder.encode(parameters) }
  319. // Then
  320. let expected = "four%5B%5D=1&four%5B%5D=2&four%5B%5D=3&two=2&five%5Ba%5D=a&five%5Bb%5D=b&three=1&one=one"
  321. XCTAssertEqual(result.value, expected)
  322. }
  323. func testThatManuallyEncodableSubclassCanBeEncoded() {
  324. // Given
  325. let encoder = URLEncodedFormEncoder()
  326. let parameters = ManuallyEncodableSubclass()
  327. // When
  328. let result = Result<String> { try encoder.encode(parameters) }
  329. // Then
  330. let expected = "five%5Ba%5D=a&five%5Bb%5D=b&four%5Bfour%5D=one&four%5Bfive%5D=2"
  331. XCTAssertEqual(result.value, expected)
  332. }
  333. func testThatARootArrayCannotBeEncoded() {
  334. // Given
  335. let encoder = URLEncodedFormEncoder()
  336. let parameters = [1]
  337. // When
  338. let result = Result<String> { try encoder.encode(parameters) }
  339. // Then
  340. XCTAssertFalse(result.isSuccess)
  341. }
  342. func testThatARootValueCannotBeEncoded() {
  343. // Given
  344. let encoder = URLEncodedFormEncoder()
  345. let parameters = "string"
  346. // When
  347. let result = Result<String> { try encoder.encode(parameters) }
  348. // Then
  349. XCTAssertFalse(result.isSuccess)
  350. }
  351. func testThatOptionalValuesCannotBeEncoded() {
  352. // Givenp
  353. let encoder = URLEncodedFormEncoder()
  354. let parameters: [String: String?] = ["string": nil]
  355. // When
  356. let result = Result<String> { try encoder.encode(parameters) }
  357. // Then
  358. XCTAssertFalse(result.isSuccess)
  359. }
  360. func testThatBoolsCanBeLiteralEncoded() {
  361. // Given
  362. let encoder = URLEncodedFormEncoder(boolEncoding: .literal)
  363. let parameters = ["bool": true]
  364. // When
  365. let result = Result<String> { try encoder.encode(parameters) }
  366. // Then
  367. XCTAssertEqual(result.value, "bool=true")
  368. }
  369. func testThatArraysCanBeEncodedWithoutBrackets() {
  370. // Given
  371. let encoder = URLEncodedFormEncoder(arrayEncoding: .noBrackets)
  372. let parameters = ["array": [1, 2]]
  373. // When
  374. let result = Result<String> { try encoder.encode(parameters) }
  375. // Then
  376. XCTAssertEqual(result.value, "array=1&array=2")
  377. }
  378. func testThatSpacesCanBeEncodedAsPluses() {
  379. // Given
  380. let encoder = URLEncodedFormEncoder(spaceEncoding: .plusReplaced)
  381. let parameters = ["spaces": "replace with spaces"]
  382. // When
  383. let result = Result<String> { try encoder.encode(parameters) }
  384. // Then
  385. XCTAssertEqual(result.value, "spaces=replace+with+spaces")
  386. }
  387. func testThatEscapedCharactersCanBeCustomized() {
  388. // Given
  389. var allowed = CharacterSet.afURLQueryAllowed
  390. allowed.remove(charactersIn: "?/")
  391. let encoder = URLEncodedFormEncoder(allowedCharacters: allowed)
  392. let parameters = ["allowed": "?/"]
  393. // When
  394. let result = Result<String> { try encoder.encode(parameters) }
  395. // Then
  396. XCTAssertEqual(result.value, "allowed=%3F%2F")
  397. }
  398. func testThatUnreservedCharactersAreNotPercentEscaped() {
  399. // Given
  400. let encoder = URLEncodedFormEncoder()
  401. let parameters = ["lowercase": "abcdefghijklmnopqrstuvwxyz",
  402. "uppercase": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  403. "numbers": "0123456789"]
  404. // When
  405. let result = Result<String> { try encoder.encode(parameters) }
  406. // Then
  407. XCTAssertEqual(result.value,
  408. "uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ&numbers=0123456789&lowercase=abcdefghijklmnopqrstuvwxyz")
  409. }
  410. func testThatReseredCharactersArePercentEscaped() {
  411. // Given
  412. let encoder = URLEncodedFormEncoder()
  413. let generalDelimiters = ":#[]@"
  414. let subDelimiters = "!$&'()*+,;="
  415. let parameters = ["reserved": "\(generalDelimiters)\(subDelimiters)"]
  416. // When
  417. let result = Result<String> { try encoder.encode(parameters) }
  418. // Then
  419. XCTAssertEqual(result.value, "reserved=%3A%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D")
  420. }
  421. func testThatIllegalASCIICharactersArePercentEscaped() {
  422. // Given
  423. let encoder = URLEncodedFormEncoder()
  424. let parameters = ["illegal": " \"#%<>[]\\^`{}|"]
  425. // When
  426. let result = Result<String> { try encoder.encode(parameters) }
  427. // Then
  428. XCTAssertEqual(result.value, "illegal=%20%22%23%25%3C%3E%5B%5D%5C%5E%60%7B%7D%7C")
  429. }
  430. func testThatAmpersandsInKeysAndValuesArePercentEscaped() {
  431. // Given
  432. let encoder = URLEncodedFormEncoder()
  433. let parameters = ["foo&bar": "baz&qux", "foobar": "bazqux"]
  434. // When
  435. let result = Result<String> { try encoder.encode(parameters) }
  436. // Then
  437. XCTAssertEqual(result.value, "foobar=bazqux&foo%26bar=baz%26qux")
  438. }
  439. func testThatQuestionMarksInKeysAndValuesAreNotPercentEscaped() {
  440. // Given
  441. let encoder = URLEncodedFormEncoder()
  442. let parameters = ["?foo?": "?bar?"]
  443. // When
  444. let result = Result<String> { try encoder.encode(parameters) }
  445. // Then
  446. XCTAssertEqual(result.value, "?foo?=?bar?")
  447. }
  448. func testThatSlashesInKeysAndValuesAreNotPercentEscaped() {
  449. // Given
  450. let encoder = URLEncodedFormEncoder()
  451. let parameters = ["foo": "/bar/baz/qux"]
  452. // When
  453. let result = Result<String> { try encoder.encode(parameters) }
  454. // Then
  455. XCTAssertEqual(result.value, "foo=/bar/baz/qux")
  456. }
  457. func testThatSpacesInKeysAndValuesArePercentEscaped() {
  458. // Given
  459. let encoder = URLEncodedFormEncoder()
  460. let parameters = [" foo ": " bar "]
  461. // When
  462. let result = Result<String> { try encoder.encode(parameters) }
  463. // Then
  464. XCTAssertEqual(result.value, "%20foo%20=%20bar%20")
  465. }
  466. func testThatPlusesInKeysAndValuesArePercentEscaped() {
  467. // Given
  468. let encoder = URLEncodedFormEncoder()
  469. let parameters = ["+foo+": "+bar+"]
  470. // When
  471. let result = Result<String> { try encoder.encode(parameters) }
  472. // Then
  473. XCTAssertEqual(result.value, "%2Bfoo%2B=%2Bbar%2B")
  474. }
  475. func testThatPercentsInKeysAndValuesArePercentEscaped() {
  476. // Given
  477. let encoder = URLEncodedFormEncoder()
  478. let parameters = ["percent%": "%25"]
  479. // When
  480. let result = Result<String> { try encoder.encode(parameters) }
  481. // Then
  482. XCTAssertEqual(result.value, "percent%25=%2525")
  483. }
  484. func testThatNonLatinCharactersArePercentEscaped() {
  485. // Given
  486. let encoder = URLEncodedFormEncoder()
  487. let parameters = [
  488. "french": "français",
  489. "japanese": "日本語",
  490. "arabic": "العربية",
  491. "emoji": "😃"
  492. ]
  493. // When
  494. let result = Result<String> { try encoder.encode(parameters) }
  495. // Then
  496. let expectedParameterValues = [
  497. "arabic=%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9",
  498. "japanese=%E6%97%A5%E6%9C%AC%E8%AA%9E",
  499. "french=fran%C3%A7ais",
  500. "emoji=%F0%9F%98%83"
  501. ].joined(separator: "&")
  502. XCTAssertEqual(result.value, expectedParameterValues)
  503. }
  504. func testStringWithThousandsOfChineseCharactersIsPercentEscaped() {
  505. // Given
  506. let encoder = URLEncodedFormEncoder()
  507. let repeatedCount = 2_000
  508. let parameters = ["chinese": String(repeating: "一二三四五六七八九十", count: repeatedCount)]
  509. // When
  510. let result = Result<String> { try encoder.encode(parameters) }
  511. // Then
  512. let escaped = String(repeating: "%E4%B8%80%E4%BA%8C%E4%B8%89%E5%9B%9B%E4%BA%94%E5%85%AD%E4%B8%83%E5%85%AB%E4%B9%9D%E5%8D%81",
  513. count: repeatedCount)
  514. let expected = "chinese=\(escaped)"
  515. XCTAssertEqual(result.value, expected)
  516. }
  517. }
  518. private struct EncodableStruct: Encodable {
  519. let one = "one"
  520. let two = 2
  521. let three = true
  522. let four = [1, 2, 3]
  523. let five = ["a": "a"]
  524. let six = ["a": ["b": "b"]]
  525. let seven = NestedEncodableStruct()
  526. }
  527. private struct NestedEncodableStruct: Encodable {
  528. let a = "a"
  529. }
  530. private class EncodableSuperclass: Encodable {
  531. let one = "one"
  532. let two = 2
  533. let three = true
  534. }
  535. private final class EncodableSubclass: EncodableSuperclass {
  536. let four = [1, 2, 3]
  537. let five = ["a": "a", "b": "b"]
  538. private enum CodingKeys: String, CodingKey {
  539. case four, five
  540. }
  541. override func encode(to encoder: Encoder) throws {
  542. try super.encode(to: encoder)
  543. var container = encoder.container(keyedBy: CodingKeys.self)
  544. try container.encode(four, forKey: .four)
  545. try container.encode(five, forKey: .five)
  546. }
  547. }
  548. private final class ManuallyEncodableSubclass: EncodableSuperclass {
  549. let four = [1, 2, 3]
  550. let five = ["a": "a", "b": "b"]
  551. private enum CodingKeys: String, CodingKey {
  552. case four, five
  553. }
  554. override func encode(to encoder: Encoder) throws {
  555. var keyedContainer = encoder.container(keyedBy: CodingKeys.self)
  556. try keyedContainer.encode(four, forKey: .four)
  557. try keyedContainer.encode(five, forKey: .five)
  558. let superEncoder = keyedContainer.superEncoder()
  559. var superContainer = superEncoder.container(keyedBy: CodingKeys.self)
  560. try superContainer.encode(one, forKey: .four)
  561. let keyedSuperEncoder = keyedContainer.superEncoder(forKey: .four)
  562. var superKeyedContainer = keyedSuperEncoder.container(keyedBy: CodingKeys.self)
  563. try superKeyedContainer.encode(two, forKey: .five)
  564. var unkeyedContainer = keyedContainer.nestedUnkeyedContainer(forKey: .four)
  565. let unkeyedSuperEncoder = unkeyedContainer.superEncoder()
  566. var keyedUnkeyedSuperContainer = unkeyedSuperEncoder.container(keyedBy: CodingKeys.self)
  567. try keyedUnkeyedSuperContainer.encode(one, forKey: .four)
  568. }
  569. }
  570. private struct ManuallyEncodableStruct: Encodable {
  571. let a = ["string": "string"]
  572. let b = [1, 2, 3]
  573. private enum RootKey: String, CodingKey {
  574. case root
  575. }
  576. private enum TypeKeys: String, CodingKey {
  577. case a, b
  578. }
  579. func encode(to encoder: Encoder) throws {
  580. var container = encoder.container(keyedBy: RootKey.self)
  581. var nestedKeyedContainer = container.nestedContainer(keyedBy: TypeKeys.self, forKey: .root)
  582. try nestedKeyedContainer.encode(a, forKey: .a)
  583. var nestedUnkeyedContainer = container.nestedUnkeyedContainer(forKey: .root)
  584. try nestedUnkeyedContainer.encode(b)
  585. var nestedUnkeyedKeyedContainer = nestedUnkeyedContainer.nestedContainer(keyedBy: TypeKeys.self)
  586. try nestedUnkeyedKeyedContainer.encode(a, forKey: .a)
  587. var nestedUnkeyedUnkeyedContainer = nestedUnkeyedContainer.nestedUnkeyedContainer()
  588. try nestedUnkeyedUnkeyedContainer.encode(b)
  589. }
  590. }
  591. private struct FailingOptionalStruct: Encodable {
  592. enum TestedContainer {
  593. case keyed, unkeyed
  594. }
  595. enum CodingKeys: String, CodingKey { case a }
  596. let testedContainer: TestedContainer
  597. func encode(to encoder: Encoder) throws {
  598. var container = encoder.container(keyedBy: CodingKeys.self)
  599. switch testedContainer {
  600. case .keyed:
  601. var nested = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .a)
  602. try nested.encodeNil(forKey: .a)
  603. case .unkeyed:
  604. var nested = container.nestedUnkeyedContainer(forKey: .a)
  605. try nested.encodeNil()
  606. }
  607. }
  608. }