This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / models / logger_test.go
4.8 kB 182 lines
1package models 2 3import ( 4 "encoding/json" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9) 10 11func testWorkflowId(name string) WorkflowId { 12 return WorkflowId{PipelineId: PipelineId{Knot: "knot1", Rkey: "rkey1"}, Name: name} 13} 14 15func readDataContents(t *testing.T, path string) []string { 16 t.Helper() 17 raw, err := os.ReadFile(path) 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 var got []string 23 for _, encoded := range strings.Split(strings.TrimSpace(string(raw)), "\n") { 24 var line LogLine 25 if err := json.Unmarshal([]byte(encoded), &line); err != nil { 26 t.Fatalf("decode log line %q: %v", encoded, err) 27 } 28 got = append(got, line.Content) 29 } 30 return got 31} 32 33func TestDataWriterMasksSecretSplitAcrossWrites(t *testing.T) { 34 dir := t.TempDir() 35 secret := "hunter2-super-secret-token" 36 wid := testWorkflowId("mask") 37 logger, err := NewFileWorkflowLogger(dir, wid, []string{secret}) 38 if err != nil { 39 t.Fatal(err) 40 } 41 w := logger.DataWriter(0, "stdout") 42 43 for _, ch := range strings.Split("prefix "+secret+" suffix", "") { 44 if _, err := w.Write([]byte(ch)); err != nil { 45 t.Fatal(err) 46 } 47 } 48 if err := logger.Close(); err != nil { 49 t.Fatal(err) 50 } 51 52 raw, err := os.ReadFile(filepath.Join(dir, wid.String()+".log")) 53 if err != nil { 54 t.Fatal(err) 55 } 56 if strings.Contains(string(raw), secret) { 57 t.Errorf("log contains raw secret: %s", raw) 58 } 59 if !strings.Contains(string(raw), "***") { 60 t.Errorf("log does not contain masked marker: %s", raw) 61 } 62 // trailing bytes land in the final flush entry contiguously 63 if !strings.Contains(string(raw), "suffix") { 64 t.Errorf("log lost trailing output: %s", raw) 65 } 66 if got := strings.Join(readDataContents(t, filepath.Join(dir, wid.String()+".log")), "\n"); got != "prefix *** suffix" { 67 t.Errorf("masked output changed: %q", got) 68 } 69} 70 71func TestDataWriterMasksSingleFrame(t *testing.T) { 72 dir := t.TempDir() 73 secret := "hunter2-super-secret-token" 74 wid := testWorkflowId("frame") 75 logger, err := NewFileWorkflowLogger(dir, wid, []string{secret}) 76 if err != nil { 77 t.Fatal(err) 78 } 79 w := logger.DataWriter(0, "stdout") 80 if _, err := w.Write([]byte("token is " + secret + " ok")); err != nil { 81 t.Fatal(err) 82 } 83 if err := logger.Close(); err != nil { 84 t.Fatal(err) 85 } 86 87 raw, err := os.ReadFile(filepath.Join(dir, wid.String()+".log")) 88 if err != nil { 89 t.Fatal(err) 90 } 91 if strings.Contains(string(raw), secret) { 92 t.Errorf("log contains raw secret: %s", raw) 93 } 94 if !strings.Contains(string(raw), "en is *** ok") { 95 t.Errorf("masked entry mangled: %s", raw) 96 } 97} 98 99func TestDataWriterNoMaskPassthrough(t *testing.T) { 100 dir := t.TempDir() 101 wid := testWorkflowId("plain") 102 logger, err := NewFileWorkflowLogger(dir, wid, nil) 103 if err != nil { 104 t.Fatal(err) 105 } 106 w := logger.DataWriter(0, "stdout") 107 if _, err := w.Write([]byte("hello")); err != nil { 108 t.Fatal(err) 109 } 110 if _, err := w.Write([]byte(" world")); err != nil { 111 t.Fatal(err) 112 } 113 if err := logger.Close(); err != nil { 114 t.Fatal(err) 115 } 116 117 raw, err := os.ReadFile(filepath.Join(dir, wid.String()+".log")) 118 if err != nil { 119 t.Fatal(err) 120 } 121 if !strings.Contains(string(raw), "hello") || !strings.Contains(string(raw), " world") { 122 t.Errorf("log missing output: %s", raw) 123 } 124} 125 126func TestDataWriterDoesNotSplitSafeFragmentsIntoLogLines(t *testing.T) { 127 dir := t.TempDir() 128 wid := testWorkflowId("line-boundaries") 129 logger, err := NewFileWorkflowLogger(dir, wid, []string{"a-secret-with-a-long-window"}) 130 if err != nil { 131 t.Fatal(err) 132 } 133 w := logger.DataWriter(0, "stdout") 134 want := []string{ 135 "first line", 136 "second line", 137 "third line", 138 "fourth line", 139 "fifth line", 140 "sixth line", 141 "seventh line", 142 "eighth line", 143 } 144 for _, line := range want { 145 if _, err := w.Write([]byte(line + "\n")); err != nil { 146 t.Fatal(err) 147 } 148 } 149 if err := logger.Close(); err != nil { 150 t.Fatal(err) 151 } 152 153 got := readDataContents(t, filepath.Join(dir, wid.String()+".log")) 154 155 if joined := strings.Join(got, "\n"); joined != strings.Join(want, "\n") { 156 t.Fatalf("log content was split at masking window:\n got: %q\nwant: %q", joined, strings.Join(want, "\n")) 157 } 158} 159 160func TestDataWriterMasksMultilineSecret(t *testing.T) { 161 dir := t.TempDir() 162 secret := "line-one\nline-two" 163 wid := testWorkflowId("multiline-mask") 164 logger, err := NewFileWorkflowLogger(dir, wid, []string{secret}) 165 if err != nil { 166 t.Fatal(err) 167 } 168 w := logger.DataWriter(0, "stdout") 169 chunk := strings.Repeat("p", 40) + "\nline-one\nline-two\n" + strings.Repeat("t", 30) + "\nsuffix\n" 170 if _, err := w.Write([]byte(chunk)); err != nil { 171 t.Fatal(err) 172 } 173 if err := logger.Close(); err != nil { 174 t.Fatal(err) 175 } 176 177 got := strings.Join(readDataContents(t, filepath.Join(dir, wid.String()+".log")), "\n") 178 want := strings.Repeat("p", 40) + "\n***\n***\n" + strings.Repeat("t", 30) + "\nsuffix" 179 if got != want { 180 t.Fatalf("multiline secret was not masked: %q", got) 181 } 182}