Skip to content

Commit 683f003

Browse files
committed
reenable async_taskgroup_discarding_dontLeak.swift
1 parent 7020cf3 commit 683f003

File tree

1 file changed

+148
-78
lines changed

1 file changed

+148
-78
lines changed
Lines changed: 148 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) | %FileCheck %s --dump-input=always
22
// TODO: move to target-run-simple-leaks-swift once CI is using at least Xcode 14.3
33

4-
// rdar://109998145 - Temporarily disable this test
5-
// REQUIRES: rdar109998145
6-
74
// REQUIRES: concurrency
85
// REQUIRES: executable_test
96
// REQUIRES: concurrency_runtime
@@ -16,6 +13,37 @@
1613

1714
import _Concurrency
1815

16+
actor SimpleCountDownLatch {
17+
let from: Int
18+
var count: Int
19+
20+
var continuation: CheckedContinuation<Void, Never>?
21+
22+
init(from: Int) {
23+
self.from = from
24+
self.count = from
25+
}
26+
27+
func hit() {
28+
defer { count -= 1 }
29+
if count == 0 {
30+
fatalError("Counted down more times than expected! (From: \(from))")
31+
} else if count == 1 {
32+
continuation?.resume()
33+
}
34+
}
35+
36+
func wait() async {
37+
guard self.count > 0 else {
38+
return // we're done
39+
}
40+
41+
return await withCheckedContinuation { cc in
42+
self.continuation = cc
43+
}
44+
}
45+
}
46+
1947
final class PrintDeinit {
2048
let id: String
2149
init(id: String) {
@@ -60,96 +88,138 @@ final class SomeClass: @unchecked Sendable {
6088

6189
// NOTE: Not as StdlibUnittest/TestSuite since these types of tests are unreasonably slow to load/debug.
6290

63-
@main struct Main {
64-
static func main() async {
65-
_ = try? await withThrowingDiscardingTaskGroup() { group in
66-
group.addTask {
67-
throw Boom(id: "race-boom-class")
68-
}
91+
func testTwo() async {
92+
let latch = SimpleCountDownLatch(from: 2)
93+
94+
_ = try? await withThrowingDiscardingTaskGroup() { group in
95+
group.addTask {
96+
await latch.hit()
97+
throw Boom(id: "race-boom")
98+
}
99+
group.addTask {
100+
await latch.hit()
101+
SomeClass(id: "race-boom-class") // will be discarded
102+
}
103+
104+
return 12
105+
}
106+
107+
// since values may deinit in any order, we just assert their count basically
108+
// CHECK-DAG: deinit, id: race-boom
109+
// CHECK-DAG: deinit, id: race-boom
110+
await latch.wait()
111+
print("done") // CHECK: done
112+
}
113+
114+
func manyOk() async {
115+
let latch = SimpleCountDownLatch(from: 6)
116+
117+
_ = try? await withThrowingDiscardingTaskGroup() { group in
118+
for i in 0..<6 {
69119
group.addTask {
70-
SomeClass(id: "race-boom-class") // will be discarded
120+
await latch.hit()
121+
_ = SomeClass(id: "many-ok") // will be discarded
71122
}
72-
// since values may deinit in any order, we just assert their count basically
73-
// CHECK-DAG: deinit, id: race-boom-class
74-
// CHECK-DAG: deinit, id: race-boom-class
75-
76-
return 12
77123
}
78124

79-
// many ok
80-
_ = try? await withThrowingDiscardingTaskGroup() { group in
125+
return 12
126+
}
127+
// since values may deinit in any order, we just assert their count basically
128+
// CHECK-DAG: deinit, id: many-ok
129+
// CHECK-DAG: deinit, id: many-ok
130+
// CHECK-DAG: deinit, id: many-ok
131+
// CHECK-DAG: deinit, id: many-ok
132+
// CHECK-DAG: deinit, id: many-ok
133+
// CHECK-DAG: deinit, id: many-ok
134+
135+
await latch.wait()
136+
print("done") // CHECK: done
137+
}
138+
139+
func manyThrows() async {
140+
let latch = SimpleCountDownLatch(from: 6)
141+
142+
do {
143+
let value: Void = try await withThrowingDiscardingTaskGroup() { group in
81144
for i in 0..<6 {
82145
group.addTask {
83-
SomeClass(id: "many-ok") // will be discarded
146+
await latch.hit()
147+
throw BoomClass(id: "many-error") // will be rethrown
84148
}
85-
// since values may deinit in any order, we just assert their count basically
86-
// CHECK-DAG: deinit, id: many-ok
87-
// CHECK-DAG: deinit, id: many-ok
88-
// CHECK-DAG: deinit, id: many-ok
89-
// CHECK-DAG: deinit, id: many-ok
90-
// CHECK-DAG: deinit, id: many-ok
91-
// CHECK-DAG: deinit, id: many-ok
92149
}
93150

94-
return 12
151+
// since values may deinit in any order, we just assert their count basically
152+
// CHECK-DAG: deinit, id: many-error
153+
// CHECK-DAG: deinit, id: many-error
154+
// CHECK-DAG: deinit, id: many-error
155+
// CHECK-DAG: deinit, id: many-error
156+
// CHECK-DAG: deinit, id: many-error
157+
// CHECK-DAG: deinit, id: many-error
158+
159+
12 // must be ignored
95160
}
161+
preconditionFailure("Should throw")
162+
} catch {
163+
precondition("\(error)" == "main.BoomClass", "error was: \(error)")
164+
}
96165

97-
// many throws
98-
do {
99-
let value = try await withThrowingDiscardingTaskGroup() { group in
100-
for i in 0..<6 {
101-
group.addTask {
102-
throw BoomClass(id: "many-error") // will be rethrown
103-
}
104-
}
166+
await latch.wait()
167+
print("done") // CHECK: done
168+
}
105169

106-
// since values may deinit in any order, we just assert their count basically
107-
// CHECK-DAG: deinit, id: many-error
108-
// CHECK-DAG: deinit, id: many-error
109-
// CHECK-DAG: deinit, id: many-error
110-
// CHECK-DAG: deinit, id: many-error
111-
// CHECK-DAG: deinit, id: many-error
112-
// CHECK-DAG: deinit, id: many-error
170+
func manyValuesThrows() async {
171+
let latch = SimpleCountDownLatch(from: 6)
113172

114-
12 // must be ignored
115-
}
116-
preconditionFailure("Should throw")
117-
} catch {
118-
precondition("\(error)" == "main.BoomClass", "error was: \(error)")
173+
// many errors, many values
174+
_ = try? await withThrowingDiscardingTaskGroup() { group in
175+
group.addTask {
176+
await latch.hit()
177+
_ = SomeClass(id: "mixed-ok") // will be discarded
178+
}
179+
group.addTask {
180+
await latch.hit()
181+
_ = SomeClass(id: "mixed-ok") // will be discarded
182+
}
183+
group.addTask {
184+
await latch.hit()
185+
_ = SomeClass(id: "mixed-ok") // will be discarded
186+
}
187+
group.addTask {
188+
await latch.hit()
189+
throw Boom(id: "mixed-error")
190+
}
191+
group.addTask {
192+
await latch.hit()
193+
throw Boom(id: "mixed-error")
194+
}
195+
group.addTask {
196+
await latch.hit()
197+
throw Boom(id: "mixed-error")
119198
}
120199

121-
// many errors, many values
122-
_ = try? await withThrowingDiscardingTaskGroup() { group in
123-
group.addTask {
124-
SomeClass(id: "mixed-ok") // will be discarded
125-
}
126-
group.addTask {
127-
SomeClass(id: "mixed-ok") // will be discarded
128-
}
129-
group.addTask {
130-
SomeClass(id: "mixed-ok") // will be discarded
131-
}
132-
group.addTask {
133-
throw Boom(id: "mixed-error")
134-
}
135-
group.addTask {
136-
throw Boom(id: "mixed-error")
137-
}
138-
group.addTask {
139-
throw Boom(id: "mixed-error")
140-
}
141200

142-
// since values may deinit in any order, we just assert their count basically
143-
// three ok's
144-
// CHECK-DAG: deinit, id: mixed
145-
// CHECK-DAG: deinit, id: mixed
146-
// CHECK-DAG: deinit, id: mixed
147-
// three errors
148-
// CHECK-DAG: deinit, id: mixed
149-
// CHECK-DAG: deinit, id: mixed
150-
// CHECK-DAG: deinit, id: mixed
151-
152-
return 12
153-
}
201+
return 12
202+
}
203+
204+
// since values may deinit in any order, we just assert their count basically
205+
// three ok's
206+
// CHECK-DAG: deinit, id: mixed
207+
// CHECK-DAG: deinit, id: mixed
208+
// CHECK-DAG: deinit, id: mixed
209+
// three errors
210+
// CHECK-DAG: deinit, id: mixed
211+
// CHECK-DAG: deinit, id: mixed
212+
// CHECK-DAG: deinit, id: mixed
213+
214+
await latch.wait()
215+
print("done") // CHECK: done
216+
}
217+
218+
@main struct Main {
219+
static func main() async {
220+
await testTwo()
221+
await manyOk()
222+
await manyThrows()
223+
await manyValuesThrows()
154224
}
155225
}

0 commit comments

Comments
 (0)