Skip to content

Commit a4a2e65

Browse files
committed
Cleaner debug information for assertive
Signed-off-by: apostasie <[email protected]>
1 parent b477fee commit a4a2e65

File tree

1 file changed

+57
-30
lines changed

1 file changed

+57
-30
lines changed

mod/tigron/internal/assertive/assertive.go

+57-30
Original file line numberDiff line numberDiff line change
@@ -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-
3634
const (
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.
168168
func 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
205205
func 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.
232246
func 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

Comments
 (0)