@@ -19,15 +19,126 @@ package latencytracker
19
19
import (
20
20
"testing"
21
21
"time"
22
+
23
+ apiv1 "k8s.io/api/core/v1"
24
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22
25
)
23
26
24
- func TestObserveDeletion_NoOpIfNodeNotTracked (t * testing.T ) {
25
- tracker := NewNodeLatencyTracker ()
26
- now := time .Now ()
27
+ func TestNodeLatencyTracker (t * testing.T ) {
28
+ baseTime := time .Now ()
29
+
30
+ tests := []struct {
31
+ name string
32
+ setupNodes map [string ]NodeInfo
33
+ unneededList []string
34
+ currentlyInDeletion map [string ]bool
35
+ updateThresholds map [string ]time.Duration
36
+ observeDeletion []string
37
+ expectedTrackedNodes []string
38
+ expectedDeletionTimes map [string ]time.Duration
39
+ }{
40
+ {
41
+ name : "add new unneeded nodes" ,
42
+ setupNodes : map [string ]NodeInfo {},
43
+ unneededList : []string {"node1" , "node2" },
44
+ currentlyInDeletion : map [string ]bool {},
45
+ updateThresholds : map [string ]time.Duration {},
46
+ observeDeletion : []string {},
47
+ expectedTrackedNodes : []string {"node1" , "node2" },
48
+ },
49
+ {
50
+ name : "observe deletion with threshold" ,
51
+ setupNodes : map [string ]NodeInfo {
52
+ "node1" : {UnneededSince : baseTime , Threshold : 2 * time .Second },
53
+ },
54
+ unneededList : []string {},
55
+ currentlyInDeletion : map [string ]bool {},
56
+ updateThresholds : map [string ]time.Duration {},
57
+ observeDeletion : []string {"node1" },
58
+ expectedTrackedNodes : []string {},
59
+ expectedDeletionTimes : map [string ]time.Duration {
60
+ "node1" : 3 * time .Second , // simulate observation 5s after UnneededSince, threshold 2s
61
+ },
62
+ },
63
+ {
64
+ name : "remove unneeded node not in deletion" ,
65
+ setupNodes : map [string ]NodeInfo {
66
+ "node1" : {UnneededSince : baseTime , Threshold : 1 * time .Second },
67
+ "node2" : {UnneededSince : baseTime , Threshold : 0 },
68
+ },
69
+ unneededList : []string {"node2" }, // node1 is removed from unneeded
70
+ currentlyInDeletion : map [string ]bool {},
71
+ updateThresholds : map [string ]time.Duration {},
72
+ observeDeletion : []string {},
73
+ expectedTrackedNodes : []string {"node2" },
74
+ expectedDeletionTimes : map [string ]time.Duration {
75
+ "node1" : 5 * time .Second - 1 * time .Second , // assume current timestamp baseTime+5s
76
+ },
77
+ },
78
+ {
79
+ name : "update threshold" ,
80
+ setupNodes : map [string ]NodeInfo {
81
+ "node1" : {UnneededSince : baseTime , Threshold : 1 * time .Second },
82
+ },
83
+ unneededList : []string {"node1" },
84
+ currentlyInDeletion : map [string ]bool {},
85
+ updateThresholds : map [string ]time.Duration {
86
+ "node1" : 4 * time .Second ,
87
+ },
88
+ observeDeletion : []string {},
89
+ expectedTrackedNodes : []string {"node1" },
90
+ },
91
+ }
92
+
93
+ for _ , tt := range tests {
94
+ t .Run (tt .name , func (t * testing.T ) {
95
+ tracker := NewNodeLatencyTracker ()
96
+ for name , info := range tt .setupNodes {
97
+ tracker .nodes [name ] = info
98
+ }
99
+
100
+ for node , threshold := range tt .updateThresholds {
101
+ tracker .UpdateThreshold (node , threshold )
102
+ }
103
+ unneededNodes := make ([]* apiv1.Node , len (tt .unneededList ))
104
+ for i , name := range tt .unneededList {
105
+ unneededNodes [i ] = & apiv1.Node {ObjectMeta : metav1.ObjectMeta {Name : name }}
106
+ }
107
+ // simulate current timestamp as baseTime + 5s
108
+ currentTime := baseTime .Add (5 * time .Second )
109
+ tracker .UpdateStateWithUnneededList (unneededNodes , tt .currentlyInDeletion , currentTime )
110
+
111
+ // Observe deletions
112
+ for _ , node := range tt .observeDeletion {
113
+ tracker .ObserveDeletion (node , currentTime )
114
+ }
27
115
28
- tracker .ObserveDeletion ("node1" , now )
116
+ // Check tracked nodes
117
+ gotTracked := tracker .GetTrackedNodes ()
118
+ expectedMap := make (map [string ]struct {})
119
+ for _ , n := range tt .expectedTrackedNodes {
120
+ expectedMap [n ] = struct {}{}
121
+ }
122
+ for _ , n := range gotTracked {
123
+ if _ , ok := expectedMap [n ]; ! ok {
124
+ t .Errorf ("unexpected tracked node %q" , n )
125
+ }
126
+ delete (expectedMap , n )
127
+ }
128
+ for n := range expectedMap {
129
+ t .Errorf ("expected node %q to be tracked, but was not" , n )
130
+ }
29
131
30
- if len (tracker .nodes ) != 0 {
31
- t .Errorf ("expected no nodes tracked, got %d" , len (tracker .nodes ))
132
+ for node , expectedDuration := range tt .expectedDeletionTimes {
133
+ info , ok := tt .setupNodes [node ]
134
+ if ! ok {
135
+ continue
136
+ }
137
+ duration := currentTime .Sub (info .UnneededSince ) - info .Threshold
138
+ if duration != expectedDuration {
139
+ t .Errorf ("node %q expected deletion duration %v, got %v" , node , expectedDuration , duration )
140
+ }
141
+ }
142
+ })
32
143
}
33
144
}
0 commit comments