Skip to content

Commit 7ce00dd

Browse files
committed
add async tests
1 parent f187e2a commit 7ce00dd

File tree

4 files changed

+178
-11
lines changed

4 files changed

+178
-11
lines changed

Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public func asyncSum(i1: Int64, i2: Int64) async -> Int64 {
1919
return i1 + i2
2020
}
2121

22+
public func asyncSleep() async throws {
23+
try await Task.sleep(for: .milliseconds(500))
24+
}
25+
2226
public func asyncCopy(myClass: MySwiftClass) async throws -> MySwiftClass {
2327
let new = MySwiftClass(x: myClass.x, y: myClass.y)
2428
try await Task.sleep(for: .milliseconds(500))

Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,19 @@ void asyncSum() {
3939
}
4040

4141
@Test
42-
void asyncCopy() throws Exception {
42+
void asyncSleep() {
43+
CompletableFuture<Void> future = MySwiftLibrary.asyncSleep();
44+
future.join();
45+
}
46+
47+
@Test
48+
void asyncCopy() {
4349
try (var arena = SwiftArena.ofConfined()) {
4450
MySwiftClass obj = MySwiftClass.init(10, 5, arena);
4551
CompletableFuture<MySwiftClass> future = MySwiftLibrary.asyncCopy(obj, arena);
4652

4753
MySwiftClass result = future.join();
54+
4855
assertEquals(10, result.getX());
4956
assertEquals(5, result.getY());
5057
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,12 @@ extension JNISwift2JavaGenerator {
354354

355355
// Lower the result.
356356
func innerBody(in printer: inout CodePrinter) -> String {
357+
let loweredResult = nativeSignature.result.conversion.render(&printer, result)
358+
357359
if !decl.functionSignature.result.type.isVoid {
358-
let loweredResult = nativeSignature.result.conversion.render(&printer, result)
359360
return "return \(loweredResult)"
360361
} else {
361-
return result
362+
return loweredResult
362363
}
363364
}
364365

Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift

Lines changed: 163 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Testing
1818
@Suite
1919
struct JNIAsyncTests {
2020

21-
@Test("Import: async -> Void (CompletableFuture)")
21+
@Test("Import: async -> Void (Java, CompletableFuture)")
2222
func completableFuture_asyncVoid_java() throws {
2323
try assertOutput(
2424
input: "public func asyncVoid() async",
@@ -33,7 +33,7 @@ struct JNIAsyncTests {
3333
* }
3434
*/
3535
public static java.util.concurrent.CompletableFuture<Void> asyncVoid() {
36-
return CompletableFuture.supplyAsync(() -> {
36+
return java.util.concurrent.CompletableFuture.supplyAsync(() -> {
3737
SwiftModule.$asyncVoid();
3838
return null;
3939
}
@@ -47,7 +47,39 @@ struct JNIAsyncTests {
4747
)
4848
}
4949

50-
@Test("Import: async throws -> Void (CompletableFuture)")
50+
@Test("Import: async -> Void (Swift, CompletableFuture)")
51+
func completableFuture_asyncVoid_swift() throws {
52+
try assertOutput(
53+
input: "public func asyncVoid() async",
54+
.jni, .swift,
55+
detectChunkByInitialLines: 1,
56+
expectedChunks: [
57+
"""
58+
@_cdecl("Java_com_example_swift_SwiftModule__00024asyncVoid__")
59+
func Java_com_example_swift_SwiftModule__00024asyncVoid__(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass) {
60+
let _semaphore$ = _Semaphore(value: 0)
61+
var swiftResult$: ()!
62+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
63+
Task.immediate {
64+
swiftResult$ = await SwiftModule.asyncVoid()
65+
_semaphore$.signal()
66+
}
67+
}
68+
else {
69+
Task {
70+
swiftResult$ = await SwiftModule.asyncVoid()
71+
_semaphore$.signal()
72+
}
73+
}
74+
_semaphore$.wait()
75+
swiftResult$
76+
}
77+
"""
78+
]
79+
)
80+
}
81+
82+
@Test("Import: async throws -> Void (Java, CompletableFuture)")
5183
func completableFuture_asyncThrowsVoid_java() throws {
5284
try assertOutput(
5385
input: "public func async() async throws",
@@ -62,7 +94,7 @@ struct JNIAsyncTests {
6294
* }
6395
*/
6496
public static java.util.concurrent.CompletableFuture<Void> async() {
65-
return CompletableFuture.supplyAsync(() -> {
97+
return java.util.concurrent.CompletableFuture.supplyAsync(() -> {
6698
SwiftModule.$async();
6799
return null;
68100
}
@@ -76,7 +108,53 @@ struct JNIAsyncTests {
76108
)
77109
}
78110

79-
@Test("Import: (Int64) async -> Int64 (CompletableFuture)")
111+
@Test("Import: async throws -> Void (Swift, CompletableFuture)")
112+
func completableFuture_asyncThrowsVoid_swift() throws {
113+
try assertOutput(
114+
input: "public func async() async throws",
115+
.jni, .swift,
116+
detectChunkByInitialLines: 1,
117+
expectedChunks: [
118+
"""
119+
@_cdecl("Java_com_example_swift_SwiftModule__00024async__")
120+
func Java_com_example_swift_SwiftModule__00024async__(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass) {
121+
do {
122+
let _semaphore$ = _Semaphore(value: 0)
123+
var swiftResult$: Result<(), any Error>!
124+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
125+
Task.immediate {
126+
do {
127+
swiftResult$ = await Result.success(try SwiftModule.async())
128+
}
129+
catch {
130+
swiftResult$ = Result.failure(error)
131+
}
132+
_semaphore$.signal()
133+
}
134+
}
135+
else {
136+
Task {
137+
do {
138+
swiftResult$ = await Result.success(try SwiftModule.async())
139+
}
140+
catch {
141+
swiftResult$ = Result.failure(error)
142+
}
143+
_semaphore$.signal()
144+
}
145+
}
146+
_semaphore$.wait()
147+
try swiftResult$.get()
148+
} catch {
149+
environment.throwAsException(error)
150+
151+
}
152+
"""
153+
]
154+
)
155+
}
156+
157+
@Test("Import: (Int64) async -> Int64 (Java, CompletableFuture)")
80158
func completableFuture_asyncIntToInt_java() throws {
81159
try assertOutput(
82160
input: "public func async(i: Int64) async -> Int64",
@@ -91,7 +169,7 @@ struct JNIAsyncTests {
91169
* }
92170
*/
93171
public static java.util.concurrent.CompletableFuture<Long> async(long i) {
94-
return CompletableFuture.supplyAsync(() -> {
172+
return java.util.concurrent.CompletableFuture.supplyAsync(() -> {
95173
return SwiftModule.$async(i);
96174
}
97175
);
@@ -104,7 +182,39 @@ struct JNIAsyncTests {
104182
)
105183
}
106184

107-
@Test("Import: (MyClass) async -> MyClass (CompletableFuture)")
185+
@Test("Import: (Int64) async -> Int64 (Swift, CompletableFuture)")
186+
func completableFuture_asyncIntToInt_swift() throws {
187+
try assertOutput(
188+
input: "public func async(i: Int64) async -> Int64",
189+
.jni, .swift,
190+
detectChunkByInitialLines: 1,
191+
expectedChunks: [
192+
"""
193+
@_cdecl("Java_com_example_swift_SwiftModule__00024async__J")
194+
func Java_com_example_swift_SwiftModule__00024async__J(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, i: jlong) -> jlong {
195+
let _semaphore$ = _Semaphore(value: 0)
196+
var swiftResult$: Int64!
197+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
198+
Task.immediate {
199+
swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment!))
200+
_semaphore$.signal()
201+
}
202+
}
203+
else {
204+
Task {
205+
swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment!))
206+
_semaphore$.signal()
207+
}
208+
}
209+
_semaphore$.wait()
210+
return swiftResult$.getJNIValue(in: environment!)
211+
}
212+
"""
213+
]
214+
)
215+
}
216+
217+
@Test("Import: (MyClass) async -> MyClass (Java, CompletableFuture)")
108218
func completableFuture_asyncMyClassToMyClass_java() throws {
109219
try assertOutput(
110220
input: """
@@ -123,7 +233,7 @@ struct JNIAsyncTests {
123233
* }
124234
*/
125235
public static java.util.concurrent.CompletableFuture<MyClass> async(MyClass c, SwiftArena swiftArena$) {
126-
return CompletableFuture.supplyAsync(() -> {
236+
return java.util.concurrent.CompletableFuture.supplyAsync(() -> {
127237
return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$async(c.$memoryAddress()), swiftArena$);
128238
}
129239
);
@@ -135,4 +245,49 @@ struct JNIAsyncTests {
135245
]
136246
)
137247
}
248+
249+
@Test("Import: (MyClass) async -> MyClass (Swift, CompletableFuture)")
250+
func completableFuture_asyncMyClassToMyClass_swift() throws {
251+
try assertOutput(
252+
input: """
253+
class MyClass { }
254+
255+
public func async(c: MyClass) async -> MyClass
256+
""",
257+
.jni, .swift,
258+
detectChunkByInitialLines: 1,
259+
expectedChunks: [
260+
"""
261+
@_cdecl("Java_com_example_swift_SwiftModule__00024async__J")
262+
func Java_com_example_swift_SwiftModule__00024async__J(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, c: jlong) -> jlong {
263+
assert(c != 0, "c memory address was null")
264+
let cBits$ = Int(Int64(fromJNI: c, in: environment!))
265+
let c$ = UnsafeMutablePointer<MyClass>(bitPattern: cBits$)
266+
guard let c$ else {
267+
fatalError("c memory address was null in call to \\(#function)!")
268+
}
269+
let _semaphore$ = _Semaphore(value: 0)
270+
var swiftResult$: MyClass!
271+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
272+
Task.immediate {
273+
swiftResult$ = await SwiftModule.async(c: c$.pointee)
274+
_semaphore$.signal()
275+
} // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:873
276+
} // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:872
277+
else {
278+
Task {
279+
swiftResult$ = await SwiftModule.async(c: c$.pointee)
280+
_semaphore$.signal()
281+
} // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:878
282+
} // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:877
283+
_semaphore$.wait()
284+
let result$ = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
285+
result$.initialize(to: swiftResult$)
286+
let resultBits$ = Int64(Int(bitPattern: result$))
287+
return resultBits$.getJNIValue(in: environment!)
288+
}
289+
"""
290+
]
291+
)
292+
}
138293
}

0 commit comments

Comments
 (0)