repositories / bugabinga.net
bugabinga.net
personal infrastructure for bugabinga!
owned by admin
services/luci/internal/logs/sanitize_test.go
Rawpackage logs
import (
"bytes"
"errors"
"io"
"strings"
"sync"
"testing"
)
func TestSanitizerStripsANSIAndMasksSecretsAcrossWrites(t *testing.T) {
var output bytes.Buffer
writer := NewSanitizer(&output, [][]byte{[]byte("top-secret"), []byte("secret")})
parts := []string{
"plain \x1b[31mred\x1b[0m ",
"top-",
"secret and sec",
"ret\n",
"link \x1b]8;;https://example.invalid\x1b\\text\x1b]8;;\x1b\\ done",
}
for _, part := range parts {
if _, err := io.WriteString(writer, part); err != nil {
t.Fatal(err)
}
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
if got, want := output.String(), "plain red [MASKED] and [MASKED]\nlink text done"; got != want {
t.Fatalf("output=%q want %q", got, want)
}
}
func TestSanitizerDropsIncompleteANSIAndRejectsWritesAfterClose(t *testing.T) {
var output bytes.Buffer
writer := NewSanitizer(&output, nil)
_, _ = io.WriteString(writer, "before\x1b[31")
if err := writer.Close(); err != nil {
t.Fatal(err)
}
if output.String() != "before" {
t.Fatalf("output=%q", output.String())
}
if _, err := writer.Write([]byte("after")); !errors.Is(err, io.ErrClosedPipe) {
t.Fatalf("write err=%v", err)
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
}
func TestBoundedSanitizerTruncatesOnceWithoutFailingWriter(t *testing.T) {
var output bytes.Buffer
writer := NewBoundedSanitizer(&output, [][]byte{[]byte("secret")})
input := append(bytes.Repeat([]byte("x"), MaxLogBytes), []byte("secret")...)
if n, err := writer.Write(input); err != nil || n != len(input) {
t.Fatalf("Write() = %d, %v", n, err)
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
if !writer.Truncated() {
t.Fatal("truncation not reported")
}
if output.Len() > MaxLogBytes || !strings.HasSuffix(output.String(), truncationMarker) || strings.Count(output.String(), truncationMarker) != 1 {
t.Fatalf("output len=%d suffix=%q", output.Len(), output.String()[max(0, output.Len()-len(truncationMarker)):])
}
if strings.Contains(output.String(), "secret") {
t.Fatalf("secret leaked in output: %q", output.String()[max(0, output.Len()-128):])
}
}
func TestSanitizerSerializesConcurrentOutput(t *testing.T) {
var output bytes.Buffer
writer := NewSanitizer(&output, [][]byte{[]byte("secret")})
var wait sync.WaitGroup
for range 20 {
wait.Add(1)
go func() {
defer wait.Done()
_, _ = io.WriteString(writer, "\x1b[32msecret\x1b[0m\n")
}()
}
wait.Wait()
if err := writer.Close(); err != nil {
t.Fatal(err)
}
if strings.Count(output.String(), "[MASKED]\n") != 20 || strings.Contains(output.String(), "secret") || strings.ContainsRune(output.String(), '\x1b') {
t.Fatalf("output=%q", output.String())
}
}
type rejectedWriter struct{}
func (rejectedWriter) Write([]byte) (int, error) { return 0, errors.New("rejected") }
func TestSanitizerReportsDestinationFailure(t *testing.T) {
writer := NewSanitizer(rejectedWriter{}, nil)
if _, err := writer.Write([]byte("x")); err == nil {
t.Fatal("write failure hidden")
}
}