spb/zyquo-router Public MIT
One local endpoint, every AI provider — a private OpenAI-compatible LLM gateway for your Mac (170 models, 12 providers).
Swift 95.7%
Python 2.3%
Shell 1.2%
Makefile 0.9%
1//2// HTTPServerTests.swift3// Zyquo Router4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Phase 2 gate: bind, serve /health and /v1/models, detect port-in-use,9// shut down gracefully on cancellation (socket must be reusable right after).10//1112import XCTest13@testable import ZyquoRouter1415final class HTTPServerTests: XCTestCase {16 private static let port = 187871718 private func makeServer(port: Int) -> HTTPServer {19 let routes = Routes(router: RequestRouter())20 return HTTPServer(host: "127.0.0.1", port: port) { request in21 await routes.handle(request)22 }23 }2425 /// Starts a server task and waits until the socket is accepting.26 private func startServer(port: Int) async -> Task<Void, Error> {27 let started = expectation(description: "server started on \(port)")28 let task = Task { [server = makeServer(port: port)] in29 try await server.run { started.fulfill() }30 }31 await fulfillment(of: [started], timeout: 5)32 return task33 }3435 private func get(_ path: String, port: Int) async throws -> (Int, Data) {36 let (data, response) = try await URLSession.shared.data(37 from: URL(string: "http://127.0.0.1:\(port)\(path)")!38 )39 return ((response as! HTTPURLResponse).statusCode, data)40 }4142 func testServeHealthAndModelsThenGracefulStop() async throws {43 let task = await startServer(port: Self.port)4445 let (healthStatus, healthBody) = try await get("/health", port: Self.port)46 XCTAssertEqual(healthStatus, 200)47 let health = try JSONSerialization.jsonObject(with: healthBody) as! [String: Any]48 XCTAssertEqual(health["status"] as? String, "ok")4950 let (modelsStatus, modelsBody) = try await get("/v1/models", port: Self.port)51 XCTAssertEqual(modelsStatus, 200)52 let list = try JSONSerialization.jsonObject(with: modelsBody) as! [String: Any]53 XCTAssertEqual(list["object"] as? String, "list")54 let data = list["data"] as! [[String: Any]]55 XCTAssertEqual(data.count, ModelCatalogData.all.count)56 XCTAssertTrue((data[0]["id"] as! String).contains("/"), "model IDs must be namespaced")5758 // Graceful stop: cancel, wait for run() to return, then the port must59 // be immediately bindable again.60 task.cancel()61 _ = try? await task.value6263 let restarted = await startServer(port: Self.port)64 let (again, _) = try await get("/health", port: Self.port)65 XCTAssertEqual(again, 200)66 restarted.cancel()67 _ = try? await restarted.value68 }6970 func testPortInUseError() async throws {71 let task = await startServer(port: Self.port + 1)7273 let second = makeServer(port: Self.port + 1)74 do {75 try await second.run {}76 XCTFail("second bind should fail")77 } catch let error as ServerError {78 guard case .portInUse(_, let port) = error else {79 return XCTFail("expected portInUse, got \(error)")80 }81 XCTAssertEqual(port, Self.port + 1)82 }8384 task.cancel()85 _ = try? await task.value86 }87}88