github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/monitor/cnr_indicator_test.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package monitor 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 v1 "k8s.io/api/core/v1" 27 "k8s.io/apimachinery/pkg/api/resource" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/runtime" 30 "k8s.io/client-go/tools/cache" 31 32 "github.com/kubewharf/katalyst-api/pkg/apis/node/v1alpha1" 33 "github.com/kubewharf/katalyst-api/pkg/consts" 34 katalyst_base "github.com/kubewharf/katalyst-core/cmd/base" 35 "github.com/kubewharf/katalyst-core/cmd/katalyst-agent/app/options" 36 metricspool "github.com/kubewharf/katalyst-core/pkg/metrics/metrics-pool" 37 ) 38 39 func Test_checkNumaExclusiveAnomaly(t *testing.T) { 40 t.Parallel() 41 42 type fields struct { 43 pods []*v1.Pod 44 cnr *v1alpha1.CustomNodeResource 45 } 46 47 tests := []struct { 48 name string 49 fields fields 50 wantResult bool 51 }{ 52 { 53 name: "numa exclusive anomaly with numa binding and numa exclusive pod", 54 fields: fields{ 55 pods: []*v1.Pod{ 56 { 57 ObjectMeta: metav1.ObjectMeta{ 58 Name: "test-pod1", 59 Namespace: "test-namespace", 60 Annotations: map[string]string{ 61 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 62 consts.PodAnnotationMemoryEnhancementKey: `{ 63 "numa_binding": "true", 64 "numa_exclusive": "true" 65 }`, 66 }, 67 }, 68 }, 69 { 70 ObjectMeta: metav1.ObjectMeta{ 71 Name: "test-pod2", 72 Namespace: "test-namespace", 73 Annotations: map[string]string{ 74 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 75 consts.PodAnnotationMemoryEnhancementKey: `{ 76 "numa_binding": "true", 77 "numa_exclusive": "true" 78 }`, 79 }, 80 }, 81 }, 82 }, 83 cnr: &v1alpha1.CustomNodeResource{ 84 ObjectMeta: metav1.ObjectMeta{ 85 Name: "test", 86 }, 87 Status: v1alpha1.CustomNodeResourceStatus{ 88 TopologyZone: []*v1alpha1.TopologyZone{ 89 { 90 Type: v1alpha1.TopologyTypeSocket, 91 Children: []*v1alpha1.TopologyZone{ 92 { 93 Type: v1alpha1.TopologyTypeNIC, 94 Attributes: []v1alpha1.Attribute{ 95 { 96 Name: "katalyst.kubewharf.io/resource_identifier", 97 Value: "enp0s3", 98 }, 99 }, 100 Name: "eth0", 101 }, 102 { 103 Type: v1alpha1.TopologyTypeNuma, 104 Allocations: []*v1alpha1.Allocation{ 105 { 106 Consumer: "test-namespace/test-pod1/13414141", 107 }, 108 { 109 Consumer: "test-namespace/test-pod2/31413414", 110 }, 111 }, 112 Name: "0", 113 }, 114 }, 115 }, 116 }, 117 }, 118 }, 119 }, 120 wantResult: true, 121 }, 122 { 123 name: "numa exclusive anomaly test with non numa binding and non numa exclusive pod", 124 fields: fields{ 125 pods: []*v1.Pod{ 126 { 127 ObjectMeta: metav1.ObjectMeta{ 128 Name: "test-pod1", 129 Namespace: "test-namespace", 130 }, 131 }, 132 { 133 ObjectMeta: metav1.ObjectMeta{ 134 Name: "test-pod2", 135 Namespace: "test-namespace", 136 }, 137 }, 138 }, 139 cnr: &v1alpha1.CustomNodeResource{ 140 ObjectMeta: metav1.ObjectMeta{ 141 Name: "test", 142 }, 143 Status: v1alpha1.CustomNodeResourceStatus{ 144 TopologyZone: []*v1alpha1.TopologyZone{ 145 { 146 Type: v1alpha1.TopologyTypeSocket, 147 Children: []*v1alpha1.TopologyZone{ 148 { 149 Type: v1alpha1.TopologyTypeNIC, 150 Attributes: []v1alpha1.Attribute{ 151 { 152 Name: "katalyst.kubewharf.io/resource_identifier", 153 Value: "enp0s3", 154 }, 155 }, 156 Name: "eth0", 157 }, 158 { 159 Type: v1alpha1.TopologyTypeNuma, 160 Allocations: []*v1alpha1.Allocation{ 161 { 162 Consumer: "test-namespace/test-pod1/13414141", 163 }, 164 { 165 Consumer: "test-namespace/test-pod2/31413414", 166 }, 167 }, 168 Name: "0", 169 }, 170 }, 171 }, 172 }, 173 }, 174 }, 175 }, 176 wantResult: false, 177 }, 178 { 179 name: "numa exclusive anomaly with non numa binding and numa exclusive pod", 180 fields: fields{ 181 pods: []*v1.Pod{ 182 { 183 ObjectMeta: metav1.ObjectMeta{ 184 Name: "test-pod1", 185 Namespace: "test-namespace", 186 Annotations: map[string]string{ 187 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 188 consts.PodAnnotationMemoryEnhancementKey: `{ 189 "numa_binding": "false", 190 "numa_exclusive": "true" 191 }`, 192 }, 193 }, 194 }, 195 { 196 ObjectMeta: metav1.ObjectMeta{ 197 Name: "test-pod2", 198 Namespace: "test-namespace", 199 Annotations: map[string]string{ 200 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 201 consts.PodAnnotationMemoryEnhancementKey: `{ 202 "numa_binding": "true", 203 "numa_exclusive": "false" 204 }`, 205 }, 206 }, 207 }, 208 }, 209 cnr: &v1alpha1.CustomNodeResource{ 210 ObjectMeta: metav1.ObjectMeta{ 211 Name: "test", 212 }, 213 Status: v1alpha1.CustomNodeResourceStatus{ 214 TopologyZone: []*v1alpha1.TopologyZone{ 215 { 216 Type: v1alpha1.TopologyTypeSocket, 217 Children: []*v1alpha1.TopologyZone{ 218 { 219 Type: v1alpha1.TopologyTypeNIC, 220 Attributes: []v1alpha1.Attribute{ 221 { 222 Name: "katalyst.kubewharf.io/resource_identifier", 223 Value: "enp0s3", 224 }, 225 }, 226 Name: "eth0", 227 }, 228 { 229 Type: v1alpha1.TopologyTypeNuma, 230 Allocations: []*v1alpha1.Allocation{ 231 { 232 Consumer: "test-namespace/test-pod1/13414141", 233 }, 234 { 235 Consumer: "test-namespace/test-pod2/31413414", 236 }, 237 }, 238 Name: "0", 239 }, 240 }, 241 }, 242 }, 243 }, 244 }, 245 }, 246 wantResult: false, 247 }, 248 { 249 name: "numa exclusive anomaly with numa binding and non numa exclusive pod", 250 fields: fields{ 251 pods: []*v1.Pod{ 252 { 253 ObjectMeta: metav1.ObjectMeta{ 254 Name: "test-pod1", 255 Namespace: "test-namespace", 256 Annotations: map[string]string{ 257 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 258 consts.PodAnnotationMemoryEnhancementKey: `{ 259 "numa_binding": "true", 260 "numa_exclusive": "false" 261 }`, 262 }, 263 }, 264 }, 265 { 266 ObjectMeta: metav1.ObjectMeta{ 267 Name: "test-pod2", 268 Namespace: "test-namespace", 269 }, 270 }, 271 }, 272 cnr: &v1alpha1.CustomNodeResource{ 273 ObjectMeta: metav1.ObjectMeta{ 274 Name: "test", 275 }, 276 Status: v1alpha1.CustomNodeResourceStatus{ 277 TopologyZone: []*v1alpha1.TopologyZone{ 278 { 279 Type: v1alpha1.TopologyTypeSocket, 280 Children: []*v1alpha1.TopologyZone{ 281 { 282 Type: v1alpha1.TopologyTypeNIC, 283 Attributes: []v1alpha1.Attribute{ 284 { 285 Name: "katalyst.kubewharf.io/resource_identifier", 286 Value: "enp0s3", 287 }, 288 }, 289 Name: "eth0", 290 }, 291 { 292 Type: v1alpha1.TopologyTypeNuma, 293 Allocations: []*v1alpha1.Allocation{ 294 { 295 Consumer: "test-namespace/test-pod1/13414141", 296 }, 297 { 298 Consumer: "test-namespace/test-pod2/31413414", 299 }, 300 }, 301 Name: "0", 302 }, 303 }, 304 }, 305 }, 306 }, 307 }, 308 }, 309 wantResult: false, 310 }, 311 } 312 for _, tt := range tests { 313 tt := tt 314 315 t.Run(tt.name, func(t *testing.T) { 316 t.Parallel() 317 318 genericCtx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{tt.fields.pods[0], tt.fields.pods[1]}, []runtime.Object{tt.fields.cnr}) 319 assert.NoError(t, err) 320 321 conf, err := options.NewOptions().Config() 322 require.NoError(t, err) 323 require.NotNil(t, conf) 324 325 ctrl, err := NewCNRMonitorController( 326 context.Background(), 327 conf.GenericConfiguration, 328 conf.GenericControllerConfiguration, 329 conf.CNRMonitorConfig, 330 genericCtx.Client, 331 genericCtx.KubeInformerFactory.Core().V1().Nodes(), 332 genericCtx.KubeInformerFactory.Core().V1().Pods(), 333 genericCtx.InternalInformerFactory.Node().V1alpha1().CustomNodeResources(), 334 metricspool.DummyMetricsEmitterPool.GetDefaultMetricsEmitter(metricspool.DummyMetricsEmitterPool{}), 335 ) 336 assert.NoError(t, err) 337 338 // test cache synced 339 genericCtx.KubeInformerFactory.Start(ctrl.ctx.Done()) 340 genericCtx.InternalInformerFactory.Start(ctrl.ctx.Done()) 341 342 cache.WaitForCacheSync(ctrl.ctx.Done(), ctrl.cnrListerSynced, ctrl.podListerSynced) 343 time.Sleep(100 * time.Millisecond) 344 345 result := ctrl.checkNumaExclusiveAnomaly(tt.fields.cnr) 346 assert.Equal(t, tt.wantResult, result) 347 }) 348 } 349 } 350 351 func Test_checkNumaAllocatableSumAnomaly(t *testing.T) { 352 t.Parallel() 353 354 type fields struct { 355 node *v1.Node 356 cnr *v1alpha1.CustomNodeResource 357 } 358 359 tests := []struct { 360 name string 361 fields fields 362 wantResult bool 363 }{ 364 { 365 name: "numa allocatable sum anomaly not found", 366 fields: fields{ 367 node: &v1.Node{ 368 ObjectMeta: metav1.ObjectMeta{ 369 Name: "test", 370 }, 371 Status: v1.NodeStatus{ 372 Allocatable: v1.ResourceList{ 373 v1.ResourceCPU: *resource.NewQuantity(int64(6), resource.DecimalSI), 374 v1.ResourceMemory: *resource.NewQuantity(int64(2000), resource.BinarySI), 375 }, 376 Capacity: v1.ResourceList{ 377 v1.ResourceCPU: *resource.NewQuantity(int64(6), resource.DecimalSI), 378 v1.ResourceMemory: *resource.NewQuantity(int64(2000), resource.BinarySI), 379 }, 380 }, 381 }, 382 cnr: &v1alpha1.CustomNodeResource{ 383 ObjectMeta: metav1.ObjectMeta{ 384 Name: "test", 385 }, 386 Status: v1alpha1.CustomNodeResourceStatus{ 387 TopologyZone: []*v1alpha1.TopologyZone{ 388 { 389 Type: v1alpha1.TopologyTypeSocket, 390 Children: []*v1alpha1.TopologyZone{ 391 { 392 Type: v1alpha1.TopologyTypeNIC, 393 Attributes: []v1alpha1.Attribute{ 394 { 395 Name: "katalyst.kubewharf.io/resource_identifier", 396 Value: "enp0s3", 397 }, 398 }, 399 Name: "eth0", 400 }, 401 { 402 Type: v1alpha1.TopologyTypeNuma, 403 Resources: v1alpha1.Resources{ 404 Allocatable: &v1.ResourceList{ 405 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 406 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 407 }, 408 }, 409 Name: "0", 410 }, 411 { 412 Type: v1alpha1.TopologyTypeNuma, 413 Resources: v1alpha1.Resources{ 414 Allocatable: &v1.ResourceList{ 415 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 416 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 417 }, 418 }, 419 Name: "1", 420 }, 421 }, 422 }, 423 }, 424 }, 425 }, 426 }, 427 wantResult: false, 428 }, 429 { 430 name: "numa allocatable sum anomaly found", 431 fields: fields{ 432 node: &v1.Node{ 433 ObjectMeta: metav1.ObjectMeta{ 434 Name: "test", 435 }, 436 Status: v1.NodeStatus{ 437 Allocatable: v1.ResourceList{ 438 v1.ResourceCPU: *resource.NewQuantity(int64(5), resource.DecimalSI), 439 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 440 }, 441 Capacity: v1.ResourceList{ 442 v1.ResourceCPU: *resource.NewQuantity(int64(5), resource.DecimalSI), 443 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 444 }, 445 }, 446 }, 447 cnr: &v1alpha1.CustomNodeResource{ 448 ObjectMeta: metav1.ObjectMeta{ 449 Name: "test", 450 }, 451 Status: v1alpha1.CustomNodeResourceStatus{ 452 TopologyZone: []*v1alpha1.TopologyZone{ 453 { 454 Type: v1alpha1.TopologyTypeSocket, 455 Children: []*v1alpha1.TopologyZone{ 456 { 457 Type: v1alpha1.TopologyTypeNIC, 458 Attributes: []v1alpha1.Attribute{ 459 { 460 Name: "katalyst.kubewharf.io/resource_identifier", 461 Value: "enp0s3", 462 }, 463 }, 464 Name: "eth0", 465 }, 466 { 467 Type: v1alpha1.TopologyTypeNuma, 468 Resources: v1alpha1.Resources{ 469 Allocatable: &v1.ResourceList{ 470 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 471 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 472 }, 473 }, 474 Name: "0", 475 }, 476 }, 477 }, 478 { 479 Type: v1alpha1.TopologyTypeSocket, 480 Children: []*v1alpha1.TopologyZone{ 481 { 482 Type: v1alpha1.TopologyTypeNuma, 483 Resources: v1alpha1.Resources{ 484 Allocatable: &v1.ResourceList{ 485 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 486 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 487 }, 488 }, 489 Name: "0", 490 }, 491 }, 492 }, 493 }, 494 }, 495 }, 496 }, 497 wantResult: true, 498 }, 499 } 500 for _, tt := range tests { 501 tt := tt 502 t.Run(tt.name, func(t *testing.T) { 503 t.Parallel() 504 505 genericCtx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{tt.fields.node}, []runtime.Object{tt.fields.cnr}) 506 assert.NoError(t, err) 507 508 conf, err := options.NewOptions().Config() 509 require.NoError(t, err) 510 require.NotNil(t, conf) 511 512 ctrl, err := NewCNRMonitorController( 513 context.Background(), 514 conf.GenericConfiguration, 515 conf.GenericControllerConfiguration, 516 conf.CNRMonitorConfig, 517 genericCtx.Client, 518 genericCtx.KubeInformerFactory.Core().V1().Nodes(), 519 genericCtx.KubeInformerFactory.Core().V1().Pods(), 520 genericCtx.InternalInformerFactory.Node().V1alpha1().CustomNodeResources(), 521 metricspool.DummyMetricsEmitterPool.GetDefaultMetricsEmitter(metricspool.DummyMetricsEmitterPool{}), 522 ) 523 assert.NoError(t, err) 524 525 // test cache synced 526 genericCtx.KubeInformerFactory.Start(ctrl.ctx.Done()) 527 genericCtx.InternalInformerFactory.Start(ctrl.ctx.Done()) 528 529 cache.WaitForCacheSync(ctrl.ctx.Done(), ctrl.cnrListerSynced, ctrl.podListerSynced) 530 time.Sleep(100 * time.Millisecond) 531 532 result := ctrl.checkNumaAllocatableSumAnomaly(tt.fields.cnr) 533 assert.Equal(t, tt.wantResult, result) 534 }) 535 } 536 } 537 538 func Test_checkPodAllocationSumAnomaly(t *testing.T) { 539 t.Parallel() 540 541 type fields struct { 542 pods []*v1.Pod 543 cnr *v1alpha1.CustomNodeResource 544 } 545 546 tests := []struct { 547 name string 548 fields fields 549 wantResult bool 550 }{ 551 { 552 name: "pod allocatable sum anomaly not found", 553 fields: fields{ 554 pods: []*v1.Pod{ 555 { 556 ObjectMeta: metav1.ObjectMeta{ 557 Name: "test-pod1", 558 Namespace: "test-namespace", 559 Annotations: map[string]string{ 560 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 561 consts.PodAnnotationMemoryEnhancementKey: `{ 562 "numa_binding": "true", 563 "numa_exclusive": "false" 564 }`, 565 }, 566 }, 567 }, 568 }, 569 cnr: &v1alpha1.CustomNodeResource{ 570 ObjectMeta: metav1.ObjectMeta{ 571 Name: "test", 572 }, 573 Status: v1alpha1.CustomNodeResourceStatus{ 574 TopologyZone: []*v1alpha1.TopologyZone{ 575 { 576 Type: v1alpha1.TopologyTypeSocket, 577 Children: []*v1alpha1.TopologyZone{ 578 { 579 Type: v1alpha1.TopologyTypeNIC, 580 Attributes: []v1alpha1.Attribute{ 581 { 582 Name: "katalyst.kubewharf.io/resource_identifier", 583 Value: "enp0s3", 584 }, 585 }, 586 Name: "eth0", 587 }, 588 { 589 Type: v1alpha1.TopologyTypeNuma, 590 Allocations: []*v1alpha1.Allocation{ 591 { 592 Consumer: "test-namespace/test-pod1/13414141", 593 Requests: &v1.ResourceList{ 594 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 595 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 596 }, 597 }, 598 }, 599 Resources: v1alpha1.Resources{ 600 Allocatable: &v1.ResourceList{ 601 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 602 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 603 }, 604 }, 605 Name: "0", 606 }, 607 }, 608 }, 609 }, 610 }, 611 }, 612 }, 613 wantResult: false, 614 }, 615 { 616 name: "pod allocatable sum anomaly found", 617 fields: fields{ 618 pods: []*v1.Pod{ 619 { 620 ObjectMeta: metav1.ObjectMeta{ 621 Name: "test-pod1", 622 Namespace: "test-namespace", 623 Annotations: map[string]string{ 624 consts.PodAnnotationQoSLevelKey: consts.PodAnnotationQoSLevelDedicatedCores, 625 consts.PodAnnotationMemoryEnhancementKey: `{ 626 "numa_binding": "true", 627 "numa_exclusive": "false" 628 }`, 629 }, 630 }, 631 }, 632 }, 633 cnr: &v1alpha1.CustomNodeResource{ 634 ObjectMeta: metav1.ObjectMeta{ 635 Name: "test", 636 }, 637 Status: v1alpha1.CustomNodeResourceStatus{ 638 TopologyZone: []*v1alpha1.TopologyZone{ 639 { 640 Type: v1alpha1.TopologyTypeSocket, 641 Children: []*v1alpha1.TopologyZone{ 642 { 643 Type: v1alpha1.TopologyTypeNIC, 644 Attributes: []v1alpha1.Attribute{ 645 { 646 Name: "katalyst.kubewharf.io/resource_identifier", 647 Value: "enp0s3", 648 }, 649 }, 650 Name: "eth0", 651 }, 652 { 653 Type: v1alpha1.TopologyTypeNuma, 654 Allocations: []*v1alpha1.Allocation{ 655 { 656 Consumer: "test-namespace/test-pod1/13414141", 657 Requests: &v1.ResourceList{ 658 v1.ResourceCPU: *resource.NewQuantity(int64(4), resource.DecimalSI), 659 v1.ResourceMemory: *resource.NewQuantity(int64(1001), resource.BinarySI), 660 }, 661 }, 662 }, 663 Resources: v1alpha1.Resources{ 664 Allocatable: &v1.ResourceList{ 665 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 666 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 667 }, 668 }, 669 Name: "0", 670 }, 671 }, 672 }, 673 }, 674 }, 675 }, 676 }, 677 wantResult: true, 678 }, 679 } 680 for _, tt := range tests { 681 tt := tt 682 t.Run(tt.name, func(t *testing.T) { 683 t.Parallel() 684 685 genericCtx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{tt.fields.pods[0]}, []runtime.Object{tt.fields.cnr}) 686 assert.NoError(t, err) 687 688 conf, err := options.NewOptions().Config() 689 require.NoError(t, err) 690 require.NotNil(t, conf) 691 692 ctrl, err := NewCNRMonitorController( 693 context.Background(), 694 conf.GenericConfiguration, 695 conf.GenericControllerConfiguration, 696 conf.CNRMonitorConfig, 697 genericCtx.Client, 698 genericCtx.KubeInformerFactory.Core().V1().Nodes(), 699 genericCtx.KubeInformerFactory.Core().V1().Pods(), 700 genericCtx.InternalInformerFactory.Node().V1alpha1().CustomNodeResources(), 701 metricspool.DummyMetricsEmitterPool.GetDefaultMetricsEmitter(metricspool.DummyMetricsEmitterPool{}), 702 ) 703 assert.NoError(t, err) 704 705 // test cache synced 706 genericCtx.KubeInformerFactory.Start(ctrl.ctx.Done()) 707 genericCtx.InternalInformerFactory.Start(ctrl.ctx.Done()) 708 709 cache.WaitForCacheSync(ctrl.ctx.Done(), ctrl.cnrListerSynced, ctrl.podListerSynced) 710 time.Sleep(100 * time.Millisecond) 711 712 result := ctrl.checkPodAllocationSumAnomaly(tt.fields.cnr) 713 assert.Equal(t, tt.wantResult, result) 714 }) 715 } 716 } 717 718 func Test_checkAndEmitCNRReportLantencyMetric(t *testing.T) { 719 t.Parallel() 720 721 cnr := &v1alpha1.CustomNodeResource{ 722 ObjectMeta: metav1.ObjectMeta{ 723 Name: "test", 724 }, 725 Status: v1alpha1.CustomNodeResourceStatus{ 726 TopologyZone: []*v1alpha1.TopologyZone{ 727 { 728 Type: v1alpha1.TopologyTypeSocket, 729 Children: []*v1alpha1.TopologyZone{ 730 { 731 Type: v1alpha1.TopologyTypeNIC, 732 Attributes: []v1alpha1.Attribute{ 733 { 734 Name: "katalyst.kubewharf.io/resource_identifier", 735 Value: "enp0s3", 736 }, 737 }, 738 Name: "eth0", 739 }, 740 { 741 Type: v1alpha1.TopologyTypeNuma, 742 Allocations: []*v1alpha1.Allocation{ 743 { 744 Consumer: "test-namespace/test-pod1/1111111111", 745 Requests: &v1.ResourceList{ 746 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 747 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 748 }, 749 }, 750 }, 751 Resources: v1alpha1.Resources{ 752 Allocatable: &v1.ResourceList{ 753 v1.ResourceCPU: *resource.NewQuantity(int64(3), resource.DecimalSI), 754 v1.ResourceMemory: *resource.NewQuantity(int64(1000), resource.BinarySI), 755 }, 756 }, 757 Name: "0", 758 }, 759 }, 760 }, 761 }, 762 }, 763 } 764 765 genericCtx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{}, []runtime.Object{cnr}) 766 assert.NoError(t, err) 767 768 conf, err := options.NewOptions().Config() 769 require.NoError(t, err) 770 require.NotNil(t, conf) 771 772 ctrl, err := NewCNRMonitorController( 773 context.Background(), 774 conf.GenericConfiguration, 775 conf.GenericControllerConfiguration, 776 conf.CNRMonitorConfig, 777 genericCtx.Client, 778 genericCtx.KubeInformerFactory.Core().V1().Nodes(), 779 genericCtx.KubeInformerFactory.Core().V1().Pods(), 780 genericCtx.InternalInformerFactory.Node().V1alpha1().CustomNodeResources(), 781 metricspool.DummyMetricsEmitterPool.GetDefaultMetricsEmitter(metricspool.DummyMetricsEmitterPool{}), 782 ) 783 784 ctrl.podTimeMap.Store("test-namespace/test-pod1/1111111111", time.Now()) 785 time.Sleep(2 * time.Millisecond) 786 assert.NoError(t, err) 787 788 err = ctrl.checkAndEmitCNRReportLantencyMetric(cnr) 789 assert.NoError(t, err) 790 if _, ok := ctrl.podTimeMap.Load("test-namespace/test-pod1/1111111111"); ok { 791 t.Errorf("podTimeMap should not have key test-namespace/test-pod1/1111111111") 792 } 793 }