1
+ //
2
+ // This source file is part of the Swift.org open source project
3
+ //
4
+ // Copyright (c) 2025 Apple Inc. and the Swift project authors
5
+ // Licensed under Apache License v2.0 with Runtime Library Exception
6
+ //
7
+ // See https://swift.org/LICENSE.txt for license information
8
+ // See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9
+ //
10
+
11
+ @testable @_spi ( Experimental) @_spi ( ForToolsIntegrationOnly) import Testing
12
+
13
+ @Suite ( " Advanced Console Output Recorder Tests " )
14
+ struct AdvancedConsoleOutputRecorderTests {
15
+ final class Stream : TextOutputStream , Sendable {
16
+ let buffer = Locked < String > ( rawValue: " " )
17
+
18
+ @Sendable func write( _ string: String ) {
19
+ buffer. withLock {
20
+ $0. append ( string)
21
+ }
22
+ }
23
+ }
24
+
25
+ @Test ( " Recorder initialization with default options " )
26
+ func recorderInitialization( ) {
27
+ let stream = Stream ( )
28
+ let recorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
29
+
30
+ // Verify the recorder was created successfully and has expected defaults
31
+ #expect( recorder. options. base. useANSIEscapeCodes == false ) // Default for non-TTY
32
+ }
33
+
34
+ @Test ( " Recorder initialization with custom options " )
35
+ func recorderInitializationWithCustomOptions( ) {
36
+ let stream = Stream ( )
37
+ var options = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> . Options( )
38
+ options. base. useANSIEscapeCodes = true
39
+
40
+ let recorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> (
41
+ options: options,
42
+ writingUsing: stream. write
43
+ )
44
+
45
+ // Verify the custom options were applied
46
+ #expect( recorder. options. base. useANSIEscapeCodes == true )
47
+ }
48
+
49
+ @Test ( " Basic event recording produces output " )
50
+ func basicEventRecording( ) async {
51
+ let stream = Stream ( )
52
+
53
+ var configuration = Configuration ( )
54
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
55
+ configuration. eventHandler = { event, context in
56
+ eventRecorder. record ( event, in: context)
57
+ }
58
+
59
+ // Run a simple test to generate events
60
+ await Test ( name: " Sample Test " ) {
61
+ #expect( Bool ( true ) )
62
+ } . run ( configuration: configuration)
63
+
64
+ let buffer = stream. buffer. rawValue
65
+ // Verify that the hierarchical output was generated
66
+ #expect( buffer. contains ( " HIERARCHICAL TEST RESULTS " ) )
67
+ #expect( buffer. contains ( " Test run started " ) )
68
+ }
69
+
70
+ @Test ( " Hierarchical output structure is generated " )
71
+ func hierarchicalOutputStructure( ) async {
72
+ let stream = Stream ( )
73
+
74
+ var configuration = Configuration ( )
75
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
76
+ configuration. eventHandler = { event, context in
77
+ eventRecorder. record ( event, in: context)
78
+ }
79
+
80
+ // Run tests that will create a hierarchy
81
+ await runTest ( for: HierarchicalTestSuite . self, configuration: configuration)
82
+
83
+ let buffer = stream. buffer. rawValue
84
+
85
+ // Verify hierarchical output headers are generated
86
+ #expect( buffer. contains ( " HIERARCHICAL TEST RESULTS " ) )
87
+ #expect( buffer. contains ( " completed " ) )
88
+
89
+ // Should contain tree structure characters
90
+ #expect( buffer. contains ( " ├─ " ) || buffer. contains ( " ╰─ " ) || buffer. contains ( " ┌─ " ) )
91
+ }
92
+
93
+ @Test ( " Failed test details are properly formatted " )
94
+ func failedTestDetails( ) async {
95
+ let stream = Stream ( )
96
+
97
+ var configuration = Configuration ( )
98
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
99
+ configuration. eventHandler = { event, context in
100
+ eventRecorder. record ( event, in: context)
101
+ }
102
+
103
+ // Run tests with failures
104
+ await runTest ( for: FailingTestSuite . self, configuration: configuration)
105
+
106
+ let buffer = stream. buffer. rawValue
107
+
108
+ // Verify failure details section is generated
109
+ #expect( buffer. contains ( " FAILED TEST DETAILS " ) )
110
+
111
+ // Should show test hierarchy in failure details
112
+ #expect( buffer. contains ( " FailingTestSuite " ) )
113
+ }
114
+
115
+ @Test ( " Test statistics are correctly calculated " )
116
+ func testStatisticsCalculation( ) async {
117
+ let stream = Stream ( )
118
+
119
+ var configuration = Configuration ( )
120
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
121
+ configuration. eventHandler = { event, context in
122
+ eventRecorder. record ( event, in: context)
123
+ }
124
+
125
+ // Run mixed passing and failing tests
126
+ await runTest ( for: MixedTestSuite . self, configuration: configuration)
127
+
128
+ let buffer = stream. buffer. rawValue
129
+
130
+ // Verify that statistics are correctly calculated and displayed
131
+ #expect( buffer. contains ( " completed " ) )
132
+ #expect( buffer. contains ( " pass: " ) || buffer. contains ( " fail: " ) )
133
+ }
134
+
135
+ @Test ( " Duration formatting is consistent " )
136
+ func durationFormatting( ) async {
137
+ let stream = Stream ( )
138
+
139
+ var configuration = Configuration ( )
140
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
141
+ configuration. eventHandler = { event, context in
142
+ eventRecorder. record ( event, in: context)
143
+ }
144
+
145
+ // Run a simple test to generate timing
146
+ await Test ( name: " Timed Test " ) {
147
+ #expect( Bool ( true ) )
148
+ } . run ( configuration: configuration)
149
+
150
+ let buffer = stream. buffer. rawValue
151
+
152
+ // Should not crash and should generate some output with timing
153
+ #expect( !buffer. isEmpty)
154
+ #expect( buffer. contains ( " s " ) ) // Duration formatting should include 's' suffix
155
+ }
156
+
157
+ @Test ( " Event consolidation works correctly " )
158
+ func eventConsolidation( ) async {
159
+ let stream = Stream ( )
160
+
161
+ var configuration = Configuration ( )
162
+ let eventRecorder = Event . AdvancedConsoleOutputRecorder< ABI . HighestVersion> ( writingUsing: stream. write)
163
+ configuration. eventHandler = { event, context in
164
+ eventRecorder. record ( event, in: context)
165
+ }
166
+
167
+ // Run tests to verify the consolidated data structure works
168
+ await runTest ( for: SimpleTestSuite . self, configuration: configuration)
169
+
170
+ let buffer = stream. buffer. rawValue
171
+
172
+ // Basic verification that the recorder processes events without crashing
173
+ #expect( !buffer. isEmpty)
174
+ #expect( buffer. contains ( " HIERARCHICAL TEST RESULTS " ) )
175
+ }
176
+ }
177
+
178
+ // MARK: - Test Suites for Testing
179
+
180
+ @Suite ( . hidden)
181
+ struct HierarchicalTestSuite {
182
+ @Test ( . hidden)
183
+ func passingTest( ) {
184
+ #expect( Bool ( true ) )
185
+ }
186
+
187
+ @Test ( . hidden)
188
+ func anotherPassingTest( ) {
189
+ #expect( 1 + 1 == 2 )
190
+ }
191
+
192
+ @Suite ( . hidden)
193
+ struct NestedSuite {
194
+ @Test ( . hidden)
195
+ func nestedTest( ) {
196
+ #expect( " hello " . count == 5 )
197
+ }
198
+ }
199
+ }
200
+
201
+ @Suite ( . hidden)
202
+ struct FailingTestSuite {
203
+ @Test ( . hidden)
204
+ func failingTest( ) {
205
+ #expect( Bool ( false ) , " This test is designed to fail " )
206
+ }
207
+
208
+ @Test ( . hidden)
209
+ func passingTest( ) {
210
+ #expect( Bool ( true ) )
211
+ }
212
+ }
213
+
214
+ @Suite ( . hidden)
215
+ struct MixedTestSuite {
216
+ @Test ( . hidden)
217
+ func test1( ) {
218
+ #expect( Bool ( true ) )
219
+ }
220
+
221
+ @Test ( . hidden)
222
+ func test2( ) {
223
+ #expect( Bool ( false ) , " Intentional failure " )
224
+ }
225
+
226
+ @Test ( . hidden)
227
+ func test3( ) {
228
+ #expect( 1 == 1 )
229
+ }
230
+ }
231
+
232
+ @Suite ( . hidden)
233
+ struct SimpleTestSuite {
234
+ @Test ( . hidden)
235
+ func simpleTest( ) {
236
+ #expect( Bool ( true ) )
237
+ }
238
+ }
0 commit comments