1
+ import XCTest
2
+ import NIO
3
+
4
+ @testable import DataLoader
5
+
6
+ #if compiler(>=5.5) && canImport(_Concurrency)
7
+
8
+ /// Primary API
9
+ @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
10
+ final class DataLoaderAsyncTests : XCTestCase {
11
+
12
+ /// Builds a really really simple data loader with async await
13
+ func testReallyReallySimpleDataLoader( ) async throws {
14
+ let eventLoopGroup = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
15
+ defer {
16
+ XCTAssertNoThrow ( try eventLoopGroup. syncShutdownGracefully ( ) )
17
+ }
18
+
19
+ let identityLoader = DataLoader < Int , Int > (
20
+ on: eventLoopGroup. next ( ) ,
21
+ options: DataLoaderOptions ( batchingEnabled: false )
22
+ ) { keys async in
23
+ let task = Task {
24
+ keys. map { DataLoaderFutureValue . success ( $0) }
25
+ }
26
+ return await task. value
27
+ }
28
+
29
+ let value = try await identityLoader. load ( key: 1 , on: eventLoopGroup)
30
+
31
+ XCTAssertEqual ( value, 1 )
32
+ }
33
+
34
+ /// Supports loading multiple keys in one call
35
+ func testLoadingMultipleKeys( ) async throws {
36
+ let eventLoopGroup = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
37
+ defer {
38
+ XCTAssertNoThrow ( try eventLoopGroup. syncShutdownGracefully ( ) )
39
+ }
40
+
41
+ let identityLoader = DataLoader < Int , Int > ( on: eventLoopGroup. next ( ) ) { keys in
42
+ let task = Task {
43
+ keys. map { DataLoaderFutureValue . success ( $0) }
44
+ }
45
+ return await task. value
46
+ }
47
+
48
+ let values = try await identityLoader. loadMany ( keys: [ 1 , 2 ] , on: eventLoopGroup)
49
+
50
+ XCTAssertEqual ( values, [ 1 , 2 ] )
51
+
52
+ let empty = try await identityLoader. loadMany ( keys: [ ] , on: eventLoopGroup)
53
+
54
+ XCTAssertTrue ( empty. isEmpty)
55
+ }
56
+
57
+ // Batches multiple requests
58
+ func testMultipleRequests( ) async throws {
59
+ let eventLoopGroup = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
60
+ defer {
61
+ XCTAssertNoThrow ( try eventLoopGroup. syncShutdownGracefully ( ) )
62
+ }
63
+
64
+ actor LoadCalls {
65
+ var loadCalls = [ [ Int] ] ( )
66
+
67
+ func append( _ calls: [ Int ] ) {
68
+ loadCalls. append ( calls)
69
+ }
70
+
71
+ static let shared : LoadCalls = . init( )
72
+ }
73
+
74
+ let identityLoader = DataLoader < Int , Int > (
75
+ on: eventLoopGroup. next ( ) ,
76
+ options: DataLoaderOptions (
77
+ batchingEnabled: true ,
78
+ executionPeriod: nil
79
+ )
80
+ ) { keys in
81
+ await LoadCalls . shared. append ( keys)
82
+ let task = Task {
83
+ keys. map { DataLoaderFutureValue . success ( $0) }
84
+ }
85
+ return await task. value
86
+ }
87
+
88
+ async let value1 = identityLoader. load ( key: 1 , on: eventLoopGroup)
89
+ async let value2 = identityLoader. load ( key: 2 , on: eventLoopGroup)
90
+
91
+ /// Have to wait for a split second because Tasks may not be executed before this statement
92
+ try await Task . sleep ( nanoseconds: 500_000 )
93
+
94
+ XCTAssertNoThrow ( try identityLoader. execute ( ) )
95
+
96
+ let result1 = try await value1
97
+ XCTAssertEqual ( result1, 1 )
98
+ let result2 = try await value2
99
+ XCTAssertEqual ( result2, 2 )
100
+
101
+ let loadCalls = await LoadCalls . shared. loadCalls
102
+ XCTAssertEqual ( loadCalls, [ [ 1 , 2 ] ] )
103
+ }
104
+ }
105
+
106
+ #endif
0 commit comments