89 lines
3.1 KiB
Swift
89 lines
3.1 KiB
Swift
//
|
|
// JellyfinClientReconnectTests.swift
|
|
//
|
|
// Copyright 2026 Brendan Szymanski <hello@bscubed.dev>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
|
|
import Foundation
|
|
import HTTPTypes
|
|
import LuminateCore
|
|
import OpenAPIRuntime
|
|
import Synchronization
|
|
import Testing
|
|
|
|
@testable import LuminateServices
|
|
|
|
/// A transport double that always answers with the same canned public-users payload.
|
|
private struct FixedPublicUsersTransport: ClientTransport {
|
|
let responseBody: String
|
|
|
|
func send(
|
|
_ request: HTTPRequest,
|
|
body: HTTPBody?,
|
|
baseURL: URL,
|
|
operationID: String
|
|
) async throws -> (HTTPResponse, HTTPBody?) {
|
|
let response = HTTPResponse(status: .ok, headerFields: [.contentType: "application/json"])
|
|
return (response, HTTPBody(responseBody))
|
|
}
|
|
}
|
|
|
|
/// Covers ``JellyfinClient/reconnect()``: the fix for a transport that failed once (most notably,
|
|
/// `URLSession` caching a DNS resolution failure for its whole lifetime on Linux) and must be
|
|
/// rebuilt from scratch, rather than reused, before a retry can possibly succeed.
|
|
@Suite struct JellyfinClientReconnectTests {
|
|
private static func publicUsersBody(name: String, id: String) -> String {
|
|
"""
|
|
[
|
|
{
|
|
"Name": "\(name)",
|
|
"Id": "\(id)"
|
|
}
|
|
]
|
|
"""
|
|
}
|
|
|
|
@Test("reconnect() rebuilds the API client against a freshly constructed transport")
|
|
func reconnectRebuildsTransport() async throws {
|
|
let invocationCount = Mutex(0)
|
|
let responses = [
|
|
Self.publicUsersBody(name: "alpha", id: "user-1"),
|
|
Self.publicUsersBody(name: "beta", id: "user-2"),
|
|
]
|
|
let client = JellyfinClient(
|
|
configuration: JellyfinClientConfiguration(serverURL: URL(string: "http://localhost")!),
|
|
makeTransport: {
|
|
let index = invocationCount.withLock { count in
|
|
defer { count += 1 }
|
|
return count
|
|
}
|
|
return FixedPublicUsersTransport(responseBody: responses[index])
|
|
}
|
|
)
|
|
|
|
let beforeReconnect = try await client.publicUsers()
|
|
#expect(beforeReconnect.map(\.name) == ["alpha"])
|
|
#expect(invocationCount.withLock { $0 } == 1)
|
|
|
|
await client.reconnect()
|
|
|
|
let afterReconnect = try await client.publicUsers()
|
|
#expect(afterReconnect.map(\.name) == ["beta"])
|
|
#expect(invocationCount.withLock { $0 } == 2)
|
|
}
|
|
}
|