| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- package state
- import (
- "testing"
- "time"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "github.com/mk6i/retro-aim-server/wire"
- )
- func TestUser_HashPassword(t *testing.T) {
- tests := []struct {
- name string
- user User
- password string
- expectedWeakMD5 []byte
- expectedStrongMD5 []byte
- wantError bool
- }{
- {
- name: "Valid AIM password",
- user: User{AuthKey: "someAuthKey", IsICQ: false},
- password: "validPassword",
- expectedWeakMD5: wire.WeakMD5PasswordHash("validPassword", "someAuthKey"),
- expectedStrongMD5: wire.StrongMD5PasswordHash("validPassword", "someAuthKey"),
- wantError: false,
- },
- {
- name: "Empty AIM password",
- user: User{AuthKey: "someAuthKey", IsICQ: false},
- password: "",
- expectedWeakMD5: nil,
- expectedStrongMD5: nil,
- wantError: true,
- },
- {
- name: "AIM password too short",
- user: User{AuthKey: "someAuthKey", IsICQ: false},
- password: "abc",
- expectedWeakMD5: nil,
- expectedStrongMD5: nil,
- wantError: true,
- },
- {
- name: "AIM password too long",
- user: User{AuthKey: "someAuthKey", IsICQ: false},
- password: "thispasswordistoolong",
- expectedWeakMD5: nil,
- expectedStrongMD5: nil,
- wantError: true,
- },
- {
- name: "Valid ICQ password",
- user: User{AuthKey: "someAuthKey", IsICQ: true},
- password: "validICQ",
- expectedWeakMD5: wire.WeakMD5PasswordHash("validICQ", "someAuthKey"),
- expectedStrongMD5: wire.StrongMD5PasswordHash("validICQ", "someAuthKey"),
- wantError: false,
- },
- {
- name: "Empty ICQ password",
- user: User{AuthKey: "someAuthKey", IsICQ: true},
- password: "",
- expectedWeakMD5: nil,
- expectedStrongMD5: nil,
- wantError: true,
- },
- {
- name: "ICQ password too long",
- user: User{AuthKey: "someAuthKey", IsICQ: true},
- password: "icqpass89",
- expectedWeakMD5: nil,
- expectedStrongMD5: nil,
- wantError: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- err := tt.user.HashPassword(tt.password)
- if tt.wantError {
- require.Error(t, err)
- } else {
- require.NoError(t, err)
- assert.Equal(t, tt.expectedWeakMD5, tt.user.WeakMD5Pass)
- assert.Equal(t, tt.expectedStrongMD5, tt.user.StrongMD5Pass)
- }
- })
- }
- }
- func TestAge(t *testing.T) {
- tests := []struct {
- name string
- user User
- timeNow func() time.Time
- expectedAge uint16
- }{
- {
- name: "Valid birthday, only year is set",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 34,
- },
- {
- name: "Valid birthday, birthday passed this year",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- BirthMonth: 5,
- BirthDay: 10,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 34,
- },
- {
- name: "Valid birthday, birthday not yet passed this year",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- BirthMonth: 12,
- BirthDay: 10,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 33,
- },
- {
- name: "Birthday is today",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- BirthMonth: 8,
- BirthDay: 1,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 34,
- },
- {
- name: "Invalid birthday, year is zero",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 0,
- BirthMonth: 8,
- BirthDay: 1,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 0,
- },
- {
- name: "Invalid birthday, day is zero",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- BirthMonth: 8,
- BirthDay: 0,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 0,
- },
- {
- name: "Invalid birthday, month is zero",
- user: User{
- ICQMoreInfo: ICQMoreInfo{
- BirthYear: 1990,
- BirthMonth: 0,
- BirthDay: 1,
- },
- },
- timeNow: func() time.Time {
- return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
- },
- expectedAge: 0,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- age := tt.user.Age(tt.timeNow)
- if age != tt.expectedAge {
- t.Errorf("expected age %d, got %d", tt.expectedAge, age)
- }
- })
- }
- }
- func TestDisplayScreenName_ValidateAIMHandle(t *testing.T) {
- tests := []struct {
- name string
- input DisplayScreenName
- wantErr error
- }{
- {"Valid handle no spaces", "User123", nil},
- {"Valid handle with min character count and space", "U SR", nil},
- {"Valid handle with min character including letters and numbers", "dj3520", nil},
- {"Valid handle with max character count", "JustTheRightSize", nil},
- {"Valid handle with max character count and spaces", "Just RightSize", nil},
- {"Too short", "Us", ErrAIMHandleLength},
- {"Too short due to spaces", "U S", ErrAIMHandleLength},
- {"Too long", "ThisIsAReallyLongScreenName", ErrAIMHandleLength},
- {"Too many spaces", "User 123 ", ErrAIMHandleLength},
- {"Starts with number", "1User", ErrAIMHandleInvalidFormat},
- {"Ends with space", "User123 ", ErrAIMHandleInvalidFormat},
- {"Contains invalid character", "User@123", ErrAIMHandleInvalidFormat},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- err := tt.input.ValidateAIMHandle()
- if tt.wantErr != nil {
- assert.ErrorIs(t, err, tt.wantErr, "ValidateAIMHandle() error = %v, wantErr %v", err, tt.wantErr)
- } else {
- assert.NoError(t, err, "ValidateAIMHandle() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
- }
- func TestDisplayScreenName_ValidateICQHandle(t *testing.T) {
- tests := []struct {
- name string
- input DisplayScreenName
- wantErr error
- }{
- {"Valid UIN", "123456", nil},
- {"Too low", "9999", ErrICQUINInvalidFormat},
- {"Too high", "2147483647", ErrICQUINInvalidFormat},
- {"Non-numeric", "abcd", ErrICQUINInvalidFormat},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- err := tt.input.ValidateUIN()
- if tt.wantErr != nil {
- assert.ErrorIs(t, err, tt.wantErr, "ValidateUIN() error = %v, wantErr %v", err, tt.wantErr)
- } else {
- assert.NoError(t, err, "ValidateUIN() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
- }
- func TestUser_ValidateRoastedPass(t *testing.T) {
- tests := []struct {
- name string
- user User
- roastedPass []byte
- expected bool
- }{
- {
- name: "Valid roasted password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARPassword([]byte("testPassword")),
- expected: true,
- },
- {
- name: "Invalid roasted password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARPassword([]byte("wrongPassword")),
- expected: false,
- },
- {
- name: "Empty roasted password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARPassword([]byte("")),
- expected: false,
- },
- {
- name: "Empty stored password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: []byte{},
- },
- roastedPass: wire.RoastOSCARPassword([]byte("testPassword")),
- expected: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := tt.user.ValidateRoastedPass(tt.roastedPass)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- func TestUser_ValidateRoastedJavaPass(t *testing.T) {
- tests := []struct {
- name string
- user User
- roastedPass []byte
- expected bool
- }{
- {
- name: "Valid roasted Java password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARJavaPassword([]byte("testPassword")),
- expected: true,
- },
- {
- name: "Invalid roasted Java password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARJavaPassword([]byte("wrongPassword")),
- expected: false,
- },
- {
- name: "Empty roasted Java password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastOSCARJavaPassword([]byte("")),
- expected: false,
- },
- {
- name: "Empty stored password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: []byte{},
- },
- roastedPass: wire.RoastOSCARJavaPassword([]byte("testPassword")),
- expected: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := tt.user.ValidateRoastedJavaPass(tt.roastedPass)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- func TestUser_ValidateRoastedTOCPass(t *testing.T) {
- tests := []struct {
- name string
- user User
- roastedPass []byte
- expected bool
- }{
- {
- name: "Valid roasted TOC password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastTOCPassword([]byte("testPassword")),
- expected: true,
- },
- {
- name: "Invalid roasted TOC password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastTOCPassword([]byte("wrongPassword")),
- expected: false,
- },
- {
- name: "Empty roasted TOC password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastTOCPassword([]byte("")),
- expected: false,
- },
- {
- name: "Empty stored password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: []byte{},
- },
- roastedPass: wire.RoastTOCPassword([]byte("testPassword")),
- expected: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := tt.user.ValidateRoastedTOCPass(tt.roastedPass)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- func TestUser_ValidatePlaintextPass(t *testing.T) {
- tests := []struct {
- name string
- user User
- plaintextPass []byte
- expected bool
- }{
- {
- name: "Valid plaintext password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- plaintextPass: []byte("testPassword"),
- expected: true,
- },
- {
- name: "Invalid plaintext password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- plaintextPass: []byte("wrongPassword"),
- expected: false,
- },
- {
- name: "Empty plaintext password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- plaintextPass: []byte(""),
- expected: false,
- },
- {
- name: "Empty stored password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: []byte{},
- },
- plaintextPass: []byte("testPassword"),
- expected: false,
- },
- {
- name: "Password with special characters",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("test@123!", "testAuthKey"),
- },
- plaintextPass: []byte("test@123!"),
- expected: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := tt.user.ValidatePlaintextPass(tt.plaintextPass)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- func TestUser_ValidateRoastedKerberosPass(t *testing.T) {
- tests := []struct {
- name string
- user User
- roastedPass []byte
- expected bool
- }{
- {
- name: "Valid roasted Kerberos password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastKerberosPassword([]byte("testPassword")),
- expected: true,
- },
- {
- name: "Invalid roasted Kerberos password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastKerberosPassword([]byte("wrongPassword")),
- expected: false,
- },
- {
- name: "Empty roasted Kerberos password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: wire.WeakMD5PasswordHash("testPassword", "testAuthKey"),
- },
- roastedPass: wire.RoastKerberosPassword([]byte("")),
- expected: false,
- },
- {
- name: "Empty stored password",
- user: User{
- AuthKey: "testAuthKey",
- WeakMD5Pass: []byte{},
- },
- roastedPass: wire.RoastKerberosPassword([]byte("testPassword")),
- expected: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := tt.user.ValidateRoastedKerberosPass(tt.roastedPass)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
|