1
16
17 package framework
18
19 import (
20 "fmt"
21 "testing"
22 )
23
24 type fakeData struct {
25 data string
26 }
27
28 func (f *fakeData) Clone() StateData {
29 copy := &fakeData{
30 data: f.data,
31 }
32 return copy
33 }
34
35 var key StateKey = "fakedata_key"
36
37
38
39 func createCycleStateWithFakeData(data string, recordPluginMetrics bool) *CycleState {
40 c := NewCycleState()
41 c.Write(key, &fakeData{
42 data: data,
43 })
44 c.SetRecordPluginMetrics(recordPluginMetrics)
45 return c
46 }
47
48
49
50 func isCycleStateEqual(a, b *CycleState) (bool, string) {
51 if a == nil && b == nil {
52 return true, ""
53 }
54 if a == nil || b == nil {
55 return false, fmt.Sprintf("one CycleState is nil, but another one is not nil. A: %v, B: %v", a, b)
56 }
57
58 if a.recordPluginMetrics != b.recordPluginMetrics {
59 return false, fmt.Sprintf("CycleState A and B have a different recordPluginMetrics. A: %v, B: %v", a.recordPluginMetrics, b.recordPluginMetrics)
60 }
61
62 var msg string
63 isEqual := true
64 countA := 0
65 a.storage.Range(func(k, v1 interface{}) bool {
66 countA++
67 v2, ok := b.storage.Load(k)
68 if !ok {
69 isEqual = false
70 msg = fmt.Sprintf("CycleState B doesn't have the data which CycleState A has. key: %v, data: %v", k, v1)
71 return false
72 }
73
74 typed1, ok1 := v1.(*fakeData)
75 typed2, ok2 := v2.(*fakeData)
76 if !ok1 || !ok2 {
77 isEqual = false
78 msg = fmt.Sprintf("CycleState has the data which is not type *fakeData.")
79 return false
80 }
81
82 if typed1.data != typed2.data {
83 isEqual = false
84 msg = fmt.Sprintf("CycleState B has a different data on key %v. A: %v, B: %v", k, typed1.data, typed2.data)
85 return false
86 }
87
88 return true
89 })
90
91 if !isEqual {
92 return false, msg
93 }
94
95 countB := 0
96 b.storage.Range(func(k, _ interface{}) bool {
97 countB++
98 return true
99 })
100
101 if countA != countB {
102 return false, fmt.Sprintf("two Cyclestates have different numbers of data. A: %v, B: %v", countA, countB)
103 }
104
105 return true, ""
106 }
107
108 func TestCycleStateClone(t *testing.T) {
109 tests := []struct {
110 name string
111 state *CycleState
112 wantClonedState *CycleState
113 }{
114 {
115 name: "clone with recordPluginMetrics true",
116 state: createCycleStateWithFakeData("data", true),
117 wantClonedState: createCycleStateWithFakeData("data", true),
118 },
119 {
120 name: "clone with recordPluginMetrics false",
121 state: createCycleStateWithFakeData("data", false),
122 wantClonedState: createCycleStateWithFakeData("data", false),
123 },
124 {
125 name: "clone with nil CycleState",
126 state: nil,
127 wantClonedState: nil,
128 },
129 }
130
131 for _, tt := range tests {
132 t.Run(tt.name, func(t *testing.T) {
133 state := tt.state
134 stateCopy := state.Clone()
135
136 if isEqual, msg := isCycleStateEqual(stateCopy, tt.wantClonedState); !isEqual {
137 t.Errorf("unexpected cloned state: %v", msg)
138 }
139
140 if state == nil || stateCopy == nil {
141
142 return
143 }
144
145 stateCopy.Write(key, &fakeData{data: "modified"})
146 if isEqual, _ := isCycleStateEqual(state, stateCopy); isEqual {
147 t.Errorf("the change for a cloned state should not affect the original state.")
148 }
149 })
150 }
151 }
152
View as plain text