Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · ci/redact/redact_test.go

Line attribution on main · 130 line(s)

e82bbe7d
Keenan Nemetz
7d ago
1 package redact
2
3 import (
4 "bytes"
5 "strings"
6 "sync"
7 "testing"
8 )
9
10 // A value split across two writes is the case the carry exists for: a step's
11 // output arrives in whatever sizes the pipe gives it, and a token has no reason to
12 // land on a boundary.
13 func TestAValueSplitAcrossWritesIsStillMasked(t *testing.T) {
14 t.Parallel()
15 var out bytes.Buffer
16 w := NewWriter(&out, []string{"s3cret-token"})
17 for _, piece := range []string{"the token is s3c", "ret-to", "ken, ok"} {
18 if _, err := w.Write([]byte(piece)); err != nil {
19 t.Fatal(err)
20 }
21 }
22 if err := w.Flush(); err != nil {
23 t.Fatal(err)
24 }
25 if got := out.String(); got != "the token is "+Placeholder+", ok" {
26 t.Fatalf("output = %q", got)
27 }
28 }
29
30 func TestMaskKeepsTheLongestValue(t *testing.T) {
31 t.Parallel()
32 out := (&strings.Builder{})
33 w := NewWriter(out, []string{"abc", "abcdefgh", "abcdef"})
34 if _, err := w.Write([]byte("value abcdefgh")); err != nil {
35 t.Fatal(err)
36 }
37 if err := w.Flush(); err != nil {
38 t.Fatal(err)
39 }
40 // "abc" and "abcdef" are prefixes of "abcdefgh"; the whole value is replaced, so
41 // no tail of it survives.
42 if got := out.String(); got != "value "+Placeholder {
43 t.Fatalf("output = %q, want the longest value masked whole", got)
44 }
45 }
46
47 func TestShortValuesAreNotMasked(t *testing.T) {
48 t.Parallel()
49 out := &strings.Builder{}
50 w := NewWriter(out, []string{"yes", "1", "abc"})
51 if _, err := w.Write([]byte("yes 1 abc and abcd")); err != nil {
52 t.Fatal(err)
53 }
54 if err := w.Flush(); err != nil {
55 t.Fatal(err)
56 }
57 // Three bytes is a flag or a version; masking it would rewrite the log.
58 if got := out.String(); got != "yes 1 abc and abcd" {
59 t.Fatalf("output = %q", got)
60 }
61 // Four is the floor.
62 out.Reset()
63 if _, err := NewWriter(out, []string{"abcd"}).Write([]byte("abcd")); err != nil {
64 t.Fatal(err)
65 }
66 if got := out.String(); got != Placeholder {
67 t.Fatalf("a four-byte value was not masked: %q", got)
68 }
69 }
70
71 func TestMultiLineValuesAreMasked(t *testing.T) {
72 t.Parallel()
73 value := "-----BEGIN KEY-----\nMIIB\n-----END KEY-----"
74 out := &strings.Builder{}
75 w := NewWriter(out, []string{value})
76 if _, err := w.Write([]byte("key:\n" + value + "\ndone\n")); err != nil {
77 t.Fatal(err)
78 }
79 if err := w.Flush(); err != nil {
80 t.Fatal(err)
81 }
82 if got := out.String(); got != "key:\n"+Placeholder+"\ndone\n" {
83 t.Fatalf("output = %q", got)
84 }
85 }
86
87 func TestEveryWriteIsReportedAsTaken(t *testing.T) {
88 t.Parallel()
89 var out bytes.Buffer
90 w := NewWriter(&out, []string{"s3cret"})
91 // A short write would make exec kill the program that printed its own secret.
92 n, err := w.Write([]byte("s3cret-ish"))
93 if err != nil || n != len("s3cret-ish") {
94 t.Fatalf("Write = %d, %v", n, err)
95 }
96 }
97
98 func TestStringMasksAWholeMessage(t *testing.T) {
99 t.Parallel()
100 m := New([]string{"s3cret"})
101 if got := m.String("cannot start: s3cret"); got != "cannot start: "+Placeholder {
102 t.Fatalf("String = %q", got)
103 }
104 if New(nil).String("plain") != "plain" {
105 t.Fatal("an empty mask changed a message")
106 }
107 }
108
109 func TestWriterIsSafeFromTwoGoroutines(t *testing.T) {
110 t.Parallel()
111 out := &strings.Builder{}
112 w := NewWriter(out, []string{"s3cret"})
113 var wg sync.WaitGroup
114 for i := 0; i < 8; i++ {
115 wg.Add(1)
116 go func() {
117 defer wg.Done()
118 for j := 0; j < 50; j++ {
119 _, _ = w.Write([]byte("x s3cret y\n"))
120 }
121 }()
122 }
123 wg.Wait()
124 if err := w.Flush(); err != nil {
125 t.Fatal(err)
126 }
127 if strings.Contains(out.String(), "s3cret") {
128 t.Fatalf("a value survived concurrent writes:\n%s", out.String())
129 }
130 }