github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/devicetwin/dtclient/deviceattr_db_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 dtclient
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/astaxie/beego/orm"
    23  	"github.com/golang/mock/gomock"
    24  
    25  	"github.com/kubeedge/kubeedge/edge/mocks/beego"
    26  	"github.com/kubeedge/kubeedge/edge/pkg/common/dbm"
    27  )
    28  
    29  // TestSaveDeviceAttr is function to test SaveDeviceAttr
    30  func TestSaveDeviceAttr(t *testing.T) {
    31  	//Initialize Global Variables (Mocks)
    32  	// ormerMock is mocked Ormer implementation
    33  	var ormerMock *beego.MockOrmer
    34  
    35  	mockCtrl := gomock.NewController(t)
    36  	defer mockCtrl.Finish()
    37  	ormerMock = beego.NewMockOrmer(mockCtrl)
    38  	dbm.DBAccess = ormerMock
    39  
    40  	cases := []struct {
    41  		// name is name of the testcase
    42  		name string
    43  		// returnInt is first return of mock interface ormerMock
    44  		returnInt int64
    45  		// returnErr is second return of mock interface ormerMock which is also expected error
    46  		returnErr error
    47  	}{{
    48  		// Success Case
    49  		name:      "SuccessCase",
    50  		returnInt: int64(1),
    51  		returnErr: nil,
    52  	}, {
    53  		// Failure Case
    54  		name:      "FailureCase",
    55  		returnInt: int64(1),
    56  		returnErr: errFailedDBOperation,
    57  	},
    58  	}
    59  
    60  	// run the test cases
    61  	for _, test := range cases {
    62  		t.Run(test.name, func(t *testing.T) {
    63  			ormerMock.EXPECT().Insert(gomock.Any()).Return(test.returnInt, test.returnErr).Times(1)
    64  			err := SaveDeviceAttr(&DeviceAttr{})
    65  			if test.returnErr != err {
    66  				t.Errorf("Save Device Attr Case failed: wanted error %v and got error %v", test.returnErr, err)
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  // TestDeleteDeviceAttrByDeviceID is function to test DeleteDeviceAttrByDeviceID
    73  func TestDeleteDeviceAttrByDeviceID(t *testing.T) {
    74  	// ormerMock is mocked Ormer implementation
    75  	var ormerMock *beego.MockOrmer
    76  	// querySeterMock is mocked QuerySeter implementation
    77  	var querySeterMock *beego.MockQuerySeter
    78  
    79  	mockCtrl := gomock.NewController(t)
    80  	defer mockCtrl.Finish()
    81  	ormerMock = beego.NewMockOrmer(mockCtrl)
    82  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
    83  	dbm.DBAccess = ormerMock
    84  
    85  	cases := []struct {
    86  		// name is name of the testcase
    87  		name string
    88  		// filterReturn is the return of mock interface querySeterMock's filter function
    89  		filterReturn orm.QuerySeter
    90  		// deleteReturnInt is the first return of mock interface querySeterMock's delete function
    91  		deleteReturnInt int64
    92  		// deleteReturnErr is the second return of mock interface querySeterMocks's delete function also expected error
    93  		deleteReturnErr error
    94  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
    95  		queryTableReturn orm.QuerySeter
    96  	}{{
    97  		// Success Case
    98  		name:             "SuccessCase",
    99  		filterReturn:     querySeterMock,
   100  		deleteReturnInt:  int64(1),
   101  		deleteReturnErr:  nil,
   102  		queryTableReturn: querySeterMock,
   103  	}, {
   104  		// Failure Case
   105  		name:             "FailureCase",
   106  		filterReturn:     querySeterMock,
   107  		deleteReturnInt:  int64(0),
   108  		deleteReturnErr:  errFailedDBOperation,
   109  		queryTableReturn: querySeterMock,
   110  	},
   111  	}
   112  
   113  	// run the test cases
   114  	for _, test := range cases {
   115  		t.Run(test.name, func(t *testing.T) {
   116  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(1)
   117  			querySeterMock.EXPECT().Delete().Return(test.deleteReturnInt, test.deleteReturnErr).Times(1)
   118  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   119  			err := DeleteDeviceAttrByDeviceID("test")
   120  			if test.deleteReturnErr != err {
   121  				t.Errorf("DeleteDeviceAttrByDeviceID Case failed: wanted error %v and got error %v", test.deleteReturnErr, err)
   122  			}
   123  		})
   124  	}
   125  }
   126  
   127  // TestDeleteDeviceAttr is function to test DeleteDeviceAttr
   128  func TestDeleteDeviceAttr(t *testing.T) {
   129  	// ormerMock is mocked Ormer implementation
   130  	var ormerMock *beego.MockOrmer
   131  	// querySeterMock is mocked QuerySeter implementation
   132  	var querySeterMock *beego.MockQuerySeter
   133  
   134  	mockCtrl := gomock.NewController(t)
   135  	defer mockCtrl.Finish()
   136  	ormerMock = beego.NewMockOrmer(mockCtrl)
   137  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   138  	dbm.DBAccess = ormerMock
   139  
   140  	cases := []struct {
   141  		// name is name of the testcase
   142  		name string
   143  		// filterReturn is the return of mock interface querySeterMock's filter function
   144  		filterReturn orm.QuerySeter
   145  		// deleteReturnInt is the first return of mock interface querySeterMock's delete function
   146  		deleteReturnInt int64
   147  		// deleteReturnErr is the second return of mock interface querySeterMocks's delete function also expected error
   148  		deleteReturnErr error
   149  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   150  		queryTableReturn orm.QuerySeter
   151  	}{{
   152  		// Success Case
   153  		name:             "SuccessCase",
   154  		filterReturn:     querySeterMock,
   155  		deleteReturnInt:  int64(1),
   156  		deleteReturnErr:  nil,
   157  		queryTableReturn: querySeterMock,
   158  	}, {
   159  		// Failure Case
   160  		name:             "FailureCase",
   161  		filterReturn:     querySeterMock,
   162  		deleteReturnInt:  int64(0),
   163  		deleteReturnErr:  errFailedDBOperation,
   164  		queryTableReturn: querySeterMock,
   165  	},
   166  	}
   167  
   168  	// run the test cases
   169  	for _, test := range cases {
   170  		querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(2)
   171  		querySeterMock.EXPECT().Delete().Return(test.deleteReturnInt, test.deleteReturnErr).Times(1)
   172  		ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   173  		err := DeleteDeviceAttr("test", "test")
   174  		t.Run(test.name, func(t *testing.T) {
   175  			if test.deleteReturnErr != err {
   176  				t.Errorf("DeleteDeviceAttr Case failed: wanted error %v and got error %v", test.deleteReturnErr, err)
   177  			}
   178  		})
   179  	}
   180  }
   181  
   182  // TestUpdateDeviceAttrField is function to test UpdateDeviceAttrField
   183  func TestUpdateDeviceAttrField(t *testing.T) {
   184  	// ormerMock is mocked Ormer implementation
   185  	var ormerMock *beego.MockOrmer
   186  	// querySeterMock is mocked QuerySeter implementation
   187  	var querySeterMock *beego.MockQuerySeter
   188  
   189  	mockCtrl := gomock.NewController(t)
   190  	defer mockCtrl.Finish()
   191  	ormerMock = beego.NewMockOrmer(mockCtrl)
   192  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   193  	dbm.DBAccess = ormerMock
   194  
   195  	cases := []struct {
   196  		// name is name of the testcase
   197  		name string
   198  		// filterReturn is the return of mock interface querySeterMock's filter function
   199  		filterReturn orm.QuerySeter
   200  		// updateReturnInt is the first return of mock interface querySeterMock's update function
   201  		updateReturnInt int64
   202  		// updateReturnErr is the second return of mock interface querySeterMocks's update function also expected error
   203  		updateReturnErr error
   204  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   205  		queryTableReturn orm.QuerySeter
   206  	}{{
   207  		// Success Case
   208  		name:             "SuccessCase",
   209  		filterReturn:     querySeterMock,
   210  		updateReturnInt:  int64(1),
   211  		updateReturnErr:  nil,
   212  		queryTableReturn: querySeterMock,
   213  	}, {
   214  		// Failure Case
   215  		name:             "FailureCase",
   216  		filterReturn:     querySeterMock,
   217  		updateReturnInt:  int64(0),
   218  		updateReturnErr:  errFailedDBOperation,
   219  		queryTableReturn: querySeterMock,
   220  	},
   221  	}
   222  
   223  	// run the test cases
   224  	for _, test := range cases {
   225  		t.Run(test.name, func(t *testing.T) {
   226  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(2)
   227  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(1)
   228  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   229  			err := UpdateDeviceAttrField("test", "test", "test", "test")
   230  			if test.updateReturnErr != err {
   231  				t.Errorf("UpdateDeviceAttrField Case failed: wanted error %v and got error %v", test.updateReturnErr, err)
   232  			}
   233  		})
   234  	}
   235  }
   236  
   237  // TestUpdateDeviceAttrFields is function to test UpdateDeviceAttrFields
   238  func TestUpdateDeviceAttrFields(t *testing.T) {
   239  	// ormerMock is mocked Ormer implementation
   240  	var ormerMock *beego.MockOrmer
   241  	// querySeterMock is mocked QuerySeter implementation
   242  	var querySeterMock *beego.MockQuerySeter
   243  
   244  	mockCtrl := gomock.NewController(t)
   245  	defer mockCtrl.Finish()
   246  	ormerMock = beego.NewMockOrmer(mockCtrl)
   247  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   248  	dbm.DBAccess = ormerMock
   249  
   250  	cases := []struct {
   251  		// name is name of the testcase
   252  		name string
   253  		// filterReturn is the return of mock interface querySeterMock's filter function
   254  		filterReturn orm.QuerySeter
   255  		// updateReturnInt is the first return of mock interface querySeterMock's update function
   256  		updateReturnInt int64
   257  		// updateReturnErr is the second return of mock interface querySeterMocks's update function also expected error
   258  		updateReturnErr error
   259  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   260  		queryTableReturn orm.QuerySeter
   261  	}{{
   262  		// Success Case
   263  		name:             "SuccessCase",
   264  		filterReturn:     querySeterMock,
   265  		updateReturnInt:  int64(1),
   266  		updateReturnErr:  nil,
   267  		queryTableReturn: querySeterMock,
   268  	}, {
   269  		// Failure Case
   270  		name:             "FailureCase",
   271  		filterReturn:     querySeterMock,
   272  		updateReturnInt:  int64(0),
   273  		updateReturnErr:  errFailedDBOperation,
   274  		queryTableReturn: querySeterMock,
   275  	},
   276  	}
   277  
   278  	// run the test cases
   279  	for _, test := range cases {
   280  		t.Run(test.name, func(t *testing.T) {
   281  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(2)
   282  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(1)
   283  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   284  			err := UpdateDeviceAttrFields("test", "test", make(map[string]interface{}))
   285  			if test.updateReturnErr != err {
   286  				t.Errorf("UpdateDeviceAttrFields Case failed: wanted error %v and got error %v", test.updateReturnErr, err)
   287  			}
   288  		})
   289  	}
   290  }
   291  
   292  // TestQueryDeviceAttr is function to test QueryDeviceAttr
   293  func TestQueryDeviceAttr(t *testing.T) {
   294  	// ormerMock is mocked Ormer implementation
   295  	var ormerMock *beego.MockOrmer
   296  	// querySeterMock is mocked QuerySeter implementation
   297  	var querySeterMock *beego.MockQuerySeter
   298  
   299  	mockCtrl := gomock.NewController(t)
   300  	defer mockCtrl.Finish()
   301  	ormerMock = beego.NewMockOrmer(mockCtrl)
   302  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   303  	dbm.DBAccess = ormerMock
   304  
   305  	cases := []struct {
   306  		// name is name of the testcase
   307  		name string
   308  		// filterReturn is the return of mock interface querySeterMock's filter function
   309  		filterReturn orm.QuerySeter
   310  		// allReturnInt is the first return of mock interface querySeterMock's all function
   311  		allReturnInt int64
   312  		// allReturnErr is the second return of mock interface querySeterMocks's all function also expected error
   313  		allReturnErr error
   314  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   315  		queryTableReturn orm.QuerySeter
   316  	}{{
   317  		// Success Case
   318  		name:             "SuccessCase",
   319  		filterReturn:     querySeterMock,
   320  		allReturnInt:     int64(1),
   321  		allReturnErr:     nil,
   322  		queryTableReturn: querySeterMock,
   323  	}, {
   324  		// Failure Case
   325  		name:             "FailureCase",
   326  		filterReturn:     querySeterMock,
   327  		allReturnInt:     int64(0),
   328  		allReturnErr:     errFailedDBOperation,
   329  		queryTableReturn: querySeterMock,
   330  	},
   331  	}
   332  
   333  	// fakeDeviceAttr is used to set the argument of All function
   334  	fakeDeviceAttr := new([]DeviceAttr)
   335  	fakeDeviceAttrArray := make([]DeviceAttr, 1)
   336  	fakeDeviceAttrArray[0] = DeviceAttr{DeviceID: "Test"}
   337  	fakeDeviceAttr = &fakeDeviceAttrArray
   338  
   339  	// run the test cases
   340  	for _, test := range cases {
   341  		t.Run(test.name, func(t *testing.T) {
   342  			querySeterMock.EXPECT().All(gomock.Any()).SetArg(0, *fakeDeviceAttr).Return(test.allReturnInt, test.allReturnErr).Times(1)
   343  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(1)
   344  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   345  			device, err := QueryDeviceAttr("test", "test")
   346  			if test.allReturnErr != err {
   347  				t.Errorf("QueryDeviceAttr Case failed: wanted error %v and got error %v", test.allReturnErr, err)
   348  			}
   349  
   350  			if err == nil {
   351  				if len(*device) != 1 {
   352  					t.Errorf("QueryDeviceAttr Case failed: wanted length 1 and got length %v", len(*device))
   353  				}
   354  			}
   355  		})
   356  	}
   357  }
   358  
   359  // TestUpdateDeviceAttrMulti is function to test UpdateDeviceAttrMulti
   360  func TestUpdateDeviceAttrMulti(t *testing.T) {
   361  	// ormerMock is mocked Ormer implementation
   362  	var ormerMock *beego.MockOrmer
   363  	// querySeterMock is mocked QuerySeter implementation
   364  	var querySeterMock *beego.MockQuerySeter
   365  
   366  	mockCtrl := gomock.NewController(t)
   367  	defer mockCtrl.Finish()
   368  	ormerMock = beego.NewMockOrmer(mockCtrl)
   369  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   370  	dbm.DBAccess = ormerMock
   371  
   372  	cases := []struct {
   373  		// name is name of the testcase
   374  		name string
   375  		// filterReturn is the return of mock interface querySeterMock's filter function
   376  		filterReturn orm.QuerySeter
   377  		// updateReturnInt is the first return of mock interface querySeterMock's update function
   378  		updateReturnInt int64
   379  		// updateReturnErr is the second return of mock interface querySeterMocks's update function also expected error
   380  		updateReturnErr error
   381  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   382  		queryTableReturn orm.QuerySeter
   383  	}{{
   384  		// Success Case
   385  		name:             "SuccessCase",
   386  		filterReturn:     querySeterMock,
   387  		updateReturnInt:  int64(1),
   388  		updateReturnErr:  nil,
   389  		queryTableReturn: querySeterMock,
   390  	}, {
   391  		// Failure Case
   392  		name:             "FailureCase",
   393  		filterReturn:     querySeterMock,
   394  		updateReturnInt:  int64(0),
   395  		updateReturnErr:  errFailedDBOperation,
   396  		queryTableReturn: querySeterMock,
   397  	},
   398  	}
   399  
   400  	// updateDevice is argument to UpdateDeviceAttrMulti function
   401  	updateDevice := make([]DeviceAttrUpdate, 0)
   402  	updateDevice = append(updateDevice, DeviceAttrUpdate{DeviceID: "test"})
   403  
   404  	// run the test cases
   405  	for _, test := range cases {
   406  		t.Run(test.name, func(t *testing.T) {
   407  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(2)
   408  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(1)
   409  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(1)
   410  			err := UpdateDeviceAttrMulti(updateDevice)
   411  			if test.updateReturnErr != err {
   412  				t.Errorf("UpdateDeviceAttrMulti Case failed: wanted error %v and got error %v", test.updateReturnErr, err)
   413  			}
   414  		})
   415  	}
   416  }
   417  
   418  // TestDeviceAttrTrans is function to test DeviceAttrTrans
   419  func TestDeviceAttrTrans(t *testing.T) {
   420  	// ormerMock is mocked Ormer implementation
   421  	var ormerMock *beego.MockOrmer
   422  	// querySeterMock is mocked QuerySeter implementation
   423  	var querySeterMock *beego.MockQuerySeter
   424  
   425  	mockCtrl := gomock.NewController(t)
   426  	defer mockCtrl.Finish()
   427  	ormerMock = beego.NewMockOrmer(mockCtrl)
   428  	querySeterMock = beego.NewMockQuerySeter(mockCtrl)
   429  	dbm.DBAccess = ormerMock
   430  
   431  	cases := []struct {
   432  		// name is name of the testcase
   433  		name string
   434  		// rollBackTimes is number of times rollback is expected
   435  		rollBackTimes int
   436  		// commitTimes is number of times commit is expected
   437  		commitTimes int
   438  		// beginTimes is number of times begin is expected
   439  		beginTimes int
   440  		// filterReturn is the return of mock interface querySeterMock's filter function
   441  		filterReturn orm.QuerySeter
   442  		// filterTimes is the number of times filter is called
   443  		filterTimes int
   444  		// insertReturnInt is the first return of mock interface ormerMock's Insert function
   445  		insertReturnInt int64
   446  		// insertReturnErr is the second return of mock interface ormerMock's Insert function
   447  		insertReturnErr error
   448  		// insertTimes is number of times Insert is expected
   449  		insertTimes int
   450  		// deleteReturnInt is the first return of mock interface ormerMock's Delete function
   451  		deleteReturnInt int64
   452  		// deleteReturnErr is the second return of mock interface ormerMock's Delete function
   453  		deleteReturnErr error
   454  		// deleteTimes is number of times Delete is expected
   455  		deleteTimes int
   456  		// updateReturnInt is the first return of mock interface ormerMock's Update function
   457  		updateReturnInt int64
   458  		// updateReturnErr is the second return of mock interface ormerMock's Update function
   459  		updateReturnErr error
   460  		// updateTimes is number of times Update is expected
   461  		updateTimes int
   462  		// queryTableReturn is the return of mock interface ormerMock's QueryTable function
   463  		queryTableReturn orm.QuerySeter
   464  		// queryTableTimes is the number of times queryTable is called
   465  		queryTableTimes int
   466  		// wantErr is expected error
   467  		wantErr error
   468  	}{{
   469  		// Failure Case SaveDeviceAttr
   470  		name:             "DeviceAttrTransSaveDeviceAttrFailureCase",
   471  		rollBackTimes:    1,
   472  		commitTimes:      0,
   473  		beginTimes:       1,
   474  		filterReturn:     nil,
   475  		filterTimes:      0,
   476  		insertReturnInt:  int64(1),
   477  		insertReturnErr:  errFailedDBOperation,
   478  		insertTimes:      1,
   479  		deleteReturnInt:  int64(1),
   480  		deleteReturnErr:  nil,
   481  		deleteTimes:      0,
   482  		updateReturnInt:  int64(1),
   483  		updateReturnErr:  nil,
   484  		updateTimes:      0,
   485  		queryTableReturn: nil,
   486  		queryTableTimes:  0,
   487  		wantErr:          errFailedDBOperation,
   488  	}, {
   489  		// Failure Case DeleteDeviceAttr
   490  		name:             "DeviceAttrTransDeleteDeviceAttrFailureCase",
   491  		rollBackTimes:    1,
   492  		commitTimes:      0,
   493  		beginTimes:       1,
   494  		filterReturn:     querySeterMock,
   495  		filterTimes:      2,
   496  		insertReturnInt:  int64(1),
   497  		insertReturnErr:  nil,
   498  		insertTimes:      1,
   499  		deleteReturnInt:  int64(1),
   500  		deleteReturnErr:  errFailedDBOperation,
   501  		deleteTimes:      1,
   502  		updateReturnInt:  int64(1),
   503  		updateReturnErr:  nil,
   504  		updateTimes:      0,
   505  		queryTableReturn: querySeterMock,
   506  		queryTableTimes:  1,
   507  		wantErr:          errFailedDBOperation,
   508  	}, {
   509  		// Failure Case UpdateDeviceAttrFields
   510  		name:             "DeviceAttrTransUpdateDeviceAttrFieldsFailureCase",
   511  		rollBackTimes:    1,
   512  		commitTimes:      0,
   513  		beginTimes:       1,
   514  		filterReturn:     querySeterMock,
   515  		filterTimes:      4,
   516  		insertReturnInt:  int64(1),
   517  		insertReturnErr:  nil,
   518  		insertTimes:      1,
   519  		deleteReturnInt:  int64(1),
   520  		deleteReturnErr:  nil,
   521  		deleteTimes:      1,
   522  		updateReturnInt:  int64(1),
   523  		updateReturnErr:  errFailedDBOperation,
   524  		updateTimes:      1,
   525  		queryTableReturn: querySeterMock,
   526  		queryTableTimes:  2,
   527  		wantErr:          errFailedDBOperation,
   528  	}, {
   529  		// Success Case
   530  		name:             "DeviceAttrTransSuccessCase",
   531  		rollBackTimes:    0,
   532  		commitTimes:      1,
   533  		beginTimes:       1,
   534  		filterReturn:     querySeterMock,
   535  		filterTimes:      4,
   536  		insertReturnInt:  int64(1),
   537  		insertReturnErr:  nil,
   538  		insertTimes:      1,
   539  		deleteReturnInt:  int64(1),
   540  		deleteReturnErr:  nil,
   541  		deleteTimes:      1,
   542  		updateReturnInt:  int64(1),
   543  		updateReturnErr:  nil,
   544  		updateTimes:      1,
   545  		queryTableReturn: querySeterMock,
   546  		queryTableTimes:  2,
   547  		wantErr:          nil,
   548  	},
   549  	}
   550  
   551  	// adds is fake DeviceAttr used as argument
   552  	adds := make([]DeviceAttr, 0)
   553  	// deletes is fake DeviceDelete used as argument
   554  	deletes := make([]DeviceDelete, 0)
   555  	// updates is fake DeviceAttrUpdate used as argument
   556  	updates := make([]DeviceAttrUpdate, 0)
   557  	adds = append(adds, DeviceAttr{DeviceID: "Test"})
   558  	deletes = append(deletes, DeviceDelete{DeviceID: "test", Name: "test"})
   559  	updates = append(updates, DeviceAttrUpdate{DeviceID: "test", Name: "test", Cols: make(map[string]interface{})})
   560  
   561  	// run the test cases
   562  	for _, test := range cases {
   563  		t.Run(test.name, func(t *testing.T) {
   564  			ormerMock.EXPECT().Rollback().Return(nil).Times(test.rollBackTimes)
   565  			ormerMock.EXPECT().Commit().Return(nil).Times(test.commitTimes)
   566  			ormerMock.EXPECT().Begin().Return(nil).Times(test.beginTimes)
   567  			ormerMock.EXPECT().Insert(gomock.Any()).Return(test.insertReturnInt, test.insertReturnErr).Times(test.insertTimes)
   568  			ormerMock.EXPECT().QueryTable(gomock.Any()).Return(test.queryTableReturn).Times(test.queryTableTimes)
   569  
   570  			querySeterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(test.filterReturn).Times(test.filterTimes)
   571  			querySeterMock.EXPECT().Delete().Return(test.deleteReturnInt, test.deleteReturnErr).Times(test.deleteTimes)
   572  			querySeterMock.EXPECT().Update(gomock.Any()).Return(test.updateReturnInt, test.updateReturnErr).Times(test.updateTimes)
   573  			err := DeviceAttrTrans(adds, deletes, updates)
   574  			if test.wantErr != err {
   575  				t.Errorf("TestDeviceAttrTrans Case failed: wanted error %v and got error %v", test.wantErr, err)
   576  			}
   577  		})
   578  	}
   579  }