Files

67 lines
3.2 KiB
Swift

import XCTest
@testable import AIFabric
/// S2-Fa(config ) + S2-Fb( ) + S2-Fe(/ ).
final class CompositionTests: XCTestCase {
// MARK: S2-Fa config
func testConfigDefaults() {
let c = AIProviderConfiguration.resolved(environment: [:])
XCTAssertEqual(c.localMLXBaseURL.absoluteString, "http://100.76.254.116:8890")
XCTAssertEqual(c.localMLXModel, "mac-mini-default")
XCTAssertEqual(c.dsBaseURL.absoluteString, "https://document.hyungi.net/api")
XCTAssertEqual(c.probeTimeout, 2)
}
func testConfigEnvOverride() {
let c = AIProviderConfiguration.resolved(environment: [
"AIFABRIC_LOCALMLX_URL": "http://127.0.0.1:9999",
"AIFABRIC_LOCALMLX_MODEL": "test-model",
"AIFABRIC_DS_URL": "http://100.110.63.63:8000/api",
])
XCTAssertEqual(c.localMLXBaseURL.absoluteString, "http://127.0.0.1:9999")
XCTAssertEqual(c.localMLXModel, "test-model")
XCTAssertEqual(c.dsBaseURL.absoluteString, "http://100.110.63.63:8000/api")
}
// MARK: S2-Fb (4 provider )
func testMakeDefaultRouterRegistersAllFour() async throws {
let client = MockDSAskClient(response: try Fixture.decode(AskResponse.self, from: "ask.json"))
let router = makeDefaultRouter(client: client, session: MockURLProtocol.session(), log: { _ in })
XCTAssertEqual(Set(router.providers.keys), Set(AIProviderID.allCases))
// corpusAsk RemoteDS citations .
let resp = try await router.route(AICompletionRequest(task: .corpusAsk, prompt: "p"))
XCTAssertEqual(resp.providerUsed, .remoteDS)
XCTAssertEqual(resp.citations.count, 1)
}
func testMakeDefaultRouterVisionFallbackVisible() async throws {
let client = MockDSAskClient(response: try Fixture.decode(AskResponse.self, from: "ask.json"))
let sink = LogSink()
let router = makeDefaultRouter(client: client, session: MockURLProtocol.session(), log: { sink.append($0) })
// specialized scaffold() onDevice. (onDevice specialized log )
_ = try? await router.route(AICompletionRequest(task: .vision, prompt: "p"))
XCTAssertTrue(sink.lines.contains { $0.contains("specialized") && $0.contains("unavailable") },
"specialized 불가가 침묵 아닌 log 로 가시화")
}
// MARK: S2-Fe (URLSession )
func testCancellationPropagatesThroughRouter() async throws {
let router = AIRouter(providers: [.localMLX: SleepingProvider(id: .localMLX)])
let task = Task {
try await router.route(AICompletionRequest(task: .classify, prompt: "p"))
}
try? await Task.sleep(nanoseconds: 100_000_000)
task.cancel()
do {
_ = try await task.value
XCTFail("취소된 생성은 CancellationError 전파")
} catch is CancellationError {
// : URLSession async/Task.sleep honor. OnDevice respond() (S2-3a).
}
}
}