github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/edgehub/process_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 edgehub 18 19 import ( 20 "errors" 21 "fmt" 22 "reflect" 23 "testing" 24 "time" 25 26 "github.com/golang/mock/gomock" 27 28 "github.com/kubeedge/beehive/pkg/core" 29 beehiveContext "github.com/kubeedge/beehive/pkg/core/context" 30 "github.com/kubeedge/beehive/pkg/core/model" 31 "github.com/kubeedge/kubeedge/edge/mocks/edgehub" 32 module "github.com/kubeedge/kubeedge/edge/pkg/common/modules" 33 "github.com/kubeedge/kubeedge/edge/pkg/edgehub/config" 34 ) 35 36 //TestAddKeepChannel() tests the addition of channel to the syncKeeper 37 func TestAddKeepChannel(t *testing.T) { 38 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 39 tests := []struct { 40 name string 41 hub *EdgeHub 42 msgID string 43 }{ 44 { 45 name: "Adding a valid keep channel", 46 hub: &EdgeHub{ 47 syncKeeper: make(map[string]chan model.Message), 48 }, 49 msgID: "test", 50 }, 51 } 52 for _, tt := range tests { 53 t.Run(tt.name, func(t *testing.T) { 54 got := tt.hub.addKeepChannel(tt.msgID) 55 if !reflect.DeepEqual(tt.hub.syncKeeper[tt.msgID], got) { 56 t.Errorf("TestController_addKeepChannel() = %v, want %v", got, tt.hub.syncKeeper[tt.msgID]) 57 } 58 }) 59 } 60 } 61 62 //TestDeleteKeepChannel() tests the deletion of channel in the syncKeeper 63 func TestDeleteKeepChannel(t *testing.T) { 64 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 65 tests := []struct { 66 name string 67 hub *EdgeHub 68 msgID string 69 }{ 70 { 71 name: "Deleting a valid keep channel", 72 hub: &EdgeHub{ 73 syncKeeper: make(map[string]chan model.Message), 74 }, 75 msgID: "test", 76 }, 77 } 78 for _, tt := range tests { 79 t.Run(tt.name, func(t *testing.T) { 80 tt.hub.addKeepChannel(tt.msgID) 81 tt.hub.deleteKeepChannel(tt.msgID) 82 if _, exist := tt.hub.syncKeeper[tt.msgID]; exist { 83 t.Errorf("TestController_deleteKeepChannel = %v, want %v", tt.hub.syncKeeper[tt.msgID], nil) 84 } 85 }) 86 } 87 } 88 89 //TestIsSyncResponse() tests whether there exists a channel with the given message_id in the syncKeeper 90 func TestIsSyncResponse(t *testing.T) { 91 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 92 tests := []struct { 93 name string 94 hub *EdgeHub 95 msgID string 96 want bool 97 }{ 98 { 99 name: "Sync message response case", 100 hub: &EdgeHub{ 101 syncKeeper: make(map[string]chan model.Message), 102 }, 103 msgID: "test", 104 want: true, 105 }, 106 { 107 name: "Non sync message response case", 108 hub: &EdgeHub{ 109 syncKeeper: make(map[string]chan model.Message), 110 }, 111 msgID: "", 112 want: false, 113 }, 114 } 115 for _, tt := range tests { 116 t.Run(tt.name, func(t *testing.T) { 117 if tt.want { 118 tt.hub.addKeepChannel(tt.msgID) 119 } 120 if got := tt.hub.isSyncResponse(tt.msgID); got != tt.want { 121 t.Errorf("TestController_isSyncResponse() = %v, want %v", got, tt.want) 122 } 123 }) 124 } 125 } 126 127 //TestSendToKeepChannel() tests the reception of response in the syncKeep channel 128 func TestSendToKeepChannel(t *testing.T) { 129 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 130 message := model.NewMessage("test_id") 131 tests := []struct { 132 name string 133 hub *EdgeHub 134 message *model.Message 135 keepChannelParentID string 136 expectedError error 137 }{ 138 { 139 name: "SyncKeeper Error Case in send to keep channel", 140 hub: &EdgeHub{ 141 syncKeeper: make(map[string]chan model.Message), 142 }, 143 message: message, 144 keepChannelParentID: "wrong_id", 145 expectedError: fmt.Errorf("failed to get sync keeper channel, messageID:%+v", *message), 146 }, 147 { 148 name: "Negative Test Case without syncKeeper Error ", 149 hub: &EdgeHub{ 150 syncKeeper: make(map[string]chan model.Message), 151 }, 152 message: model.NewMessage("test_id"), 153 keepChannelParentID: "test_id", 154 expectedError: fmt.Errorf("failed to send message to sync keep channel"), 155 }, 156 { 157 name: "Send to keep channel with valid input", 158 hub: &EdgeHub{ 159 syncKeeper: make(map[string]chan model.Message), 160 }, 161 message: model.NewMessage("test_id"), 162 keepChannelParentID: "test_id", 163 expectedError: nil}, 164 } 165 for _, tt := range tests { 166 t.Run(tt.name, func(t *testing.T) { 167 keep := tt.hub.addKeepChannel(tt.keepChannelParentID) 168 if tt.expectedError == nil { 169 receive := func() { 170 <-keep 171 } 172 go receive() 173 } 174 time.Sleep(1 * time.Second) 175 err := tt.hub.sendToKeepChannel(*tt.message) 176 if !reflect.DeepEqual(err, tt.expectedError) { 177 t.Errorf("TestController_sendToKeepChannel() error = %v, expectedError %v", err, tt.expectedError) 178 } 179 }) 180 } 181 } 182 183 //TestDispatch() tests whether the messages are properly dispatched to their respective modules 184 func TestDispatch(t *testing.T) { 185 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 186 tests := []struct { 187 name string 188 hub *EdgeHub 189 message *model.Message 190 expectedError error 191 isResponse bool 192 }{ 193 { 194 name: "dispatch with valid input", 195 hub: &EdgeHub{ 196 syncKeeper: make(map[string]chan model.Message), 197 }, 198 message: model.NewMessage("").BuildRouter(ModuleNameEdgeHub, module.TwinGroup, "", ""), 199 expectedError: nil, 200 isResponse: false, 201 }, 202 { 203 name: "Error Case in dispatch", 204 hub: &EdgeHub{ 205 syncKeeper: make(map[string]chan model.Message), 206 }, 207 message: model.NewMessage("test").BuildRouter(ModuleNameEdgeHub, module.EdgedGroup, "", ""), 208 expectedError: fmt.Errorf("msg_group not found"), 209 isResponse: true, 210 }, 211 { 212 name: "Response Case in dispatch", 213 hub: &EdgeHub{ 214 syncKeeper: make(map[string]chan model.Message), 215 }, 216 message: model.NewMessage("test").BuildRouter(ModuleNameEdgeHub, module.TwinGroup, "", ""), 217 expectedError: nil, 218 isResponse: true, 219 }, 220 } 221 for _, tt := range tests { 222 t.Run(tt.name, func(t *testing.T) { 223 if tt.expectedError == nil && !tt.isResponse { 224 receive := func() { 225 keepChannel := tt.hub.addKeepChannel(tt.message.GetParentID()) 226 <-keepChannel 227 } 228 go receive() 229 } 230 time.Sleep(1 * time.Second) 231 err := tt.hub.dispatch(*tt.message) 232 if !reflect.DeepEqual(err, tt.expectedError) { 233 t.Errorf("TestController_dispatch() error = %v, wantErr %v", err, tt.expectedError) 234 } 235 }) 236 } 237 } 238 239 //TestRouteToEdge() is used to test whether the message received from websocket is dispatched to the required modules 240 func TestRouteToEdge(t *testing.T) { 241 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 242 mockCtrl := gomock.NewController(t) 243 defer mockCtrl.Finish() 244 mockAdapter := edgehub.NewMockAdapter(mockCtrl) 245 hub := newEdgeHub(true) 246 hub.chClient = mockAdapter 247 248 tests := []struct { 249 name string 250 hub *EdgeHub 251 receiveTimes int 252 }{ 253 { 254 name: "Route to edge with proper input", 255 hub: hub, 256 receiveTimes: 0, 257 }, 258 { 259 name: "Receive Error in route to edge", 260 hub: hub, 261 receiveTimes: 1, 262 }, 263 } 264 for _, tt := range tests { 265 t.Run(tt.name, func(t *testing.T) { 266 mockAdapter.EXPECT().Receive().Return(*model.NewMessage("test").BuildRouter(ModuleNameEdgeHub, module.EdgedGroup, "", ""), nil).Times(tt.receiveTimes) 267 mockAdapter.EXPECT().Receive().Return(*model.NewMessage("test").BuildRouter(ModuleNameEdgeHub, module.TwinGroup, "", ""), nil).Times(tt.receiveTimes) 268 mockAdapter.EXPECT().Receive().Return(*model.NewMessage(""), errors.New("Connection Refused")).Times(1) 269 go tt.hub.routeToEdge() 270 stop := <-tt.hub.reconnectChan 271 if stop != struct{}{} { 272 t.Errorf("TestRouteToEdge error got: %v want: %v", stop, struct{}{}) 273 } 274 }) 275 } 276 } 277 278 //TestSendToCloud() tests whether the send to cloud functionality works properly 279 func TestSendToCloud(t *testing.T) { 280 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 281 mockCtrl := gomock.NewController(t) 282 defer mockCtrl.Finish() 283 mockAdapter := edgehub.NewMockAdapter(mockCtrl) 284 285 msg := model.NewMessage("").BuildHeader("test_id", "", 1) 286 msg.Header.Sync = true 287 tests := []struct { 288 name string 289 hub *EdgeHub 290 message model.Message 291 expectedError error 292 waitError bool 293 mockError error 294 HeartbeatPeriod int32 295 }{ 296 { 297 name: "send to cloud with proper input", 298 hub: &EdgeHub{ 299 chClient: mockAdapter, 300 syncKeeper: make(map[string]chan model.Message), 301 }, 302 HeartbeatPeriod: 6, 303 message: *msg, 304 expectedError: nil, 305 waitError: false, 306 mockError: nil, 307 }, 308 { 309 name: "Wait Error in send to cloud", 310 hub: &EdgeHub{ 311 chClient: mockAdapter, 312 syncKeeper: make(map[string]chan model.Message), 313 }, 314 HeartbeatPeriod: 3, 315 message: *msg, 316 expectedError: nil, 317 waitError: true, 318 mockError: nil, 319 }, 320 { 321 name: "Send Failure in send to cloud", 322 hub: &EdgeHub{ 323 chClient: mockAdapter, 324 syncKeeper: make(map[string]chan model.Message), 325 }, 326 HeartbeatPeriod: 3, 327 message: model.Message{}, 328 expectedError: fmt.Errorf("failed to send message, error: Connection Refused"), 329 waitError: false, 330 mockError: errors.New("Connection Refused"), 331 }, 332 } 333 for _, tt := range tests { 334 t.Run(tt.name, func(t *testing.T) { 335 mockAdapter.EXPECT().Send(gomock.Any()).Return(tt.mockError).Times(1) 336 config.Config.Heartbeat = tt.HeartbeatPeriod 337 if !tt.waitError && tt.expectedError == nil { 338 go tt.hub.sendToCloud(tt.message) 339 time.Sleep(1 * time.Second) 340 tempChannel := tt.hub.syncKeeper["test_id"] 341 tempChannel <- *model.NewMessage("test_id") 342 time.Sleep(1 * time.Second) 343 if _, exist := tt.hub.syncKeeper["test_id"]; exist { 344 t.Errorf("SendToCloud() error in receiving message") 345 } 346 return 347 } 348 err := tt.hub.sendToCloud(tt.message) 349 if !reflect.DeepEqual(err, tt.expectedError) { 350 t.Errorf("SendToCloud() error = %v, wantErr %v", err, tt.expectedError) 351 } 352 time.Sleep(time.Duration(tt.HeartbeatPeriod+2) * time.Second) 353 if _, exist := tt.hub.syncKeeper["test_id"]; exist { 354 t.Errorf("SendToCloud() error in waiting for timeout") 355 } 356 }) 357 } 358 } 359 360 //TestRouteToCloud() tests the reception of the message from the beehive framework and forwarding of that message to cloud 361 func TestRouteToCloud(t *testing.T) { 362 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 363 mockCtrl := gomock.NewController(t) 364 defer mockCtrl.Finish() 365 mockAdapter := edgehub.NewMockAdapter(mockCtrl) 366 hub := newEdgeHub(true) 367 hub.chClient = mockAdapter 368 369 tests := []struct { 370 name string 371 hub *EdgeHub 372 }{ 373 { 374 name: "Route to cloud with valid input", 375 hub: hub, 376 }, 377 } 378 for _, tt := range tests { 379 t.Run(tt.name, func(t *testing.T) { 380 mockAdapter.EXPECT().Send(gomock.Any()).Return(errors.New("Connection Refused")).AnyTimes() 381 go tt.hub.routeToCloud() 382 time.Sleep(2 * time.Second) 383 core.Register(&EdgeHub{}) 384 beehiveContext.AddModule(ModuleNameEdgeHub) 385 msg := model.NewMessage("").BuildHeader("test_id", "", 1) 386 beehiveContext.Send(ModuleNameEdgeHub, *msg) 387 stopChan := <-tt.hub.reconnectChan 388 if stopChan != struct{}{} { 389 t.Errorf("Error in route to cloud") 390 } 391 }) 392 } 393 } 394 395 //TestKeepalive() tests whether ping message sent to the cloud at regular intervals happens properly 396 func TestKeepalive(t *testing.T) { 397 CertFile := "/tmp/kubeedge/certs/edge.crt" 398 KeyFile := "/tmp/kubeedge/certs/edge.key" 399 beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel) 400 mockCtrl := gomock.NewController(t) 401 defer mockCtrl.Finish() 402 mockAdapter := edgehub.NewMockAdapter(mockCtrl) 403 tests := []struct { 404 name string 405 hub *EdgeHub 406 }{ 407 { 408 name: "Heartbeat failure Case", 409 hub: &EdgeHub{ 410 chClient: mockAdapter, 411 reconnectChan: make(chan struct{}), 412 }, 413 }, 414 } 415 edgeHubConfig := config.Config 416 edgeHubConfig.TLSCertFile = CertFile 417 edgeHubConfig.TLSPrivateKeyFile = KeyFile 418 419 for _, tt := range tests { 420 t.Run(tt.name, func(t *testing.T) { 421 mockAdapter.EXPECT().Send(gomock.Any()).Return(nil).Times(1) 422 mockAdapter.EXPECT().Send(gomock.Any()).Return(errors.New("Connection Refused")).Times(1) 423 go tt.hub.keepalive() 424 got := <-tt.hub.reconnectChan 425 if got != struct{}{} { 426 t.Errorf("TestKeepalive() StopChan = %v, want %v", got, struct{}{}) 427 } 428 }) 429 } 430 }