github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/devicetwin/dtmanager/device_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  	"encoding/json"
    21  	"errors"
    22  	"reflect"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/astaxie/beego/orm"
    27  	"github.com/golang/mock/gomock"
    28  
    29  	beehiveContext "github.com/kubeedge/beehive/pkg/core/context"
    30  	"github.com/kubeedge/beehive/pkg/core/model"
    31  	"github.com/kubeedge/kubeedge/edge/mocks/beego"
    32  	"github.com/kubeedge/kubeedge/edge/pkg/common/dbm"
    33  	"github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtclient"
    34  	"github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtcommon"
    35  	"github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dtcontext"
    36  	"github.com/kubeedge/kubeedge/edge/pkg/devicetwin/dttype"
    37  )
    38  
    39  var called bool
    40  
    41  //testAction is a dummy function for testing Start
    42  func testAction(context *dtcontext.DTContext, resource string, msg interface{}) (interface{}, error) {
    43  	called = true
    44  	return called, errors.New("Called the dummy function for testing")
    45  }
    46  
    47  // TestDeviceStartAction is function to test Start() when value is passed in ReceiverChan.
    48  func TestDeviceStartAction(t *testing.T) {
    49  	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)
    50  	dtContextStateConnected, _ := dtcontext.InitDTContext()
    51  	dtContextStateConnected.State = dtcommon.Connected
    52  	content := dttype.DeviceUpdate{}
    53  	bytes, _ := json.Marshal(content)
    54  	msg := model.Message{Content: bytes}
    55  
    56  	receiveChanActionPresent := make(chan interface{}, 1)
    57  	receiveChanActionPresent <- &dttype.DTMessage{
    58  		Action:   "testAction",
    59  		Identity: "identity",
    60  		Msg:      &msg,
    61  	}
    62  
    63  	receiveChanActionNotPresent := make(chan interface{}, 1)
    64  	receiveChanActionNotPresent <- &dttype.DTMessage{
    65  		Action:   "action",
    66  		Identity: "identity",
    67  		Msg: &model.Message{
    68  			Content: "msg",
    69  		},
    70  	}
    71  	tests := []struct {
    72  		name   string
    73  		Worker Worker
    74  	}{
    75  		{
    76  			name: "StartTest-ActionNotPresentInActionCallback",
    77  			Worker: Worker{
    78  				ReceiverChan: receiveChanActionNotPresent,
    79  				DTContexts:   dtContextStateConnected,
    80  			},
    81  		},
    82  	}
    83  	for _, test := range tests {
    84  		t.Run(test.name, func(t *testing.T) {
    85  			dw := DeviceWorker{
    86  				Worker: test.Worker,
    87  			}
    88  			go dw.Start()
    89  			time.Sleep(1 * time.Millisecond)
    90  			//Adding a dummy function to callback to ensure Start is successful.
    91  			deviceActionCallBack["testAction"] = testAction
    92  			dw.ReceiverChan <- &dttype.DTMessage{
    93  				Action:   "testAction",
    94  				Identity: "identity",
    95  				Msg:      &msg,
    96  			}
    97  			time.Sleep(1 * time.Millisecond)
    98  			if !called {
    99  				t.Errorf("Start failed")
   100  			}
   101  		})
   102  	}
   103  }
   104  
   105  // TestDevicetHeartBeat is function to test Start() when value is passed in HeartBeatChan.
   106  func TestDeviceStartHeartBeat(t *testing.T) {
   107  	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)
   108  	dtContexts, _ := dtcontext.InitDTContext()
   109  	heartChanStop := make(chan interface{}, 1)
   110  	heartChanPing := make(chan interface{}, 1)
   111  	heartChanStop <- "stop"
   112  	heartChanPing <- "ping"
   113  	tests := []struct {
   114  		name   string
   115  		Worker Worker
   116  		Group  string
   117  	}{
   118  		{
   119  			name: "StartTest-PingInHeartBeatChannel",
   120  			Worker: Worker{
   121  				HeartBeatChan: heartChanPing,
   122  				DTContexts:    dtContexts,
   123  			},
   124  			Group: "group",
   125  		},
   126  		{
   127  			name: "StartTest-StopInHeartBeatChannel",
   128  			Worker: Worker{
   129  				HeartBeatChan: heartChanStop,
   130  				DTContexts:    dtContexts,
   131  			},
   132  			Group: "group",
   133  		},
   134  	}
   135  	for _, test := range tests {
   136  		t.Run(test.name, func(t *testing.T) {
   137  			dw := DeviceWorker{
   138  				Worker: test.Worker,
   139  				Group:  test.Group,
   140  			}
   141  			go dw.Start()
   142  			time.Sleep(1 * time.Millisecond)
   143  			if test.Worker.HeartBeatChan == heartChanPing {
   144  				_, exist := test.Worker.DTContexts.ModulesHealth.Load("group")
   145  				if !exist {
   146  					t.Errorf("Start Failed to add module in beehiveContext")
   147  				}
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  // TestDealDeviceStatusUpdate test dealDeviceStatusUpdate
   154  func TestDealDeviceStateUpdate(t *testing.T) {
   155  	var ormerMock *beego.MockOrmer
   156  	var querySeterMock *beego.MockQuerySeter
   157  	var emptyDevUpdate dttype.DeviceUpdate
   158  	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)
   159  	mockCtrl := gomock.NewController(t)
   160  	defer mockCtrl.Finish()
   161  	ormerMock = beego.NewMockOrmer(mockCtrl)
   162  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   163  	dbm.DBAccess = ormerMock
   164  
   165  	dtContexts, err := dtcontext.InitDTContext()
   166  	if err != nil {
   167  		t.Errorf("InitDTContext error %v", err)
   168  		return
   169  	}
   170  
   171  	dtContexts.DeviceList.Store("DeviceC", "DeviceC")
   172  	deviceD := &dttype.Device{}
   173  	dtContexts.DeviceList.Store("DeviceD", deviceD)
   174  	bytesEmptyDevUpdate, err := json.Marshal(emptyDevUpdate)
   175  	if err != nil {
   176  		t.Errorf("marshal error %v", err)
   177  		return
   178  	}
   179  	devUpdate := &dttype.DeviceUpdate{State: "online"}
   180  	bytesDevUpdate, err := json.Marshal(devUpdate)
   181  	if err != nil {
   182  		t.Errorf("marshal error %v", err)
   183  		return
   184  	}
   185  
   186  	tests := []struct {
   187  		name     string
   188  		context  *dtcontext.DTContext
   189  		resource string
   190  		msg      interface{}
   191  		want     interface{}
   192  		wantErr  error
   193  		// filterReturn is the return of mock interface querySeterMock's filter function
   194  		filterReturn orm.QuerySeter
   195  		// updateReturnInt is the first return of mock interface querySeterMock's update function
   196  		updateReturnInt int64
   197  		// updateReturnErr is the second return of mock interface querySeterMocks's update function also expected error
   198  		updateReturnErr error
   199  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   200  		queryTableReturn orm.QuerySeter
   201  		times            int
   202  	}{
   203  		{
   204  			name:     "dealDeviceStateUpdateTest-WrongMessageType",
   205  			context:  dtContexts,
   206  			resource: "DeviceA",
   207  			msg:      "",
   208  			want:     nil,
   209  			wantErr:  errors.New("msg not Message type"),
   210  		},
   211  		{
   212  			name:     "dealDeviceStateUpdateTest-DeviceDoesNotExist",
   213  			context:  dtContexts,
   214  			resource: "DeviceB",
   215  			msg:      &model.Message{Content: bytesEmptyDevUpdate},
   216  			want:     nil,
   217  			wantErr:  nil,
   218  		},
   219  		{
   220  			name:     "dealDeviceStateUpdateTest-DeviceExist",
   221  			context:  dtContexts,
   222  			resource: "DeviceC",
   223  			msg:      &model.Message{Content: bytesEmptyDevUpdate},
   224  			want:     nil,
   225  			wantErr:  nil,
   226  		},
   227  		{
   228  			name:     "dealDeviceStateUpdateTest-CorrectDeviceType",
   229  			context:  dtContexts,
   230  			resource: "DeviceD",
   231  			msg:      &model.Message{Content: bytesEmptyDevUpdate},
   232  			want:     nil,
   233  			wantErr:  nil,
   234  		},
   235  		{
   236  			name:             "dealDeviceStateUpdateTest-UpdatePresent",
   237  			context:          dtContexts,
   238  			resource:         "DeviceD",
   239  			msg:              &model.Message{Content: bytesDevUpdate},
   240  			want:             nil,
   241  			wantErr:          nil,
   242  			filterReturn:     querySeterMock,
   243  			updateReturnInt:  int64(1),
   244  			updateReturnErr:  nil,
   245  			queryTableReturn: querySeterMock,
   246  			times:            2,
   247  		},
   248  	}
   249  	for _, test := range tests {
   250  		t.Run(test.name, func(t *testing.T) {
   251  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(test.times)
   252  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(test.times)
   253  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(test.times)
   254  			got, err := dealDeviceStateUpdate(test.context, test.resource, test.msg)
   255  			if !reflect.DeepEqual(err, test.wantErr) {
   256  				t.Errorf("dealDeviceStateUpdate() error = %v, wantErr %v", err, test.wantErr)
   257  				return
   258  			}
   259  			if !reflect.DeepEqual(got, test.want) {
   260  				t.Errorf("dealDeviceStateUpdate() = %v, want %v", got, test.want)
   261  			}
   262  		})
   263  	}
   264  }
   265  
   266  //TestDealDeviceUpdated is function to test dealDeviceUpdated().
   267  func TestDealDeviceUpdated(t *testing.T) {
   268  	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)
   269  	dtContexts, _ := dtcontext.InitDTContext()
   270  	content := dttype.DeviceUpdate{}
   271  	bytes, err := json.Marshal(content)
   272  	if err != nil {
   273  		t.Errorf("marshal error %v", err)
   274  		return
   275  	}
   276  	msg := model.Message{Content: bytes}
   277  	tests := []struct {
   278  		name     string
   279  		context  *dtcontext.DTContext
   280  		resource string
   281  		msg      interface{}
   282  		want     interface{}
   283  		wantErr  error
   284  	}{
   285  		{
   286  			name:     "DealDeviceUpdatedTest-Wrong Message Type",
   287  			context:  dtContexts,
   288  			resource: "Device",
   289  			msg:      "",
   290  			want:     nil,
   291  			wantErr:  errors.New("msg not Message type"),
   292  		},
   293  		{
   294  			name:     "DealDeviceUpdatedTest-Correct Message Type",
   295  			context:  dtContexts,
   296  			resource: "DeviceA",
   297  			msg:      &msg,
   298  			want:     nil,
   299  			wantErr:  nil,
   300  		},
   301  	}
   302  	for _, test := range tests {
   303  		t.Run(test.name, func(t *testing.T) {
   304  			got, err := dealDeviceUpdated(test.context, test.resource, test.msg)
   305  			if !reflect.DeepEqual(err, test.wantErr) {
   306  				t.Errorf("dealDeviceUpdated() error = %v, wantErr %v", err, test.wantErr)
   307  				return
   308  			}
   309  			if !reflect.DeepEqual(got, test.want) {
   310  				t.Errorf("dealDeviceUpdated() = %v, want %v", got, test.want)
   311  			}
   312  		})
   313  	}
   314  }
   315  
   316  // TestDeviceUpdated is function to test DeviceUpdated().
   317  func TestDeviceUpdated(t *testing.T) {
   318  	var ormerMock *beego.MockOrmer
   319  	var querySeterMock *beego.MockQuerySeter
   320  	beehiveContext.InitContext(beehiveContext.MsgCtxTypeChannel)
   321  	mockCtrl := gomock.NewController(t)
   322  	defer mockCtrl.Finish()
   323  	ormerMock = beego.NewMockOrmer(mockCtrl)
   324  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   325  	dbm.DBAccess = ormerMock
   326  
   327  	// adds is fake DeviceAttr used as argument
   328  	adds := make([]dtclient.DeviceAttr, 0)
   329  	// deletes is fake DeviceDelete used as argument
   330  	deletes := make([]dtclient.DeviceDelete, 0)
   331  	// updates is fake DeviceAttrUpdate used as argument
   332  	updates := make([]dtclient.DeviceAttrUpdate, 0)
   333  	adds = append(adds, dtclient.DeviceAttr{
   334  		DeviceID: "Test",
   335  	})
   336  	deletes = append(deletes, dtclient.DeviceDelete{
   337  		DeviceID: "test",
   338  		Name:     "test",
   339  	})
   340  	updates = append(updates, dtclient.DeviceAttrUpdate{
   341  		DeviceID: "test",
   342  		Name:     "test",
   343  		Cols:     make(map[string]interface{}),
   344  	})
   345  
   346  	dtContexts, _ := dtcontext.InitDTContext()
   347  	dtContexts.DeviceList.Store("EmptyDevice", "Device")
   348  
   349  	devA := &dttype.Device{ID: "DeviceA"}
   350  	dtContexts.DeviceList.Store("DeviceA", devA)
   351  
   352  	messageAttributes := make(map[string]*dttype.MsgAttr)
   353  	optional := true
   354  	msgattr := &dttype.MsgAttr{
   355  		Value:    "ON",
   356  		Optional: &optional,
   357  		Metadata: &dttype.TypeMetadata{
   358  			Type: "device",
   359  		},
   360  	}
   361  	messageAttributes["DeviceA"] = msgattr
   362  	baseMessage := dttype.BuildBaseMessage()
   363  
   364  	tests := []struct {
   365  		name        string
   366  		context     *dtcontext.DTContext
   367  		deviceID    string
   368  		attributes  map[string]*dttype.MsgAttr
   369  		baseMessage dttype.BaseMessage
   370  		dealType    int
   371  		want        interface{}
   372  		wantErr     error
   373  		// commitTimes is number of times commit is expected
   374  		commitTimes int
   375  		// beginTimes is number of times begin is expected
   376  		beginTimes int
   377  		// filterReturn is the return of mock interface querySeterMock's filter function
   378  		filterReturn orm.QuerySeter
   379  		// filterTimes is the number of times filter is called
   380  		filterTimes int
   381  		// insertReturnInt is the first return of mock interface ormerMock's Insert function
   382  		insertReturnInt int64
   383  		// insertReturnErr is the second return of mock interface ormerMock's Insert function
   384  		insertReturnErr error
   385  		// insertTimes is number of times Insert is expected
   386  		insertTimes int
   387  		// deleteReturnInt is the first return of mock interface ormerMock's Delete function
   388  		deleteReturnInt int64
   389  		// deleteReturnErr is the second return of mock interface ormerMock's Delete function
   390  		deleteReturnErr error
   391  		// deleteTimes is number of times Delete is expected
   392  		deleteTimes int
   393  		// updateReturnInt is the first return of mock interface ormerMock's Update function
   394  		updateReturnInt int64
   395  		// updateReturnErr is the second return of mock interface ormerMock's Update function
   396  		updateReturnErr error
   397  		// updateTimes is number of times Update is expected
   398  		updateTimes int
   399  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   400  		queryTableReturn orm.QuerySeter
   401  		// queryTableTimes is the number of times queryTable is called
   402  		queryTableTimes int
   403  	}{
   404  		{
   405  			name:        "Test1",
   406  			context:     dtContexts,
   407  			deviceID:    "Device",
   408  			attributes:  messageAttributes,
   409  			baseMessage: baseMessage,
   410  			want:        nil,
   411  			wantErr:     nil,
   412  		},
   413  		{
   414  			name:        "Test2",
   415  			context:     dtContexts,
   416  			deviceID:    "EmptyDevice",
   417  			attributes:  messageAttributes,
   418  			baseMessage: baseMessage,
   419  			want:        nil,
   420  			wantErr:     nil,
   421  		},
   422  		{
   423  			name:             "Test3",
   424  			context:          dtContexts,
   425  			deviceID:         "DeviceA",
   426  			attributes:       messageAttributes,
   427  			baseMessage:      baseMessage,
   428  			wantErr:          nil,
   429  			want:             nil,
   430  			commitTimes:      1,
   431  			beginTimes:       1,
   432  			filterReturn:     querySeterMock,
   433  			filterTimes:      0,
   434  			insertReturnInt:  int64(1),
   435  			insertReturnErr:  nil,
   436  			insertTimes:      1,
   437  			deleteReturnInt:  int64(1),
   438  			deleteReturnErr:  nil,
   439  			deleteTimes:      0,
   440  			updateReturnInt:  int64(1),
   441  			updateReturnErr:  nil,
   442  			updateTimes:      0,
   443  			queryTableReturn: querySeterMock,
   444  			queryTableTimes:  0,
   445  		},
   446  	}
   447  	for _, test := range tests {
   448  		t.Run(test.name, func(t *testing.T) {
   449  			ormerMock.EXPECT().Commit().Return(nil).Times(test.commitTimes)
   450  			ormerMock.EXPECT().Begin().Return(nil).Times(test.beginTimes)
   451  			ormerMock.EXPECT().Insert(gomock.Any()).Return(test.insertReturnInt, test.insertReturnErr).Times(test.insertTimes)
   452  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(test.queryTableTimes)
   453  
   454  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(test.filterTimes)
   455  			querySeterMock.EXPECT().Delete().Return(test.deleteReturnInt, test.deleteReturnErr).Times(test.deleteTimes)
   456  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(test.updateTimes)
   457  
   458  			got, err := DeviceUpdated(test.context, test.deviceID, test.attributes, test.baseMessage, test.dealType)
   459  			if !reflect.DeepEqual(err, test.wantErr) {
   460  				t.Errorf("DeviceUpdated() error = %v, wantErr %v", err, test.wantErr)
   461  				return
   462  			}
   463  			if !reflect.DeepEqual(got, test.want) {
   464  				t.Errorf("DeviceUpdated() failed Got = %v, want %v", got, test.want)
   465  			}
   466  		})
   467  	}
   468  }
   469  
   470  // TestDealMsgAttr is function to test DealMsgAttr().
   471  func TestDealMsgAttr(t *testing.T) {
   472  	dtContextsEmptyAttributes, err := dtcontext.InitDTContext()
   473  	if err != nil {
   474  		t.Errorf("initDtcontext error %v", err)
   475  		return
   476  	}
   477  	dtContextsNonEmptyAttributes, err := dtcontext.InitDTContext()
   478  	if err != nil {
   479  		t.Errorf("initDtcontext error %v", err)
   480  		return
   481  	}
   482  	//Creating want and message attributes when device attribute is not present
   483  	devA := &dttype.Device{ID: "DeviceA"}
   484  	dtContextsEmptyAttributes.DeviceList.Store("DeviceA", devA)
   485  
   486  	messageAttributes := make(map[string]*dttype.MsgAttr)
   487  	optional := true
   488  
   489  	msgattr := &dttype.MsgAttr{
   490  		Value:    "ON",
   491  		Optional: &optional,
   492  		Metadata: &dttype.TypeMetadata{
   493  			Type: "device",
   494  		},
   495  	}
   496  	messageAttributes["DeviceA"] = msgattr
   497  	add := []dtclient.DeviceAttr{}
   498  	add = append(add, dtclient.DeviceAttr{
   499  		ID:       0,
   500  		DeviceID: "DeviceA",
   501  		Name:     "DeviceA",
   502  		Value:    "ON",
   503  		Optional: true,
   504  		AttrType: "device",
   505  		Metadata: "{}",
   506  	})
   507  	result := make(map[string]*dttype.MsgAttr)
   508  	result["DeviceA"] = msgattr
   509  	wantDealAttrResult := dttype.DealAttrResult{
   510  		Add:    add,
   511  		Delete: []dtclient.DeviceDelete{},
   512  		Update: []dtclient.DeviceAttrUpdate{},
   513  		Result: result,
   514  		Err:    nil,
   515  	}
   516  	//Creating want and message attributes when device attribute is present
   517  	attributes := map[string]*dttype.MsgAttr{}
   518  	attributes["DeviceB"] = msgattr
   519  	attr := map[string]*dttype.MsgAttr{}
   520  	opt := false
   521  	attr["DeviceB"] = &dttype.MsgAttr{
   522  		Value:    "OFF",
   523  		Optional: &opt,
   524  		Metadata: &dttype.TypeMetadata{
   525  			Type: "device",
   526  		},
   527  	}
   528  	devB := &dttype.Device{ID: "DeviceB", Attributes: attr}
   529  	update := []dtclient.DeviceAttrUpdate{}
   530  	cols := make(map[string]interface{})
   531  	cols["value"] = "ON"
   532  	upd := dtclient.DeviceAttrUpdate{
   533  		Name:     "DeviceB",
   534  		DeviceID: "DeviceB",
   535  		Cols:     cols,
   536  	}
   537  	update = append(update, upd)
   538  	dtContextsNonEmptyAttributes.DeviceList.Store("DeviceB", devB)
   539  	want := dttype.DealAttrResult{
   540  		Add:    []dtclient.DeviceAttr{},
   541  		Delete: []dtclient.DeviceDelete{},
   542  		Update: update,
   543  	}
   544  
   545  	tests := []struct {
   546  		name          string
   547  		context       *dtcontext.DTContext
   548  		deviceID      string
   549  		msgAttributes map[string]*dttype.MsgAttr
   550  		dealType      int
   551  		want          dttype.DealAttrResult
   552  	}{
   553  		{
   554  			name:          "DealMsgAttrTest-DeviceAttribute not present",
   555  			context:       dtContextsEmptyAttributes,
   556  			deviceID:      "DeviceA",
   557  			msgAttributes: messageAttributes,
   558  			want:          wantDealAttrResult,
   559  		},
   560  		{
   561  			name:          "DealMsgAttrTest-DeviceAttribute present",
   562  			context:       dtContextsNonEmptyAttributes,
   563  			deviceID:      "DeviceB",
   564  			msgAttributes: attributes,
   565  			dealType:      1,
   566  			want:          want,
   567  		},
   568  	}
   569  	for _, tt := range tests {
   570  		t.Run(tt.name, func(t *testing.T) {
   571  			got := DealMsgAttr(tt.context, tt.deviceID, tt.msgAttributes, tt.dealType)
   572  			if !reflect.DeepEqual(got.Add, tt.want.Add) {
   573  				t.Errorf("Add error , Got = %v, Want = %v", got.Add, tt.want.Add)
   574  				return
   575  			}
   576  			if !reflect.DeepEqual(got.Delete, tt.want.Delete) {
   577  				t.Errorf("Delete error , Got = %v, Want = %v", got.Delete, tt.want.Delete)
   578  				return
   579  			}
   580  			if !reflect.DeepEqual(got.Update, tt.want.Update) {
   581  				t.Errorf("Update error , Got = %v, Want = %v", got.Update, tt.want.Update)
   582  				return
   583  			}
   584  			if !reflect.DeepEqual(got.Err, tt.want.Err) {
   585  				t.Errorf("Error error , Got = %v, Want = %v", got.Update, tt.want.Update)
   586  				return
   587  			}
   588  			for key, value := range tt.want.Result {
   589  				check := false
   590  				for key1, value1 := range got.Result {
   591  					if key == key1 {
   592  						if value == value1 {
   593  							check = true
   594  							break
   595  						}
   596  					}
   597  					if check == false {
   598  						t.Errorf("Wrong Map")
   599  						return
   600  					}
   601  				}
   602  			}
   603  		})
   604  	}
   605  }