-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Verifies serialized data matches expected data in tests * Handle xmlName trait - Adds code to properly set the xml root key if the object has a custom xml name set - Sets the xmlName trait for operation shapes since we modify operation shape names * No longer encodes floats and doubles as strings * Updates tests * ktlintformat * Addresses PR feedback * Adds explicit FoundationXML import for linux * Checks Any objects for equality * Cleans up code and adds docs
- Loading branch information
Showing
17 changed files
with
295 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
|
||
public struct JSONComparator { | ||
/// Returns true if the JSON documents, for the corresponding data objects, are equal. | ||
/// - Parameters: | ||
/// - dataA: The first data object to compare to the second data object. | ||
/// - dataB: The second data object to compare to the first data object. | ||
/// - Returns: Returns true if the JSON documents, for the corresponding data objects, are equal. | ||
public static func jsonData(_ dataA: Data, isEqualTo dataB: Data) throws -> Bool { | ||
let jsonDictA = try JSONSerialization.jsonObject(with: dataA) | ||
let jsonDictB = try JSONSerialization.jsonObject(with: dataB) | ||
return anyValuesAreEqual(jsonDictA, jsonDictB) | ||
} | ||
} | ||
|
||
fileprivate func anyDictsAreEqual(_ lhs: [String: Any], _ rhs: [String: Any]) -> Bool { | ||
guard lhs.keys == rhs.keys else { return false } | ||
for key in lhs.keys { | ||
if !anyValuesAreEqual(lhs[key], rhs[key]) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
fileprivate func anyArraysAreEqual(_ lhs: [Any], _ rhs: [Any]) -> Bool { | ||
guard lhs.count == rhs.count else { return false } | ||
for i in 0..<lhs.count { | ||
if !anyValuesAreEqual(lhs[i], rhs[i]) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
fileprivate func anyValuesAreEqual(_ lhs: Any?, _ rhs: Any?) -> Bool { | ||
if lhs == nil && rhs == nil { return true } | ||
guard let lhs = lhs, let rhs = rhs else { return false } | ||
if let lhsDict = lhs as? [String: Any], let rhsDict = rhs as? [String: Any] { | ||
return anyDictsAreEqual(lhsDict, rhsDict) | ||
} else if let lhsArray = lhs as? [Any], let rhsArray = rhs as? [Any] { | ||
return anyArraysAreEqual(lhsArray, rhsArray) | ||
} else { | ||
return type(of: lhs) == type(of: rhs) && "\(lhs)" == "\(rhs)" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
import XCTest | ||
|
||
public func XCTAssertJSONDataEqual( | ||
_ expression1: @autoclosure () throws -> Data, | ||
_ expression2: @autoclosure () throws -> Data, | ||
_ message: @autoclosure () -> String = "", | ||
file: StaticString = #filePath, | ||
line: UInt = #line | ||
) { | ||
do { | ||
let data1 = try expression1() | ||
let data2 = try expression2() | ||
guard data1 != data2 else { return } | ||
XCTAssertTrue( | ||
try JSONComparator.jsonData(data1, isEqualTo: data2), | ||
message(), | ||
file: file, | ||
line: line | ||
) | ||
} catch { | ||
XCTFail("Failed to evaluate JSON with error: \(error)", file: file, line: line) | ||
} | ||
} | ||
|
||
public func XCTAssertXMLDataEqual( | ||
_ expression1: @autoclosure () throws -> Data, | ||
_ expression2: @autoclosure () throws -> Data, | ||
_ message: @autoclosure () -> String = "", | ||
file: StaticString = #filePath, | ||
line: UInt = #line | ||
) { | ||
do { | ||
let data1 = try expression1() | ||
let data2 = try expression2() | ||
guard data1 != data2 else { return } | ||
XCTAssertTrue(XMLComparator.xmlData(data1, isEqualTo: data2), message(), file: file, line: line) | ||
} catch { | ||
XCTFail("Failed to evaluate XML with error: \(error)", file: file, line: line) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
#if canImport(FoundationXML) | ||
// As of Swift 5.1, the Foundation module on Linux only has the same set of dependencies as the Swift standard library itself | ||
// Therefore, we need to explicitly import FoundationXML on linux. | ||
// The preferred way to do this, is to check if FoundationXML can be imported. | ||
// https://github.com/apple/swift-corelibs-foundation/blob/main/Docs/ReleaseNotes_Swift5.md | ||
import FoundationXML | ||
#endif | ||
|
||
public struct XMLComparator { | ||
/// Returns true if the XML documents, for the corresponding data objects, are equal. | ||
/// Order of elements within the document do not affect equality. | ||
/// - Parameters: | ||
/// - dataA: The first data object to compare to the second data object. | ||
/// - dataB: The second data object to compare to the first data object. | ||
/// - Returns: Returns true if the XML documents, for the corresponding data objects, are equal. | ||
public static func xmlData(_ dataA: Data, isEqualTo dataB: Data) -> Bool { | ||
let rootA = XMLConverter.xmlTree(with: dataA) | ||
let rootB = XMLConverter.xmlTree(with: dataB) | ||
return rootA == rootB | ||
} | ||
} | ||
|
||
private struct XMLElement: Hashable { | ||
var name: String? | ||
var attributes: [String : String]? | ||
var string: String? | ||
var elements: Set<XMLElement> = [] | ||
} | ||
|
||
private class XMLConverter: NSObject { | ||
/// Keeps track of the value since `foundCharacters` can be called multiple times for the same element | ||
private var valueBuffer = "" | ||
private var stack: [XMLElement] = [] | ||
|
||
static func xmlTree(with data: Data) -> XMLElement { | ||
let converter = XMLConverter() | ||
converter.stack.append(XMLElement()) | ||
|
||
let parser = XMLParser(data: data) | ||
parser.delegate = converter | ||
parser.parse() | ||
|
||
return converter.stack.first! | ||
} | ||
} | ||
|
||
extension XMLConverter: XMLParserDelegate { | ||
func parser( | ||
_ parser: XMLParser, | ||
didStartElement elementName: String, | ||
namespaceURI: String?, | ||
qualifiedName qName: String?, | ||
attributes attributeDict: [String : String] = [:] | ||
) { | ||
let parent = stack.last! | ||
let element = XMLElement( | ||
name: elementName, | ||
attributes: attributeDict | ||
) | ||
|
||
stack.append(element) | ||
} | ||
|
||
func parser(_ parser: XMLParser, foundCharacters string: String) { | ||
let trimmedString = string.trimmingCharacters(in: .whitespacesAndNewlines) | ||
valueBuffer.append(trimmedString) | ||
} | ||
|
||
func parser( | ||
_ parser: XMLParser, didEndElement | ||
elementName: String, | ||
namespaceURI: String?, | ||
qualifiedName qName: String? | ||
) { | ||
var element = stack.popLast()! | ||
var parent = stack.last! | ||
|
||
element.string = valueBuffer | ||
|
||
var elements = parent.elements | ||
elements.insert(element) | ||
parent.elements = elements | ||
|
||
stack[stack.endIndex - 1] = parent | ||
valueBuffer = "" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.