feat: Renaming and moves some items around, listeners now manage reconnection events.
All checks were successful
CI / Run Tests (push) Successful in 4m16s
All checks were successful
CI / Run Tests (push) Successful in 4m16s
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
import Dependencies
|
||||
import Logging
|
||||
import Models
|
||||
@_spi(Internal) import MQTTConnectionManager
|
||||
@_spi(Internal) import MQTTManager
|
||||
import MQTTNIO
|
||||
import NIO
|
||||
import PsychrometricClientLive
|
||||
@_spi(Internal) import SensorsService
|
||||
import TopicDependencies
|
||||
import XCTest
|
||||
|
||||
final class SensorsClientTests: XCTestCase {
|
||||
@@ -23,25 +22,24 @@ final class SensorsClientTests: XCTestCase {
|
||||
let client = createClient(identifier: "\(Self.self)")
|
||||
|
||||
withDependencies {
|
||||
$0.mqttConnectionManager = .live(client: client, logger: Self.logger)
|
||||
$0.mqtt = .live(client: client, logger: Self.logger)
|
||||
$0.psychrometricClient = PsychrometricClient.liveValue
|
||||
$0.topicListener = .live(client: client)
|
||||
$0.topicPublisher = .live(client: client)
|
||||
} operation: {
|
||||
super.invokeTest()
|
||||
}
|
||||
}
|
||||
|
||||
func testListeningResumesAfterDisconnectThenReconnect() async throws {
|
||||
@Dependency(\.mqttConnectionManager) var manager
|
||||
struct TimeoutError: Error {}
|
||||
|
||||
let sensor = TemperatureAndHumiditySensor(location: .return)
|
||||
var results = [TopicPublisher.PublishRequest]()
|
||||
let results = ResultContainer()
|
||||
|
||||
try await withDependencies {
|
||||
$0.topicPublisher = .capturing { results.append($0) }
|
||||
$0.mqtt.publish = results.append
|
||||
} operation: {
|
||||
@Dependency(\.mqtt) var manager
|
||||
|
||||
let sensorsService = SensorsService(sensors: [sensor], logger: Self.logger)
|
||||
let task = Task { try await sensorsService.run() }
|
||||
defer { task.cancel() }
|
||||
@@ -58,9 +56,7 @@ final class SensorsClientTests: XCTestCase {
|
||||
}
|
||||
|
||||
// Give time to re-subscribe.
|
||||
while !(await sensorsService.isListening) {
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
}
|
||||
try await Task.sleep(for: .milliseconds(200))
|
||||
|
||||
try await client.publish(
|
||||
to: sensor.topics.temperature,
|
||||
@@ -77,7 +73,7 @@ final class SensorsClientTests: XCTestCase {
|
||||
}
|
||||
|
||||
var timeoutCount = 0
|
||||
while !(results.count == 2) {
|
||||
while !(await results.count == 2) {
|
||||
guard timeoutCount < 20 else {
|
||||
throw TimeoutError()
|
||||
}
|
||||
@@ -85,6 +81,8 @@ final class SensorsClientTests: XCTestCase {
|
||||
timeoutCount += 1
|
||||
}
|
||||
|
||||
let results = await results.results()
|
||||
|
||||
XCTAssertEqual(results.count, 2)
|
||||
XCTAssert(results.contains(where: { $0.topicName == sensor.topics.dewPoint }))
|
||||
XCTAssert(results.contains(where: { $0.topicName == sensor.topics.enthalpy }))
|
||||
@@ -122,63 +120,23 @@ final class SensorsClientTests: XCTestCase {
|
||||
|
||||
// MARK: Helpers for tests.
|
||||
|
||||
class PublishInfoContainer {
|
||||
private(set) var info: [MQTTPublishInfo]
|
||||
private var topicFilters: [String]?
|
||||
|
||||
init(topicFilters: [String]? = nil) {
|
||||
self.info = []
|
||||
self.topicFilters = topicFilters
|
||||
}
|
||||
|
||||
func addPublishInfo(_ info: MQTTPublishInfo) async {
|
||||
guard let topicFilters else {
|
||||
self.info.append(info)
|
||||
return
|
||||
}
|
||||
if topicFilters.contains(info.topicName) {
|
||||
self.info.append(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TopicPublisher {
|
||||
static func capturing(
|
||||
_ callback: @escaping (PublishRequest) -> Void
|
||||
) -> Self {
|
||||
.init { callback($0) }
|
||||
}
|
||||
}
|
||||
|
||||
// extension SensorsClient {
|
||||
//
|
||||
// static func testing(
|
||||
// yielding: [(value: Double, to: String)],
|
||||
// capturePublishedValues: @escaping (Double, String) -> Void,
|
||||
// captureShutdownEvent: @escaping (Bool) -> Void
|
||||
// ) -> Self {
|
||||
// let (stream, continuation) = AsyncStream.makeStream(of: PublishInfo.self)
|
||||
// let logger = Logger(label: "\(Self.self).testing")
|
||||
//
|
||||
// return .init(
|
||||
// listen: { topics in
|
||||
// for (value, topic) in yielding where topics.contains(topic) {
|
||||
// continuation.yield(
|
||||
// (buffer: ByteBuffer(string: "\(value)"), topic: topic)
|
||||
// )
|
||||
// }
|
||||
// return stream
|
||||
// },
|
||||
// logger: logger,
|
||||
// publish: { value, topic in
|
||||
// capturePublishedValues(value, topic)
|
||||
// },
|
||||
// shutdown: {
|
||||
// captureShutdownEvent(true)
|
||||
// continuation.finish()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
struct TopicNotFoundError: Error {}
|
||||
|
||||
actor ResultContainer: Sendable {
|
||||
|
||||
private var storage = [MQTTManager.PublishRequest]()
|
||||
|
||||
init() {}
|
||||
|
||||
@Sendable func append(_ result: MQTTManager.PublishRequest) async {
|
||||
storage.append(result)
|
||||
}
|
||||
|
||||
var count: Int {
|
||||
get async { storage.count }
|
||||
}
|
||||
|
||||
func results() async -> [MQTTManager.PublishRequest] {
|
||||
storage
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user