cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
at main 291 lines 7.3 kB view raw
1package shared 2 3import ( 4 "bytes" 5 "errors" 6 "io" 7 "testing" 8) 9 10func TestCompoundWriter(t *testing.T) { 11 t.Run("New", func(t *testing.T) { 12 t.Run("creates writer with primary and secondary", func(t *testing.T) { 13 var primary bytes.Buffer 14 var secondary bytes.Buffer 15 16 cw := New(&primary, &secondary) 17 18 if cw == nil { 19 t.Fatal("Expected CompoundWriter to be created") 20 } 21 if cw.primary == nil { 22 t.Error("Expected primary writer to be set") 23 } 24 if cw.secondary == nil { 25 t.Error("Expected secondary writer to be set") 26 } 27 }) 28 }) 29 30 t.Run("Write", func(t *testing.T) { 31 t.Run("writes to both primary and secondary", func(t *testing.T) { 32 var primary bytes.Buffer 33 var secondary bytes.Buffer 34 35 cw := New(&primary, &secondary) 36 37 testData := []byte("test message") 38 n, err := cw.Write(testData) 39 40 if err != nil { 41 t.Errorf("Expected no error, got %v", err) 42 } 43 if n != len(testData) { 44 t.Errorf("Expected to write %d bytes, got %d", len(testData), n) 45 } 46 47 if primary.String() != "test message" { 48 t.Errorf("Expected primary to contain 'test message', got '%s'", primary.String()) 49 } 50 if secondary.String() != "test message" { 51 t.Errorf("Expected secondary to contain 'test message', got '%s'", secondary.String()) 52 } 53 }) 54 55 t.Run("writes multiple times to both sinks", func(t *testing.T) { 56 var primary bytes.Buffer 57 var secondary bytes.Buffer 58 59 cw := New(&primary, &secondary) 60 61 messages := []string{"first", "second", "third"} 62 for _, msg := range messages { 63 _, err := cw.Write([]byte(msg)) 64 if err != nil { 65 t.Errorf("Expected no error writing '%s', got %v", msg, err) 66 } 67 } 68 69 expected := "firstsecondthird" 70 if primary.String() != expected { 71 t.Errorf("Expected primary to contain '%s', got '%s'", expected, primary.String()) 72 } 73 if secondary.String() != expected { 74 t.Errorf("Expected secondary to contain '%s', got '%s'", expected, secondary.String()) 75 } 76 }) 77 78 t.Run("returns error from primary writer", func(t *testing.T) { 79 var secondary bytes.Buffer 80 expectedErr := errors.New("primary write failed") 81 primary := &errorWriter{err: expectedErr} 82 83 cw := New(primary, &secondary) 84 85 _, err := cw.Write([]byte("test")) 86 87 if err == nil { 88 t.Error("Expected error from primary writer") 89 } 90 if !errors.Is(err, expectedErr) { 91 t.Errorf("Expected error '%v', got '%v'", expectedErr, err) 92 } 93 }) 94 95 t.Run("returns error from secondary writer", func(t *testing.T) { 96 var primary bytes.Buffer 97 expectedErr := errors.New("secondary write failed") 98 secondary := &errorWriter{err: expectedErr} 99 100 cw := New(&primary, secondary) 101 102 _, err := cw.Write([]byte("test")) 103 104 if err == nil { 105 t.Error("Expected error from secondary writer") 106 } 107 if !errors.Is(err, expectedErr) { 108 t.Errorf("Expected error '%v', got '%v'", expectedErr, err) 109 } 110 }) 111 112 t.Run("writes to primary even if secondary fails", func(t *testing.T) { 113 var primary bytes.Buffer 114 expectedErr := errors.New("secondary write failed") 115 secondary := &errorWriter{err: expectedErr} 116 117 cw := New(&primary, secondary) 118 119 testData := []byte("test message") 120 _, _ = cw.Write(testData) 121 122 if primary.String() != "test message" { 123 t.Errorf("Expected primary to contain 'test message' even with secondary error, got '%s'", primary.String()) 124 } 125 }) 126 127 t.Run("handles empty write", func(t *testing.T) { 128 var primary bytes.Buffer 129 var secondary bytes.Buffer 130 131 cw := New(&primary, &secondary) 132 133 n, err := cw.Write([]byte{}) 134 135 if err != nil { 136 t.Errorf("Expected no error on empty write, got %v", err) 137 } 138 if n != 0 { 139 t.Errorf("Expected to write 0 bytes, got %d", n) 140 } 141 }) 142 143 t.Run("handles large write", func(t *testing.T) { 144 var primary bytes.Buffer 145 var secondary bytes.Buffer 146 147 cw := New(&primary, &secondary) 148 149 largeData := make([]byte, 1024*1024) // 1MB 150 for i := range largeData { 151 largeData[i] = byte(i % 256) 152 } 153 154 n, err := cw.Write(largeData) 155 156 if err != nil { 157 t.Errorf("Expected no error on large write, got %v", err) 158 } 159 if n != len(largeData) { 160 t.Errorf("Expected to write %d bytes, got %d", len(largeData), n) 161 } 162 163 if !bytes.Equal(primary.Bytes(), largeData) { 164 t.Error("Primary writer didn't receive correct data") 165 } 166 if !bytes.Equal(secondary.Bytes(), largeData) { 167 t.Error("Secondary writer didn't receive correct data") 168 } 169 }) 170 }) 171 172 t.Run("WithStdErr", func(t *testing.T) { 173 t.Run("creates writer with stderr as primary", func(t *testing.T) { 174 var buf bytes.Buffer 175 closer := &nopCloser{Writer: &buf} 176 177 cw := LogWithStdErr(closer) 178 179 if cw == nil { 180 t.Fatal("Expected CompoundWriter to be created") 181 } 182 183 testData := []byte("test") 184 _, err := cw.Write(testData) 185 if err != nil { 186 t.Errorf("Expected no error, got %v", err) 187 } 188 189 if buf.String() != "test" { 190 t.Errorf("Expected secondary to contain 'test', got '%s'", buf.String()) 191 } 192 }) 193 }) 194 195 t.Run("WithStdOut", func(t *testing.T) { 196 t.Run("creates writer with stdout as primary", func(t *testing.T) { 197 var buf bytes.Buffer 198 closer := &nopCloser{Writer: &buf} 199 200 cw := LogWithStdOut(closer) 201 202 if cw == nil { 203 t.Fatal("Expected CompoundWriter to be created") 204 } 205 206 testData := []byte("test") 207 _, err := cw.Write(testData) 208 if err != nil { 209 t.Errorf("Expected no error, got %v", err) 210 } 211 212 if buf.String() != "test" { 213 t.Errorf("Expected secondary to contain 'test', got '%s'", buf.String()) 214 } 215 }) 216 }) 217} 218 219func TestConfigError(t *testing.T) { 220 t.Run("wraps error with message", func(t *testing.T) { 221 originalErr := errors.New("original error") 222 configErr := ConfigError("test message", originalErr) 223 224 if configErr == nil { 225 t.Fatal("Expected error to be returned") 226 } 227 228 errMsg := configErr.Error() 229 if errMsg != "configuration error\ntest message: original error" { 230 t.Errorf("Expected specific error format, got '%s'", errMsg) 231 } 232 }) 233 234 t.Run("is detectable with IsConfigError", func(t *testing.T) { 235 originalErr := errors.New("original error") 236 configErr := ConfigError("test message", originalErr) 237 238 if !IsConfigError(configErr) { 239 t.Error("Expected IsConfigError to return true") 240 } 241 }) 242 243 t.Run("wraps original error", func(t *testing.T) { 244 originalErr := errors.New("original error") 245 configErr := ConfigError("test message", originalErr) 246 247 if !errors.Is(configErr, originalErr) { 248 t.Error("Expected config error to wrap original error") 249 } 250 }) 251} 252 253func TestIsConfigError(t *testing.T) { 254 t.Run("returns true for config error", func(t *testing.T) { 255 configErr := ConfigError("test", errors.New("inner")) 256 257 if !IsConfigError(configErr) { 258 t.Error("Expected IsConfigError to return true for config error") 259 } 260 }) 261 262 t.Run("returns false for non-config error", func(t *testing.T) { 263 regularErr := errors.New("regular error") 264 265 if IsConfigError(regularErr) { 266 t.Error("Expected IsConfigError to return false for regular error") 267 } 268 }) 269 270 t.Run("returns false for nil error", func(t *testing.T) { 271 if IsConfigError(nil) { 272 t.Error("Expected IsConfigError to return false for nil error") 273 } 274 }) 275} 276 277type errorWriter struct { 278 err error 279} 280 281func (w *errorWriter) Write(p []byte) (int, error) { 282 return 0, w.err 283} 284 285type nopCloser struct { 286 io.Writer 287} 288 289func (nc *nopCloser) Close() error { 290 return nil 291}