package store import ( "errors" "testing" "github.com/mattn/go-sqlite3" "orblivion/lbry-id/auth" ) func expectAccountExists(t *testing.T, s *Store, email auth.Email, password auth.Password) { rows, err := s.db.Query( `SELECT 1 from accounts WHERE email=? AND password=?`, email, password.Obfuscate(), ) if err != nil { t.Fatalf("Error finding account for: %s %s - %+v", email, password, err) } defer rows.Close() for rows.Next() { return // found something, we're good } t.Fatalf("Expected account for: %s %s", email, password) } func expectAccountNotExists(t *testing.T, s *Store, email auth.Email, password auth.Password) { rows, err := s.db.Query( `SELECT 1 from accounts WHERE email=? AND password=?`, email, password.Obfuscate(), ) if err != nil { t.Fatalf("Error finding account for: %s %s - %+v", email, password, err) } defer rows.Close() for rows.Next() { t.Fatalf("Expected no account for: %s %s", email, password) } // found nothing, we're good } // Test CreateAccount, using GetUserId as a helper // Try CreateAccount twice with the same email and different password, error the second time func TestStoreCreateAccount(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) email, password := auth.Email("abc@example.com"), auth.Password("123") // Get an account, come back empty expectAccountNotExists(t, &s, email, password) // Create an account if err := s.CreateAccount(email, password); err != nil { t.Fatalf("Unexpected error in CreateAccount: %+v", err) } // Get and confirm the account we just put in expectAccountExists(t, &s, email, password) newPassword := auth.Password("xyz") // Try to create a new account with the same email and different password, // fail because email already exists if err := s.CreateAccount(email, newPassword); err != ErrDuplicateAccount { t.Fatalf(`CreateAccount err: wanted "%+v", got "%+v"`, ErrDuplicateAccount, err) } // Get the email and same *first* password we successfully put in, but not the second expectAccountExists(t, &s, email, password) expectAccountNotExists(t, &s, email, newPassword) } // Test GetUserId, using CreateAccount as a helper // Try GetUserId before creating an account (fail), and after (succeed) func TestStoreGetUserId(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) email, password := auth.Email("abc@example.com"), auth.Password("123") // Check that there's no user id for email and password first if userId, err := s.GetUserId(email, password); err != ErrNoUId || userId != 0 { t.Fatalf(`CreateAccount err: wanted "%+v", got "%+v. userId: %v"`, ErrNoUId, err, userId) } // Create the account _ = s.CreateAccount(email, password) // Check that there's now a user id for the email and password if userId, err := s.GetUserId(email, password); err != nil || userId == 0 { t.Fatalf("Unexpected error in GetUserId: err: %+v userId: %v", err, userId) } } func TestStoreAccountEmptyFields(t *testing.T) { // Make sure expiration doesn't get set if sanitization fails tt := []struct { name string email auth.Email password auth.Password }{ { name: "missing email", email: "", password: "xyz", }, // Not testing empty password because it gets obfuscated to something // non-empty in the method } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) var sqliteErr sqlite3.Error err := s.CreateAccount(tc.email, tc.password) if errors.As(err, &sqliteErr) { if errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintCheck) { return // We got the error we expected } } t.Errorf("Expected check constraint error for empty field. Got %+v", err) }) } }