user_test.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package state
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/require"
  7. "github.com/mk6i/retro-aim-server/wire"
  8. )
  9. func TestUser_HashPassword(t *testing.T) {
  10. tests := []struct {
  11. name string
  12. user User
  13. password string
  14. expectedWeakMD5 []byte
  15. expectedStrongMD5 []byte
  16. wantError bool
  17. }{
  18. {
  19. name: "Valid AIM password",
  20. user: User{AuthKey: "someAuthKey", IsICQ: false},
  21. password: "validPassword",
  22. expectedWeakMD5: wire.WeakMD5PasswordHash("validPassword", "someAuthKey"),
  23. expectedStrongMD5: wire.StrongMD5PasswordHash("validPassword", "someAuthKey"),
  24. wantError: false,
  25. },
  26. {
  27. name: "Empty AIM password",
  28. user: User{AuthKey: "someAuthKey", IsICQ: false},
  29. password: "",
  30. expectedWeakMD5: nil,
  31. expectedStrongMD5: nil,
  32. wantError: true,
  33. },
  34. {
  35. name: "AIM password too short",
  36. user: User{AuthKey: "someAuthKey", IsICQ: false},
  37. password: "abc",
  38. expectedWeakMD5: nil,
  39. expectedStrongMD5: nil,
  40. wantError: true,
  41. },
  42. {
  43. name: "AIM password too long",
  44. user: User{AuthKey: "someAuthKey", IsICQ: false},
  45. password: "thispasswordistoolong",
  46. expectedWeakMD5: nil,
  47. expectedStrongMD5: nil,
  48. wantError: true,
  49. },
  50. {
  51. name: "Valid ICQ password",
  52. user: User{AuthKey: "someAuthKey", IsICQ: true},
  53. password: "validICQ",
  54. expectedWeakMD5: wire.WeakMD5PasswordHash("validICQ", "someAuthKey"),
  55. expectedStrongMD5: wire.StrongMD5PasswordHash("validICQ", "someAuthKey"),
  56. wantError: false,
  57. },
  58. {
  59. name: "Empty ICQ password",
  60. user: User{AuthKey: "someAuthKey", IsICQ: true},
  61. password: "",
  62. expectedWeakMD5: nil,
  63. expectedStrongMD5: nil,
  64. wantError: true,
  65. },
  66. {
  67. name: "ICQ password too long",
  68. user: User{AuthKey: "someAuthKey", IsICQ: true},
  69. password: "icqpass89",
  70. expectedWeakMD5: nil,
  71. expectedStrongMD5: nil,
  72. wantError: true,
  73. },
  74. }
  75. for _, tt := range tests {
  76. t.Run(tt.name, func(t *testing.T) {
  77. err := tt.user.HashPassword(tt.password)
  78. if tt.wantError {
  79. require.Error(t, err)
  80. } else {
  81. require.NoError(t, err)
  82. assert.Equal(t, tt.expectedWeakMD5, tt.user.WeakMD5Pass)
  83. assert.Equal(t, tt.expectedStrongMD5, tt.user.StrongMD5Pass)
  84. }
  85. })
  86. }
  87. }
  88. func TestAge(t *testing.T) {
  89. tests := []struct {
  90. name string
  91. user User
  92. timeNow func() time.Time
  93. expectedAge uint16
  94. }{
  95. {
  96. name: "Valid birthday, only year is set",
  97. user: User{
  98. ICQMoreInfo: ICQMoreInfo{
  99. BirthYear: 1990,
  100. },
  101. },
  102. timeNow: func() time.Time {
  103. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  104. },
  105. expectedAge: 34,
  106. },
  107. {
  108. name: "Valid birthday, birthday passed this year",
  109. user: User{
  110. ICQMoreInfo: ICQMoreInfo{
  111. BirthYear: 1990,
  112. BirthMonth: 5,
  113. BirthDay: 10,
  114. },
  115. },
  116. timeNow: func() time.Time {
  117. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  118. },
  119. expectedAge: 34,
  120. },
  121. {
  122. name: "Valid birthday, birthday not yet passed this year",
  123. user: User{
  124. ICQMoreInfo: ICQMoreInfo{
  125. BirthYear: 1990,
  126. BirthMonth: 12,
  127. BirthDay: 10,
  128. },
  129. },
  130. timeNow: func() time.Time {
  131. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  132. },
  133. expectedAge: 33,
  134. },
  135. {
  136. name: "Birthday is today",
  137. user: User{
  138. ICQMoreInfo: ICQMoreInfo{
  139. BirthYear: 1990,
  140. BirthMonth: 8,
  141. BirthDay: 1,
  142. },
  143. },
  144. timeNow: func() time.Time {
  145. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  146. },
  147. expectedAge: 34,
  148. },
  149. {
  150. name: "Invalid birthday, year is zero",
  151. user: User{
  152. ICQMoreInfo: ICQMoreInfo{
  153. BirthYear: 0,
  154. BirthMonth: 8,
  155. BirthDay: 1,
  156. },
  157. },
  158. timeNow: func() time.Time {
  159. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  160. },
  161. expectedAge: 0,
  162. },
  163. {
  164. name: "Invalid birthday, day is zero",
  165. user: User{
  166. ICQMoreInfo: ICQMoreInfo{
  167. BirthYear: 1990,
  168. BirthMonth: 8,
  169. BirthDay: 0,
  170. },
  171. },
  172. timeNow: func() time.Time {
  173. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  174. },
  175. expectedAge: 0,
  176. },
  177. {
  178. name: "Invalid birthday, month is zero",
  179. user: User{
  180. ICQMoreInfo: ICQMoreInfo{
  181. BirthYear: 1990,
  182. BirthMonth: 0,
  183. BirthDay: 1,
  184. },
  185. },
  186. timeNow: func() time.Time {
  187. return time.Date(2024, 8, 1, 0, 0, 0, 0, time.UTC)
  188. },
  189. expectedAge: 0,
  190. },
  191. }
  192. for _, tt := range tests {
  193. t.Run(tt.name, func(t *testing.T) {
  194. age := tt.user.Age(tt.timeNow)
  195. if age != tt.expectedAge {
  196. t.Errorf("expected age %d, got %d", tt.expectedAge, age)
  197. }
  198. })
  199. }
  200. }
  201. func TestDisplayScreenName_ValidateAIMHandle(t *testing.T) {
  202. tests := []struct {
  203. name string
  204. input DisplayScreenName
  205. wantErr error
  206. }{
  207. {"Valid handle no spaces", "User123", nil},
  208. {"Valid handle with min character count and space", "U SR", nil},
  209. {"Valid handle with max character count", "JustTheRightSize", nil},
  210. {"Valid handle with max character count and spaces", "Just RightSize", nil},
  211. {"Too short", "Us", ErrAIMHandleLength},
  212. {"Too short due to spaces", "U S", ErrAIMHandleLength},
  213. {"Too long", "ThisIsAReallyLongScreenName", ErrAIMHandleLength},
  214. {"Starts with number", "1User", ErrAIMHandleInvalidFormat},
  215. {"Ends with space", "User123 ", ErrAIMHandleInvalidFormat},
  216. {"Contains invalid character", "User@123", ErrAIMHandleInvalidFormat},
  217. }
  218. for _, tt := range tests {
  219. t.Run(tt.name, func(t *testing.T) {
  220. err := tt.input.ValidateAIMHandle()
  221. if tt.wantErr != nil {
  222. assert.ErrorIs(t, err, tt.wantErr, "ValidateAIMHandle() error = %v, wantErr %v", err, tt.wantErr)
  223. } else {
  224. assert.NoError(t, err, "ValidateAIMHandle() error = %v, wantErr %v", err, tt.wantErr)
  225. }
  226. })
  227. }
  228. }
  229. func TestDisplayScreenName_ValidateICQHandle(t *testing.T) {
  230. tests := []struct {
  231. name string
  232. input DisplayScreenName
  233. wantErr error
  234. }{
  235. {"Valid UIN", "123456", nil},
  236. {"Too low", "9999", ErrICQUINInvalidFormat},
  237. {"Too high", "2147483647", ErrICQUINInvalidFormat},
  238. {"Non-numeric", "abcd", ErrICQUINInvalidFormat},
  239. }
  240. for _, tt := range tests {
  241. t.Run(tt.name, func(t *testing.T) {
  242. err := tt.input.ValidateUIN()
  243. if tt.wantErr != nil {
  244. assert.ErrorIs(t, err, tt.wantErr, "ValidateUIN() error = %v, wantErr %v", err, tt.wantErr)
  245. } else {
  246. assert.NoError(t, err, "ValidateUIN() error = %v, wantErr %v", err, tt.wantErr)
  247. }
  248. })
  249. }
  250. }