Skip to content

Commit

Permalink
Add some missing tests, add AsyncTestQueueDriver to XCTQueues, respec…
Browse files Browse the repository at this point in the history
…t LOG_LEVEL env var in tests
  • Loading branch information
gwynne committed Jun 13, 2024
1 parent 8ea29ee commit 895858a
Show file tree
Hide file tree
Showing 5 changed files with 370 additions and 26 deletions.
57 changes: 53 additions & 4 deletions Sources/XCTQueues/TestQueueDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ extension Application.Queues.Provider {
return $0.queues.use(custom: TestQueuesDriver())
}
}

public static var asyncTest: Self {
.init {
$0.queues.initializeAsyncTestStorage()
return $0.queues.use(custom: AsyncTestQueuesDriver())
}
}
}

struct TestQueuesDriver: QueuesDriver {
Expand All @@ -24,10 +31,29 @@ struct TestQueuesDriver: QueuesDriver {
}
}

struct AsyncTestQueuesDriver: QueuesDriver {
init() {}
func makeQueue(with context: QueueContext) -> any Queue { AsyncTestQueue(_context: .init(context)) }
func shutdown() {}
}

extension Application.Queues {
public final class TestQueueStorage: @unchecked Sendable {
public var jobs: [JobIdentifier: JobData] = [:]
public var queue: [JobIdentifier] = []
public final class TestQueueStorage: Sendable {
private struct Box: Sendable {
var jobs: [JobIdentifier: JobData] = [:]
var queue: [JobIdentifier] = []
}
private let box = NIOLockedValueBox<Box>(.init())

public var jobs: [JobIdentifier: JobData] {
get { self.box.withLockedValue { $0.jobs } }
set { self.box.withLockedValue { $0.jobs = newValue } }
}

public var queue: [JobIdentifier] {
get { self.box.withLockedValue { $0.queue } }
set { self.box.withLockedValue { $0.queue = newValue } }
}

/// Returns the payloads of all jobs in the queue having type `J`.
public func all<J: Job>(_ job: J.Type) -> [J.Payload] {
Expand Down Expand Up @@ -58,14 +84,26 @@ extension Application.Queues {
struct TestQueueKey: StorageKey, LockKey {
typealias Value = TestQueueStorage
}

public var test: TestQueueStorage {
self.application.storage[TestQueueKey.self]!
}

func initializeTestStorage() {
self.application.storage[TestQueueKey.self] = .init()
}

struct AsyncTestQueueKey: StorageKey, LockKey {
typealias Value = TestQueueStorage
}

public var asyncTest: TestQueueStorage {
self.application.storage[AsyncTestQueueKey.self]!
}

func initializeAsyncTestStorage() {
self.application.storage[AsyncTestQueueKey.self] = .init()
}
}

struct TestQueue: Queue {
Expand Down Expand Up @@ -106,3 +144,14 @@ struct TestQueue: Queue {
}
}
}

struct AsyncTestQueue: AsyncQueue {
let _context: NIOLockedValueBox<QueueContext>
var context: QueueContext { self._context.withLockedValue { $0 } }

func get(_ id: JobIdentifier) async throws -> JobData { self._context.withLockedValue { $0.application.queues.asyncTest.jobs[id]! } }
func set(_ id: JobIdentifier, to data: JobData) async throws { self._context.withLockedValue { $0.application.queues.asyncTest.jobs[id] = data } }
func clear(_ id: JobIdentifier) async throws { self._context.withLockedValue { $0.application.queues.asyncTest.jobs[id] = nil } }
func pop() async throws -> JobIdentifier? { self._context.withLockedValue { $0.application.queues.asyncTest.queue.popLast() } }
func push(_ id: JobIdentifier) async throws { self._context.withLockedValue { $0.application.queues.asyncTest.queue.append(id) } }
}
36 changes: 35 additions & 1 deletion Tests/QueuesTests/AsyncQueueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ func XCTAssertNoThrowAsync<T>(
final class AsyncQueueTests: XCTestCase {
var app: Application!

override class func setUp() {
XCTAssert(isLoggingConfigured)
}

override func setUp() async throws {
app = try await Application.make(.testing)
}
Expand All @@ -25,7 +29,7 @@ final class AsyncQueueTests: XCTestCase {
try await app.asyncShutdown()
}

func testAsyncJob() async throws {
func testAsyncJobWithSyncQueue() async throws {
app.queues.use(.test)

let promise = app.eventLoopGroup.any().makePromise(of: Void.self)
Expand Down Expand Up @@ -54,6 +58,36 @@ final class AsyncQueueTests: XCTestCase {

await XCTAssertNoThrowAsync(try await promise.futureResult.get())
}

func testAsyncJobWithAsyncQueue() async throws {
app.queues.use(.asyncTest)

let promise = app.eventLoopGroup.any().makePromise(of: Void.self)
app.queues.add(MyAsyncJob(promise: promise))

app.get("foo") { req in
try await req.queue.dispatch(MyAsyncJob.self, .init(foo: "bar"))
return "done"
}

try await app.testable().test(.GET, "foo") { res async in
XCTAssertEqual(res.status, .ok)
XCTAssertEqual(res.body.string, "done")
}

XCTAssertEqual(app.queues.asyncTest.queue.count, 1)
XCTAssertEqual(app.queues.asyncTest.jobs.count, 1)
let job = app.queues.asyncTest.first(MyAsyncJob.self)
XCTAssert(app.queues.asyncTest.contains(MyAsyncJob.self))
XCTAssertNotNil(job)
XCTAssertEqual(job!.foo, "bar")

try await app.queues.queue.worker.run().get()
XCTAssertEqual(app.queues.asyncTest.queue.count, 0)
XCTAssertEqual(app.queues.asyncTest.jobs.count, 0)

await XCTAssertNoThrowAsync(try await promise.futureResult.get())
}
}

struct MyAsyncJob: AsyncJob {
Expand Down
Loading

0 comments on commit 895858a

Please sign in to comment.