Skip to content

Commit

Permalink
continuing to fill out document external dereferencing test. fix bug …
Browse files Browse the repository at this point in the history
…with array ordering. fix bug with missing path items components
  • Loading branch information
mattpolzin committed Apr 22, 2024
1 parent b80657e commit 6ce5f4f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 61 deletions.
9 changes: 6 additions & 3 deletions Sources/OpenAPIKit/Components Object/Components.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ extension OpenAPI.Components {
let oldRequestBodies = requestBodies
let oldHeaders = headers
let oldSecuritySchemes = securitySchemes

let oldCallbacks = callbacks
let oldPathItems = pathItems

async let (newSchemas, c1) = oldSchemas.externallyDereferenced(with: context)
async let (newResponses, c2) = oldResponses.externallyDereferenced(with: context)
Expand All @@ -321,6 +321,7 @@ extension OpenAPI.Components {
async let (newRequestBodies, c5) = oldRequestBodies.externallyDereferenced(with: context)
async let (newHeaders, c6) = oldHeaders.externallyDereferenced(with: context)
async let (newSecuritySchemes, c7) = oldSecuritySchemes.externallyDereferenced(with: context)
async let (newPathItems, c9) = oldPathItems.externallyDereferenced(with: context)

// async let (newCallbacks, c8) = oldCallbacks.externallyDereferenced(with: context)
var c8 = OpenAPI.Components()
Expand All @@ -338,8 +339,8 @@ extension OpenAPI.Components {
requestBodies = try await newRequestBodies
headers = try await newHeaders
securitySchemes = try await newSecuritySchemes

callbacks = newCallbacks
pathItems = try await newPathItems

let c1Resolved = try await c1
let c2Resolved = try await c2
Expand All @@ -349,6 +350,7 @@ extension OpenAPI.Components {
let c6Resolved = try await c6
let c7Resolved = try await c7
let c8Resolved = c8
let c9Resolved = try await c9

let noNewComponents =
c1Resolved.isEmpty
Expand All @@ -359,6 +361,7 @@ extension OpenAPI.Components {
&& c6Resolved.isEmpty
&& c7Resolved.isEmpty
&& c8Resolved.isEmpty
&& c9Resolved.isEmpty

if noNewComponents { return }

Expand All @@ -369,8 +372,8 @@ extension OpenAPI.Components {
try merge(c5Resolved)
try merge(c6Resolved)
try merge(c7Resolved)

try merge(c8Resolved)
try merge(c9Resolved)

switch depth {
case .iterations(let number):
Expand Down
17 changes: 10 additions & 7 deletions Sources/OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ import OpenAPIKitCore
extension Array where Element: ExternallyDereferenceable {

public func externallyDereferenced<Context: ExternalLoader>(with loader: Context.Type) async throws -> (Self, OpenAPI.Components) {
try await withThrowingTaskGroup(of: (Element, OpenAPI.Components).self) { group in
for elem in self {
try await withThrowingTaskGroup(of: (Int, (Element, OpenAPI.Components)).self) { group in
for (idx, elem) in zip(self.indices, self) {
group.addTask {
return try await elem.externallyDereferenced(with: loader)
return try await (idx, elem.externallyDereferenced(with: loader))
}
}

var newElems = Self()
var newElems = Array<(Int, Element)>()
var newComponents = OpenAPI.Components()

for try await (elem, components) in group {
newElems.append(elem)
for try await (idx, (elem, components)) in group {
newElems.append((idx, elem))
try newComponents.merge(components)
}
return (newElems, newComponents)
// things may come in out of order because of concurrency
// so we reorder after completing all entries.
newElems.sort { left, right in left.0 < right.0 }
return (newElems.map { $0.1 }, newComponents)
}
}
}
146 changes: 95 additions & 51 deletions Tests/OpenAPIKitTests/Document/DocumentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,6 @@ extension DocumentTests {

/// Mock up some data, just for the example.
static func mockData(_ key: OpenAPIKit.OpenAPI.ComponentKey) async throws -> Data {
print("looking up \(key.rawValue)")
return try XCTUnwrap(files[key.rawValue])
}

Expand All @@ -1229,6 +1228,80 @@ extension DocumentTests {
{
"type": "string"
}
""",
"paths_webhook_json": """
{
"summary": "just a webhook",
"get": {
"requestBody": {
"$ref": "file://./requests/webhook.json"
},
"responses": {
"200": {
"$ref": "file://./responses/webhook.json"
}
}
}
}
""",
"requests_webhook_json": """
{
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"body": {
"type": "string"
}
}
},
"examples": {
"good": {
"$ref": "file://./examples/good.json"
}
}
}
}
}
""",
"responses_webhook_json": """
{
"description": "webhook response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"body": {
"type": "string"
},
"length": {
"type": "integer",
"minimum": 0
}
}
}
}
},
"headers": {
"X-Hello": {
"$ref": "file://./headers/webhook.json"
}
}
}
""",
"headers_webhook_json": """
{
"schema": {
"$ref": "file://./schemas/name_param.json"
}
}
""",
"examples_good_json": """
{
"value": "{\\"body\\": \\"request me\\"}"
}
"""
].mapValues { $0.data(using: .utf8)! }
}
Expand All @@ -1246,9 +1319,16 @@ extension DocumentTests {
parameters: [
.reference(.external(URL(string: "file://./params/name.json")!))
]
)
),
"/webhook": .reference(.external(URL(string: "file://./paths/webhook.json")!))
],
webhooks: [
"webhook": .reference(.external(URL(string: "file://./paths/webhook.json")!))
],
components: .init(
schemas: [
"name_param": .reference(.external(URL(string: "file://./schemas/name_param.json")!))
],
// just to show, no parameters defined within document components :
parameters: [:]
)
Expand All @@ -1260,63 +1340,27 @@ extension DocumentTests {
var docCopy1 = document
try await docCopy1.externallyDereference(in: ExampleLoader.self)
try await docCopy1.externallyDereference(in: ExampleLoader.self)
try await docCopy1.externallyDereference(in: ExampleLoader.self)

var docCopy2 = document
try await docCopy2.externallyDereference(in: ExampleLoader.self, depth: 2)
try await docCopy2.externallyDereference(in: ExampleLoader.self, depth: 3)

var docCopy3 = document
try await docCopy3.externallyDereference(in: ExampleLoader.self, depth: .full)

XCTAssertEqual(docCopy1, docCopy2)
// XCTAssertEqual(docCopy1, docCopy2)
XCTAssertEqual(docCopy2, docCopy3)
XCTAssertEqual(String(describing: docCopy2), String(describing: docCopy3))

// - MARK: After
print(
String(data: try encoder.encode(docCopy1), encoding: .utf8)!
)
/*
{
"info" : {
"version" : "1.0.0",
"title" : "test document"
},
"openapi" : "3.1.0",
"paths" : {
"\/goodbye\/{name}" : {
"parameters" : [
{
"$ref" : "#\/components\/parameters\/params_name_json"
}
]
},
"\/hello\/{name}" : {
"parameters" : [
{
"$ref" : "#\/components\/parameters\/params_name_json"
}
]
}
},
"components" : {
"parameters" : {
"params_name_json" : {
"description" : "a lonely parameter",
"in" : "path",
"name" : "name",
"x-source-url" : "file:\/\/.\/params\/name.json",
"required" : true,
"schema" : {
"$ref" : "#\/components\/schemas\/schemas_name_param_json"
}
}
},
"schemas" : {
"schemas_name_param_json" : {
"type" : "string"
}
}
}
}
*/
// print(
// String(data: try encoder.encode(docCopy1), encoding: .utf8)!
// )
// print(
// String(data: try encoder.encode(docCopy2), encoding: .utf8)!
// )
// print(
// String(data: try encoder.encode(docCopy3), encoding: .utf8)!
// )
}
}

0 comments on commit 6ce5f4f

Please sign in to comment.