go.fuchsia.dev/jiri@v0.0.0-20240502161911-b66513b29486/timing/timer_test.go (about) 1 // Copyright 2015 The Vanadium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package timing 6 7 import ( 8 "bytes" 9 "fmt" 10 "math/rand" 11 "reflect" 12 "strings" 13 "testing" 14 "time" 15 ) 16 17 func sec(d int) time.Duration { 18 return time.Second * time.Duration(d) 19 } 20 21 func tsec(d int) time.Time { 22 return time.Time{}.Add(sec(d)) 23 } 24 25 // fakeNow is a simulated clock where now is set manually. 26 type fakeNow struct{ now int } 27 28 func (f *fakeNow) Now() time.Time { return tsec(f.now) } 29 30 // stepNow is a simulated clock where now increments in 1 second steps. 31 type stepNow struct{ now int } 32 33 func (s *stepNow) Now() time.Time { 34 s.now++ 35 return tsec(s.now) 36 } 37 38 type ( 39 // op represents the operations that can be performed on a Timer, with a fake 40 // clock. This makes it easy to construct test cases. 41 op interface { 42 run(f *fakeNow, t *Timer) 43 } 44 push struct { 45 now int 46 name string 47 } 48 pop struct { 49 now int 50 } 51 finish struct { 52 now int 53 } 54 ) 55 56 func (x push) run(f *fakeNow, t *Timer) { 57 f.now = x.now 58 t.Push(x.name) 59 } 60 func (x pop) run(f *fakeNow, t *Timer) { 61 f.now = x.now 62 t.Pop() 63 } 64 func (x finish) run(f *fakeNow, t *Timer) { 65 f.now = x.now 66 t.Finish() 67 } 68 69 // stripGaps strips out leading newlines, and also strips any line with an 70 // asterisk (*). Asterisks appear in lines with gaps, as shown here: 71 // 72 // 00:00:01.000 root 98.000s 00:01:39.000 73 // 00:00:01.000 * 9.000s 00:00:10.000 74 // 00:00:10.000 abc 89.000s 00:01:39.000 75 func stripGaps(out string) string { 76 out = strings.TrimLeft(out, "\n") 77 var lines []string 78 for _, line := range strings.Split(out, "\n") { 79 if !strings.ContainsRune(line, '*') { 80 lines = append(lines, line) 81 } 82 } 83 return strings.Join(lines, "\n") 84 } 85 86 func TestTimer(t *testing.T) { 87 t.Parallel() 88 tests := []struct { 89 ops []op 90 intervals []Interval 91 str string 92 }{ 93 { 94 nil, 95 []Interval{{"root", 0, sec(0), InvalidDuration}}, 96 ` 97 00:00:01.000 root 999.000s ---------now 98 `, 99 }, 100 { 101 []op{pop{123}}, 102 []Interval{{"root", 0, sec(0), InvalidDuration}}, 103 ` 104 00:00:01.000 root 999.000s ---------now 105 `, 106 }, 107 { 108 []op{finish{99}}, 109 []Interval{{"root", 0, sec(0), sec(98)}}, 110 ` 111 00:00:01.000 root 98.000s 00:01:39.000 112 `, 113 }, 114 { 115 []op{finish{99}, pop{123}}, 116 []Interval{{"root", 0, sec(0), sec(98)}}, 117 ` 118 00:00:01.000 root 98.000s 00:01:39.000 119 `, 120 }, 121 { 122 []op{push{10, "abc"}}, 123 []Interval{ 124 {"root", 0, sec(0), InvalidDuration}, 125 {"abc", 1, sec(9), InvalidDuration}, 126 }, 127 ` 128 00:00:01.000 root 999.000s ---------now 129 00:00:01.000 * 9.000s 00:00:10.000 130 00:00:10.000 abc 990.000s ---------now 131 `, 132 }, 133 { 134 []op{push{10, "abc"}, finish{99}}, 135 []Interval{ 136 {"root", 0, sec(0), sec(98)}, 137 {"abc", 1, sec(9), sec(98)}, 138 }, 139 ` 140 00:00:01.000 root 98.000s 00:01:39.000 141 00:00:01.000 * 9.000s 00:00:10.000 142 00:00:10.000 abc 89.000s 00:01:39.000 143 `, 144 }, 145 { 146 []op{push{10, "abc"}, pop{20}, finish{99}}, 147 []Interval{ 148 {"root", 0, sec(0), sec(98)}, 149 {"abc", 1, sec(9), sec(19)}, 150 }, 151 ` 152 00:00:01.000 root 98.000s 00:01:39.000 153 00:00:01.000 * 9.000s 00:00:10.000 154 00:00:10.000 abc 10.000s 00:00:20.000 155 00:00:20.000 * 79.000s 00:01:39.000 156 `, 157 }, 158 { 159 []op{push{10, "A1"}, push{20, "A1_1"}}, 160 []Interval{ 161 {"root", 0, sec(0), InvalidDuration}, 162 {"A1", 1, sec(9), InvalidDuration}, 163 {"A1_1", 2, sec(19), InvalidDuration}, 164 }, 165 ` 166 00:00:01.000 root 999.000s ---------now 167 00:00:01.000 * 9.000s 00:00:10.000 168 00:00:10.000 A1 990.000s ---------now 169 00:00:10.000 * 10.000s 00:00:20.000 170 00:00:20.000 A1_1 980.000s ---------now 171 `, 172 }, 173 { 174 []op{push{10, "A1"}, push{20, "A1_1"}, finish{99}}, 175 []Interval{ 176 {"root", 0, sec(0), sec(98)}, 177 {"A1", 1, sec(9), sec(98)}, 178 {"A1_1", 2, sec(19), sec(98)}, 179 }, 180 ` 181 00:00:01.000 root 98.000s 00:01:39.000 182 00:00:01.000 * 9.000s 00:00:10.000 183 00:00:10.000 A1 89.000s 00:01:39.000 184 00:00:10.000 * 10.000s 00:00:20.000 185 00:00:20.000 A1_1 79.000s 00:01:39.000 186 `, 187 }, 188 { 189 []op{push{10, "A1"}, push{20, "A1_1"}, pop{30}, finish{99}}, 190 []Interval{ 191 {"root", 0, sec(0), sec(98)}, 192 {"A1", 1, sec(9), sec(98)}, 193 {"A1_1", 2, sec(19), sec(29)}, 194 }, 195 ` 196 00:00:01.000 root 98.000s 00:01:39.000 197 00:00:01.000 * 9.000s 00:00:10.000 198 00:00:10.000 A1 89.000s 00:01:39.000 199 00:00:10.000 * 10.000s 00:00:20.000 200 00:00:20.000 A1_1 10.000s 00:00:30.000 201 00:00:30.000 * 69.000s 00:01:39.000 202 `, 203 }, 204 { 205 []op{push{10, "A1"}, push{20, "A1_1"}, pop{30}, pop{40}, finish{99}}, 206 []Interval{ 207 {"root", 0, sec(0), sec(98)}, 208 {"A1", 1, sec(9), sec(39)}, 209 {"A1_1", 2, sec(19), sec(29)}, 210 }, 211 ` 212 00:00:01.000 root 98.000s 00:01:39.000 213 00:00:01.000 * 9.000s 00:00:10.000 214 00:00:10.000 A1 30.000s 00:00:40.000 215 00:00:10.000 * 10.000s 00:00:20.000 216 00:00:20.000 A1_1 10.000s 00:00:30.000 217 00:00:30.000 * 10.000s 00:00:40.000 218 00:00:40.000 * 59.000s 00:01:39.000 219 `, 220 }, 221 { 222 []op{push{10, "A1"}, push{20, "A1_1"}, push{30, "A1_1_1"}}, 223 []Interval{ 224 {"root", 0, sec(0), InvalidDuration}, 225 {"A1", 1, sec(9), InvalidDuration}, 226 {"A1_1", 2, sec(19), InvalidDuration}, 227 {"A1_1_1", 3, sec(29), InvalidDuration}, 228 }, 229 ` 230 00:00:01.000 root 999.000s ---------now 231 00:00:01.000 * 9.000s 00:00:10.000 232 00:00:10.000 A1 990.000s ---------now 233 00:00:10.000 * 10.000s 00:00:20.000 234 00:00:20.000 A1_1 980.000s ---------now 235 00:00:20.000 * 10.000s 00:00:30.000 236 00:00:30.000 A1_1_1 970.000s ---------now 237 `, 238 }, 239 { 240 []op{push{10, "A1"}, push{20, "A1_1"}, push{30, "A1_1_1"}, finish{99}}, 241 []Interval{ 242 {"root", 0, sec(0), sec(98)}, 243 {"A1", 1, sec(9), sec(98)}, 244 {"A1_1", 2, sec(19), sec(98)}, 245 {"A1_1_1", 3, sec(29), sec(98)}, 246 }, 247 ` 248 00:00:01.000 root 98.000s 00:01:39.000 249 00:00:01.000 * 9.000s 00:00:10.000 250 00:00:10.000 A1 89.000s 00:01:39.000 251 00:00:10.000 * 10.000s 00:00:20.000 252 00:00:20.000 A1_1 79.000s 00:01:39.000 253 00:00:20.000 * 10.000s 00:00:30.000 254 00:00:30.000 A1_1_1 69.000s 00:01:39.000 255 `, 256 }, 257 { 258 []op{push{10, "A1"}, push{20, "A1_1"}, push{30, "A1_1_1"}, pop{40}, finish{99}}, 259 []Interval{ 260 {"root", 0, sec(0), sec(98)}, 261 {"A1", 1, sec(9), sec(98)}, 262 {"A1_1", 2, sec(19), sec(98)}, 263 {"A1_1_1", 3, sec(29), sec(39)}, 264 }, 265 ` 266 00:00:01.000 root 98.000s 00:01:39.000 267 00:00:01.000 * 9.000s 00:00:10.000 268 00:00:10.000 A1 89.000s 00:01:39.000 269 00:00:10.000 * 10.000s 00:00:20.000 270 00:00:20.000 A1_1 79.000s 00:01:39.000 271 00:00:20.000 * 10.000s 00:00:30.000 272 00:00:30.000 A1_1_1 10.000s 00:00:40.000 273 00:00:40.000 * 59.000s 00:01:39.000 274 `, 275 }, 276 { 277 []op{push{10, "A1"}, push{20, "A1_1"}, push{30, "A1_1_1"}, pop{40}, pop{55}, finish{99}}, 278 []Interval{ 279 {"root", 0, sec(0), sec(98)}, 280 {"A1", 1, sec(9), sec(98)}, 281 {"A1_1", 2, sec(19), sec(54)}, 282 {"A1_1_1", 3, sec(29), sec(39)}, 283 }, 284 ` 285 00:00:01.000 root 98.000s 00:01:39.000 286 00:00:01.000 * 9.000s 00:00:10.000 287 00:00:10.000 A1 89.000s 00:01:39.000 288 00:00:10.000 * 10.000s 00:00:20.000 289 00:00:20.000 A1_1 35.000s 00:00:55.000 290 00:00:20.000 * 10.000s 00:00:30.000 291 00:00:30.000 A1_1_1 10.000s 00:00:40.000 292 00:00:40.000 * 15.000s 00:00:55.000 293 00:00:55.000 * 44.000s 00:01:39.000 294 `, 295 }, 296 { 297 []op{push{10, "A1"}, push{20, "A1_1"}, push{30, "A1_1_1"}, pop{40}, pop{55}, pop{75}, finish{99}}, 298 []Interval{ 299 {"root", 0, sec(0), sec(98)}, 300 {"A1", 1, sec(9), sec(74)}, 301 {"A1_1", 2, sec(19), sec(54)}, 302 {"A1_1_1", 3, sec(29), sec(39)}, 303 }, 304 ` 305 00:00:01.000 root 98.000s 00:01:39.000 306 00:00:01.000 * 9.000s 00:00:10.000 307 00:00:10.000 A1 65.000s 00:01:15.000 308 00:00:10.000 * 10.000s 00:00:20.000 309 00:00:20.000 A1_1 35.000s 00:00:55.000 310 00:00:20.000 * 10.000s 00:00:30.000 311 00:00:30.000 A1_1_1 10.000s 00:00:40.000 312 00:00:40.000 * 15.000s 00:00:55.000 313 00:00:55.000 * 20.000s 00:01:15.000 314 00:01:15.000 * 24.000s 00:01:39.000 315 `, 316 }, 317 { 318 []op{push{10, "A1"}, push{20, "A1_1"}, finish{30}, push{40, "B1"}}, 319 []Interval{ 320 {"root", 0, sec(0), InvalidDuration}, 321 {"A1", 1, sec(9), sec(29)}, 322 {"A1_1", 2, sec(19), sec(29)}, 323 {"B1", 1, sec(39), InvalidDuration}, 324 }, 325 ` 326 00:00:01.000 root 999.000s ---------now 327 00:00:01.000 * 9.000s 00:00:10.000 328 00:00:10.000 A1 20.000s 00:00:30.000 329 00:00:10.000 * 10.000s 00:00:20.000 330 00:00:20.000 A1_1 10.000s 00:00:30.000 331 00:00:30.000 * 10.000s 00:00:40.000 332 00:00:40.000 B1 960.000s ---------now 333 `, 334 }, 335 { 336 []op{push{10, "A1"}, push{20, "A1_1"}, finish{30}, push{40, "B1"}, finish{99}}, 337 []Interval{ 338 {"root", 0, sec(0), sec(98)}, 339 {"A1", 1, sec(9), sec(29)}, 340 {"A1_1", 2, sec(19), sec(29)}, 341 {"B1", 1, sec(39), sec(98)}, 342 }, 343 ` 344 00:00:01.000 root 98.000s 00:01:39.000 345 00:00:01.000 * 9.000s 00:00:10.000 346 00:00:10.000 A1 20.000s 00:00:30.000 347 00:00:10.000 * 10.000s 00:00:20.000 348 00:00:20.000 A1_1 10.000s 00:00:30.000 349 00:00:30.000 * 10.000s 00:00:40.000 350 00:00:40.000 B1 59.000s 00:01:39.000 351 `, 352 }, 353 { 354 []op{push{10, "foo"}, push{15, "foo1"}, pop{37}, push{37, "foo2"}, pop{55}, pop{55}, push{55, "bar"}, pop{80}, push{80, "baz"}, pop{99}, finish{99}}, 355 []Interval{ 356 {"root", 0, sec(0), sec(98)}, 357 {"foo", 1, sec(9), sec(54)}, 358 {"foo1", 2, sec(14), sec(36)}, 359 {"foo2", 2, sec(36), sec(54)}, 360 {"bar", 1, sec(54), sec(79)}, 361 {"baz", 1, sec(79), sec(98)}, 362 }, 363 ` 364 00:00:01.000 root 98.000s 00:01:39.000 365 00:00:01.000 * 9.000s 00:00:10.000 366 00:00:10.000 foo 45.000s 00:00:55.000 367 00:00:10.000 * 5.000s 00:00:15.000 368 00:00:15.000 foo1 22.000s 00:00:37.000 369 00:00:37.000 foo2 18.000s 00:00:55.000 370 00:00:55.000 bar 25.000s 00:01:20.000 371 00:01:20.000 baz 19.000s 00:01:39.000 372 `, 373 }, 374 { 375 []op{push{10, "foo"}, push{15, "foo1"}, pop{30}, push{37, "foo2"}, pop{50}, pop{53}, push{55, "bar"}, pop{75}, push{80, "baz"}, pop{90}, finish{99}}, 376 []Interval{ 377 {"root", 0, sec(0), sec(98)}, 378 {"foo", 1, sec(9), sec(52)}, 379 {"foo1", 2, sec(14), sec(29)}, 380 {"foo2", 2, sec(36), sec(49)}, 381 {"bar", 1, sec(54), sec(74)}, 382 {"baz", 1, sec(79), sec(89)}, 383 }, 384 ` 385 00:00:01.000 root 98.000s 00:01:39.000 386 00:00:01.000 * 9.000s 00:00:10.000 387 00:00:10.000 foo 43.000s 00:00:53.000 388 00:00:10.000 * 5.000s 00:00:15.000 389 00:00:15.000 foo1 15.000s 00:00:30.000 390 00:00:30.000 * 7.000s 00:00:37.000 391 00:00:37.000 foo2 13.000s 00:00:50.000 392 00:00:50.000 * 3.000s 00:00:53.000 393 00:00:53.000 * 2.000s 00:00:55.000 394 00:00:55.000 bar 20.000s 00:01:15.000 395 00:01:15.000 * 5.000s 00:01:20.000 396 00:01:20.000 baz 10.000s 00:01:30.000 397 00:01:30.000 * 9.000s 00:01:39.000 398 `, 399 }, 400 } 401 for _, test := range tests { 402 // Run all ops. 403 now := &fakeNow{1} 404 nowFunc = now.Now 405 timer := NewTimer("root") 406 for _, op := range test.ops { 407 op.run(now, timer) 408 } 409 name := fmt.Sprintf("%#v", test.ops) 410 // Check all intervals. 411 if got, want := timer.Intervals, test.intervals; !reflect.DeepEqual(got, want) { 412 t.Errorf("%s got intervals %v, want %v", name, got, want) 413 } 414 // Check string output. 415 now.now = 1000 416 if got, want := timer.String(), strings.TrimLeft(test.str, "\n"); got != want { 417 t.Errorf("%s GOT STRING\n%sWANT\n%s", name, got, want) 418 } 419 // Check print output hiding all gaps. 420 var buf bytes.Buffer 421 printer := IntervalPrinter{Zero: timer.Zero, MinGap: time.Hour} 422 if err := printer.Print(&buf, timer.Intervals, nowFunc().Sub(timer.Zero)); err != nil { 423 t.Errorf("%s got printer error: %v", name, err) 424 } 425 if got, want := buf.String(), stripGaps(test.str); got != want { 426 t.Errorf("%s GOT PRINT\n%sWANT\n%s", name, got, want) 427 } 428 } 429 nowFunc = time.Now 430 } 431 432 // TestIntervalPrinterCornerCases tests corner cases for the printer. These are 433 // all cases where only a subset of the full Timer intervals is printed. 434 func TestIntervalPrinterCornerCases(t *testing.T) { 435 t.Parallel() 436 tests := []struct { 437 intervals []Interval 438 str string 439 }{ 440 { 441 []Interval{{"abc", 1, sec(9), InvalidDuration}}, 442 ` 443 00:00:01.000 * 9.000s 00:00:10.000 444 00:00:10.000 abc 990.000s ---------now 445 `, 446 }, 447 { 448 []Interval{{"abc", 1, sec(9), sec(98)}}, 449 ` 450 00:00:01.000 * 9.000s 00:00:10.000 451 00:00:10.000 abc 89.000s 00:01:39.000 452 `, 453 }, 454 { 455 []Interval{ 456 {"A1", 1, sec(9), InvalidDuration}, 457 {"A1_1", 2, sec(19), InvalidDuration}, 458 }, 459 ` 460 00:00:01.000 * 9.000s 00:00:10.000 461 00:00:10.000 A1 990.000s ---------now 462 00:00:10.000 * 10.000s 00:00:20.000 463 00:00:20.000 A1_1 980.000s ---------now 464 `, 465 }, 466 { 467 []Interval{ 468 {"A1", 1, sec(9), InvalidDuration}, 469 {"A1_1", 2, sec(19), sec(49)}, 470 }, 471 ` 472 00:00:01.000 * 9.000s 00:00:10.000 473 00:00:10.000 A1 990.000s ---------now 474 00:00:10.000 * 10.000s 00:00:20.000 475 00:00:20.000 A1_1 30.000s 00:00:50.000 476 00:00:50.000 * 950.000s ---------now 477 `, 478 }, 479 { 480 []Interval{ 481 {"A1", 1, sec(9), sec(98)}, 482 {"A1_1", 2, sec(19), sec(49)}, 483 }, 484 ` 485 00:00:01.000 * 9.000s 00:00:10.000 486 00:00:10.000 A1 89.000s 00:01:39.000 487 00:00:10.000 * 10.000s 00:00:20.000 488 00:00:20.000 A1_1 30.000s 00:00:50.000 489 00:00:50.000 * 49.000s 00:01:39.000 490 `, 491 }, 492 { 493 []Interval{ 494 {"A1_1", 2, sec(9), sec(19)}, 495 {"B1", 1, sec(39), InvalidDuration}, 496 }, 497 ` 498 00:00:01.000 * 9.000s 00:00:10.000 499 00:00:10.000 A1_1 10.000s 00:00:20.000 500 00:00:20.000 * 20.000s 00:00:40.000 501 00:00:40.000 B1 960.000s ---------now 502 `, 503 }, 504 { 505 []Interval{ 506 {"A1_1", 2, sec(9), sec(19)}, 507 {"B1", 1, sec(39), sec(64)}, 508 }, 509 ` 510 00:00:01.000 * 9.000s 00:00:10.000 511 00:00:10.000 A1_1 10.000s 00:00:20.000 512 00:00:20.000 * 20.000s 00:00:40.000 513 00:00:40.000 B1 25.000s 00:01:05.000 514 `, 515 }, 516 { 517 []Interval{ 518 {"A1_1", 2, sec(9), sec(19)}, 519 {"B1", 1, sec(39), sec(64)}, 520 {"C1", 1, sec(69), sec(84)}, 521 }, 522 ` 523 00:00:01.000 * 9.000s 00:00:10.000 524 00:00:10.000 A1_1 10.000s 00:00:20.000 525 00:00:20.000 * 20.000s 00:00:40.000 526 00:00:40.000 B1 25.000s 00:01:05.000 527 00:01:05.000 * 5.000s 00:01:10.000 528 00:01:10.000 C1 15.000s 00:01:25.000 529 `, 530 }, 531 { 532 []Interval{ 533 {"A1_1", 2, sec(9), sec(19)}, 534 {"B1", 1, sec(39), sec(84)}, 535 {"B1_1", 2, sec(64), sec(69)}, 536 }, 537 ` 538 00:00:01.000 * 9.000s 00:00:10.000 539 00:00:10.000 A1_1 10.000s 00:00:20.000 540 00:00:20.000 * 20.000s 00:00:40.000 541 00:00:40.000 B1 45.000s 00:01:25.000 542 00:00:40.000 * 25.000s 00:01:05.000 543 00:01:05.000 B1_1 5.000s 00:01:10.000 544 00:01:10.000 * 15.000s 00:01:25.000 545 `, 546 }, 547 { 548 []Interval{ 549 {"A1_1", 2, sec(9), sec(19)}, 550 {"B1", 1, sec(39), sec(89)}, 551 {"B1_1", 2, sec(64), sec(69)}, 552 {"B1_2", 2, sec(79), sec(87)}, 553 }, 554 ` 555 00:00:01.000 * 9.000s 00:00:10.000 556 00:00:10.000 A1_1 10.000s 00:00:20.000 557 00:00:20.000 * 20.000s 00:00:40.000 558 00:00:40.000 B1 50.000s 00:01:30.000 559 00:00:40.000 * 25.000s 00:01:05.000 560 00:01:05.000 B1_1 5.000s 00:01:10.000 561 00:01:10.000 * 10.000s 00:01:20.000 562 00:01:20.000 B1_2 8.000s 00:01:28.000 563 00:01:28.000 * 2.000s 00:01:30.000 564 `, 565 }, 566 { 567 []Interval{ 568 {"A1_1_1", 3, sec(9), sec(19)}, 569 {"B1", 1, sec(39), InvalidDuration}, 570 }, 571 ` 572 00:00:01.000 * 9.000s 00:00:10.000 573 00:00:10.000 A1_1_1 10.000s 00:00:20.000 574 00:00:20.000 * 20.000s 00:00:40.000 575 00:00:40.000 B1 960.000s ---------now 576 `, 577 }, 578 { 579 []Interval{ 580 {"A1_1_1", 3, sec(9), sec(19)}, 581 {"B1", 1, sec(39), sec(64)}, 582 }, 583 ` 584 00:00:01.000 * 9.000s 00:00:10.000 585 00:00:10.000 A1_1_1 10.000s 00:00:20.000 586 00:00:20.000 * 20.000s 00:00:40.000 587 00:00:40.000 B1 25.000s 00:01:05.000 588 `, 589 }, 590 { 591 []Interval{ 592 {"A1_1_1", 3, sec(9), sec(19)}, 593 {"B1", 1, sec(39), sec(64)}, 594 {"C1", 1, sec(69), sec(84)}, 595 }, 596 ` 597 00:00:01.000 * 9.000s 00:00:10.000 598 00:00:10.000 A1_1_1 10.000s 00:00:20.000 599 00:00:20.000 * 20.000s 00:00:40.000 600 00:00:40.000 B1 25.000s 00:01:05.000 601 00:01:05.000 * 5.000s 00:01:10.000 602 00:01:10.000 C1 15.000s 00:01:25.000 603 `, 604 }, 605 { 606 []Interval{ 607 {"A1_1_1", 3, sec(9), sec(19)}, 608 {"B1", 1, sec(39), sec(84)}, 609 {"B1_1", 2, sec(59), sec(69)}, 610 }, 611 ` 612 00:00:01.000 * 9.000s 00:00:10.000 613 00:00:10.000 A1_1_1 10.000s 00:00:20.000 614 00:00:20.000 * 20.000s 00:00:40.000 615 00:00:40.000 B1 45.000s 00:01:25.000 616 00:00:40.000 * 20.000s 00:01:00.000 617 00:01:00.000 B1_1 10.000s 00:01:10.000 618 00:01:10.000 * 15.000s 00:01:25.000 619 `, 620 }, 621 { 622 []Interval{ 623 {"A1_1", 2, sec(9), sec(84)}, 624 {"A1_1_1", 3, sec(39), sec(79)}, 625 {"A1_1_1_1", 4, sec(54), sec(69)}, 626 {"B1", 1, sec(89), sec(99)}, 627 }, 628 ` 629 00:00:01.000 * 9.000s 00:00:10.000 630 00:00:10.000 A1_1 75.000s 00:01:25.000 631 00:00:10.000 * 30.000s 00:00:40.000 632 00:00:40.000 A1_1_1 40.000s 00:01:20.000 633 00:00:40.000 * 15.000s 00:00:55.000 634 00:00:55.000 A1_1_1_1 15.000s 00:01:10.000 635 00:01:10.000 * 10.000s 00:01:20.000 636 00:01:20.000 * 5.000s 00:01:25.000 637 00:01:25.000 * 5.000s 00:01:30.000 638 00:01:30.000 B1 10.000s 00:01:40.000 639 `, 640 }, 641 } 642 for _, test := range tests { 643 name := fmt.Sprintf("%#v", test.intervals) 644 // Check print output with gaps. 645 var buf bytes.Buffer 646 printer := IntervalPrinter{Zero: tsec(1)} 647 if err := printer.Print(&buf, test.intervals, sec(999)); err != nil { 648 t.Errorf("%s got printer error: %v", name, err) 649 } 650 if got, want := buf.String(), strings.TrimLeft(test.str, "\n"); got != want { 651 t.Errorf("%s GOT STRING\n%sWANT\n%s", name, got, want) 652 } 653 } 654 } 655 656 func BenchmarkTimerPush(b *testing.B) { 657 t := NewTimer("root") 658 for i := 0; i < b.N; i++ { 659 t.Push("child") 660 } 661 } 662 663 func BenchmarkTimerPushPop(b *testing.B) { 664 t := NewTimer("root") 665 for i := 0; i < b.N; i++ { 666 timerPushPop(t) 667 } 668 } 669 func timerPushPop(t *Timer) { 670 t.Push("child1") 671 t.Pop() 672 t.Push("child2") 673 t.Push("child2_1") 674 t.Pop() 675 t.Push("child2_2") 676 t.Pop() 677 t.Pop() 678 t.Push("child3") 679 t.Pop() 680 } 681 682 var randSource = rand.NewSource(123) 683 684 func BenchmarkTimerRandom(b *testing.B) { 685 t, rng := NewTimer("root"), rand.New(randSource) 686 for i := 0; i < b.N; i++ { 687 timerRandom(rng, t) 688 } 689 } 690 func timerRandom(rng *rand.Rand, t *Timer) { 691 switch pct := rng.Intn(100); { 692 case pct < 60: 693 timerPushPop(t) 694 case pct < 90: 695 t.Push("foo") 696 case pct < 99: 697 t.Pop() 698 default: 699 t.Finish() 700 } 701 } 702 703 func BenchmarkTimerString(b *testing.B) { 704 t, rng, now := NewTimer("root"), rand.New(randSource), &stepNow{0} 705 nowFunc = now.Now 706 for i := 0; i < 1000; i++ { 707 timerRandom(rng, t) 708 } 709 t.Finish() // Make sure all intervals are closed. 710 want := t.String() 711 b.ResetTimer() 712 for i := 0; i < b.N; i++ { 713 if got := t.String(); got != want { 714 b.Fatalf("GOT\n%sWANT\n%s\nTIMER\n%#v", got, want, t) 715 } 716 } 717 nowFunc = time.Now 718 }