@@ -31,12 +31,12 @@ import (
31
31
"github.com/containerd/nerdctl/mod/tigron/tig"
32
32
)
33
33
34
- // TODO: once debugging output will be cleaned-up, reintroduce hexdump.
35
-
36
34
const (
35
+ markLineLength = 20
37
36
expectedSuccessDecorator = "✅️ does verify:\t \t "
38
- expectedFailDecorator = "❌ does not verify: \t "
37
+ expectedFailDecorator = "❌ FAILED! \t \t "
39
38
receivedDecorator = "👀 testing:\t \t "
39
+ annotationDecorator = "🖊️"
40
40
hyperlinkDecorator = "🔗"
41
41
)
42
42
@@ -163,8 +163,8 @@ func True(testing tig.T, comp bool, msg ...string) bool {
163
163
164
164
// WithFailLater will allow an assertion to not fail the test immediately.
165
165
// Failing later is necessary when asserting inside go routines, and also if you want many
166
- // successive asserts to all
167
- // evaluate instead of stopping at the first failing one .
166
+ // successive asserts to all evaluate instead of stopping at the first failing one.
167
+ // FIXME: it should be possible to have both WithFailLater and WithSilentSuccess at the same time .
168
168
func WithFailLater (t tig.T ) tig.T {
169
169
return & failLater {
170
170
t ,
@@ -205,49 +205,76 @@ func evaluate(testing tig.T, isSuccess bool, actual, expected any, msg ...string
205
205
func decorate (testing tig.T , isSuccess bool , actual , expected any , msg ... string ) {
206
206
testing .Helper ()
207
207
208
- header := "\t "
208
+ if _ , ok := testing .(* silentSuccess ); ! isSuccess || ! ok {
209
+ head := strings .Repeat ("<" , markLineLength )
210
+ footer := strings .Repeat (">" , markLineLength )
211
+ header := "\t "
209
212
210
- hyperlink := getTopFrameFile ()
211
- if hyperlink != "" {
212
- msg = append ([]string {hyperlink + "\n " }, msg ... )
213
- }
213
+ custom := fmt .Sprintf ("\t %s %s" , annotationDecorator , strings .Join (msg , "\n " ))
214
214
215
- msg = append (msg , fmt . Sprintf ( " \t %s`%v` " , receivedDecorator , actual ) )
215
+ msg = append ([] string { " " , head }, custom )
216
216
217
- if isSuccess {
218
- msg = append (msg ,
219
- fmt .Sprintf ("\t %s%v" , expectedSuccessDecorator , expected ),
220
- )
221
- } else {
222
- msg = append (msg ,
223
- fmt .Sprintf ("\t %s%v" , expectedFailDecorator , expected ),
224
- )
225
- }
217
+ msg = append ([]string {getTopFrameFile ()}, msg ... )
226
218
227
- if _ , ok := testing .(* silentSuccess ); ! isSuccess || ! ok {
228
- testing .Log (header + strings .Join (msg , "\n " ) + "\n " )
219
+ msg = append (msg , fmt .Sprintf ("\t %s`%v`" , receivedDecorator , actual ))
220
+
221
+ if isSuccess {
222
+ msg = append (msg ,
223
+ fmt .Sprintf ("\t %s%v" , expectedSuccessDecorator , expected ),
224
+ )
225
+ } else {
226
+ msg = append (msg ,
227
+ fmt .Sprintf ("\t %s%v" , expectedFailDecorator , expected ),
228
+ )
229
+ }
230
+
231
+ testing .Log (header + strings .Join (msg , "\n " ) + "\n " + footer + "\n " )
229
232
}
230
233
}
231
234
235
+ // XXX FIXME #expert
236
+ // Because of how golang testing works, the upper frame is the one from where t.Run is being called,
237
+ // as (presumably) the passed function is starting with its own stack in a go routine.
238
+ // In the case of subtests, t.Run being called from inside Tigron will make it so that the top frame
239
+ // is case.go around line 233 (where we call Command.Run(), which is the one calling assertive).
240
+ // To possibly address this:
241
+ // plan a. just drop entirely OSC8 links and source extracts and trash all of this
242
+ // plan b. get the top frame from the root test, and pass it to subtests on a custom property, the somehow into here
243
+ // plan c. figure out a hack to call t.Run from the test file without ruining the Tigron UX
244
+ // Dereference t.Run? Return a closure to be called from the top? w/o disabling inlining in the right place?
245
+ // Short term, blacklisting /tigron (and /nerdtest) will at least prevent the wrong links from appearing in the output.
232
246
func getTopFrameFile () string {
233
- // Get the frames.
247
+ // Get the frames. Skip the first two frames - current one and caller.
234
248
//nolint:mnd // Whatever mnd...
235
- pc := make ([]uintptr , 20 )
249
+ pc := make ([]uintptr , 40 )
236
250
//nolint:mnd // Whatever mnd...
237
251
n := runtime .Callers (2 , pc )
238
252
callersFrames := runtime .CallersFrames (pc [:n ])
239
253
240
- var file string
254
+ var (
255
+ file string
256
+ lineNumber int
257
+ frame runtime.Frame
258
+ )
241
259
242
- var lineNumber int
260
+ more := true
261
+ for more {
262
+ frame , more = callersFrames .Next ()
243
263
244
- var frame runtime.Frame
245
- for range 20 {
246
- frame , _ = callersFrames .Next ()
264
+ // Once we are in the go main stack, bail out
247
265
if ! strings .Contains (frame .Function , "/" ) {
248
266
break
249
267
}
250
268
269
+ // XXX see note above
270
+ if strings .Contains (frame .File , "/tigron" ) {
271
+ continue
272
+ }
273
+
274
+ if strings .Contains (frame .File , "/nerdtest" ) {
275
+ continue
276
+ }
277
+
251
278
file = frame .File
252
279
lineNumber = frame .Line
253
280
}
@@ -282,6 +309,6 @@ func getTopFrameFile() string {
282
309
return hyperlinkDecorator + " " + (& formatter.OSC8 {
283
310
Text : line ,
284
311
Location : "file://" + file ,
285
- Line : frame . Line ,
312
+ Line : lineNumber ,
286
313
}).String ()
287
314
}
0 commit comments