Skip to content

Commit 14ea9a3

Browse files
authored
[lldb] Script determinism of TestSwiftActorUnprioritisedJobs (llvm#10435)
* [lldb] Make TestSwiftActorUnprioritisedJobs deterministic * Run and show `bt all` * Attempt forward progress of other threads * Add missing thread.Suspend() * Unconditionally run other threads * Increase sleep wait * Add actor call to hopefully initialize swift concurrency threads * New algorithm to ensure actor is sufficiently setup Credit Adrian for the idea. * Add IsValid asserts * New approach did not work, restore previous * Another round of changes * Remove dead test code; Run the test 20x * Pause to allow for occupy() call * Remove stress testing of multiple test runs
1 parent efab758 commit 14ea9a3

File tree

2 files changed

+27
-20
lines changed

2 files changed

+27
-20
lines changed

lldb/test/API/lang/swift/async/actors/unprioritised_jobs/TestSwiftActorUnprioritisedJobs.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,21 @@
77
class TestCase(TestBase):
88

99
@swiftTest
10-
@skipUnlessFoundation
11-
@skipIfWindows # temporarily skip test until fails can be investigated
12-
@skipIfLinux # temporarily skip test until fails can be investigated
13-
@skipIfDarwin # temporarily skip test until fails can be investigated
1410
def test_actor_unprioritised_jobs(self):
1511
"""Verify that an actor exposes its unprioritised jobs (queue)."""
1612
self.build()
17-
_, _, thread, _ = lldbutil.run_to_source_breakpoint(
18-
self, "break here", lldb.SBFileSpec("main.swift")
19-
)
20-
frame = thread.GetSelectedFrame()
13+
_, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "breakHere")
14+
15+
frame = thread.frames[0]
16+
self.assertEqual(frame.var("a.data").unsigned, 15)
17+
2118
defaultActor = frame.var("a.$defaultActor")
2219
self.assertEqual(defaultActor.summary, "running")
20+
2321
unprioritised_jobs = defaultActor.GetChildMemberWithName("unprioritised_jobs")
2422
# There are 4 child tasks (async let), the first one occupies the actor
25-
# with a sleep, the next 3 go on to the queue.
26-
# TODO: rdar://148377173
27-
# self.assertEqual(unprioritised_jobs.num_children, 3)
23+
# with a call to readLine, the next 3 go on the queue.
24+
self.assertEqual(unprioritised_jobs.num_children, 3)
2825
for job in unprioritised_jobs:
2926
self.assertRegex(job.name, r"^\d+")
30-
self.assertRegex(job.summary, r"^id:\d+ flags:\S+")
27+
self.assertRegex(job.summary, r"^id:[1-9]\d* flags:\S+")
Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import Foundation
2-
31
actor Actor {
42
var data: Int = 15
53

64
func occupy() async {
7-
Thread.sleep(forTimeInterval: 100)
5+
_ = readLine()
86
}
97

108
func work() async -> Int {
@@ -14,13 +12,25 @@ actor Actor {
1412
}
1513
}
1614

15+
func breakHere(_ a: Actor) {}
16+
1717
@main struct Entry {
1818
static func main() async {
1919
let a = Actor()
20-
async let _ = a.occupy()
21-
async let _ = a.work()
22-
async let _ = a.work()
23-
async let _ = a.work()
24-
print("break here")
20+
21+
async let w: Void = a.occupy()
22+
// Provide time for the global concurrent executor to run this async
23+
// let, which enqueues a "blocking" job on the actor.
24+
try? await Task.sleep(for: .seconds(2))
25+
26+
async let x = a.work()
27+
async let y = a.work()
28+
async let z = a.work()
29+
// Provide time for the global concurrent executor to kick off of these
30+
// async let tasks, which in turn enqueue jobs on the busy actor.
31+
try? await Task.sleep(for: .seconds(2))
32+
33+
breakHere(a)
34+
await print(w, x, y, z)
2535
}
2636
}

0 commit comments

Comments
 (0)