github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/devicetwin/dtmanager/communicate_test.go (about) 1 /* 2 Copyright 2019 The KubeEdge 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 dtmanager 18 19 import ( 20 "errors" 21 "reflect" 22 "testing" 23 "time" 24 25 beehiveContext "github.com/kubeedge/beehive/pkg/core/context" 26 "github.com/kubeedge/beehive/pkg/core/model" 27 cloudconn "github.com/kubeedge/kubeedge/edge/pkg/common/cloudconnection" 28 "github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtcommon" 29 "github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtcontext" 30 "github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dttype" 31 ) 32 33 // TestStartAction is function to test Start() when value is passed in ReceiverChan. 34 func TestStartAction(t *testing.T) { 35 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 36 37 dtContextStateConnected, _ := dtcontext.InitDTContext() 38 dtContextStateConnected.State = dtcommon.Connected 39 receiveChanActionPresent := make(chan interface{}, 1) 40 41 const delay = 10 * time.Millisecond 42 const maxRetries = 5 43 44 receiveChanActionPresent <- &dttype.DTMessage{ 45 Action: dtcommon.SendToCloud, 46 Identity: "identity", 47 Msg: &model.Message{ 48 Header: model.MessageHeader{ 49 ID: "message", 50 }, 51 Content: "msg", 52 }, 53 } 54 55 receiveChanActionNotPresent := make(chan interface{}, 1) 56 receiveChanActionNotPresent <- &dttype.DTMessage{ 57 Action: "action", 58 Identity: "identity", 59 Msg: &model.Message{ 60 Content: "msg", 61 }, 62 } 63 tests := []struct { 64 name string 65 Worker Worker 66 }{ 67 { 68 name: "StartTest-ActionPresentInActionCallback", 69 Worker: Worker{ 70 ReceiverChan: receiveChanActionPresent, 71 DTContexts: dtContextStateConnected, 72 }, 73 }, 74 { 75 name: "StartTest-ActionNotPresentInActionCallback", 76 Worker: Worker{ 77 ReceiverChan: receiveChanActionNotPresent, 78 DTContexts: dtContextStateConnected, 79 }, 80 }, 81 } 82 for _, test := range tests { 83 retry := 0 84 t.Run(test.name, func(t *testing.T) { 85 cw := CommWorker{ 86 Worker: test.Worker, 87 } 88 go cw.Start() 89 if test.Worker.ReceiverChan == receiveChanActionPresent { 90 for retry < maxRetries { 91 time.Sleep(delay) 92 retry++ 93 _, exist := test.Worker.DTContexts.ConfirmMap.Load("message") 94 if exist { 95 break 96 } 97 } 98 if retry >= maxRetries { 99 t.Errorf("Start Failed to store message in ConfirmMap") 100 } 101 } 102 }) 103 } 104 } 105 106 // TestStartHeartBeat is function to test Start() when value is passed in HeartBeatChan. 107 func TestStartHeartBeat(t *testing.T) { 108 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 109 110 dtContexts, _ := dtcontext.InitDTContext() 111 heartChanStop := make(chan interface{}, 1) 112 heartChanPing := make(chan interface{}, 1) 113 heartChanStop <- "stop" 114 heartChanPing <- "ping" 115 116 const delay = 10 * time.Millisecond 117 const maxRetries = 5 118 119 tests := []struct { 120 name string 121 Worker Worker 122 Group string 123 }{ 124 { 125 name: "StartTest-PingInHeartBeatChannel", 126 Worker: Worker{ 127 HeartBeatChan: heartChanPing, 128 DTContexts: dtContexts, 129 }, 130 Group: "group", 131 }, 132 { 133 name: "StartTest-StopInHeartBeatChannel", 134 Worker: Worker{ 135 HeartBeatChan: heartChanStop, 136 DTContexts: dtContexts, 137 }, 138 Group: "group", 139 }, 140 } 141 for _, test := range tests { 142 retry := 0 143 t.Run(test.name, func(t *testing.T) { 144 cw := CommWorker{ 145 Worker: test.Worker, 146 Group: test.Group, 147 } 148 go cw.Start() 149 if test.Worker.HeartBeatChan == heartChanPing { 150 for retry < maxRetries { 151 time.Sleep(delay) 152 retry++ 153 _, exist := test.Worker.DTContexts.ModulesHealth.Load("group") 154 if exist { 155 break 156 } 157 } 158 if retry >= maxRetries { 159 t.Errorf("Start Failed to add module in beehiveContext") 160 } 161 162 } 163 }) 164 } 165 } 166 167 // TestDealSendToCloud is function to test dealSendToCloud(). 168 func TestDealSendToCloud(t *testing.T) { 169 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 170 171 dtContextStateDisconnected, _ := dtcontext.InitDTContext() 172 dtContextStateConnected, _ := dtcontext.InitDTContext() 173 dtContextStateConnected.State = dtcommon.Connected 174 msg := &model.Message{ 175 Header: model.MessageHeader{ 176 ID: "message", 177 }, 178 } 179 180 expectedMessage := &dttype.DTMessage{ 181 Msg: msg, 182 Action: dtcommon.SendToCloud, 183 Type: dtcommon.CommModule, 184 } 185 tests := []struct { 186 name string 187 context *dtcontext.DTContext 188 resource string 189 msg interface{} 190 wantErr error 191 }{ 192 { 193 name: "dealSendToCloudTest-StateDisconnected", 194 context: dtContextStateDisconnected, 195 msg: "", 196 wantErr: nil, 197 }, 198 { 199 name: "dealSendToCloudTest-StateConnected", 200 context: dtContextStateConnected, 201 msg: "", 202 wantErr: errors.New("msg not Message type"), 203 }, 204 { 205 name: "dealSendToCloudTest-ActualMsg", 206 context: dtContextStateConnected, 207 msg: msg, 208 wantErr: nil, 209 }, 210 } 211 for _, test := range tests { 212 t.Run(test.name, func(t *testing.T) { 213 _, err := dealSendToCloud(test.context, test.resource, test.msg) 214 if !reflect.DeepEqual(err, test.wantErr) { 215 t.Errorf("dealSendToCloud() error = %v, wantErr %v", err, test.wantErr) 216 return 217 } 218 // Testing whether the message is properly stored in ConfirmMap of beehiveContext when correct message is passed 219 if err == nil && test.context.State == dtcommon.Connected { 220 gotMsg, exist := test.context.ConfirmMap.Load("message") 221 if !exist { 222 t.Errorf("dealSendToCloud() failed to store message in ConfirmMap") 223 return 224 } 225 if !reflect.DeepEqual(expectedMessage, gotMsg) { 226 t.Errorf("dealSendToCloud() failed due to wrong gotMsg in ConfirmMap Got =%v Want=%v", test.msg, gotMsg) 227 } 228 } 229 }) 230 } 231 } 232 233 // TestDealLifeCycle is function to test dealLifeCycle(). 234 func TestDealLifeCycle(t *testing.T) { 235 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 236 dtContext, _ := dtcontext.InitDTContext() 237 tests := []struct { 238 name string 239 context *dtcontext.DTContext 240 resource string 241 msg interface{} 242 wantErr error 243 }{ 244 { 245 name: "dealLifeCycleTest-WrongMessageFormat", 246 context: dtContext, 247 msg: "", 248 wantErr: errors.New("msg not Message type"), 249 }, 250 { 251 name: "dealLifeCycleTest-CloudConnected", 252 context: dtContext, 253 msg: &model.Message{Content: cloudconn.CloudConnected}, 254 wantErr: nil, 255 }, 256 { 257 name: "dealLifeCycleTest-CloudNotConnected", 258 context: dtContext, 259 msg: &model.Message{Content: cloudconn.CloudDisconnected}, 260 wantErr: nil, 261 }, 262 } 263 for _, test := range tests { 264 t.Run(test.name, func(t *testing.T) { 265 _, err := dealLifeCycle(test.context, test.resource, test.msg) 266 if !reflect.DeepEqual(err, test.wantErr) { 267 t.Errorf("dealLifeCycle() error = %v, wantErr %v", err, test.wantErr) 268 } 269 }) 270 } 271 } 272 273 // TestDealConfirm is function to test dealConfirm(). 274 func TestDealConfirm(t *testing.T) { 275 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 276 dtContext, _ := dtcontext.InitDTContext() 277 tests := []struct { 278 name string 279 context *dtcontext.DTContext 280 resource string 281 msg interface{} 282 wantErr error 283 }{ 284 { 285 name: "dealConfirmTest-WrongMsg", 286 context: dtContext, 287 msg: "", 288 wantErr: errors.New("CommModule deal confirm, type not correct"), 289 }, 290 { 291 name: "dealConfirmTest-CorrectMsg", 292 context: dtContext, 293 msg: &model.Message{Header: model.MessageHeader{ID: "id", ParentID: "parentId"}}, 294 wantErr: nil, 295 }, 296 } 297 for _, test := range tests { 298 t.Run(test.name, func(t *testing.T) { 299 _, err := dealConfirm(test.context, test.resource, test.msg) 300 if !reflect.DeepEqual(err, test.wantErr) { 301 t.Errorf("dealConfirm() error = %v, wantErr %v", err, test.wantErr) 302 return 303 } 304 if err == nil { 305 _, exist := test.context.ConfirmMap.Load("parentId") 306 if exist { 307 t.Errorf("dealConfirm failed() ParentMessageId still present in beehiveContext ConfirmMap") 308 } 309 } 310 }) 311 } 312 } 313 314 // TestCheckConfirm is function to test checkConfirm(). 315 func TestCheckConfirm(t *testing.T) { 316 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 317 dtContext, _ := dtcontext.InitDTContext() 318 dtContext.State = dtcommon.Connected 319 dtContext.ConfirmMap.Store("emptyMessage", &dttype.DTMessage{}) 320 dtContext.ConfirmMap.Store("actionMessage", &dttype.DTMessage{ 321 Msg: &model.Message{}, 322 Action: dtcommon.SendToCloud, 323 }) 324 tests := []struct { 325 name string 326 Worker Worker 327 context *dtcontext.DTContext 328 msg interface{} 329 }{ 330 { 331 name: "checkConfirmTest", 332 Worker: Worker{DTContexts: dtContext}, 333 context: dtContext, 334 msg: &dttype.DTMessage{Action: "action"}, 335 }, 336 } 337 for _, test := range tests { 338 t.Run(test.name, func(t *testing.T) { 339 cw := CommWorker{ 340 Worker: test.Worker, 341 } 342 cw.checkConfirm(test.context, test.msg) 343 _, exist := test.context.ConfirmMap.Load("actionMessage") 344 if !exist { 345 t.Errorf(" checkconfirm() failed because dealSendToCloud() failed to store message in ConfirmMap") 346 return 347 } 348 }) 349 } 350 }