@@ -31,12 +31,12 @@ import (
3131 "github.com/containerd/nerdctl/mod/tigron/tig"
3232)
3333
34- // TODO: once debugging output will be cleaned-up, reintroduce hexdump.
35-
3634const (
35+ markLineLength = 20
3736 expectedSuccessDecorator = "✅️ does verify:\t \t "
38- expectedFailDecorator = "❌ does not verify: \t "
37+ expectedFailDecorator = "❌ FAILED! \t \t "
3938 receivedDecorator = "👀 testing:\t \t "
39+ annotationDecorator = "🖊️"
4040 hyperlinkDecorator = "🔗"
4141)
4242
@@ -163,8 +163,8 @@ func True(testing tig.T, comp bool, msg ...string) bool {
163163
164164// WithFailLater will allow an assertion to not fail the test immediately.
165165// 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 .
168168func WithFailLater (t tig.T ) tig.T {
169169 return & failLater {
170170 t ,
@@ -205,49 +205,76 @@ func evaluate(testing tig.T, isSuccess bool, actual, expected any, msg ...string
205205func decorate (testing tig.T , isSuccess bool , actual , expected any , msg ... string ) {
206206 testing .Helper ()
207207
208- header := "\t "
208+ if _ , ok := testing .(* silentSuccess ); ! isSuccess || ! ok {
209+ head := strings .Repeat ("<" , markLineLength )
210+ footer := strings .Repeat (">" , markLineLength )
211+ header := "\t "
209212
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 " ))
214214
215- msg = append (msg , fmt . Sprintf ( " \t %s`%v` " , receivedDecorator , actual ) )
215+ msg = append ([] string { " " , head }, custom )
216216
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 ... )
226218
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 " )
229232 }
230233}
231234
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.
232246func getTopFrameFile () string {
233- // Get the frames.
247+ // Get the frames. Skip the first two frames - current one and caller.
234248 //nolint:mnd // Whatever mnd...
235- pc := make ([]uintptr , 20 )
249+ pc := make ([]uintptr , 40 )
236250 //nolint:mnd // Whatever mnd...
237251 n := runtime .Callers (2 , pc )
238252 callersFrames := runtime .CallersFrames (pc [:n ])
239253
240- var file string
254+ var (
255+ file string
256+ lineNumber int
257+ frame runtime.Frame
258+ )
241259
242- var lineNumber int
260+ more := true
261+ for more {
262+ frame , more = callersFrames .Next ()
243263
244- var frame runtime.Frame
245- for range 20 {
246- frame , _ = callersFrames .Next ()
264+ // Once we are in the go main stack, bail out
247265 if ! strings .Contains (frame .Function , "/" ) {
248266 break
249267 }
250268
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+
251278 file = frame .File
252279 lineNumber = frame .Line
253280 }
@@ -282,6 +309,6 @@ func getTopFrameFile() string {
282309 return hyperlinkDecorator + " " + (& formatter.OSC8 {
283310 Text : line ,
284311 Location : "file://" + file ,
285- Line : frame . Line ,
312+ Line : lineNumber ,
286313 }).String ()
287314}
0 commit comments