github.com/decred/politeia@v1.4.0/politeiawww/legacy/user/mysql/mysql_test.go (about) 1 // Copyright (c) 2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package mysql 6 7 import ( 8 "database/sql" 9 "database/sql/driver" 10 "encoding/binary" 11 "encoding/hex" 12 "encoding/json" 13 "errors" 14 "fmt" 15 "regexp" 16 "testing" 17 "time" 18 19 "github.com/DATA-DOG/go-sqlmock" 20 "github.com/decred/politeia/politeiad/api/v1/identity" 21 "github.com/decred/politeia/politeiawww/legacy/user" 22 "github.com/decred/politeia/util" 23 "github.com/google/uuid" 24 ) 25 26 // Custom go-sqlmock types for type assertion 27 type AnyBlob struct{} 28 type AnyTime struct{} 29 30 func (a AnyBlob) Match(v driver.Value) bool { 31 _, ok := v.([]byte) 32 return ok 33 } 34 35 func (a AnyTime) Match(v driver.Value) bool { 36 _, ok := v.(int64) 37 return ok 38 } 39 40 // Helpers 41 var ( 42 errSelect = fmt.Errorf("select user error") 43 errDelete = fmt.Errorf("delete user error") 44 ) 45 46 func newUser(t *testing.T, mdb *mysql) (user.User, []byte) { 47 t.Helper() 48 49 uuid := uuid.New() 50 u := user.User{ 51 ID: uuid, 52 Username: "test" + uuid.String(), 53 } 54 55 // Make user identity 56 fid, err := identity.New() 57 if err != nil { 58 t.Fatalf("%v", err) 59 } 60 id, err := user.NewIdentity(hex.EncodeToString(fid.Public.Key[:])) 61 if err != nil { 62 t.Fatalf("%v", err) 63 } 64 u.Identities = append(u.Identities, *id) 65 66 // Make user blob 67 eu, err := user.EncodeUser(u) 68 if err != nil { 69 t.Fatalf("%s", err) 70 } 71 eb, err := mdb.encrypt(user.VersionUser, eu) 72 if err != nil { 73 t.Fatalf("%s", err) 74 } 75 76 return u, eb 77 } 78 79 func setupTestDB(t *testing.T) (*mysql, sqlmock.Sqlmock, func()) { 80 t.Helper() 81 82 db, mock, err := sqlmock.New() 83 if err != nil { 84 t.Fatalf("error %s while creating stub db conn", err) 85 } 86 87 b := []byte("random") 88 var key [32]byte 89 copy(key[:], b) 90 91 c := &mysql{ 92 userDB: db, 93 encryptionKey: &key, 94 } 95 96 return c, mock, func() { 97 db.Close() 98 } 99 } 100 101 func newPaywallAddressIndex(t *testing.T, i uint64) *[]byte { 102 t.Helper() 103 104 index := make([]byte, 8) 105 binary.LittleEndian.PutUint64(index, i) 106 return &index 107 } 108 109 // Tests 110 func TestUserNew(t *testing.T) { 111 mdb, mock, close := setupTestDB(t) 112 defer close() 113 114 // Arguments 115 index := newPaywallAddressIndex(t, 1) 116 usr := user.User{ 117 Email: "test@test.com", 118 Username: "test", 119 } 120 121 // Queries 122 sqlSelectIndex := `SELECT v FROM key_value WHERE k = ?` 123 sqlInsertUser := `INSERT INTO users ` + 124 `(id, username, u_blob, created_at) ` + 125 `VALUES (?, ?, ?, ?)` 126 sqlUpsertIndex := `INSERT INTO key_value (k,v) 127 VALUES (?, ?) 128 ON DUPLICATE KEY UPDATE 129 v = ?` 130 131 // Success Expectations 132 mock.ExpectBegin() 133 // Select paywall address index 134 mock.ExpectQuery(regexp.QuoteMeta(sqlSelectIndex)). 135 WithArgs(keyPaywallAddressIndex). 136 WillReturnRows(sqlmock.NewRows([]string{"v"}). 137 AddRow(index)) 138 // Insert user to db 139 mock.ExpectExec(regexp.QuoteMeta(sqlInsertUser)). 140 WithArgs(sqlmock.AnyArg(), usr.Username, AnyBlob{}, AnyTime{}). 141 WillReturnResult(sqlmock.NewResult(0, 1)) 142 // Update paywall address index 143 mock.ExpectExec(regexp.QuoteMeta(sqlUpsertIndex)). 144 WithArgs(keyPaywallAddressIndex, sqlmock.AnyArg(), sqlmock.AnyArg()). 145 WillReturnResult(sqlmock.NewResult(0, 1)) 146 mock.ExpectCommit() 147 148 // Execute method 149 err := mdb.UserNew(usr) 150 if err != nil { 151 t.Errorf("UserNew unwanted error: %s", err) 152 } 153 154 // Negative Expectations 155 expectedError := user.ErrUserExists 156 mock.ExpectBegin() 157 mock.ExpectQuery(regexp.QuoteMeta(sqlSelectIndex)). 158 WithArgs(keyPaywallAddressIndex). 159 WillReturnRows(sqlmock.NewRows([]string{"v"}). 160 AddRow(index)) 161 // User already exists error 162 mock.ExpectExec(regexp.QuoteMeta(sqlInsertUser)). 163 WithArgs(sqlmock.AnyArg(), usr.Username, AnyBlob{}, AnyTime{}). 164 WillReturnError(expectedError) 165 mock.ExpectRollback() 166 167 // Execute method 168 err = mdb.UserNew(usr) 169 if err == nil { 170 t.Errorf("expecting error but there was none") 171 } 172 173 // Make sure we got the expected error 174 wantErr := fmt.Errorf("create user: %v", expectedError) 175 if err.Error() != wantErr.Error() { 176 t.Errorf("expecting error %s but got %s", expectedError, err) 177 } 178 179 // Make sure expectations were met for both success and failure 180 // conditions 181 err = mock.ExpectationsWereMet() 182 if err != nil { 183 t.Errorf("unfulfilled expectations: %s", err) 184 } 185 } 186 187 func TestUserUpdate(t *testing.T) { 188 mdb, mock, close := setupTestDB(t) 189 defer close() 190 191 // Arguments 192 id := uuid.New() 193 usr := user.User{ 194 ID: id, 195 Identities: []user.Identity{}, 196 Email: "test@test.com", 197 Username: "test", 198 } 199 200 // Update user query 201 uq := `UPDATE users ` + 202 `SET username = ?, u_blob = ?, updated_at = ? ` + 203 `WHERE id = ?` 204 205 // Success Expectations 206 mock.ExpectBegin() 207 mock.ExpectExec(regexp.QuoteMeta(uq)). 208 WithArgs(usr.Username, AnyBlob{}, AnyTime{}, usr.ID). 209 WillReturnResult(sqlmock.NewResult(1, 1)) 210 211 // Upsert user identities query 212 iq := "INSERT INTO identities (public_key, user_id, activated, deactivated) " + 213 "VALUES ON DUPLICATE KEY UPDATE " + 214 "activated=VALUES(activated), deactivated=VALUES(deactivated)" 215 216 mock.ExpectExec(regexp.QuoteMeta(iq)). 217 WithArgs(). 218 WillReturnResult(sqlmock.NewResult(1, 1)) 219 mock.ExpectCommit() 220 221 // Execute method 222 err := mdb.UserUpdate(usr) 223 if err != nil { 224 t.Errorf("UserUpdate unwanted error: %s", err) 225 } 226 227 // Make sure expectations were met 228 err = mock.ExpectationsWereMet() 229 if err != nil { 230 t.Errorf("unfulfilled expectations: %s", err) 231 } 232 } 233 234 func TestUserGetByUsername(t *testing.T) { 235 mdb, mock, close := setupTestDB(t) 236 defer close() 237 238 // Arguments 239 usr, blob := newUser(t, mdb) 240 241 // Mock rows data 242 rows := sqlmock.NewRows([]string{ 243 "u_blob", 244 }).AddRow(blob) 245 246 // Query 247 sql := `SELECT u_blob FROM users WHERE username = ?` 248 249 // Success Expectations 250 mock.ExpectQuery(regexp.QuoteMeta(sql)). 251 WithArgs(usr.Username). 252 WillReturnRows(rows) 253 254 // Execute method 255 u, err := mdb.UserGetByUsername(usr.Username) 256 if err != nil { 257 t.Errorf("UserGetByUsername unwanted error: %s", err) 258 } 259 260 // Make sure correct user was fetched 261 if u.ID != usr.ID { 262 t.Errorf("expecting user of id %s but received %s", usr.ID, u.ID) 263 } 264 265 // Negative Expectations 266 randomUsername := "random" 267 expectedError := user.ErrUserNotFound 268 mock.ExpectQuery(regexp.QuoteMeta(sql)). 269 WithArgs(randomUsername). 270 WillReturnError(expectedError) 271 272 // Execute method 273 u, err = mdb.UserGetByUsername(randomUsername) 274 if err == nil { 275 t.Errorf("expecting error %s, but there was none", expectedError) 276 } 277 278 // Make sure no user was fetched 279 if u != nil { 280 t.Errorf("expecting nil user to be returned, but got user %s", u.ID) 281 } 282 283 // Make sure we got the expected error 284 if !errors.Is(err, expectedError) { 285 t.Errorf("expecting error %s but got %s", expectedError, err) 286 } 287 288 // Make sure expectations were met for both success and failure 289 // conditions 290 err = mock.ExpectationsWereMet() 291 if err != nil { 292 t.Errorf("unfulfilled expectations: %s", err) 293 } 294 } 295 296 func TestUserGetById(t *testing.T) { 297 mdb, mock, close := setupTestDB(t) 298 defer close() 299 300 // Arguments 301 usr, blob := newUser(t, mdb) 302 303 // Mock rows data 304 rows := sqlmock.NewRows([]string{ 305 "u_blob", 306 }).AddRow(blob) 307 308 // Query 309 sql := `SELECT u_blob FROM users WHERE id = ?` 310 311 // Success Expectations 312 mock.ExpectQuery(regexp.QuoteMeta(sql)). 313 WithArgs(usr.ID). 314 WillReturnRows(rows) 315 316 // Execute method 317 u, err := mdb.UserGetById(usr.ID) 318 if err != nil { 319 t.Errorf("UserGetById unwanted error: %s", err) 320 } 321 322 // Make sure correct user was fetched 323 if u.ID != usr.ID { 324 t.Errorf("expecting user of id %s but received %s", usr.ID, u.ID) 325 } 326 327 // Negative Expectations 328 expectedError := user.ErrUserNotFound 329 randomID := uuid.New() 330 mock.ExpectQuery(regexp.QuoteMeta(sql)). 331 WithArgs(randomID). 332 WillReturnError(expectedError) 333 334 // Execute method 335 u, err = mdb.UserGetById(randomID) 336 if err == nil { 337 t.Errorf("expecting error %s, but there was none", expectedError) 338 } 339 340 // Make sure no user was fetched 341 if u != nil { 342 t.Errorf("expecting nil user to be returned, but got user %s", u.ID) 343 } 344 345 // Make sure we got the expected error 346 if !errors.Is(err, expectedError) { 347 t.Errorf("expecting error %s but got %s", expectedError, err) 348 } 349 350 // Make sure expectations were met for both success and failure 351 // conditions 352 err = mock.ExpectationsWereMet() 353 if err != nil { 354 t.Errorf("unfulfilled expectations: %s", err) 355 } 356 } 357 358 func TestUserGetByPubKey(t *testing.T) { 359 mdb, mock, close := setupTestDB(t) 360 defer close() 361 362 // Arguments 363 usr, blob := newUser(t, mdb) 364 pubkey := usr.Identities[0].String() 365 366 // Mock rows data 367 rows := sqlmock.NewRows([]string{ 368 "u_blob", 369 }).AddRow(blob) 370 371 // Query 372 sql := `SELECT u_blob FROM users ` + 373 `INNER JOIN identities ON users.id = identities.user_id ` + 374 `WHERE identities.public_key = ?` 375 376 // Success Expectations 377 mock.ExpectQuery(regexp.QuoteMeta(sql)). 378 WithArgs(pubkey). 379 WillReturnRows(rows) 380 381 // Execute method 382 ur, err := mdb.UserGetByPubKey(pubkey) 383 if err != nil { 384 t.Errorf("UserGetByPubKey unwanted error: %s", err) 385 } 386 387 // Make sure correct user was fetched 388 if ur.ID != usr.ID { 389 t.Errorf("expecting user of id %s but received %s", usr.ID, ur.ID) 390 } 391 392 // Negative Expectations 393 randomUsr, _ := newUser(t, mdb) 394 randomPubkey := randomUsr.Identities[0].String() 395 expectedError := user.ErrUserNotFound 396 mock.ExpectQuery(regexp.QuoteMeta(sql)). 397 WithArgs(randomPubkey). 398 WillReturnError(expectedError) 399 400 // Execute method 401 ur, err = mdb.UserGetByPubKey(randomPubkey) 402 if err == nil { 403 t.Errorf("expecting error user not found, but there was none") 404 } 405 406 // Make sure no user was fetched 407 if ur != nil { 408 t.Errorf("expecting nil user to be returned, but got user %s", ur.ID) 409 } 410 411 // Make sure we got the expected error 412 if !errors.Is(err, expectedError) { 413 t.Errorf("expecting error %s but got %s", expectedError, err) 414 } 415 416 // Make sure expectations were met for both success and failure 417 // conditions 418 err = mock.ExpectationsWereMet() 419 if err != nil { 420 t.Errorf("unfulfilled expectations: %s", err) 421 } 422 } 423 424 func TestUsersGetByPubKey(t *testing.T) { 425 mdb, mock, close := setupTestDB(t) 426 defer close() 427 428 // Arguments 429 usr, blob := newUser(t, mdb) 430 pubkey := usr.Identities[0].String() 431 432 // Mock data 433 rows := sqlmock.NewRows([]string{ 434 "u_blob", 435 }).AddRow(blob) 436 437 // Query 438 sql := `SELECT u_blob FROM users ` + 439 `INNER JOIN identities ON users.id = identities.user_id ` + 440 `WHERE identities.public_key IN (?)` 441 442 // Success Expectations 443 mock.ExpectQuery(regexp.QuoteMeta(sql)). 444 WithArgs(pubkey). 445 WillReturnRows(rows) 446 447 // Execute method 448 ur, err := mdb.UsersGetByPubKey([]string{pubkey}) 449 if err != nil { 450 t.Errorf("UsersGetByPubKey unwanted error: %s", err) 451 } 452 453 // Make sure correct user was fetched 454 fetchedUser := ur[pubkey] 455 if fetchedUser.ID != usr.ID { 456 t.Errorf("expecting user of id %s but received %s", 457 usr.ID, fetchedUser.ID) 458 } 459 460 // Negative Expectations 461 randomUsr, _ := newUser(t, mdb) 462 randomPubkey := randomUsr.Identities[0].String() 463 expectedError := user.ErrUserNotFound 464 mock.ExpectQuery(regexp.QuoteMeta(sql)). 465 WithArgs(randomPubkey). 466 WillReturnError(expectedError) 467 468 // Execute method 469 ur, err = mdb.UsersGetByPubKey([]string{randomPubkey}) 470 if err == nil { 471 t.Errorf("expecting error but there was none") 472 } 473 474 // Make sure no user was fetched 475 if len(ur) != 0 { 476 t.Errorf("expecting nil user to be returned, but got user %s", 477 ur[randomPubkey].ID) 478 } 479 480 // Make sure we got the expected error 481 if !errors.Is(err, expectedError) { 482 t.Errorf("expecting error %s but got %s", expectedError, err) 483 } 484 485 // Make sure expectations were met for both success and failure 486 // conditions 487 err = mock.ExpectationsWereMet() 488 if err != nil { 489 t.Errorf("unfulfilled expectations: %s", err) 490 } 491 } 492 493 func TestAllUsers(t *testing.T) { 494 mdb, mock, close := setupTestDB(t) 495 defer close() 496 497 // Arguments 498 _, blob := newUser(t, mdb) 499 _, blob2 := newUser(t, mdb) 500 501 // Query 502 sql := `SELECT u_blob FROM users` 503 504 // Mock data 505 rows := sqlmock.NewRows([]string{ 506 "u_blob", 507 }). 508 AddRow(blob). 509 AddRow(blob2) 510 511 // Success Expectations 512 mock.ExpectQuery(regexp.QuoteMeta(sql)). 513 WillReturnRows(rows) 514 515 // Execute method 516 var users []user.User 517 err := mdb.AllUsers(func(u *user.User) { 518 users = append(users, *u) 519 }) 520 if err != nil { 521 t.Errorf("AllUsers unwanted error: %s", err) 522 } 523 524 // Check if both mocked users were returned 525 if len(users) != 2 { 526 t.Errorf("did not return all users") 527 } 528 529 // Negative Expectations 530 expectedError := user.ErrUserNotFound 531 mock.ExpectQuery(regexp.QuoteMeta(sql)). 532 WillReturnError(expectedError) 533 534 // Execute method 535 var us []user.User 536 err = mdb.AllUsers(func(u *user.User) { 537 us = append(us, *u) 538 }) 539 if err == nil { 540 t.Errorf("expecting error but there was none") 541 } 542 543 // Make sure no users were returned 544 if len(us) != 0 { 545 t.Errorf("expected no users but returned %v users", len(us)) 546 } 547 548 // Make sure we got the expected error 549 if !errors.Is(err, expectedError) { 550 t.Errorf("expecting error %s but got %s", expectedError, err) 551 } 552 553 // Make sure expectations were met for both success and failure 554 // conditions 555 err = mock.ExpectationsWereMet() 556 if err != nil { 557 t.Errorf("unfulfilled expectations: %s", err) 558 } 559 } 560 561 func TestEmailHistoriesSave(t *testing.T) { 562 mdb, mock, close := setupTestDB(t) 563 defer close() 564 565 // Arguments 566 userID := uuid.New() 567 histories := make(map[uuid.UUID]user.EmailHistory, 1) 568 histories[userID] = user.EmailHistory{ 569 Timestamps: []int64{time.Now().Unix()}, 570 LimitWarningSent: false, 571 } 572 573 // Queries 574 sqlSelect := `SELECT user_id FROM email_histories WHERE user_id = ?` 575 576 sqlInsert := `INSERT INTO email_histories (user_id, h_blob) VALUES (?, ?)` 577 578 // Success create expectations 579 mock.ExpectBegin() 580 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 581 WithArgs(userID). 582 WillReturnError(sql.ErrNoRows) 583 mock.ExpectExec(regexp.QuoteMeta(sqlInsert)). 584 WithArgs(userID, AnyBlob{}). 585 WillReturnResult(sqlmock.NewResult(1, 1)) 586 mock.ExpectCommit() 587 588 // Execute method 589 err := mdb.EmailHistoriesSave(histories) 590 if err != nil { 591 t.Errorf("EmailHistoriesSave unwanted error: %s", err) 592 } 593 594 // Mock data for updating an email history 595 rows := sqlmock.NewRows([]string{"h_blob"}).AddRow([]byte{}) 596 597 // Query 598 sqlUpdate := `UPDATE email_histories SET h_blob = ? WHERE user_id = ?` 599 600 // Success update expectations 601 mock.ExpectBegin() 602 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 603 WithArgs(userID). 604 WillReturnRows(rows) 605 mock.ExpectExec(regexp.QuoteMeta(sqlUpdate)). 606 WithArgs(AnyBlob{}, userID). 607 WillReturnResult(sqlmock.NewResult(1, 1)) 608 mock.ExpectCommit() 609 610 // Execute method 611 err = mdb.EmailHistoriesSave(histories) 612 if err != nil { 613 t.Errorf("EmailHistoriesSave unwanted error: %s", err) 614 } 615 616 // Negative expectations 617 mock.ExpectBegin() 618 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 619 WillReturnError(errSelect) 620 mock.ExpectRollback() 621 622 // Execute method 623 badHistories := make(map[uuid.UUID]user.EmailHistory, 1) 624 badHistories[uuid.New()] = user.EmailHistory{} 625 err = mdb.EmailHistoriesSave(badHistories) 626 if err == nil { 627 t.Errorf("expected error but there was none") 628 } 629 630 // Make sure expectations were met for both success and failure 631 // conditions 632 err = mock.ExpectationsWereMet() 633 if err != nil { 634 t.Errorf("unfulfilled expectations: %s", err) 635 } 636 } 637 638 func TestEmailHistoriesGet(t *testing.T) { 639 mdb, mock, close := setupTestDB(t) 640 defer close() 641 642 // Arguments 643 userID := uuid.New() 644 ts := time.Now().Unix() 645 history := user.EmailHistory{ 646 Timestamps: []int64{ts}, 647 LimitWarningSent: false, 648 } 649 hb, err := json.Marshal(history) 650 if err != nil { 651 t.Fatalf("%s", err) 652 } 653 eb, err := mdb.encrypt(user.VersionEmailHistory, hb) 654 if err != nil { 655 t.Fatalf("%s", err) 656 } 657 658 // Mock data 659 rows := sqlmock.NewRows([]string{"user_id", "h_blob"}). 660 AddRow(userID, eb) 661 662 // Query 663 sql := `SELECT user_id, h_blob FROM email_histories WHERE user_id IN (?)` 664 665 // Success expectations 666 mock.ExpectQuery(regexp.QuoteMeta(sql)). 667 WithArgs(userID). 668 WillReturnRows(rows) 669 670 // Execute method 671 eh, err := mdb.EmailHistoriesGet([]uuid.UUID{userID}) 672 if err != nil { 673 t.Errorf("EmailHistoriesGet unwanted error: %s", err) 674 } 675 676 // Make sure correct history was returned 677 if ts != eh[userID].Timestamps[0] { 678 t.Errorf("expecting timestamp %d but got %d", 679 ts, eh[userID].Timestamps[0]) 680 } 681 682 // Negative expectations 683 randomUserID := uuid.New() 684 expectedError := errors.New("email history not found") 685 mock.ExpectQuery(regexp.QuoteMeta(sql)). 686 WithArgs(randomUserID). 687 WillReturnError(expectedError) 688 689 // Execute method 690 h, err := mdb.EmailHistoriesGet([]uuid.UUID{randomUserID}) 691 if err == nil { 692 t.Errorf("expected error but there was none") 693 } 694 695 // Make sure no sessions were returned 696 if h != nil { 697 t.Errorf("expected no email history but got %v", h) 698 } 699 700 // Make sure we got the expected error 701 if !errors.Is(err, expectedError) { 702 t.Errorf("expecting error %s but got %s", expectedError, err) 703 } 704 705 // Make sure expectations were met for both success and failure 706 // conditions 707 err = mock.ExpectationsWereMet() 708 if err != nil { 709 t.Errorf("unfulfilled expectations: %s", err) 710 } 711 } 712 713 func TestSessionSave(t *testing.T) { 714 mdb, mock, close := setupTestDB(t) 715 defer close() 716 717 // Arguments 718 session := user.Session{ 719 ID: "1", 720 UserID: uuid.New(), 721 CreatedAt: time.Now().Unix(), 722 Values: "", 723 } 724 sessionKey := hex.EncodeToString(util.Digest([]byte(session.ID))) 725 726 // Query 727 sqlSelect := `SELECT k FROM sessions WHERE k = ?` 728 729 sqlInsert := `INSERT INTO sessions ` + 730 `(k, user_id, created_at, s_blob) ` + 731 `VALUES (?, ?, ?, ?)` 732 733 // Success Create Expectations 734 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 735 WithArgs(sessionKey). 736 WillReturnError(sql.ErrNoRows) 737 mock.ExpectExec(regexp.QuoteMeta(sqlInsert)). 738 WithArgs(sessionKey, session.UserID, session.CreatedAt, AnyBlob{}). 739 WillReturnResult(sqlmock.NewResult(1, 1)) 740 741 // Execute method 742 err := mdb.SessionSave(session) 743 if err != nil { 744 t.Errorf("SessionSave unwanted error: %s", err) 745 } 746 747 // Mock data for updating a user session 748 rows := sqlmock.NewRows([]string{"s_blob"}). 749 AddRow([]byte{}) 750 751 // Queries 752 sqlUpdate := `UPDATE sessions ` + 753 `SET user_id = ?, created_at = ?, s_blob = ? ` + 754 `WHERE k = ?` 755 756 // Success Update Expectations 757 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 758 WithArgs(sessionKey). 759 WillReturnRows(rows) 760 mock.ExpectExec(regexp.QuoteMeta(sqlUpdate)). 761 WithArgs(session.UserID, session.CreatedAt, AnyBlob{}, sessionKey). 762 WillReturnResult(sqlmock.NewResult(1, 1)) 763 764 // Execute method 765 err = mdb.SessionSave(session) 766 if err != nil { 767 t.Errorf("SessionSave unwanted error: %s", err) 768 } 769 770 // Negative Expectations 771 mock.ExpectQuery(regexp.QuoteMeta(sqlSelect)). 772 WillReturnError(errSelect) 773 774 // Execute method 775 err = mdb.SessionSave(user.Session{}) 776 if err == nil { 777 t.Errorf("expected error but there was none") 778 } 779 780 // Make sure expectations were met for both success and failure 781 // conditions 782 err = mock.ExpectationsWereMet() 783 if err != nil { 784 t.Errorf("unfulfilled expectations: %s", err) 785 } 786 } 787 788 func TestSessionGetByID(t *testing.T) { 789 mdb, mock, close := setupTestDB(t) 790 defer close() 791 792 // Arguments 793 session := user.Session{ 794 ID: "1", 795 UserID: uuid.New(), 796 CreatedAt: time.Now().Unix(), 797 Values: "", 798 } 799 sessionKey := hex.EncodeToString(util.Digest([]byte(session.ID))) 800 sb, err := user.EncodeSession(session) 801 if err != nil { 802 t.Fatalf("%s", err) 803 } 804 eb, err := mdb.encrypt(user.VersionSession, sb) 805 if err != nil { 806 t.Fatalf("%s", err) 807 } 808 809 // Mock data 810 rows := sqlmock.NewRows([]string{"s_blob"}). 811 AddRow(eb) 812 813 // Queries 814 sql := `SELECT s_blob FROM sessions WHERE k = ?` 815 816 // Success Expectations 817 mock.ExpectQuery(regexp.QuoteMeta(sql)). 818 WithArgs(sessionKey). 819 WillReturnRows(rows) 820 821 // Execute method 822 s, err := mdb.SessionGetByID(session.ID) 823 if err != nil { 824 t.Errorf("SessionGetByID unwanted error: %s", err) 825 } 826 827 // Make sure correct session was returned 828 if session.ID != s.ID { 829 t.Errorf("expecting session %s but got %s", session.ID, s.ID) 830 } 831 832 // Negative Expectations 833 randomID := "2" 834 randomKey := hex.EncodeToString(util.Digest([]byte(randomID))) 835 expectedError := user.ErrSessionNotFound 836 mock.ExpectQuery(regexp.QuoteMeta(sql)). 837 WithArgs(randomKey). 838 WillReturnError(expectedError) 839 840 // Execute method 841 s, err = mdb.SessionGetByID(randomID) 842 if err == nil { 843 t.Errorf("expected error but there was none") 844 } 845 846 // Make sure no sessions were returned 847 if s != nil { 848 t.Errorf("expected no session but got %v", s) 849 } 850 851 // Make sure we got the expected error 852 if !errors.Is(err, expectedError) { 853 t.Errorf("expecting error %s but got %s", expectedError, err) 854 } 855 856 // Make sure expectations were met for both success and failure 857 // conditions 858 err = mock.ExpectationsWereMet() 859 if err != nil { 860 t.Errorf("unfulfilled expectations: %s", err) 861 } 862 } 863 864 func TestSessionDeleteByID(t *testing.T) { 865 mdb, mock, close := setupTestDB(t) 866 defer close() 867 868 // Arguments 869 session := user.Session{ 870 ID: "1", 871 UserID: uuid.New(), 872 CreatedAt: time.Now().Unix(), 873 Values: "", 874 } 875 sessionKey := hex.EncodeToString(util.Digest([]byte(session.ID))) 876 sb, err := user.EncodeSession(session) 877 if err != nil { 878 t.Fatalf("%s", err) 879 } 880 eb, err := mdb.encrypt(user.VersionSession, sb) 881 if err != nil { 882 t.Fatalf("%s", err) 883 } 884 885 // Mock data 886 sqlmock.NewRows([]string{"s_blob"}). 887 AddRow(eb) 888 889 // Queries 890 sql := `DELETE FROM sessions WHERE k = ?` 891 892 // Success Expectations 893 mock.ExpectExec(regexp.QuoteMeta(sql)). 894 WithArgs(sessionKey). 895 WillReturnResult(sqlmock.NewResult(1, 1)) 896 897 // Execute method 898 err = mdb.SessionDeleteByID(session.ID) 899 if err != nil { 900 t.Errorf("SessionDeleteByID unwanted error: %s", err) 901 } 902 903 // Negative Expectations 904 randomID := "random" 905 randomKey := hex.EncodeToString(util.Digest([]byte(randomID))) 906 mock.ExpectExec(regexp.QuoteMeta(sql)). 907 WithArgs(randomKey). 908 WillReturnError(errDelete) 909 910 // Execute method 911 err = mdb.SessionDeleteByID(randomID) 912 if err == nil { 913 t.Errorf("expected error but there was none") 914 } 915 916 // Make sure we got the expected error 917 if !errors.Is(err, errDelete) { 918 t.Errorf("expecting error %s but got %s", errDelete, err) 919 } 920 921 // Make sure expectations were met for both success and failure 922 // conditions 923 err = mock.ExpectationsWereMet() 924 if err != nil { 925 t.Errorf("unfulfilled expectations: %s", err) 926 } 927 } 928 929 func TestSessionsDeleteByUserID(t *testing.T) { 930 mdb, mock, close := setupTestDB(t) 931 defer close() 932 933 // Arguments 934 session := user.Session{ 935 ID: "1", 936 UserID: uuid.New(), 937 CreatedAt: time.Now().Unix(), 938 Values: "", 939 } 940 sb, err := user.EncodeSession(session) 941 if err != nil { 942 t.Fatalf("%s", err) 943 } 944 eb, err := mdb.encrypt(user.VersionSession, sb) 945 if err != nil { 946 t.Fatalf("%s", err) 947 } 948 949 // Mock data 950 sqlmock.NewRows([]string{"s_blob"}). 951 AddRow(eb) 952 953 // Queries 954 sql := `DELETE FROM sessions WHERE user_id = ?` 955 956 // Success Expectations 957 mock.ExpectExec(regexp.QuoteMeta(sql)). 958 WithArgs(session.UserID). 959 WillReturnResult(sqlmock.NewResult(1, 1)) 960 961 // Execute method 962 err = mdb.SessionsDeleteByUserID(session.UserID, []string{}) 963 if err != nil { 964 t.Errorf("SessionsDeleteByUserID unwanted error: %s", err) 965 } 966 967 // Negative Expectations 968 randomID := uuid.New() 969 mock.ExpectExec(regexp.QuoteMeta(sql)). 970 WithArgs(randomID). 971 WillReturnError(errDelete) 972 973 // Execute method 974 err = mdb.SessionsDeleteByUserID(randomID, []string{}) 975 if err == nil { 976 t.Errorf("expecting error but got none") 977 } 978 979 // Make sure we got the expected error 980 if !errors.Is(err, errDelete) { 981 t.Errorf("expecting error %s but got %s", errDelete, err) 982 } 983 984 // Make sure expectations were met for both success and failure 985 // conditions 986 err = mock.ExpectationsWereMet() 987 if err != nil { 988 t.Errorf("unfulfilled expectations: %s", err) 989 } 990 } 991 992 func TestSetPaywallAddressIndex(t *testing.T) { 993 mdb, mock, close := setupTestDB(t) 994 defer close() 995 996 // Query 997 sqlUpsertIndex := `INSERT INTO key_value (k,v) 998 VALUES (?, ?) 999 ON DUPLICATE KEY UPDATE 1000 v = ?` 1001 1002 // Success Expectations 1003 mock.ExpectBegin() 1004 // Upsert paywall address index 1005 mock.ExpectExec(regexp.QuoteMeta(sqlUpsertIndex)). 1006 WithArgs(keyPaywallAddressIndex, sqlmock.AnyArg(), sqlmock.AnyArg()). 1007 WillReturnResult(sqlmock.NewResult(0, 1)) 1008 mock.ExpectCommit() 1009 1010 // Execute method 1011 err := mdb.SetPaywallAddressIndex(7) 1012 if err != nil { 1013 t.Errorf("SetPaywallAddressIndex unwanted error: %s", err) 1014 } 1015 1016 // Negative Expectations 1017 expectedError := fmt.Errorf("some error") 1018 mock.ExpectBegin() 1019 // User already exists error 1020 mock.ExpectExec(regexp.QuoteMeta(sqlUpsertIndex)). 1021 WithArgs(keyPaywallAddressIndex, sqlmock.AnyArg(), sqlmock.AnyArg()). 1022 WillReturnError(expectedError) 1023 mock.ExpectRollback() 1024 1025 // Execute method 1026 err = mdb.SetPaywallAddressIndex(7) 1027 if err == nil { 1028 t.Errorf("expecting error but there was none") 1029 } 1030 1031 // Make sure expectations were met for both success and failure 1032 // conditions 1033 err = mock.ExpectationsWereMet() 1034 if err != nil { 1035 t.Errorf("unfulfilled expectations: %s", err) 1036 } 1037 }