test: lock bind/setPlayMode JSON encoding via semantic assertions
Replace brittle exact-byte equality checks in BindPayloadByteRegressionTests with substring + dict-based semantic assertions that tolerate Swift JSONEncoder key-order variance across runtime versions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,3 +103,47 @@ final class SetPlayModeGuardTests: XCTestCase {
|
||||
wait(for: [exp], timeout: 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
final class BindPayloadByteRegressionTests: XCTestCase {
|
||||
/// 关键回归:bind / unbind 在 loop=nil 时报文必须完全不含 "loop" key —— 不能输出 "loop":null。
|
||||
/// 不假设 JSONEncoder key 顺序(Swift 不同版本顺序可能不同),用 substring + dict 断言锁语义。
|
||||
func testBindPayloadNilLoopOmitsKeyAndNull() throws {
|
||||
let payload = BindPayload(type: 0x0F, userId: "abc", loop: nil)
|
||||
let data = try JSONEncoder().encode(payload)
|
||||
let json = String(data: data, encoding: .utf8) ?? ""
|
||||
// 字面层:JSON 文本不允许出现 "loop" 或 "null"
|
||||
XCTAssertFalse(json.contains("loop"), "loop key MUST be absent; got \(json)")
|
||||
XCTAssertFalse(json.contains("null"), "null literal MUST be absent; got \(json)")
|
||||
// 结构层:反序列化后只有 type / userId,无第三个 key
|
||||
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any] ?? [:]
|
||||
XCTAssertEqual(dict.count, 2)
|
||||
XCTAssertEqual(dict["type"] as? Int, 15)
|
||||
XCTAssertEqual(dict["userId"] as? String, "abc")
|
||||
XCTAssertNil(dict["loop"])
|
||||
}
|
||||
|
||||
/// setPlayMode 报文:loop=1 必须以整数形式出现(不是 "1" 字符串)。
|
||||
func testSetPlayModePayloadIncludesLoopOne() throws {
|
||||
let payload = BindPayload(type: 0x0F, userId: "abc", loop: 1)
|
||||
let data = try JSONEncoder().encode(payload)
|
||||
let json = String(data: data, encoding: .utf8) ?? ""
|
||||
// 字面层子串:必须出现 "loop":1(数字,无引号)
|
||||
XCTAssertTrue(json.contains(#""loop":1"#), "expected literal substring \"loop\":1 in \(json)")
|
||||
// 结构层
|
||||
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any] ?? [:]
|
||||
XCTAssertEqual(dict.count, 3)
|
||||
XCTAssertEqual(dict["type"] as? Int, 15)
|
||||
XCTAssertEqual(dict["userId"] as? String, "abc")
|
||||
XCTAssertEqual(dict["loop"] as? Int, 1)
|
||||
}
|
||||
|
||||
/// setPlayMode 报文:loop=0 边界情况,必须以整数 0 出现(不是被当作 "default" 省略)。
|
||||
func testSetPlayModePayloadIncludesLoopZero() throws {
|
||||
let payload = BindPayload(type: 0x0F, userId: "abc", loop: 0)
|
||||
let data = try JSONEncoder().encode(payload)
|
||||
let json = String(data: data, encoding: .utf8) ?? ""
|
||||
XCTAssertTrue(json.contains(#""loop":0"#), "expected literal substring \"loop\":0 in \(json)")
|
||||
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any] ?? [:]
|
||||
XCTAssertEqual(dict["loop"] as? Int, 0)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user