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  }