github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/merger/batchmerger/merger_test.go (about) 1 // Copyright 2021 ecodeclub 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package batchmerger 16 17 import ( 18 "context" 19 "database/sql" 20 "errors" 21 "fmt" 22 "testing" 23 24 "github.com/ecodeclub/eorm/internal/rows" 25 26 "go.uber.org/multierr" 27 28 "github.com/DATA-DOG/go-sqlmock" 29 "github.com/ecodeclub/eorm/internal/merger/internal/errs" 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 "github.com/stretchr/testify/suite" 33 ) 34 35 var ( 36 nextMockErr error = errors.New("rows: MockNextErr") 37 ) 38 39 func newCloseMockErr(dbName string) error { 40 return fmt.Errorf("rows: %s MockCloseErr", dbName) 41 } 42 43 type MergerSuite struct { 44 suite.Suite 45 mockDB01 *sql.DB 46 mock01 sqlmock.Sqlmock 47 mockDB02 *sql.DB 48 mock02 sqlmock.Sqlmock 49 mockDB03 *sql.DB 50 mock03 sqlmock.Sqlmock 51 mockDB04 *sql.DB 52 mock04 sqlmock.Sqlmock 53 } 54 55 func (ms *MergerSuite) SetupTest() { 56 t := ms.T() 57 ms.initMock(t) 58 } 59 60 func (ms *MergerSuite) TearDownTest() { 61 _ = ms.mockDB01.Close() 62 _ = ms.mockDB02.Close() 63 _ = ms.mockDB03.Close() 64 _ = ms.mockDB04.Close() 65 } 66 67 func (ms *MergerSuite) initMock(t *testing.T) { 68 var err error 69 ms.mockDB01, ms.mock01, err = sqlmock.New() 70 if err != nil { 71 t.Fatal(err) 72 } 73 ms.mockDB02, ms.mock02, err = sqlmock.New() 74 if err != nil { 75 t.Fatal(err) 76 } 77 ms.mockDB03, ms.mock03, err = sqlmock.New() 78 if err != nil { 79 t.Fatal(err) 80 } 81 ms.mockDB04, ms.mock04, err = sqlmock.New() 82 if err != nil { 83 t.Fatal(err) 84 } 85 } 86 87 func (ms *MergerSuite) TestMerger_Merge() { 88 testcases := []struct { 89 name string 90 rowsList func() []rows.Rows 91 ctx func() (context.Context, context.CancelFunc) 92 wantErr error 93 }{ 94 { 95 name: "sql.Rows列表中没有元素", 96 rowsList: func() []rows.Rows { 97 return []rows.Rows{} 98 }, 99 ctx: func() (context.Context, context.CancelFunc) { 100 return context.WithCancel(context.Background()) 101 }, 102 wantErr: errs.ErrMergerEmptyRows, 103 }, 104 { 105 name: "sql.Rows列表中有元素为nil", 106 rowsList: func() []rows.Rows { 107 return []rows.Rows{nil} 108 }, 109 ctx: func() (context.Context, context.CancelFunc) { 110 return context.WithCancel(context.Background()) 111 }, 112 wantErr: errs.ErrMergerRowsIsNull, 113 }, 114 { 115 name: "sqlRows字段不同_少一个字段", 116 ctx: func() (context.Context, context.CancelFunc) { 117 return context.WithCancel(context.Background()) 118 }, 119 rowsList: func() []rows.Rows { 120 query := "SELECT * FROM `t1`" 121 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "address"}).AddRow(1, "abex", "cn").AddRow(5, "bruce", "cn")) 122 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(3, "alex").AddRow(4, "x")) 123 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02} 124 rowsList := make([]rows.Rows, 0, len(dbs)) 125 for _, db := range dbs { 126 row, err := db.QueryContext(context.Background(), query) 127 require.NoError(ms.T(), err) 128 rowsList = append(rowsList, row) 129 } 130 return rowsList 131 }, 132 wantErr: errs.ErrMergerRowsDiff, 133 }, 134 { 135 name: "sqlRows字段不同", 136 ctx: func() (context.Context, context.CancelFunc) { 137 return context.WithCancel(context.Background()) 138 }, 139 rowsList: func() []rows.Rows { 140 query := "SELECT * FROM `t1`" 141 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "address"}).AddRow(1, "abex", "cn").AddRow(5, "bruce", "cn")) 142 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "email"}).AddRow(3, "alex", "cn").AddRow(4, "x", "cn")) 143 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02} 144 rowsList := make([]rows.Rows, 0, len(dbs)) 145 for _, db := range dbs { 146 row, err := db.QueryContext(context.Background(), query) 147 require.NoError(ms.T(), err) 148 rowsList = append(rowsList, row) 149 } 150 return rowsList 151 }, 152 wantErr: errs.ErrMergerRowsDiff, 153 }, 154 { 155 name: "正常的案例", 156 rowsList: func() []rows.Rows { 157 query := "SELECT * FROM `t1`" 158 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "address"}).AddRow(1, "abex", "cn").AddRow(5, "bruce", "cn")) 159 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "address"}).AddRow(3, "alex", "cn").AddRow(4, "x", "cn")) 160 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02} 161 rowsList := make([]rows.Rows, 0, len(dbs)) 162 for _, db := range dbs { 163 row, err := db.QueryContext(context.Background(), query) 164 require.NoError(ms.T(), err) 165 rowsList = append(rowsList, row) 166 } 167 return rowsList 168 }, 169 ctx: func() (context.Context, context.CancelFunc) { 170 return context.WithCancel(context.Background()) 171 }, 172 }, 173 { 174 name: "超时", 175 ctx: func() (context.Context, context.CancelFunc) { 176 ctx, cancel := context.WithTimeout(context.Background(), 0) 177 return ctx, cancel 178 }, 179 wantErr: context.DeadlineExceeded, 180 rowsList: func() []rows.Rows { 181 query := "SELECT * FROM `t1`;" 182 cols := []string{"id"} 183 res := make([]rows.Rows, 0, 1) 184 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow(1)) 185 rows, _ := ms.mockDB01.QueryContext(context.Background(), query) 186 res = append(res, rows) 187 return res 188 }, 189 }, 190 } 191 for _, tc := range testcases { 192 ms.T().Run(tc.name, func(t *testing.T) { 193 merger := NewMerger() 194 ctx, cancel := tc.ctx() 195 rows, err := merger.Merge(ctx, tc.rowsList()) 196 cancel() 197 assert.Equal(t, tc.wantErr, err) 198 if err != nil { 199 return 200 } 201 require.NotNil(t, rows) 202 }) 203 } 204 } 205 206 func (ms *MergerSuite) TestRows_NextAndScan() { 207 208 testCases := []struct { 209 name string 210 sqlRows func() []rows.Rows 211 wantVal []string 212 wantErr error 213 scanErr error 214 }{ 215 { 216 name: "sqlRows列表中没有空行", 217 sqlRows: func() []rows.Rows { 218 query := "SELECT * FROM `t1`;" 219 cols := []string{"id"} 220 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("1").AddRow("2")) 221 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2").AddRow("2")) 222 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 223 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02, ms.mockDB03} 224 res := make([]rows.Rows, 0, len(dbs)) 225 for _, db := range dbs { 226 row, _ := db.QueryContext(context.Background(), query) 227 res = append(res, row) 228 } 229 return res 230 }, 231 wantVal: []string{"1", "2", "2", "2", "3", "4"}, 232 }, 233 { 234 name: "sqlRows列表中,在前面有一个sqlRows返回空行在前面", 235 sqlRows: func() []rows.Rows { 236 query := "SELECT * FROM `t1`;" 237 cols := []string{"id"} 238 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("1")) 239 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 240 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 241 ms.mock04.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 242 dbs := []*sql.DB{ms.mockDB04, ms.mockDB01, ms.mockDB02, ms.mockDB03} 243 res := make([]rows.Rows, 0, len(dbs)) 244 for _, db := range dbs { 245 row, _ := db.QueryContext(context.Background(), query) 246 res = append(res, row) 247 } 248 return res 249 }, 250 wantVal: []string{"1", "2", "3", "4"}, 251 }, 252 { 253 name: "sqlRows列表中,在前面有多个sqlRows返回空行", 254 sqlRows: func() []rows.Rows { 255 query := "SELECT * FROM `t1`;" 256 cols := []string{"id"} 257 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 258 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 259 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 260 ms.mock04.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 261 dbs := []*sql.DB{ms.mockDB04, ms.mockDB01, ms.mockDB02, ms.mockDB03} 262 res := make([]rows.Rows, 0, len(dbs)) 263 for _, db := range dbs { 264 row, _ := db.QueryContext(context.Background(), query) 265 res = append(res, row) 266 } 267 return res 268 }, 269 wantVal: []string{"2", "3", "4"}, 270 }, 271 { 272 name: "sqlRows列表中,在中间有一个sqlRows返回空行", 273 sqlRows: func() []rows.Rows { 274 query := "SELECT * FROM `t1`;" 275 cols := []string{"id"} 276 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 277 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 278 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 279 dbs := []*sql.DB{ms.mockDB02, ms.mockDB01, ms.mockDB03} 280 res := make([]rows.Rows, 0, len(dbs)) 281 for _, db := range dbs { 282 row, _ := db.QueryContext(context.Background(), query) 283 res = append(res, row) 284 } 285 return res 286 }, 287 wantVal: []string{"2", "3", "4"}, 288 }, 289 { 290 name: "sqlRows列表中,在中间有多个sqlRows返回空行", 291 sqlRows: func() []rows.Rows { 292 query := "SELECT * FROM `t1`;" 293 cols := []string{"id"} 294 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 295 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 296 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 297 ms.mock04.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 298 dbs := []*sql.DB{ms.mockDB02, ms.mockDB01, ms.mockDB04, ms.mockDB03} 299 res := make([]rows.Rows, 0, len(dbs)) 300 for _, db := range dbs { 301 row, _ := db.QueryContext(context.Background(), query) 302 res = append(res, row) 303 } 304 return res 305 }, 306 wantVal: []string{"2", "3", "4"}, 307 }, 308 { 309 name: "sqlRows列表中,在后面有一个sqlRows返回空行", 310 sqlRows: func() []rows.Rows { 311 query := "SELECT * FROM `t1`;" 312 cols := []string{"id"} 313 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 314 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 315 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 316 dbs := []*sql.DB{ms.mockDB02, ms.mockDB03, ms.mockDB01} 317 res := make([]rows.Rows, 0, len(dbs)) 318 for _, db := range dbs { 319 row, _ := db.QueryContext(context.Background(), query) 320 res = append(res, row) 321 } 322 return res 323 }, 324 wantVal: []string{"2", "3", "4"}, 325 }, 326 { 327 name: "sqlRows列表中,在后面有多个个sqlRows返回空行", 328 sqlRows: func() []rows.Rows { 329 query := "SELECT * FROM `t1`;" 330 cols := []string{"id"} 331 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 332 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 333 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 334 ms.mock04.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols)) 335 dbs := []*sql.DB{ms.mockDB02, ms.mockDB03, ms.mockDB01, ms.mockDB04} 336 res := make([]rows.Rows, 0, len(dbs)) 337 for _, db := range dbs { 338 row, _ := db.QueryContext(context.Background(), query) 339 res = append(res, row) 340 } 341 return res 342 }, 343 wantVal: []string{"2", "3", "4"}, 344 }, 345 { 346 name: "sqlRows列表中的元素均返回空行", 347 sqlRows: func() []rows.Rows { 348 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id"})) 349 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id"})) 350 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows([]string{"id"})) 351 res := make([]rows.Rows, 0, 3) 352 row01, _ := ms.mockDB01.QueryContext(context.Background(), "SELECT * FROM `t1`;") 353 res = append(res, row01) 354 row02, _ := ms.mockDB02.QueryContext(context.Background(), "SELECT * FROM `t1`;") 355 res = append(res, row02) 356 row03, _ := ms.mockDB03.QueryContext(context.Background(), "SELECT * FROM `t1`;") 357 res = append(res, row03) 358 return res 359 }, 360 wantVal: []string{}, 361 }, 362 } 363 for _, tc := range testCases { 364 ms.T().Run(tc.name, func(t *testing.T) { 365 merger := Merger{} 366 rows, err := merger.Merge(context.Background(), tc.sqlRows()) 367 assert.Equal(t, tc.wantErr, err) 368 if err != nil { 369 return 370 } 371 res := make([]string, 0, 4) 372 for rows.Next() { 373 var id string 374 err = rows.Scan(&id) 375 assert.Equal(t, tc.scanErr, err) 376 if err != nil { 377 return 378 } 379 res = append(res, id) 380 } 381 require.NoError(t, rows.Err()) 382 assert.Equal(t, tc.wantVal, res) 383 }) 384 } 385 386 } 387 388 func (ms *MergerSuite) TestRows_NextAndErr() { 389 testcases := []struct { 390 name string 391 rowsList func() []rows.Rows 392 wantErr error 393 }{ 394 { 395 name: "sqlRows列表中有一个返回error", 396 rowsList: func() []rows.Rows { 397 cols := []string{"id"} 398 query := "SELECT * FROM `t1`" 399 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("1")) 400 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 401 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4").RowError(1, nextMockErr)) 402 ms.mock04.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("5")) 403 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02, ms.mockDB04, ms.mockDB03} 404 rowsList := make([]rows.Rows, 0, len(dbs)) 405 for _, db := range dbs { 406 row, err := db.QueryContext(context.Background(), query) 407 require.NoError(ms.T(), err) 408 rowsList = append(rowsList, row) 409 } 410 return rowsList 411 }, 412 wantErr: nextMockErr, 413 }, 414 } 415 for _, tc := range testcases { 416 ms.T().Run(tc.name, func(t *testing.T) { 417 merger := NewMerger() 418 rows, err := merger.Merge(context.Background(), tc.rowsList()) 419 require.NoError(t, err) 420 for rows.Next() { 421 } 422 assert.Equal(t, tc.wantErr, rows.Err()) 423 }) 424 } 425 } 426 427 func (ms *MergerSuite) TestRows_ScanAndErr() { 428 ms.T().Run("未调用Next,直接Scan,返回错", func(t *testing.T) { 429 cols := []string{"id"} 430 query := "SELECT * FROM `t1`" 431 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow(1).AddRow(5)) 432 r, err := ms.mockDB01.QueryContext(context.Background(), query) 433 require.NoError(t, err) 434 rowsList := []rows.Rows{r} 435 merger := NewMerger() 436 rows, err := merger.Merge(context.Background(), rowsList) 437 require.NoError(t, err) 438 id := 0 439 err = rows.Scan(&id) 440 require.Error(t, err) 441 }) 442 ms.T().Run("迭代过程中发现错误,调用Scan,返回迭代中发现的错误", func(t *testing.T) { 443 cols := []string{"id"} 444 query := "SELECT * FROM `t1`" 445 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow(1).RowError(0, nextMockErr)) 446 r, err := ms.mockDB01.QueryContext(context.Background(), query) 447 require.NoError(t, err) 448 rowsList := []rows.Rows{r} 449 merger := NewMerger() 450 rows, err := merger.Merge(context.Background(), rowsList) 451 require.NoError(t, err) 452 for rows.Next() { 453 } 454 id := 0 455 err = rows.Scan(&id) 456 assert.Equal(t, nextMockErr, err) 457 }) 458 459 } 460 461 func (ms *MergerSuite) TestRows_Close() { 462 cols := []string{"id"} 463 query := "SELECT * FROM `t1`" 464 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("1")) 465 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2").CloseError(newCloseMockErr("db02"))) 466 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4").CloseError(newCloseMockErr("db03"))) 467 merger := NewMerger() 468 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02, ms.mockDB03} 469 rowsList := make([]rows.Rows, 0, len(dbs)) 470 for _, db := range dbs { 471 row, err := db.QueryContext(context.Background(), query) 472 require.NoError(ms.T(), err) 473 rowsList = append(rowsList, row) 474 } 475 rs, err := merger.Merge(context.Background(), rowsList) 476 require.NoError(ms.T(), err) 477 // 判断当前是可以正常读取的 478 require.True(ms.T(), rs.Next()) 479 var id int 480 err = rs.Scan(&id) 481 require.NoError(ms.T(), err) 482 err = rs.Close() 483 ms.T().Run("close返回multierror", func(t *testing.T) { 484 assert.Equal(ms.T(), multierr.Combine(newCloseMockErr("db02"), newCloseMockErr("db03")), err) 485 }) 486 ms.T().Run("close之后Next返回false", func(t *testing.T) { 487 for i := 0; i < len(rowsList); i++ { 488 require.False(ms.T(), rowsList[i].Next()) 489 } 490 require.False(ms.T(), rs.Next()) 491 }) 492 ms.T().Run("close之后Scan返回迭代过程中的错误", func(t *testing.T) { 493 var id int 494 err := rs.Scan(&id) 495 assert.Equal(t, errs.ErrMergerRowsClosed, err) 496 }) 497 ms.T().Run("close之后调用Columns方法返回错误", func(t *testing.T) { 498 _, err := rs.Columns() 499 require.Error(t, err) 500 }) 501 ms.T().Run("close多次是等效的", func(t *testing.T) { 502 for i := 0; i < 4; i++ { 503 err = rs.Close() 504 require.NoError(t, err) 505 } 506 }) 507 } 508 509 func (ms *MergerSuite) TestRows_Columns() { 510 cols := []string{"id"} 511 query := "SELECT * FROM `t1`" 512 ms.mock01.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("1")) 513 ms.mock02.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("2")) 514 ms.mock03.ExpectQuery("SELECT *").WillReturnRows(sqlmock.NewRows(cols).AddRow("3").AddRow("4")) 515 merger := NewMerger() 516 dbs := []*sql.DB{ms.mockDB01, ms.mockDB02, ms.mockDB03} 517 rowsList := make([]rows.Rows, 0, len(dbs)) 518 for _, db := range dbs { 519 row, err := db.QueryContext(context.Background(), query) 520 require.NoError(ms.T(), err) 521 rowsList = append(rowsList, row) 522 } 523 524 rows, err := merger.Merge(context.Background(), rowsList) 525 require.NoError(ms.T(), err) 526 ms.T().Run("Next没有迭代完", func(t *testing.T) { 527 for rows.Next() { 528 columns, err := rows.Columns() 529 require.NoError(t, err) 530 assert.Equal(t, cols, columns) 531 } 532 require.NoError(t, rows.Err()) 533 }) 534 ms.T().Run("Next迭代完", func(t *testing.T) { 535 require.False(t, rows.Next()) 536 require.NoError(t, rows.Err()) 537 _, err := rows.Columns() 538 assert.Equal(t, errs.ErrMergerRowsClosed, err) 539 540 }) 541 } 542 543 func TestMerger(t *testing.T) { 544 suite.Run(t, &MergerSuite{}) 545 } 546 547 func TestRows_NextResultSet(t *testing.T) { 548 assert.False(t, (&Rows{}).NextResultSet()) 549 }