github.com/tilt-dev/tilt@v0.36.0/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 {Text: " fe │ layer 1: pending\n", SpanID: "fe", ManifestName: "fe", ProgressID: "layer 1", Time: now}, 456 {Text: " fe │ layer 2: pending\n", SpanID: "fe", ManifestName: "fe", ProgressID: "layer 2", Time: now}, 457 {Text: " be │ layer 1: pending\n", SpanID: "be", ManifestName: "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 { 472 Text: " fe │ layer 1: done\n", 473 SpanID: "fe", 474 ManifestName: "fe", 475 ProgressID: "layer 1", 476 ProgressMustPrint: true, 477 Time: now, 478 }, 479 }, l.ContinuingLines(c2)) 480 } 481 482 func TestContinuingLinesWithOptionsSuppressPrefix(t *testing.T) { 483 l := NewLogStore() 484 c1 := l.Checkpoint() 485 486 now := time.Now() 487 l.Append(testLogEvent{ 488 name: "fe", 489 message: "layer 1: pending\n", 490 ts: now, 491 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 492 }, nil) 493 l.Append(testLogEvent{ 494 name: "fe", 495 message: "layer 2: pending\n", 496 ts: now, 497 fields: map[string]string{logger.FieldNameProgressID: "layer 2"}, 498 }, nil) 499 500 assert.Equal(t, []LogLine{ 501 {Text: "layer 1: pending\n", SpanID: "fe", ManifestName: "fe", ProgressID: "layer 1", Time: now}, 502 {Text: "layer 2: pending\n", SpanID: "fe", ManifestName: "fe", ProgressID: "layer 2", Time: now}, 503 }, l.ContinuingLinesWithOptions(c1, LineOptions{SuppressPrefix: true})) 504 } 505 506 func TestContinuingLinesWithOptionsSpans(t *testing.T) { 507 l := NewLogStore() 508 c1 := l.Checkpoint() 509 510 now := time.Now() 511 l.Append(testLogEvent{ 512 name: "foo", 513 message: "layer 1: pending\n", 514 ts: now, 515 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 516 }, nil) 517 l.Append(testLogEvent{ 518 name: "foo", 519 message: "layer 2: pending\n", 520 ts: now, 521 fields: map[string]string{logger.FieldNameProgressID: "layer 2"}, 522 }, nil) 523 l.Append(testLogEvent{ 524 name: "bar", 525 message: "layer 1: pending\n", 526 ts: now, 527 fields: map[string]string{logger.FieldNameProgressID: "layer 1"}, 528 }, nil) 529 530 assert.Equal(t, []LogLine{ 531 {Text: " foo │ layer 1: pending\n", SpanID: "foo", ManifestName: "foo", ProgressID: "layer 1", Time: now}, 532 {Text: " foo │ layer 2: pending\n", SpanID: "foo", ManifestName: "foo", ProgressID: "layer 2", Time: now}, 533 }, l.ContinuingLinesWithOptions(c1, lineOptionsWithManifests("foo"))) 534 } 535 536 func TestBuildEventInit(t *testing.T) { 537 l := NewLogStore() 538 539 now := time.Now() 540 l.Append(testLogEvent{ 541 name: "", 542 message: "starting tilt\n", 543 ts: now, 544 }, nil) 545 l.Append(testLogEvent{ 546 name: "fe", 547 message: "init fe build\n", 548 ts: now, 549 fields: map[string]string{logger.FieldNameBuildEvent: "init"}, 550 }, nil) 551 l.Append(testLogEvent{ 552 name: "db", 553 message: "init db build\n", 554 ts: now, 555 fields: map[string]string{logger.FieldNameBuildEvent: "init"}, 556 }, nil) 557 558 assert.Equal(t, 5, len(l.toLogLines(logOptions{spans: l.spans}))) 559 560 assertSnapshot(t, l.String()) 561 } 562 563 func assertSnapshot(t *testing.T, output string) { 564 d1 := []byte(output) 565 gmPath := fmt.Sprintf("testdata/%s_master", t.Name()) 566 if LogstoreWriteGoldenMaster == "1" { 567 err := os.WriteFile(gmPath, d1, 0644) 568 if err != nil { 569 t.Fatal(err) 570 } 571 } 572 expected, err := os.ReadFile(gmPath) 573 if err != nil { 574 t.Fatal(err) 575 } 576 577 assert.Equal(t, string(expected), output) 578 } 579 580 func lineOptionsWithManifests(mns ...model.ManifestName) LineOptions { 581 mnSet := make(model.ManifestNameSet) 582 for _, mn := range mns { 583 mnSet[mn] = true 584 } 585 return LineOptions{ManifestNames: mnSet} 586 }