@@ -26,6 +26,7 @@ import (
26
26
"time"
27
27
28
28
"github.com/google/go-cmp/cmp"
29
+ "github.com/stretchr/testify/assert"
29
30
v1 "k8s.io/api/core/v1"
30
31
"k8s.io/apimachinery/pkg/api/resource"
31
32
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -46,7 +47,10 @@ func quantityMustParse(value string) *resource.Quantity {
46
47
47
48
func TestGetReclaimableThreshold (t * testing.T ) {
48
49
testCases := map [string ]struct {
49
- thresholds []evictionapi.Threshold
50
+ thresholds []evictionapi.Threshold
51
+ expectedThreshold evictionapi.Threshold
52
+ expectedResourceName v1.ResourceName
53
+ expectedReclaimableToBeFound bool
50
54
}{
51
55
"" : {
52
56
thresholds : []evictionapi.Threshold {
@@ -101,14 +105,40 @@ func TestGetReclaimableThreshold(t *testing.T) {
101
105
},
102
106
},
103
107
},
108
+ expectedThreshold : evictionapi.Threshold {
109
+ Signal : evictionapi .Signal ("memory.available" ),
110
+ Operator : evictionapi .OpLessThan ,
111
+ Value : evictionapi.ThresholdValue {
112
+ Quantity : quantityMustParse ("150Mi" ),
113
+ },
114
+ },
115
+ expectedResourceName : v1 .ResourceName ("memory" ),
116
+ expectedReclaimableToBeFound : true ,
117
+ },
118
+ "no thresholds" : {
119
+ thresholds : []evictionapi.Threshold {},
120
+ expectedThreshold : evictionapi.Threshold {},
121
+ expectedResourceName : v1 .ResourceName ("" ),
122
+ },
123
+ "threshold was crossed but reclaim not implemented (invalid signal)" : {
124
+ thresholds : []evictionapi.Threshold {
125
+ {
126
+ Signal : "mem.available" ,
127
+ },
128
+ },
129
+ expectedThreshold : evictionapi.Threshold {},
130
+ expectedResourceName : v1 .ResourceName ("" ),
104
131
},
105
132
}
106
- for testName , testCase := range testCases {
133
+ for _ , testCase := range testCases {
107
134
sort .Sort (byEvictionPriority (testCase .thresholds ))
108
- _ , _ , ok := getReclaimableThreshold (testCase .thresholds )
109
- if ! ok {
110
- t .Errorf ("Didn't find reclaimable threshold, test: %v" , testName )
111
- }
135
+ threshold , ressourceName , found := getReclaimableThreshold (testCase .thresholds )
136
+ assert .Equal (t , testCase .expectedReclaimableToBeFound , found )
137
+ assert .Equal (t , testCase .expectedResourceName , ressourceName )
138
+ assert .Equal (t , testCase .expectedThreshold .Signal , threshold .Signal )
139
+ assert .Equal (t , testCase .expectedThreshold .Operator , threshold .Operator )
140
+ assert .Equal (t , testCase .expectedThreshold .Value .Quantity .String (), threshold .Value .Quantity .String ())
141
+ assert .Equal (t , testCase .expectedThreshold .GracePeriod , threshold .GracePeriod )
112
142
}
113
143
}
114
144
@@ -455,6 +485,78 @@ func TestParseThresholdConfig(t *testing.T) {
455
485
expectErr : true ,
456
486
expectThresholds : []evictionapi.Threshold {},
457
487
},
488
+ "min-reclaim-invalid-signal" : {
489
+ allocatableConfig : []string {},
490
+ evictionHard : map [string ]string {},
491
+ evictionSoft : map [string ]string {},
492
+ evictionSoftGracePeriod : map [string ]string {},
493
+ evictionMinReclaim : map [string ]string {"mem.available" : "300Mi" },
494
+ expectErr : true ,
495
+ expectThresholds : []evictionapi.Threshold {},
496
+ },
497
+ "min-reclaim-empty-value" : {
498
+ allocatableConfig : []string {},
499
+ evictionHard : map [string ]string {},
500
+ evictionSoft : map [string ]string {},
501
+ evictionSoftGracePeriod : map [string ]string {},
502
+ evictionMinReclaim : map [string ]string {"memory.available" : "" },
503
+ expectErr : true ,
504
+ expectThresholds : []evictionapi.Threshold {},
505
+ },
506
+ "min-reclaim-negative-percentage" : {
507
+ allocatableConfig : []string {},
508
+ evictionHard : map [string ]string {},
509
+ evictionSoft : map [string ]string {},
510
+ evictionSoftGracePeriod : map [string ]string {},
511
+ evictionMinReclaim : map [string ]string {"memory.available" : "-15%" },
512
+ expectErr : true ,
513
+ expectThresholds : []evictionapi.Threshold {},
514
+ },
515
+ "min-reclaim-invalid-percentage" : {
516
+ allocatableConfig : []string {},
517
+ evictionHard : map [string ]string {},
518
+ evictionSoft : map [string ]string {},
519
+ evictionSoftGracePeriod : map [string ]string {},
520
+ evictionMinReclaim : map [string ]string {"memory.available" : "10..5%" },
521
+ expectErr : true ,
522
+ expectThresholds : []evictionapi.Threshold {},
523
+ },
524
+ "hard-signal-empty-eviction-value" : {
525
+ allocatableConfig : []string {},
526
+ evictionHard : map [string ]string {"memory.available" : "" },
527
+ evictionSoft : map [string ]string {},
528
+ evictionSoftGracePeriod : map [string ]string {},
529
+ evictionMinReclaim : map [string ]string {},
530
+ expectErr : true ,
531
+ expectThresholds : []evictionapi.Threshold {},
532
+ },
533
+ "hard-signal-invalid-float-percentage" : {
534
+ allocatableConfig : []string {},
535
+ evictionHard : map [string ]string {"memory.available" : "10..5%" },
536
+ evictionSoft : map [string ]string {},
537
+ evictionSoftGracePeriod : map [string ]string {},
538
+ evictionMinReclaim : map [string ]string {},
539
+ expectErr : true ,
540
+ expectThresholds : []evictionapi.Threshold {},
541
+ },
542
+ "soft-grace-period-invalid-signal" : {
543
+ allocatableConfig : []string {},
544
+ evictionHard : map [string ]string {},
545
+ evictionSoft : map [string ]string {"memory.available" : "150Mi" },
546
+ evictionSoftGracePeriod : map [string ]string {"mem.available" : "30s" },
547
+ evictionMinReclaim : map [string ]string {},
548
+ expectErr : true ,
549
+ expectThresholds : []evictionapi.Threshold {},
550
+ },
551
+ "soft-invalid-grace-period" : {
552
+ allocatableConfig : []string {},
553
+ evictionHard : map [string ]string {},
554
+ evictionSoft : map [string ]string {"memory.available" : "150Mi" },
555
+ evictionSoftGracePeriod : map [string ]string {"memory.available" : "30mins" },
556
+ evictionMinReclaim : map [string ]string {},
557
+ expectErr : true ,
558
+ expectThresholds : []evictionapi.Threshold {},
559
+ },
458
560
}
459
561
for testName , testCase := range testCases {
460
562
thresholds , err := ParseThresholdConfig (testCase .allocatableConfig , testCase .evictionHard , testCase .evictionSoft , testCase .evictionSoftGracePeriod , testCase .evictionMinReclaim )
@@ -648,6 +750,47 @@ func TestAddAllocatableThresholds(t *testing.T) {
648
750
}
649
751
}
650
752
753
+ func TestFallbackResourcesUsage (t * testing.T ) {
754
+ for _ , test := range []struct {
755
+ description string
756
+ usageFuncName string
757
+ usageFunc func () int64
758
+ }{
759
+ {
760
+ description : "disk usage, fallback value" ,
761
+ usageFuncName : "diskUsage" ,
762
+ usageFunc : func () int64 {
763
+ return diskUsage (& statsapi.FsStats {}).Value ()
764
+ },
765
+ },
766
+ {
767
+ description : "inode usage, fallback value" ,
768
+ usageFuncName : "inodeUsage" ,
769
+ usageFunc : func () int64 {
770
+ return inodeUsage (& statsapi.FsStats {}).Value ()
771
+ },
772
+ },
773
+ {
774
+ description : "memory usage, fallback value" ,
775
+ usageFuncName : "memoryUsage" ,
776
+ usageFunc : func () int64 {
777
+ return memoryUsage (& statsapi.MemoryStats {}).Value ()
778
+ },
779
+ },
780
+ {
781
+ description : "process usage, fallback value" ,
782
+ usageFuncName : "processUsage" ,
783
+ usageFunc : func () int64 {
784
+ return int64 (processUsage (& statsapi.ProcessStats {}))
785
+ },
786
+ },
787
+ } {
788
+ t .Run (test .description , func (t * testing.T ) {
789
+ assert .NotEqual (t , 0 , test .usageFunc (), fmt .Sprintf ("%s: unexpected fallback value" , test .usageFuncName ))
790
+ })
791
+ }
792
+ }
793
+
651
794
func thresholdsEqual (expected []evictionapi.Threshold , actual []evictionapi.Threshold ) bool {
652
795
if len (expected ) != len (actual ) {
653
796
return false
@@ -3259,3 +3402,49 @@ func TestEvictonMessageWithResourceResize(t *testing.T) {
3259
3402
})
3260
3403
}
3261
3404
}
3405
+
3406
+ func TestStatsNotFoundForPod (t * testing.T ) {
3407
+ pod1 := newPod ("fake-pod1" , defaultPriority , []v1.Container {
3408
+ newContainer ("fake-container1" , newResourceList ("" , "" , "" ), newResourceList ("" , "" , "" )),
3409
+ }, nil )
3410
+ pod2 := newPod ("fake-pod2" , defaultPriority , []v1.Container {
3411
+ newContainer ("fake-container2" , newResourceList ("" , "" , "" ), newResourceList ("" , "" , "" )),
3412
+ }, nil )
3413
+ statsFn := func (pod * v1.Pod ) (statsapi.PodStats , bool ) {
3414
+ return statsapi.PodStats {}, false
3415
+ }
3416
+
3417
+ for _ , test := range []struct {
3418
+ description string
3419
+ compFunc func (stats statsFunc ) cmpFunc
3420
+ }{
3421
+ {
3422
+ description : "process" ,
3423
+ compFunc : process ,
3424
+ },
3425
+ {
3426
+ description : "memory" ,
3427
+ compFunc : memory ,
3428
+ },
3429
+ {
3430
+ description : "exceedMemoryRequests" ,
3431
+ compFunc : exceedMemoryRequests ,
3432
+ },
3433
+ {
3434
+ description : "exceedDiskRequests" ,
3435
+ compFunc : func (stats statsFunc ) cmpFunc {
3436
+ return exceedDiskRequests (stats , nil , "" )
3437
+ },
3438
+ },
3439
+ {
3440
+ description : "disk" ,
3441
+ compFunc : func (stats statsFunc ) cmpFunc {
3442
+ return disk (stats , nil , "" )
3443
+ },
3444
+ },
3445
+ } {
3446
+ t .Run (test .description , func (t * testing.T ) {
3447
+ assert .Equal (t , 0 , test .compFunc (statsFn )(pod1 , pod2 ), "unexpected default result" )
3448
+ })
3449
+ }
3450
+ }
0 commit comments