github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/pkg/model/logstore/logstore_test.go (about) 1 package logstore 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12 13 "github.com/tilt-dev/tilt/pkg/logger" 14 "github.com/tilt-dev/tilt/pkg/model" 15 ) 16 17 // NOTE(dmiller): set at runtime with: 18 // go test -ldflags="-X 'github.com/tilt-dev/tilt/pkg/model/logstore.LogstoreWriteGoldenMaster=1'" ./pkg/model/logstore 19 var LogstoreWriteGoldenMaster = "0" 20 21 func TestLog_AppendUnderLimit(t *testing.T) { 22 l := NewLogStore() 23 l.Append(newGlobalTestLogEvent("foo"), nil) 24 l.Append(newGlobalTestLogEvent("bar"), nil) 25 assert.Equal(t, "foobar", l.String()) 26 } 27 28 func TestAppendDifferentLevels(t *testing.T) { 29 l := NewLogStore() 30 l.Append(newGlobalLevelTestLogEvent("foo", logger.InfoLvl), nil) 31 l.Append(newGlobalLevelTestLogEvent("bar", logger.DebugLvl), nil) 32 l.Append(newGlobalLevelTestLogEvent("baz", logger.InfoLvl), nil) 33 assert.Equal(t, "foo\nbar\nbaz", l.String()) 34 } 35 36 func TestAppendDifferentLevelsMultiLines(t *testing.T) { 37 l := NewLogStore() 38 l.Append(newGlobalTestLogEvent("hello ... "), nil) 39 l.Append(newGlobalLevelTestLogEvent("foobar", logger.DebugLvl), nil) 40 l.Append(newGlobalTestLogEvent("world\nnext line of global log"), nil) 41 assert.Equal(t, "hello ... \nfoobar\nworld\nnext line of global log", l.String()) 42 43 l.recomputeDerivedValues() 44 assert.Equal(t, "hello ... \nfoobar\nworld\nnext line of global log", l.String()) 45 } 46 47 func TestLog_AppendOverLimit(t *testing.T) { 48 l := NewLogStore() 49 l.maxLogLengthInBytes = 32 50 51 l.Append(newGlobalTestLogEvent("hello\n"), nil) 52 sb := strings.Builder{} 53 for i := 0; i < l.maxLogLengthInBytes/2; i++ { 54 _, err := sb.WriteString("x\n") 55 if err != nil { 56 t.Fatalf("error in %T.WriteString: %+v", sb, err) 57 } 58 } 59 60 s := sb.String() 61 l.Append(newGlobalTestLogEvent(s), nil) 62 assert.Equal(t, "x\nx\nx\nx\nx\nx\nx\nx\n", l.String()) 63 } 64 65 func TestLog_TruncateChattySpansFirst(t *testing.T) { 66 l := NewLogStore() 67 l.maxLogLengthInBytes = 100 68 69 l.Append(newTestLogEvent("(tiltfile)", time.Now(), "Tiltfile Success"), nil) 70 for i := 0; i < 40; i++ { 71 l.Append(newTestLogEvent("noisy", time.Now(), "Noisy Log\n"), nil) 72 } 73 74 assert.Contains(t, l.String(), "Tiltfile Success") 75 } 76 77 func TestLog_ChattyServicesDoNotTruncateTests(t *testing.T) { 78 if runtime.GOOS == "windows" { 79 t.Skip() // Windows has slightly different line-endings which effect this test 80 } 81 l := NewLogStore() 82 l.maxLogLengthInBytes = 500 83 84 l.Append(newTestLogEvent("(tiltfile)", time.Now(), "Tiltfile Success"), nil) 85 for i := 0; i < 100; i++ { 86 l.Append(newTestLogEvent(model.ManifestName(fmt.Sprintf("noisy%d", i%5)), time.Now(), "Noisy Log\n"), nil) 87 } 88 89 for i := 0; i < 5; i++ { 90 l.Append(newTestLogEvent("test", time.Now(), fmt.Sprintf("test #%d success\n", i)), nil) 91 } 92 93 for i := 0; i < 20; i++ { 94 l.Append(newTestLogEvent(model.ManifestName(fmt.Sprintf("noisy%d", i%5)), time.Now(), "Noisy Log\n"), nil) 95 } 96 97 assert.Contains(t, l.String(), "Tiltfile Success") 98 assert.Contains(t, l.String(), "test #0 success") 99 } 100 101 func TestLogPrefix(t *testing.T) { 102 l := NewLogStore() 103 l.Append(newGlobalTestLogEvent("hello\n"), nil) 104 l.Append(newTestLogEvent("prefix", time.Now(), "bar\nbaz\n"), nil) 105 106 assertSnapshot(t, l.String()) 107 } 108 109 // Assert that when logs come from two different sources, they get interleaved correctly. 110 func TestLogInterleaving(t *testing.T) { 111 l := NewLogStore() 112 l.Append(newGlobalTestLogEvent("hello ... "), nil) 113 l.Append(newTestLogEvent("prefix", time.Now(), "START LONG MESSAGE\ngoodbye ... "), nil) 114 l.Append(newGlobalTestLogEvent("world\nnext line of global log"), nil) 115 l.Append(newTestLogEvent("prefix", time.Now(), "world\nEND LONG MESSAGE"), nil) 116 117 assertSnapshot(t, l.String()) 118 } 119 120 func TestScrubSecret(t *testing.T) { 121 l := NewLogStore() 122 secretSet := model.SecretSet{} 123 secretSet.AddSecret("my-secret", "client-id", []byte("secret")) 124 l.Append(newGlobalTestLogEvent("hello\nsecret-time!\nc2VjcmV0-time!\ngoodbye"), secretSet) 125 assert.Equal(t, `hello 126 [redacted secret my-secret:client-id]-time! 127 [redacted secret my-secret:client-id]-time! 128 goodbye`, l.String()) 129 } 130 131 func TestLogTail(t *testing.T) { 132 l := NewLogStore() 133 l.Append(newGlobalTestLogEvent("1\n2\n3\n4\n5\n"), nil) 134 assert.Equal(t, "", l.Tail(0)) 135 assert.Equal(t, "5\n", l.Tail(1)) 136 assert.Equal(t, "4\n5\n", l.Tail(2)) 137 assert.Equal(t, "3\n4\n5\n", l.Tail(3)) 138 assert.Equal(t, "2\n3\n4\n5\n", l.Tail(4)) 139 assert.Equal(t, "1\n2\n3\n4\n5\n", l.Tail(5)) 140 assert.Equal(t, "1\n2\n3\n4\n5\n", l.Tail(6)) 141 } 142 143 func TestLogTailPrefixes(t *testing.T) { 144 l := NewLogStore() 145 l.Append(newGlobalTestLogEvent("1\n2\n"), nil) 146 l.Append(newTestLogEvent("fe", time.Now(), "3\n4\n"), nil) 147 l.Append(newGlobalTestLogEvent("5\n"), nil) 148 assert.Equal(t, "", l.Tail(0)) 149 assert.Equal(t, "5\n", l.Tail(1)) 150 assert.Equal(t, " fe │ 4\n5\n", l.Tail(2)) 151 assert.Equal(t, " fe │ 3\n fe │ 4\n5\n", l.Tail(3)) 152 assert.Equal(t, "2\n fe │ 3\n fe │ 4\n5\n", l.Tail(4)) 153 assert.Equal(t, "1\n2\n fe │ 3\n fe │ 4\n5\n", l.Tail(5)) 154 assert.Equal(t, "1\n2\n fe │ 3\n fe │ 4\n5\n", l.Tail(6)) 155 } 156 157 func TestLogTailSpan(t *testing.T) { 158 l := NewLogStore() 159 l.Append(newGlobalTestLogEvent("1\n2\n"), nil) 160 l.Append(newTestLogEvent("fe", time.Now(), "3\n4\n"), nil) 161 l.Append(newGlobalTestLogEvent("5\n"), nil) 162 assert.Equal(t, "5\n", l.TailSpan(1, "")) 163 assert.Equal(t, "2\n5\n", l.TailSpan(2, "")) 164 assert.Equal(t, "1\n2\n5\n", l.TailSpan(3, "")) 165 assert.Equal(t, "4\n", l.TailSpan(1, "fe")) 166 assert.Equal(t, "3\n4\n", l.TailSpan(2, "fe")) 167 assert.Equal(t, "3\n4\n", l.TailSpan(3, "fe")) 168 assert.Equal(t, "3\n4\n", l.TailSpan(30, "fe")) 169 } 170 171 func TestLogTailParts(t *testing.T) { 172 l := NewLogStore() 173 l.Append(newGlobalTestLogEvent("a"), nil) 174 l.Append(newTestLogEvent("fe", time.Now(), "xy"), nil) 175 l.Append(newGlobalTestLogEvent("bc\n"), nil) 176 l.Append(newTestLogEvent("fe", time.Now(), "z\n"), nil) 177 assert.Equal(t, " fe │ xyz\n", l.Tail(1)) 178 assert.Equal(t, "abc\n fe │ xyz\n", l.Tail(2)) 179 } 180 181 func TestContinuingString(t *testing.T) { 182 l := NewLogStore() 183 184 c1 := l.Checkpoint() 185 assert.Equal(t, "", l.ContinuingString(c1)) 186 187 l.Append(newGlobalTestLogEvent("foo"), nil) 188 c2 := l.Checkpoint() 189 assert.Equal(t, "foo", l.ContinuingString(c1)) 190 191 l.Append(newGlobalTestLogEvent("bar\n"), nil) 192 assert.Equal(t, "foobar\n", l.ContinuingString(c1)) 193 assert.Equal(t, "bar\n", l.ContinuingString(c2)) 194 } 195 196 func TestContinuingStringOneSource(t *testing.T) { 197 l := NewLogStore() 198 199 c1 := l.Checkpoint() 200 assert.Equal(t, "", l.ContinuingString(c1)) 201 202 l.Append(newTestLogEvent("fe", time.Now(), "foo"), nil) 203 c2 := l.Checkpoint() 204 assert.Equal(t, " fe │ foo", l.ContinuingString(c1)) 205 206 l.Append(newTestLogEvent("fe", time.Now(), "bar\n"), nil) 207 assert.Equal(t, " fe │ foobar\n", l.ContinuingString(c1)) 208 assert.Equal(t, "bar\n", l.ContinuingString(c2)) 209 } 210 211 func TestContinuingStringTwoSources(t *testing.T) { 212 l := NewLogStore() 213 214 c1 := l.Checkpoint() 215 216 l.Append(newGlobalTestLogEvent("a"), nil) 217 c2 := l.Checkpoint() 218 assert.Equal(t, "a", l.ContinuingString(c1)) 219 220 l.Append(newTestLogEvent("fe", time.Now(), "xy"), nil) 221 c3 := l.Checkpoint() 222 assert.Equal(t, "a\n fe │ xy", l.ContinuingString(c1)) 223 assert.Equal(t, "\n fe │ xy", l.ContinuingString(c2)) 224 225 l.Append(newGlobalTestLogEvent("bc\n"), nil) 226 c4 := l.Checkpoint() 227 assert.Equal(t, "abc\n fe │ xy", l.ContinuingString(c1)) 228 assert.Equal(t, "\n fe │ xy\nbc\n", l.ContinuingString(c2)) 229 assert.Equal(t, "\nbc\n", l.ContinuingString(c3)) 230 231 l.Append(newTestLogEvent("fe", time.Now(), "z\n"), nil) 232 assert.Equal(t, "abc\n fe │ xyz\n", l.ContinuingString(c1)) 233 assert.Equal(t, "\n fe │ xyz\nbc\n", l.ContinuingString(c2)) 234 assert.Equal(t, "\nbc\n fe │ z\n", l.ContinuingString(c3)) 235 assert.Equal(t, " fe │ z\n", l.ContinuingString(c4)) 236 } 237 238 func TestContinuingStringNextSpanFiltered(t *testing.T) { 239 l := NewLogStore() 240 opts := lineOptionsWithManifests("foo") 241 242 c1 := l.Checkpoint() 243 l.Append(newTestLogEvent("foo", time.Now(), "hello "), nil) 244 assert.Equal(t, " foo │ hello ", l.ContinuingStringWithOptions(c1, opts)) 245 246 c2 := l.Checkpoint() 247 l.Append(newTestLogEvent("bar", time.Now(), "INTERRUPTING COW!\n"), nil) 248 l.Append(newTestLogEvent("foo", time.Now(), "world\n"), nil) 249 assert.Equal(t, " foo │ hello world\n", l.ContinuingStringWithOptions(c1, opts)) 250 assert.Equal(t, "world\n", l.ContinuingStringWithOptions(c2, opts)) 251 } 252 253 func TestContinuingStringProceedingSpanFiltered(t *testing.T) { 254 l := NewLogStore() 255 opts := lineOptionsWithManifests("foo") 256 257 c1 := l.Checkpoint() 258 l.Append(newTestLogEvent("foo", time.Now(), "hello "), nil) 259 l.Append(newTestLogEvent("bar", time.Now(), "INTERRUPTING COW!\n"), nil) 260 assert.Equal(t, " foo │ hello ", l.ContinuingStringWithOptions(c1, opts)) 261 262 c2 := l.Checkpoint() 263 l.Append(newTestLogEvent("foo", time.Now(), "world\n"), nil) 264 assert.Equal(t, " foo │ hello world\n", l.ContinuingStringWithOptions(c1, opts)) 265 assert.Equal(t, "world\n", l.ContinuingStringWithOptions(c2, opts)) 266 } 267 268 func TestContinuingStringProceedingAndNextSpanFiltered(t *testing.T) { 269 l := NewLogStore() 270 opts := lineOptionsWithManifests("foo") 271 272 c1 := l.Checkpoint() 273 l.Append(newTestLogEvent("foo", time.Now(), "hello "), nil) 274 l.Append(newTestLogEvent("bar", time.Now(), "INTERRUPTING COW!\n"), nil) 275 assert.Equal(t, " foo │ hello ", l.ContinuingStringWithOptions(c1, opts)) 276 277 c2 := l.Checkpoint() 278 l.Append(newTestLogEvent("bar", time.Now(), "INTERRUPTING COW!\n"), nil) 279 l.Append(newTestLogEvent("foo", time.Now(), "world\n"), nil) 280 assert.Equal(t, " foo │ hello world\n", l.ContinuingStringWithOptions(c1, opts)) 281 assert.Equal(t, "world\n", l.ContinuingStringWithOptions(c2, opts)) 282 } 283 284 func TestContinuingStringAfterLimit(t *testing.T) { 285 l := NewLogStore() 286 l.maxLogLengthInBytes = 20 287 288 c1 := l.Checkpoint() 289 assert.Equal(t, "", l.ContinuingString(c1)) 290 291 l.Append(newGlobalTestLogEvent("123456789\n"), nil) 292 c2 := l.Checkpoint() 293 assert.Equal(t, "123456789\n", l.String()) 294 assert.Equal(t, "123456789\n", l.ContinuingString(c1)) 295 296 l.Append(newGlobalTestLogEvent("abcdefghi\n"), nil) 297 c3 := l.Checkpoint() 298 assert.Equal(t, "123456789\nabcdefghi\n", l.String()) 299 assert.Equal(t, "123456789\nabcdefghi\n", l.ContinuingString(c1)) 300 assert.Equal(t, "abcdefghi\n", l.ContinuingString(c2)) 301 302 l.Append(newGlobalTestLogEvent("jklmnopqr\n"), nil) 303 assert.Equal(t, "jklmnopqr\n", l.String()) 304 assert.Equal(t, "jklmnopqr\n", l.ContinuingString(c1)) 305 assert.Equal(t, "jklmnopqr\n", l.ContinuingString(c2)) 306 assert.Equal(t, "jklmnopqr\n", l.ContinuingString(c3)) 307 } 308 309 func TestManifestLog(t *testing.T) { 310 l := NewLogStore() 311 l.Append(newGlobalTestLogEvent("1\n2\n"), nil) 312 l.Append(newTestLogEvent("fe", time.Now(), "3\n4\n"), nil) 313 l.Append(newGlobalTestLogEvent("5\n6\n"), nil) 314 l.Append(newTestLogEvent("fe", time.Now(), "7\n8\n"), nil) 315 l.Append(newTestLogEvent("back", time.Now(), "a\nb\n"), nil) 316 l.Append(newGlobalTestLogEvent("5\n6\n"), nil) 317 assert.Equal(t, "3\n4\n7\n8\n", l.ManifestLog("fe")) 318 assert.Equal(t, "a\nb\n", l.ManifestLog("back")) 319 } 320 321 func TestManifestLogContinuation(t *testing.T) { 322 l := NewLogStore() 323 l.Append(newGlobalTestLogEvent("1\n2\n"), nil) 324 l.Append(newTestLogEvent("fe", time.Now(), "34"), nil) 325 l.Append(newGlobalTestLogEvent("5\n6\n"), nil) 326 l.Append(newTestLogEvent("fe", time.Now(), "78"), nil) 327 l.Append(newTestLogEvent("back", time.Now(), "ab"), nil) 328 l.Append(newGlobalTestLogEvent("5\n6\n"), nil) 329 assert.Equal(t, "3478", l.ManifestLog("fe")) 330 assert.Equal(t, "ab", l.ManifestLog("back")) 331 assert.Equal(t, "1\n2\n fe │ 3478\n5\n6\n back │ ab\n5\n6\n", l.String()) 332 } 333 334 func TestLogIncremental(t *testing.T) { 335 l := NewLogStore() 336 l.Append(newGlobalTestLogEvent("line1\n"), nil) 337 l.Append(newGlobalTestLogEvent("line2\n"), nil) 338 l.Append(newGlobalTestLogEvent("line3\n"), nil) 339 340 list, err := l.ToLogList(0) 341 assert.NoError(t, err) 342 assert.Equal(t, 3, len(list.Segments)) 343 assert.Equal(t, int32(0), list.FromCheckpoint) 344 assert.Equal(t, int32(3), list.ToCheckpoint) 345 346 list, err = l.ToLogList(1) 347 assert.NoError(t, err) 348 assert.Equal(t, 2, len(list.Segments)) 349 assert.Equal(t, int32(1), list.FromCheckpoint) 350 assert.Equal(t, int32(3), list.ToCheckpoint) 351 352 list, err = l.ToLogList(3) 353 assert.NoError(t, err) 354 assert.Equal(t, 0, len(list.Segments)) 355 assert.Equal(t, int32(-1), list.FromCheckpoint) 356 assert.Equal(t, int32(-1), list.ToCheckpoint) 357 358 list, err = l.ToLogList(10) 359 assert.NoError(t, err) 360 assert.Equal(t, 0, len(list.Segments)) 361 assert.Equal(t, int32(-1), list.FromCheckpoint) 362 assert.Equal(t, int32(-1), list.ToCheckpoint) 363 } 364 365 func TestWarnings(t *testing.T) { 366 l := NewLogStore() 367 l.Append(testLogEvent{ 368 name: "fe", 369 level: logger.WarnLvl, 370 message: "Warning 1 line 1\nWarning 1 line 2\nWarning 1 line 3\n", 371 }, nil) 372 l.Append(testLogEvent{ 373 name: "fe", 374 level: logger.WarnLvl, 375 message: "Warning 2 line 1\nWarning 2 line 2\n", 376 }, nil) 377 l.Append(testLogEvent{ 378 name: "fe", 379 level: logger.WarnLvl, 380 message: "Warning 3 line 1\n", 381 }, nil) 382 l.Append(testLogEvent{ 383 name: "non-fe", 384 level: logger.WarnLvl, 385 message: "non-fe warning\n", 386 }, nil) 387 388 warnings := l.Warnings("fe") 389 assert.Equal(t, warnings, []string{ 390 "Warning 1 line 1\nWarning 1 line 2\nWarning 1 line 3\n", 391 "Warning 2 line 1\nWarning 2 line 2\n", 392 "Warning 3 line 1\n", 393 }) 394 395 assertSnapshot(t, l.String()) 396 } 397 398 func TestErrors(t *testing.T) { 399 l := NewLogStore() 400 l.Append(testLogEvent{ 401 name: "fe", 402 level: logger.ErrorLvl, 403 message: "Error 1 line 1\nError 1 line 2\nError 1 line 3\n", 404 }, nil) 405 l.Append(testLogEvent{ 406 name: "fe", 407 level: logger.ErrorLvl, 408 message: "Error 2 line 1\nError 2 line 2\n", 409 }, nil) 410 l.Append(testLogEvent{ 411 name: "fe", 412 level: logger.ErrorLvl, 413 message: "Error 3 line 1\n", 414 }, nil) 415 l.Append(testLogEvent{ 416 name: "non-fe", 417 level: logger.ErrorLvl, 418 message: "non-fe warning\n", 419 }, nil) 420 421 assertSnapshot(t, l.String()) 422 } 423 424 func TestContinuingLines(t *testing.T) { 425 l := NewLogStore() 426 c1 := l.Checkpoint() 427 428 now := time.Now() 429 l.Append(testLogEvent{ 430 name: "fe", 431 message: "layer 1: pending\n", 432 ts: now, 433 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 434 }, nil) 435 l.Append(testLogEvent{ 436 name: "fe", 437 message: "layer 2: pending\n", 438 ts: now, 439 fields: map[string]string{logger.FieldNameProgressID: "layer 2"}, 440 }, nil) 441 l.Append(testLogEvent{ 442 name: "be", 443 message: "layer 1: pending\n", 444 ts: now, 445 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 446 }, nil) 447 448 assert.Equal(t, ` fe │ layer 1: pending 449 fe │ layer 2: pending 450 be │ layer 1: pending 451 `, l.ContinuingString(c1)) 452 453 c2 := l.Checkpoint() 454 assert.Equal(t, []LogLine{ 455 LogLine{Text: " fe │ layer 1: pending\n", SpanID: "fe", ProgressID: "layer 1", Time: now}, 456 LogLine{Text: " fe │ layer 2: pending\n", SpanID: "fe", ProgressID: "layer 2", Time: now}, 457 LogLine{Text: " be │ layer 1: pending\n", SpanID: "be", ProgressID: "layer 1", Time: now}, 458 }, l.ContinuingLines(c1)) 459 460 l.Append(testLogEvent{ 461 name: "fe", 462 message: "layer 1: done\n", 463 ts: now, 464 fields: map[string]string{ 465 logger.FieldNameProgressID: "layer 1", 466 logger.FieldNameProgressMustPrint: "1", 467 }, 468 }, nil) 469 470 assert.Equal(t, []LogLine{ 471 LogLine{ 472 Text: " fe │ layer 1: done\n", 473 SpanID: "fe", 474 ProgressID: "layer 1", 475 ProgressMustPrint: true, 476 Time: now, 477 }, 478 }, l.ContinuingLines(c2)) 479 } 480 481 func TestContinuingLinesWithOptionsSuppressPrefix(t *testing.T) { 482 l := NewLogStore() 483 c1 := l.Checkpoint() 484 485 now := time.Now() 486 l.Append(testLogEvent{ 487 name: "fe", 488 message: "layer 1: pending\n", 489 ts: now, 490 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 491 }, nil) 492 l.Append(testLogEvent{ 493 name: "fe", 494 message: "layer 2: pending\n", 495 ts: now, 496 fields: map[string]string{logger.FieldNameProgressID: "layer 2"}, 497 }, nil) 498 499 assert.Equal(t, []LogLine{ 500 LogLine{Text: "layer 1: pending\n", SpanID: "fe", ProgressID: "layer 1", Time: now}, 501 LogLine{Text: "layer 2: pending\n", SpanID: "fe", ProgressID: "layer 2", Time: now}, 502 }, l.ContinuingLinesWithOptions(c1, LineOptions{SuppressPrefix: true})) 503 } 504 505 func TestContinuingLinesWithOptionsSpans(t *testing.T) { 506 l := NewLogStore() 507 c1 := l.Checkpoint() 508 509 now := time.Now() 510 l.Append(testLogEvent{ 511 name: "foo", 512 message: "layer 1: pending\n", 513 ts: now, 514 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 515 }, nil) 516 l.Append(testLogEvent{ 517 name: "foo", 518 message: "layer 2: pending\n", 519 ts: now, 520 fields: map[string]string{logger.FieldNameProgressID: "layer 2"}, 521 }, nil) 522 l.Append(testLogEvent{ 523 name: "bar", 524 message: "layer 1: pending\n", 525 ts: now, 526 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 527 }, nil) 528 529 assert.Equal(t, []LogLine{ 530 LogLine{Text: " foo │ layer 1: pending\n", SpanID: "foo", ProgressID: "layer 1", Time: now}, 531 LogLine{Text: " foo │ layer 2: pending\n", SpanID: "foo", ProgressID: "layer 2", Time: now}, 532 }, l.ContinuingLinesWithOptions(c1, lineOptionsWithManifests("foo"))) 533 } 534 535 func TestBuildEventInit(t *testing.T) { 536 l := NewLogStore() 537 538 now := time.Now() 539 l.Append(testLogEvent{ 540 name: "", 541 message: "starting tilt\n", 542 ts: now, 543 }, nil) 544 l.Append(testLogEvent{ 545 name: "fe", 546 message: "init fe build\n", 547 ts: now, 548 fields: map[string]string{logger.FieldNameBuildEvent: "init"}, 549 }, nil) 550 l.Append(testLogEvent{ 551 name: "db", 552 message: "init db build\n", 553 ts: now, 554 fields: map[string]string{logger.FieldNameBuildEvent: "init"}, 555 }, nil) 556 557 assert.Equal(t, 5, len(l.toLogLines(logOptions{spans: l.spans}))) 558 559 assertSnapshot(t, l.String()) 560 } 561 562 func assertSnapshot(t *testing.T, output string) { 563 d1 := []byte(output) 564 gmPath := fmt.Sprintf("testdata/%s_master", t.Name()) 565 if LogstoreWriteGoldenMaster == "1" { 566 err := os.WriteFile(gmPath, d1, 0644) 567 if err != nil { 568 t.Fatal(err) 569 } 570 } 571 expected, err := os.ReadFile(gmPath) 572 if err != nil { 573 t.Fatal(err) 574 } 575 576 assert.Equal(t, string(expected), output) 577 } 578 579 func lineOptionsWithManifests(mns ...model.ManifestName) LineOptions { 580 mnSet := make(model.ManifestNameSet) 581 for _, mn := range mns { 582 mnSet[mn] = true 583 } 584 return LineOptions{ManifestNames: mnSet} 585 }