okami.mom/glamour

git clone https://git.nkp.pet/okami.mom/glamour

Kieran Klukasfix: close wrap writer before its downstream chain975a0f3

main
1.3 KiB46 linesraw
1package ansi
2
3import (
4	"bytes"
5	"io"
6	"testing"
7
8	"charm.land/lipgloss/v2"
9)
10
11// TestIndentWriterCloseOrder guards against a use-after-close crash in the
12// writer chain. IndentWriter.pw wraps IndentWriter.w, so closing w before pw
13// used to tear down the writer that pw's closing style/link reset flushes
14// through, panicking on a nil ANSI parser. Closing pw first avoids that.
15func TestIndentWriterCloseOrder(t *testing.T) {
16	var buf bytes.Buffer
17
18	// pw stands in for the downstream PaddingWriter: a passthrough whose own
19	// underlying WrapWriter gets closed when pw is closed.
20	pw := newWrapCloser(&buf)
21	iw := NewIndentWriter(pw, 2, nil)
22
23	// Write content carrying an open SGR style so closing flushes a reset.
24	if _, err := io.WriteString(iw, "\x1b[1mhello\n"); err != nil {
25		t.Fatalf("write: %v", err)
26	}
27
28	// Must not panic.
29	if err := iw.Close(); err != nil {
30		t.Fatalf("close: %v", err)
31	}
32}
33
34// wrapCloser models glamour's PaddingWriter: it forwards writes through an
35// inner lipgloss WrapWriter and closes that writer on Close.
36type wrapCloser struct {
37	w *lipgloss.WrapWriter
38}
39
40func newWrapCloser(w *bytes.Buffer) *wrapCloser {
41	return &wrapCloser{w: lipgloss.NewWrapWriter(w)}
42}
43
44func (c *wrapCloser) Write(p []byte) (int, error) { return c.w.Write(p) }
45
46func (c *wrapCloser) Close() error { return c.w.Close() }