|
9 | 9 | "testing"
|
10 | 10 | )
|
11 | 11 |
|
12 |
| -func TestStats(t *testing.T) { |
| 12 | +// The test for Docker Stat API of the host uses cgroup |
| 13 | +func TestStatsV1(t *testing.T) { |
13 | 14 | t.Parallel()
|
14 | 15 | jsonStats1 := `{
|
15 | 16 | "read" : "2015-01-08T22:57:31.547920715Z",
|
@@ -321,6 +322,290 @@ func TestStats(t *testing.T) {
|
321 | 322 | }
|
322 | 323 | }
|
323 | 324 |
|
| 325 | +// The test for Docker Stat API of the host uses cgroup2 |
| 326 | +func TestStatsV2(t *testing.T) { |
| 327 | + t.Parallel() |
| 328 | + jsonStats1 := `{ |
| 329 | + "read": "2022-05-18T14:37:18.175989615Z", |
| 330 | + "preread": "2022-05-18T14:37:17.171501052Z", |
| 331 | + "pids_stats": { |
| 332 | + "current": 29, |
| 333 | + "limit": 76948 |
| 334 | + }, |
| 335 | + "blkio_stats": { |
| 336 | + "io_service_bytes_recursive": [ |
| 337 | + { |
| 338 | + "major": 259, |
| 339 | + "minor": 0, |
| 340 | + "op": "read", |
| 341 | + "value": 11390976 |
| 342 | + }, |
| 343 | + { |
| 344 | + "major": 259, |
| 345 | + "minor": 0, |
| 346 | + "op": "write", |
| 347 | + "value": 0 |
| 348 | + } |
| 349 | + ], |
| 350 | + "io_serviced_recursive": null, |
| 351 | + "io_queue_recursive": null, |
| 352 | + "io_service_time_recursive": null, |
| 353 | + "io_wait_time_recursive": null, |
| 354 | + "io_merged_recursive": null, |
| 355 | + "io_time_recursive": null, |
| 356 | + "sectors_recursive": null |
| 357 | + }, |
| 358 | + "num_procs": 0, |
| 359 | + "storage_stats": {}, |
| 360 | + "cpu_stats": { |
| 361 | + "cpu_usage": { |
| 362 | + "total_usage": 185266562000, |
| 363 | + "usage_in_kernelmode": 37912635000, |
| 364 | + "usage_in_usermode": 147353926000 |
| 365 | + }, |
| 366 | + "system_cpu_usage": 26707255190000000, |
| 367 | + "online_cpus": 24, |
| 368 | + "throttling_data": { |
| 369 | + "periods": 0, |
| 370 | + "throttled_periods": 0, |
| 371 | + "throttled_time": 0 |
| 372 | + } |
| 373 | + }, |
| 374 | + "precpu_stats": { |
| 375 | + "cpu_usage": { |
| 376 | + "total_usage": 185266562000, |
| 377 | + "usage_in_kernelmode": 37912635000, |
| 378 | + "usage_in_usermode": 147353926000 |
| 379 | + }, |
| 380 | + "system_cpu_usage": 26707231080000000, |
| 381 | + "online_cpus": 24, |
| 382 | + "throttling_data": { |
| 383 | + "periods": 0, |
| 384 | + "throttled_periods": 0, |
| 385 | + "throttled_time": 0 |
| 386 | + } |
| 387 | + }, |
| 388 | + "memory_stats": { |
| 389 | + "usage": 28557312, |
| 390 | + "stats": { |
| 391 | + "active_anon": 4096, |
| 392 | + "active_file": 7446528, |
| 393 | + "anon": 16572416, |
| 394 | + "anon_thp": 0, |
| 395 | + "file": 10829824, |
| 396 | + "file_dirty": 0, |
| 397 | + "file_mapped": 9740288, |
| 398 | + "file_writeback": 0, |
| 399 | + "inactive_anon": 8069120, |
| 400 | + "inactive_file": 11882496, |
| 401 | + "kernel_stack": 475136, |
| 402 | + "pgactivate": 241, |
| 403 | + "pgdeactivate": 253, |
| 404 | + "pgfault": 7714, |
| 405 | + "pglazyfree": 3042, |
| 406 | + "pglazyfreed": 967, |
| 407 | + "pgmajfault": 155, |
| 408 | + "pgrefill": 301, |
| 409 | + "pgscan": 1802, |
| 410 | + "pgsteal": 1100, |
| 411 | + "shmem": 0, |
| 412 | + "slab": 488920, |
| 413 | + "slab_reclaimable": 159664, |
| 414 | + "slab_unreclaimable": 329256, |
| 415 | + "sock": 0, |
| 416 | + "thp_collapse_alloc": 0, |
| 417 | + "thp_fault_alloc": 0, |
| 418 | + "unevictable": 0, |
| 419 | + "workingset_activate": 0, |
| 420 | + "workingset_nodereclaim": 0, |
| 421 | + "workingset_refault": 0 |
| 422 | + }, |
| 423 | + "limit": 67353382912 |
| 424 | + }, |
| 425 | + "networks": { |
| 426 | + "eth0": { |
| 427 | + "rx_bytes": 96802652, |
| 428 | + "rx_packets": 623704, |
| 429 | + "rx_errors": 0, |
| 430 | + "rx_dropped": 0, |
| 431 | + "tx_bytes": 16597749, |
| 432 | + "tx_packets": 91982, |
| 433 | + "tx_errors": 0, |
| 434 | + "tx_dropped": 0 |
| 435 | + } |
| 436 | + } |
| 437 | + }` |
| 438 | + // 1 second later, shmem is 100 |
| 439 | + jsonStats2 := `{ |
| 440 | + "read": "2022-05-18T14:37:18.175989615Z", |
| 441 | + "preread": "2022-05-18T14:37:17.171501052Z", |
| 442 | + "pids_stats": { |
| 443 | + "current": 29, |
| 444 | + "limit": 76948 |
| 445 | + }, |
| 446 | + "blkio_stats": { |
| 447 | + "io_service_bytes_recursive": [ |
| 448 | + { |
| 449 | + "major": 259, |
| 450 | + "minor": 0, |
| 451 | + "op": "read", |
| 452 | + "value": 11390976 |
| 453 | + }, |
| 454 | + { |
| 455 | + "major": 259, |
| 456 | + "minor": 0, |
| 457 | + "op": "write", |
| 458 | + "value": 0 |
| 459 | + } |
| 460 | + ], |
| 461 | + "io_serviced_recursive": null, |
| 462 | + "io_queue_recursive": null, |
| 463 | + "io_service_time_recursive": null, |
| 464 | + "io_wait_time_recursive": null, |
| 465 | + "io_merged_recursive": null, |
| 466 | + "io_time_recursive": null, |
| 467 | + "sectors_recursive": null |
| 468 | + }, |
| 469 | + "num_procs": 0, |
| 470 | + "storage_stats": {}, |
| 471 | + "cpu_stats": { |
| 472 | + "cpu_usage": { |
| 473 | + "total_usage": 185266562000, |
| 474 | + "usage_in_kernelmode": 37912635000, |
| 475 | + "usage_in_usermode": 147353926000 |
| 476 | + }, |
| 477 | + "system_cpu_usage": 26707255190000000, |
| 478 | + "online_cpus": 24, |
| 479 | + "throttling_data": { |
| 480 | + "periods": 0, |
| 481 | + "throttled_periods": 0, |
| 482 | + "throttled_time": 0 |
| 483 | + } |
| 484 | + }, |
| 485 | + "precpu_stats": { |
| 486 | + "cpu_usage": { |
| 487 | + "total_usage": 185266562000, |
| 488 | + "usage_in_kernelmode": 37912635000, |
| 489 | + "usage_in_usermode": 147353926000 |
| 490 | + }, |
| 491 | + "system_cpu_usage": 26707231080000000, |
| 492 | + "online_cpus": 24, |
| 493 | + "throttling_data": { |
| 494 | + "periods": 0, |
| 495 | + "throttled_periods": 0, |
| 496 | + "throttled_time": 0 |
| 497 | + } |
| 498 | + }, |
| 499 | + "memory_stats": { |
| 500 | + "usage": 28557312, |
| 501 | + "stats": { |
| 502 | + "active_anon": 4096, |
| 503 | + "active_file": 7446528, |
| 504 | + "anon": 16572416, |
| 505 | + "anon_thp": 0, |
| 506 | + "file": 10829824, |
| 507 | + "file_dirty": 0, |
| 508 | + "file_mapped": 9740288, |
| 509 | + "file_writeback": 0, |
| 510 | + "inactive_anon": 8069120, |
| 511 | + "inactive_file": 11882496, |
| 512 | + "kernel_stack": 475136, |
| 513 | + "pgactivate": 241, |
| 514 | + "pgdeactivate": 253, |
| 515 | + "pgfault": 7714, |
| 516 | + "pglazyfree": 3042, |
| 517 | + "pglazyfreed": 967, |
| 518 | + "pgmajfault": 155, |
| 519 | + "pgrefill": 301, |
| 520 | + "pgscan": 1802, |
| 521 | + "pgsteal": 1100, |
| 522 | + "shmem": 100, |
| 523 | + "slab": 488920, |
| 524 | + "slab_reclaimable": 159664, |
| 525 | + "slab_unreclaimable": 329256, |
| 526 | + "sock": 0, |
| 527 | + "thp_collapse_alloc": 0, |
| 528 | + "thp_fault_alloc": 0, |
| 529 | + "unevictable": 0, |
| 530 | + "workingset_activate": 0, |
| 531 | + "workingset_nodereclaim": 0, |
| 532 | + "workingset_refault": 0 |
| 533 | + }, |
| 534 | + "limit": 67353382912 |
| 535 | + }, |
| 536 | + "networks": { |
| 537 | + "eth0": { |
| 538 | + "rx_bytes": 96802652, |
| 539 | + "rx_packets": 623704, |
| 540 | + "rx_errors": 0, |
| 541 | + "rx_dropped": 0, |
| 542 | + "tx_bytes": 16597749, |
| 543 | + "tx_packets": 91982, |
| 544 | + "tx_errors": 0, |
| 545 | + "tx_dropped": 0 |
| 546 | + } |
| 547 | + } |
| 548 | + }` |
| 549 | + var expected1 Stats |
| 550 | + var expected2 Stats |
| 551 | + err := json.Unmarshal([]byte(jsonStats1), &expected1) |
| 552 | + if err != nil { |
| 553 | + t.Fatal(err) |
| 554 | + } |
| 555 | + err = json.Unmarshal([]byte(jsonStats2), &expected2) |
| 556 | + if err != nil { |
| 557 | + t.Fatal(err) |
| 558 | + } |
| 559 | + id := "4fa6e0f0" |
| 560 | + |
| 561 | + var req http.Request |
| 562 | + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 563 | + w.Header().Set("Content-Type", "application/json") |
| 564 | + w.Write([]byte(jsonStats1)) |
| 565 | + w.Write([]byte(jsonStats2)) |
| 566 | + req = *r |
| 567 | + })) |
| 568 | + defer server.Close() |
| 569 | + client, _ := NewClient(server.URL) |
| 570 | + client.SkipServerVersionCheck = true |
| 571 | + errC := make(chan error, 1) |
| 572 | + statsC := make(chan *Stats) |
| 573 | + done := make(chan bool) |
| 574 | + defer close(done) |
| 575 | + go func() { |
| 576 | + errC <- client.Stats(StatsOptions{ID: id, Stats: statsC, Stream: true, Done: done}) |
| 577 | + close(errC) |
| 578 | + }() |
| 579 | + var resultStats []*Stats |
| 580 | + for { |
| 581 | + stats, ok := <-statsC |
| 582 | + if !ok { |
| 583 | + break |
| 584 | + } |
| 585 | + resultStats = append(resultStats, stats) |
| 586 | + } |
| 587 | + err = <-errC |
| 588 | + if err != nil { |
| 589 | + t.Fatal(err) |
| 590 | + } |
| 591 | + if len(resultStats) != 2 { |
| 592 | + t.Fatalf("Stats: Expected 2 results. Got %d.", len(resultStats)) |
| 593 | + } |
| 594 | + if !reflect.DeepEqual(resultStats[0], &expected1) { |
| 595 | + t.Errorf("Stats: Expected:\n%+v\nGot:\n%+v", expected1, resultStats[0]) |
| 596 | + } |
| 597 | + if !reflect.DeepEqual(resultStats[1], &expected2) { |
| 598 | + t.Errorf("Stats: Expected:\n%+v\nGot:\n%+v", expected2, resultStats[1]) |
| 599 | + } |
| 600 | + if req.Method != http.MethodGet { |
| 601 | + t.Errorf("Stats: wrong HTTP method. Want GET. Got %s.", req.Method) |
| 602 | + } |
| 603 | + u, _ := url.Parse(client.getURL("/containers/" + id + "/stats")) |
| 604 | + if req.URL.Path != u.Path { |
| 605 | + t.Errorf("Stats: wrong HTTP path. Want %q. Got %q.", u.Path, req.URL.Path) |
| 606 | + } |
| 607 | +} |
| 608 | + |
324 | 609 | func TestStatsContainerNotFound(t *testing.T) {
|
325 | 610 | t.Parallel()
|
326 | 611 | client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
|
|
0 commit comments