github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/devicetwin/dtcontext/dtcontext_test.go (about) 1 /* 2 Copyright 2018 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 dtcontext 18 19 import ( 20 "encoding/json" 21 "errors" 22 "reflect" 23 "sync" 24 "testing" 25 26 "github.com/kubeedge/beehive/pkg/core/model" 27 "github.com/kubeedge/kubeedge/edge/pkg/common/modules" 28 "github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtcommon" 29 "github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dttype" 30 ) 31 32 //TestCommTo is function to test CommTo(). 33 func TestCommTo(t *testing.T) { 34 commChan := make(map[string]chan interface{}) 35 testInterface := make(chan interface{}, 1) 36 commChan["ModuleB"] = testInterface 37 dtContext := &DTContext{ 38 CommChan: commChan, 39 } 40 var returnValue interface{} 41 tests := []struct { 42 name string 43 modulename string 44 content interface{} 45 wantErr error 46 }{ 47 { 48 //Failure Case 49 name: "ModuleNotPresent", 50 modulename: "ModuleA", 51 content: nil, 52 wantErr: errors.New("Not found chan to communicate"), 53 }, 54 { 55 //Success Case 56 name: "ModulePresent", 57 modulename: "ModuleB", 58 content: dttype.MembershipUpdate{AddDevices: []dttype.Device{{ID: "DeviceA", Name: "Router", State: "unknown"}}}, 59 wantErr: nil, 60 }, 61 } 62 for _, test := range tests { 63 t.Run(test.name, func(t *testing.T) { 64 err := dtContext.CommTo(test.modulename, test.content) 65 if err == nil { 66 returnValue = <-testInterface 67 } else { 68 returnValue = nil 69 } 70 if !reflect.DeepEqual(err, test.wantErr) { 71 t.Errorf("Error in CommTo %v, Want %v", err, test.wantErr) 72 return 73 } 74 if !reflect.DeepEqual(returnValue, test.content) { 75 t.Errorf("Got %v on channel, Want % v on Channel", returnValue, test.content) 76 return 77 } 78 }) 79 } 80 } 81 82 //TestHeartBeat is function to test HeartBeat(). 83 func TestHeartBeat(t *testing.T) { 84 tests := []struct { 85 name string 86 dtc *DTContext 87 moduleName string 88 content interface{} 89 wantError error 90 }{ 91 { 92 //Success Case 93 name: "PingTest", 94 dtc: &DTContext{ 95 ModulesHealth: &sync.Map{}, 96 }, 97 moduleName: "ModuleA", 98 content: "ping", 99 wantError: nil, 100 }, 101 { 102 //Failure Case 103 name: "StopTest", 104 dtc: &DTContext{ 105 ModulesHealth: &sync.Map{}, 106 }, 107 moduleName: "ModuleB", 108 content: "stop", 109 wantError: errors.New("stop"), 110 }, 111 } 112 for _, test := range tests { 113 t.Run(test.name, func(t *testing.T) { 114 dtc := &DTContext{ 115 ModulesHealth: test.dtc.ModulesHealth, 116 } 117 if err := dtc.HeartBeat(test.moduleName, test.content); !reflect.DeepEqual(err, test.wantError) { 118 t.Errorf("DTContext.HeartBeat() error = %v, Want = %v", err, test.wantError) 119 } 120 }) 121 } 122 } 123 124 //TestGetMutex is function to test GetMutex(). 125 func TestGetMutex(t *testing.T) { 126 dtc := &DTContext{ 127 DeviceMutex: &sync.Map{}, 128 } 129 var testMutex *sync.Mutex 130 dtc.DeviceMutex.Store("DeviceB", "") 131 dtc.DeviceMutex.Store("DeviceC", testMutex) 132 tests := []struct { 133 name string 134 want *sync.Mutex 135 wantBool bool 136 deviceID string 137 }{ 138 { 139 //Failure Case-No device present 140 name: "UnknownDevice", 141 wantBool: false, 142 deviceID: "DeviceA", 143 }, 144 { 145 //Failure Case-Device present but unable to get mutex 146 name: "UnableToGetMutex", 147 wantBool: false, 148 deviceID: "DeviceB", 149 }, 150 { 151 //Success Case 152 name: "KnownDevice", 153 wantBool: true, 154 deviceID: "DeviceC", 155 }, 156 } 157 for _, test := range tests { 158 t.Run(test.name, func(t *testing.T) { 159 got, gotBool := dtc.GetMutex(test.deviceID) 160 if !reflect.DeepEqual(got, test.want) { 161 t.Errorf("DTContext.GetMutex() got = %v, want = %v", got, test.want) 162 return 163 } 164 if gotBool != test.wantBool { 165 t.Errorf("DTContext.GetMutex() gotBool = %v, wantError = %v", gotBool, test.wantBool) 166 return 167 } 168 }) 169 } 170 } 171 172 //TestLock is function to test Lock(). 173 func TestLock(t *testing.T) { 174 dtc := &DTContext{ 175 Mutex: &sync.RWMutex{}, 176 DeviceMutex: &sync.Map{}, 177 } 178 var testMutex sync.Mutex 179 dtc.DeviceMutex.Store("DeviceB", &testMutex) 180 tests := []struct { 181 name string 182 deviceID string 183 wantBool bool 184 }{ 185 { 186 //Failure Case 187 name: "UnknownDevice", 188 deviceID: "DeviceA", 189 wantBool: false, 190 }, 191 { 192 //Success Case 193 name: "KnownDevice", 194 deviceID: "DeviceB", 195 wantBool: true, 196 }, 197 } 198 for _, test := range tests { 199 t.Run(test.name, func(t *testing.T) { 200 if got := dtc.Lock(test.deviceID); got != test.wantBool { 201 t.Errorf("DTContext.Lock() = %v, want = %v", got, test.wantBool) 202 } 203 }) 204 } 205 } 206 207 //TestUnlock is function to test Unlock(). 208 func TestUnlock(t *testing.T) { 209 dtc := &DTContext{ 210 Mutex: &sync.RWMutex{}, 211 DeviceMutex: &sync.Map{}, 212 } 213 // Creating a mutex variable and getting a lock over it. 214 var testMutex sync.Mutex 215 dtc.DeviceMutex.Store("DeviceB", &testMutex) 216 dtc.Lock("DeviceB") 217 tests := []struct { 218 name string 219 deviceID string 220 wantBool bool 221 }{ 222 { 223 //Failure Case 224 name: "UnknownDevice", 225 deviceID: "DeviceA", 226 wantBool: false, 227 }, 228 { 229 //Success Case 230 name: "KnownDevice", 231 deviceID: "DeviceB", 232 wantBool: true, 233 }, 234 } 235 for _, tt := range tests { 236 t.Run(tt.name, func(t *testing.T) { 237 if got := dtc.Unlock(tt.deviceID); got != tt.wantBool { 238 t.Errorf("DTContext.Unlock() = %v, Want = %v", got, tt.wantBool) 239 } 240 }) 241 } 242 } 243 244 //TestIsDeviceExist is to test IsDeviceExist(). 245 func TestIsDeviceExist(t *testing.T) { 246 dtc := &DTContext{ 247 DeviceList: &sync.Map{}, 248 } 249 dtc.DeviceList.Store("DeviceB", "") 250 tests := []struct { 251 name string 252 deviceID string 253 wantBool bool 254 }{ 255 { 256 //Failure Case 257 name: "UnknownDevice", 258 deviceID: "DeviceA", 259 wantBool: false, 260 }, 261 { 262 //Success Case 263 name: "KnownDevice", 264 deviceID: "DeviceB", 265 wantBool: true, 266 }, 267 } 268 for _, test := range tests { 269 t.Run(test.name, func(t *testing.T) { 270 if got := dtc.IsDeviceExist(test.deviceID); got != test.wantBool { 271 t.Errorf("DTContext.IsDeviceExist() = %v, Want = %v", got, test.wantBool) 272 } 273 }) 274 } 275 } 276 277 //Function TestGetDevice is to test GetDevice(). 278 func TestGetDevice(t *testing.T) { 279 dtc := &DTContext{ 280 DeviceList: &sync.Map{}, 281 } 282 var device dttype.Device 283 dtc.DeviceList.Store("DeviceA", "") 284 dtc.DeviceList.Store("DeviceB", &device) 285 tests := []struct { 286 name string 287 deviceID string 288 want *dttype.Device 289 wantBool bool 290 }{ 291 { 292 //Failure Case-DeviceID not present 293 name: "UnknownDevice", 294 deviceID: "", 295 want: nil, 296 wantBool: false, 297 }, 298 { 299 //Failure Case-DeviceID present but unable to get device 300 name: "DeviceError", 301 deviceID: "DeviceA", 302 want: nil, 303 wantBool: false, 304 }, 305 { 306 //Success Case 307 name: "KnownDevice", 308 deviceID: "DeviceB", 309 want: &dttype.Device{}, 310 wantBool: true, 311 }, 312 } 313 for _, test := range tests { 314 t.Run(test.name, func(t *testing.T) { 315 got, gotBool := dtc.GetDevice(test.deviceID) 316 if !reflect.DeepEqual(got, test.want) { 317 t.Errorf("DTContext.GetDevice() got = %v, Want = %v", got, test.want) 318 return 319 } 320 if gotBool != test.wantBool { 321 t.Errorf("DTContext.GetDevice() gotBool = %v, wantError %v", gotBool, test.wantBool) 322 return 323 } 324 }) 325 } 326 } 327 328 //Function TestSend is function to test Send(). 329 func TestSend(t *testing.T) { 330 payload := dttype.MembershipUpdate{ 331 AddDevices: []dttype.Device{ 332 { 333 ID: "DeviceA", 334 Name: "Router", 335 State: "unknown", 336 }, 337 }, 338 } 339 content, err := json.Marshal(payload) 340 if err != nil { 341 t.Errorf("Got error on marshalling: %v", err) 342 } 343 commChan := make(map[string]chan interface{}) 344 receiveCh := make(chan interface{}, 1) 345 commChan[dtcommon.TwinModule] = receiveCh 346 var msg = &model.Message{ 347 Content: content, 348 } 349 dtc := &DTContext{ 350 CommChan: commChan, 351 } 352 tests := []struct { 353 name string 354 identity string 355 action string 356 module string 357 msg *model.Message 358 wantError error 359 }{ 360 { 361 //Failure Case 362 name: "UnknownModule", 363 action: dtcommon.SendToCloud, 364 module: dtcommon.CommModule, 365 msg: msg, 366 wantError: errors.New("Not found chan to communicate"), 367 }, 368 { 369 //Success Case 370 name: "KnownModule", 371 action: dtcommon.SendToCloud, 372 module: dtcommon.TwinModule, 373 msg: msg, 374 wantError: nil, 375 }, 376 } 377 for _, test := range tests { 378 t.Run(test.name, func(t *testing.T) { 379 if err := dtc.Send(test.identity, test.action, test.module, test.msg); !reflect.DeepEqual(err, test.wantError) { 380 t.Errorf("DTContext.Send() error = %v, Want = %v", err, test.wantError) 381 } 382 }) 383 } 384 } 385 386 //TestBuildModelMessage is to test BuildModelMessage(). 387 func TestBuildModelMessage(t *testing.T) { 388 dtc := &DTContext{} 389 payload := dttype.MembershipUpdate{ 390 AddDevices: []dttype.Device{ 391 { 392 ID: "DeviceA", 393 Name: "Router", 394 State: "unknown", 395 }, 396 }, 397 } 398 content, err := json.Marshal(payload) 399 if err != nil { 400 t.Errorf("Error on Marshalling: %v", err) 401 } 402 tests := []struct { 403 name string 404 group string 405 parentID string 406 resource string 407 operation string 408 content interface{} 409 want *model.Message 410 }{ 411 { 412 name: "BuildModelMessageTest", 413 group: "resource", 414 resource: "membership/detail", 415 operation: "get", 416 content: content, 417 want: &model.Message{}, 418 }, 419 } 420 for _, test := range tests { 421 t.Run(test.name, func(t *testing.T) { 422 got := dtc.BuildModelMessage(test.group, test.parentID, test.resource, test.operation, test.content) 423 if got.Header.ParentID != test.parentID { 424 t.Errorf("DTContext.BuildModelMessage failed due to wrong parentID, Got = %v Want = %v", got.Header.ParentID, test.parentID) 425 return 426 } 427 if got.Router.Source != modules.TwinGroup { 428 t.Errorf("DtContext.BuildModelMessage failed due to wrong source, Got= %v Want = %v", got.Router.Source, modules.TwinGroup) 429 return 430 } 431 if got.Router.Group != test.group { 432 t.Errorf("DTContext.BuildModelMessage due to wrong group, Got = %v Want = %v", got.Router.Group, test.group) 433 return 434 } 435 if got.Router.Resource != test.resource { 436 t.Errorf("DTContext.BuildModelMessage failed due to wrong resource, Got = %v Want =%v ", got.Router.Resource, test.resource) 437 return 438 } 439 if got.Router.Operation != test.operation { 440 t.Errorf("DTContext.BuildModelMessage failed due to wrong operation, Got = %v Want = %v ", got.Router.Operation, test.operation) 441 return 442 } 443 if !reflect.DeepEqual(got.Content, test.content) { 444 t.Errorf("DTContext.buildModelMessage failed due to wrong content, Got= %v Want = %v", got.Content, test.content) 445 return 446 } 447 }) 448 } 449 }