Skip to content
This repository was archived by the owner on Oct 19, 2024. It is now read-only.

Conversation

gsabran
Copy link

@gsabran gsabran commented Aug 6, 2024

Changes

  • Improve tests
    • Some minor changes to remove force unwrapping in tests.
    • Existing encoding tests validate that deserialized serialized value is equal to some value. This is different than directly asserting that the serialized value is as expected, and it lets some errors go unnoticed as equality on NSDictionary is very permissive. For instance this test will pass:
let dictionary: [String: AnyEncodable] = ["k": true]
let json = try JSONEncoder().encode(dictionary)
let encodedJSONObject = try JSONSerialization.jsonObject(with: json, options: []) as! NSDictionary

let expected = "{ \"k\": 1 }".data(using: .utf8)!
let expectedJSONObject = try JSONSerialization.jsonObject(with: expected, options: []) as! NSDictionary

XCTAssertEqual(encodedJSONObject, expectedJSONObject)

Instead if we compare the serialized value ({ "k": true }) to that of the expectation ({ "k": 1 }) this test will logically fail.
I added util function to ease the comparison of serialized JSON strings.

  • Fix serialization of NSNumber. There were two issues:
    • We test for as? Bool before testing as? NSNumber. A NSNumber can always be casted as a Bool so the later case was never hit
    • Swift.Bool are represented as a char type in ObjC and the mapping was incorrect
    • Add a test for NSNumber's serialization.
  • Nit: reduce runtime computations when encoding NSNumber, which after this fix might be more frequent

@gsabran
Copy link
Author

gsabran commented Aug 6, 2024

Also related: #76, but this PR should do a better job at preventing future regressions

case cpp_or_c99_bool_objc_encoding, char_objc_encoding, unsigned_char_objc_encoding:
try container.encode(nsnumber.boolValue)
case "c":
try container.encode(nsnumber.int8Value)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this case is now mapped to a boolean

case "q":
case long_long_objc_encoding:
try container.encode(nsnumber.int64Value)
case "C":
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this case is now mapped to a boolean


let someEncodable = AnyEncodable(SomeEncodable(string: "String", int: 100, bool: true, hasUnderscore: "another string"))

let nsNumber = AnyEncodable(1 as NSNumber)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added NSNumber here to ensure there is no future regressions

Comment on lines -108 to -124

XCTAssertEqual(encodedJSONObject, expectedJSONObject)
XCTAssert(encodedJSONObject["boolean"] is Bool)

XCTAssert(encodedJSONObject["char"] is Int8)
XCTAssert(encodedJSONObject["int"] is Int16)
XCTAssert(encodedJSONObject["short"] is Int32)
XCTAssert(encodedJSONObject["long"] is Int32)
XCTAssert(encodedJSONObject["longlong"] is Int64)

XCTAssert(encodedJSONObject["uchar"] is UInt8)
XCTAssert(encodedJSONObject["uint"] is UInt16)
XCTAssert(encodedJSONObject["ushort"] is UInt32)
XCTAssert(encodedJSONObject["ulong"] is UInt32)
XCTAssert(encodedJSONObject["ulonglong"] is UInt64)

XCTAssert(encodedJSONObject["double"] is Double)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this part that is not testing decoding




func XCTAssertJsonAreIdentical(_ expression1: String, _ expression2: String, options: JSONSerialization.WritingOptions? = nil) throws {
Copy link
Author

@gsabran gsabran Aug 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper functions to test that two serialized JSON (either String or Data) are equivalent (ie ignoring keys ordering and spaces).


#if canImport(Foundation)
private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for applications where performance matters, this change should help make the code run faster.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant