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

Improve tests and fix encoding of NSNumber #84

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

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

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

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

@@ -20,10 +20,12 @@ class AnyEncodableTests: XCTestCase {
func testJSONEncoding() throws {

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).

@@ -108,28 +108,24 @@ extension _AnyEncodable {

#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