mirror of
https://github.com/pagefaultgames/rogueserver.git
synced 2025-09-19 05:33:48 +08:00
155 lines
5.0 KiB
Go
155 lines
5.0 KiB
Go
![]() |
package account
|
||
|
|
||
|
import (
|
||
|
"database/sql"
|
||
|
"errors"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func defaultMockStore() *mockDBAccountStore {
|
||
|
return &mockDBAccountStore{
|
||
|
FetchFunc: func(username string) ([]byte, []byte, error) {
|
||
|
return []byte("key"), []byte("salt"), nil
|
||
|
},
|
||
|
AddSessionFunc: func(username string, token []byte) error { return nil },
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type mockDBAccountStore struct {
|
||
|
FetchFunc func(username string) ([]byte, []byte, error)
|
||
|
AddSessionFunc func(username string, token []byte) error
|
||
|
}
|
||
|
|
||
|
func (m *mockDBAccountStore) FetchAccountKeySaltFromUsername(username string) ([]byte, []byte, error) {
|
||
|
return m.FetchFunc(username)
|
||
|
}
|
||
|
func (m *mockDBAccountStore) AddAccountSession(username string, token []byte) error {
|
||
|
return m.AddSessionFunc(username, token)
|
||
|
}
|
||
|
|
||
|
func TestLogin(t *testing.T) {
|
||
|
t.Run("UsernameMinLength", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "a", "password123")
|
||
|
if err == nil {
|
||
|
t.Errorf("expected error due to password mismatch or DB, got nil")
|
||
|
}
|
||
|
})
|
||
|
t.Run("UsernameMaxLength", func(t *testing.T) {
|
||
|
uname := "abcdefghijklmnop"
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, uname, "password123")
|
||
|
if err == nil {
|
||
|
t.Errorf("expected error due to password mismatch or DB, got nil")
|
||
|
}
|
||
|
})
|
||
|
t.Run("UsernameTooLong", func(t *testing.T) {
|
||
|
uname := "abcdefghijklmnopq"
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, uname, "password123")
|
||
|
if err == nil || err.Error() != "invalid username" {
|
||
|
t.Errorf("expected invalid username error for too long username, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("UsernameWithInvalidChars", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "user!@#", "password123")
|
||
|
if err == nil || err.Error() != "invalid username" {
|
||
|
t.Errorf("expected invalid username error for special chars, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("EmptyUsername", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "", "password123")
|
||
|
if err == nil || err.Error() != "invalid username" {
|
||
|
t.Errorf("expected invalid username error for empty username, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("EmptyPassword", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "validuser", "")
|
||
|
if err == nil || err.Error() != "invalid password" {
|
||
|
t.Errorf("expected invalid password error for empty password, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("MinPasswordLength", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "validuser", "123456")
|
||
|
if err == nil {
|
||
|
t.Errorf("expected error due to password mismatch or DB, got nil")
|
||
|
}
|
||
|
})
|
||
|
t.Run("PasswordWithSpecialChars", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "validuser", "p@$$w0rd!")
|
||
|
if err == nil {
|
||
|
t.Errorf("expected error due to password mismatch or DB, got nil")
|
||
|
}
|
||
|
})
|
||
|
t.Run("DBUnexpectedError", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
store.FetchFunc = func(username string) ([]byte, []byte, error) {
|
||
|
return nil, nil, errors.New("some db error")
|
||
|
}
|
||
|
_, err := Login(store, "validuser", "password123")
|
||
|
if err == nil || err.Error() != "some db error" {
|
||
|
t.Errorf("expected DB error to propagate, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("InvalidUsername", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "!invaliduser", "password123")
|
||
|
if err == nil || err.Error() != "invalid username" {
|
||
|
t.Errorf("expected invalid username error, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("ShortPassword", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
_, err := Login(store, "validuser", "123")
|
||
|
if err == nil || err.Error() != "invalid password" {
|
||
|
t.Errorf("expected invalid password error, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("AccountDoesNotExist", func(t *testing.T) {
|
||
|
store := defaultMockStore()
|
||
|
store.FetchFunc = func(username string) ([]byte, []byte, error) {
|
||
|
return nil, nil, sql.ErrNoRows
|
||
|
}
|
||
|
_, err := Login(store, "nonexistent", "password123")
|
||
|
if err == nil || err.Error() != "account doesn't exist" {
|
||
|
t.Errorf("expected account doesn't exist error, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("PasswordMismatch", func(t *testing.T) {
|
||
|
correctSalt := []byte("somesalt")
|
||
|
correctKey := []byte("correctkey")
|
||
|
store := defaultMockStore()
|
||
|
store.FetchFunc = func(username string) ([]byte, []byte, error) {
|
||
|
return correctKey, correctSalt, nil
|
||
|
}
|
||
|
_, err := Login(store, "validuser", "wrongpassword")
|
||
|
if err == nil || err.Error() != "password doesn't match" {
|
||
|
t.Errorf("expected password doesn't match error, got: %v", err)
|
||
|
}
|
||
|
})
|
||
|
t.Run("Success", func(t *testing.T) {
|
||
|
correctSalt := []byte("somesalt")
|
||
|
password := "goodpassword"
|
||
|
correctKey := deriveArgon2IDKey([]byte(password), correctSalt)
|
||
|
store := defaultMockStore()
|
||
|
store.FetchFunc = func(username string) ([]byte, []byte, error) {
|
||
|
return correctKey, correctSalt, nil
|
||
|
}
|
||
|
store.AddSessionFunc = func(username string, token []byte) error {
|
||
|
return nil
|
||
|
}
|
||
|
resp, err := Login(store, "validuser", password)
|
||
|
if err != nil {
|
||
|
t.Errorf("expected success, got error: %v", err)
|
||
|
}
|
||
|
if resp.Token == "" {
|
||
|
t.Errorf("expected token to be set on success")
|
||
|
}
|
||
|
})
|
||
|
}
|