github.com/darkside1809/wallet@v1.7.0/pkg/wallet/service_test.go (about) 1 package wallet 2 3 import ( 4 "fmt" 5 "log" 6 "reflect" 7 "testing" 8 "sort" 9 "github.com/darkside1809/wallet/pkg/types" 10 "github.com/google/uuid" 11 ) 12 13 14 var defaultTestAccount = testAccount{ 15 phone: "+992938151007", 16 balance: 10_000_00, 17 payments: []struct { 18 amount types.Money 19 category types.PaymentCategory 20 }{{ 21 amount: 1000_00, 22 category: "auto", 23 }}, 24 } 25 type testAccount struct { 26 phone types.Phone 27 balance types.Money 28 payments []struct { 29 amount types.Money 30 category types.PaymentCategory 31 } 32 } 33 type testService struct { 34 *Service 35 } 36 37 func newTestService() *testService { 38 return &testService{Service: &Service{}} 39 } 40 41 func (s *testService) addAccount(data testAccount) (*types.Account, []*types.Payment, error) { 42 account, err := s.RegisterAccount(data.phone) 43 if err != nil { 44 return nil, nil, fmt.Errorf("can't regist account, error = %v", err) 45 } 46 47 err = s.Deposit(account.ID, data.balance) 48 if err != nil { 49 return nil, nil, fmt.Errorf("can't deposity account, error = %v", err) 50 } 51 52 payments := make([]*types.Payment, len(data.payments)) 53 for i, payment := range data.payments { 54 payments[i], err = s.Pay(account.ID, payment.amount, payment.category) 55 if err != nil { 56 return nil, nil, fmt.Errorf("can't make payment, error = %v", err) 57 } 58 } 59 60 return account, payments, nil 61 } 62 63 func TestService_FindAccountByID_success(t *testing.T) { 64 svc := &Service{} 65 66 account, _ := svc.RegisterAccount("+992000000001") 67 68 acc, e := svc.FindAccountByID(account.ID) 69 70 if e != nil { 71 t.Error(e) 72 } 73 74 if !reflect.DeepEqual(account, acc) { 75 t.Error("Accounts doesn't match") 76 } 77 } 78 79 func TestService_FindAccountByID_notFound(t *testing.T) { 80 svc := &Service{} 81 82 _, e := svc.FindAccountByID(123) 83 84 if e != ErrAccountNotFound { 85 t.Error(e) 86 } 87 } 88 89 func TestService_FindPaymentByID_success(t *testing.T) { 90 s := newTestService() 91 92 _, payments, err := s.addAccount(defaultTestAccount) 93 if err != nil { 94 t.Error(err) 95 return 96 } 97 98 payment := payments[0] 99 got, err := s.FindPaymentByID(payment.ID) 100 if err != nil { 101 t.Errorf("FindPaymentByID(): error = %v", err) 102 return 103 } 104 105 if !reflect.DeepEqual(payment, got) { 106 t.Errorf("FindPaymentByID(): wrong paymen returned = %v", err) 107 return 108 } 109 } 110 111 func TestService_FindPaymentByID_fail(t *testing.T) { 112 s := newTestService() 113 _, _, err := s.addAccount(defaultTestAccount) 114 if err != nil { 115 t.Error(err) 116 return 117 } 118 119 _, err = s.FindPaymentByID(uuid.New().String()) 120 if err == nil { 121 t.Error("FindPaymentByID(): must return error, returned nil") 122 return 123 } 124 125 if err != ErrPaymentNotFound { 126 t.Errorf("FindPaymentByID(): must retunrn ErrPaymentNotFound, returned = %v", err) 127 return 128 } 129 } 130 131 func TestService_Reject_success(t *testing.T) { 132 s := newTestService() 133 _, payments, err := s.addAccount(defaultTestAccount) 134 if err != nil { 135 t.Error(err) 136 return 137 } 138 139 payment := payments[0] 140 err = s.Reject(payment.ID) 141 if err != nil { 142 t.Errorf("Reject(): error = %v", err) 143 return 144 } 145 146 savedPayment, err := s.FindPaymentByID(payment.ID) 147 if err != nil { 148 t.Errorf("Reject(): can't find payment by id, error = %v", err) 149 return 150 } 151 if savedPayment.Status != types.PaymentStatusFail { 152 t.Errorf("Reject(): status can't changed, error = %v", savedPayment) 153 return 154 } 155 156 savedAccount, err := s.FindAccountByID(payment.AccountID) 157 if err != nil { 158 t.Errorf("Reject(): can't find account by id, error = %v", err) 159 return 160 } 161 if savedAccount.Balance != defaultTestAccount.balance { 162 t.Errorf("Reject(), balance didn't cahnged, account = %v", savedAccount) 163 } 164 } 165 166 func TestService_Reject_fail(t *testing.T) { 167 s := newTestService() 168 _, _, err := s.addAccount(defaultTestAccount) 169 if err != nil { 170 t.Error(err) 171 return 172 } 173 174 err = s.Reject(uuid.New().String()) 175 if err == nil { 176 t.Error("Reject(): must be error, returned nil") 177 return 178 } 179 } 180 181 func TestService_Repeat_success(t *testing.T) { 182 s := newTestService() 183 _, payments, err := s.addAccount(defaultTestAccount) 184 if err != nil { 185 t.Error(err) 186 return 187 } 188 189 payment := payments[0] 190 newPayment, nil := s.Repeat(payment.ID) 191 if err != nil { 192 t.Error(err) 193 return 194 } 195 196 if payment.ID == newPayment.ID { 197 t.Error("repeated payment id not different") 198 return 199 } 200 201 if payment.AccountID != newPayment.AccountID || 202 payment.Status != newPayment.Status || 203 payment.Category != newPayment.Category || 204 payment.Amount != newPayment.Amount { 205 t.Error("some field is not equal the original") 206 } 207 } 208 209 func TestService_FavoritePayment_success(t *testing.T) { 210 s := newTestService() 211 _, payments, err := s.addAccount(defaultTestAccount) 212 if err != nil { 213 t.Error(err) 214 return 215 } 216 217 payment := payments[0] 218 219 _, err = s.FavoritePayment(payment.ID, "osh") 220 if err != nil { 221 t.Error(err) 222 } 223 } 224 225 func TestService_FavoritePayment_fail(t *testing.T) { 226 s := newTestService() 227 228 _, err := s.FavoritePayment(uuid.New().String(), "osh") 229 if err == nil { 230 t.Error("FavoritePayment(): must return error, now nil") 231 } 232 } 233 234 func TestService_PayFromFavorite_success(t *testing.T) { 235 s := newTestService() 236 237 _, payments, err := s.addAccount(defaultTestAccount) 238 if err != nil { 239 t.Error("PayFromFavorite(): can't get payments") 240 return 241 } 242 243 payment := payments[0] 244 245 favorite, err := s.FavoritePayment(payment.ID, "osh") 246 if err != nil { 247 t.Error("PayFromFavorite(): can't add payment to favorite") 248 return 249 } 250 251 _, err = s.PayFromFavorite(favorite.ID) 252 if err != nil { 253 t.Error("PayFromFavorite(): can't not pay from favorite") 254 return 255 } 256 } 257 258 func TestService_PayFromFavorite_fail(t *testing.T) { 259 s := newTestService() 260 261 _, err := s.PayFromFavorite(uuid.New().String()) 262 if err == nil { 263 t.Error("PayFromFavorite(): must be error, now returned nil") 264 } 265 } 266 func TestServiceExportToFile(t *testing.T) { 267 s := newTestService() 268 269 err := s.ExportToFile("export.txt") 270 if err != nil { 271 t.Error("ExportToFile(): cannot export data") 272 } 273 } 274 func TestService_ImportFromFile_success(t *testing.T) { 275 s := newTestService() 276 277 err := s.ImportFromFile("export.txt") 278 279 if err != nil { 280 t.Errorf("method ImportFromFile return err, err: %v", err) 281 } 282 283 } 284 285 func TestService_Import_success(t *testing.T) { 286 s := newTestService() 287 err := s.ImportFromFile("export.txt") 288 289 if err != nil { 290 t.Errorf("method Import returned not nil error, err => %v", err) 291 } 292 293 } 294 295 func TestService_Export_success(t *testing.T) { 296 s := newTestService() 297 298 s.RegisterAccount("+992000000001") 299 300 301 err := s.Export("data") 302 if err != nil { 303 t.Errorf("method ExportToFile returned not nil error, err => %v", err) 304 } 305 306 err = s.Import("data") 307 if err != nil { 308 t.Errorf("method ExportToFile returned not nil error, err => %v", err) 309 } 310 } 311 312 func TestService_ExportHistory_success(t *testing.T) { 313 s := newTestService() 314 315 account, err := s.RegisterAccount("+992000000001") 316 317 if err != nil { 318 t.Errorf("method RegisterAccount returned not nil error, account => %v", account) 319 } 320 321 err = s.Deposit(account.ID, 100_00) 322 if err != nil { 323 t.Errorf("method Deposit returned not nil error, error => %v", err) 324 } 325 326 _, err = s.Pay(account.ID, 1, "car") 327 328 if err != nil { 329 t.Errorf("method Pay returned not nil error, err => %v", err) 330 } 331 332 payments, err := s.ExportAccountHistory(account.ID) 333 334 if err != nil { 335 t.Errorf("method ExportAccountHistory returned not nil error, err => %v", err) 336 } 337 err = s.HistoryToFiles(payments, "data", 4) 338 339 if err != nil { 340 t.Errorf("method HistoryToFiles returned not nil error, err => %v", err) 341 } 342 343 } 344 345 func BenchmarkSumPayments(b *testing.B){ 346 svc := Service{} 347 account, err := svc.RegisterAccount("+9921283793") 348 349 if err != nil { 350 b.Errorf("method RegisterAccount returned not nil error, account => %v", account) 351 } 352 353 err = svc.Deposit(account.ID, 100_00) 354 if err != nil { 355 b.Errorf("method Deposit returned not nil error, error => %v", err) 356 } 357 358 _, err = svc.Pay(account.ID, 1, "Cafe") 359 360 361 if err != nil { 362 b.Errorf("method Pay returned not nil error, err => %v", err) 363 } 364 want := types.Money(1) 365 366 got := svc.SumPayments(2) 367 if want != got{ 368 b.Errorf("want: %v got: %v", want, got) 369 } 370 371 } 372 373 func BenchmarkFilterPayments(b *testing.B) { 374 s := newTestService() 375 376 account, err := s.RegisterAccount("+992000000000") 377 if err != nil { 378 b.Error(err) 379 } 380 for i := 0; i < 103; i++ { 381 s.payments = append(s.payments, &types.Payment{AccountID: account.ID, Amount: 1}) 382 } 383 384 result := 103 385 386 for i := 0; i < b.N; i++ { 387 payments, err := s.FilterPayments(account.ID, result) 388 if err != nil { 389 b.Error(err) 390 } 391 392 if result != len(payments) { 393 b.Fatalf("wrong result, got %v, want %v", len(payments), result) 394 } 395 } 396 } 397 398 func filter(payment types.Payment) bool { 399 return payment.Amount <= 540 400 } 401 402 func BenchmarkService_FilterPaymentsByFn(b *testing.B) { 403 s := newTestService() 404 405 account, err := s.RegisterAccount("+99212312133") 406 if err != nil { 407 b.Fatal(err) 408 } 409 410 err = s.Deposit(account.ID, 100_000) 411 if err != nil { 412 b.Fatal(err) 413 } 414 415 for i := 0; i < 7; i++ { 416 _, err = s.Pay(account.ID, types.Money(i * 10 + 500), "car") 417 if err != nil { 418 b.Fatal(err) 419 } 420 } 421 422 want := make([]types.Payment, 0) 423 424 for _, payment := range s.payments { 425 if filter(*payment) { 426 want = append(want, *payment) 427 } 428 } 429 430 for i := 0; i < b.N; i++ { 431 result, err := s.FilterPaymentsByFn(filter, i) 432 if err != nil { 433 b.Fatal(err) 434 } 435 436 sort.Slice(want, func (i, j int) bool { 437 return want[i].ID < want[j].ID 438 }) 439 440 sort.Slice(result, func (i, j int) bool { 441 return result[i].ID < result[j].ID 442 }) 443 444 if !reflect.DeepEqual(want, result) { 445 b.Fatalf("invalid result, want %v, got %v", want, result) 446 } 447 } 448 } 449 450 func BenchmarkSumPaymentsWithProgress(b *testing.B) { 451 var svc Service 452 account, err := svc.RegisterAccount("992918532322") 453 if err != nil { 454 b.Errorf("Acc already registered %v", ErrPhoneRegistered) 455 } 456 err = svc.Deposit(account.ID, 100_000000000000) 457 if err != nil { 458 b.Errorf("Acc already registered %v", ErrPhoneRegistered) 459 } 460 for i := types.Money(1); i <= 100_000; i++ { 461 _, err := svc.Pay(account.ID, i, "house") 462 if err != nil { 463 b.Errorf("something went wrong %v", err) 464 } 465 } 466 ch := svc.SumPaymentsWithProgress() 467 s, got := <-ch 468 if !got { 469 b.Errorf("got => %v", got) 470 } 471 log.Println(s) 472 }