github.com/condensat/bank-core@v0.1.0/database/model/accountoperation_test.go (about)

     1  // Copyright 2020 Condensat Tech. All rights reserved.
     2  // Use of this source code is governed by a MIT
     3  // license that can be found in the LICENSE file.
     4  
     5  package model
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  func newFloat(value Float) ZeroFloat {
    14  	return &value
    15  }
    16  
    17  func refAccountOperation() AccountOperation {
    18  	return AccountOperation{
    19  		ID:               1,
    20  		AccountID:        3,
    21  		SynchroneousType: SynchroneousTypeSync,
    22  		OperationType:    OperationTypeDeposit,
    23  		ReferenceID:      4,
    24  		Timestamp:        time.Now().UTC().Truncate(time.Second),
    25  		Amount:           newFloat(1.0),
    26  		Balance:          newFloat(10.0),
    27  		LockAmount:       newFloat(2.0),
    28  		TotalLocked:      newFloat(8.0),
    29  	}
    30  }
    31  
    32  func amountAccountOperation(amount, balance, lockAmount, totalLocked Float) AccountOperation {
    33  	result := refAccountOperation()
    34  	*result.Amount = amount
    35  	*result.Balance = balance
    36  	*result.LockAmount = lockAmount
    37  	*result.TotalLocked = totalLocked
    38  	return result
    39  }
    40  
    41  func TestNewAccountOperation(t *testing.T) {
    42  	t.Parallel()
    43  
    44  	ref := refAccountOperation()
    45  
    46  	type args struct {
    47  		ID               AccountOperationID
    48  		accountID        AccountID
    49  		synchroneousType SynchroneousType
    50  		operationType    OperationType
    51  		referenceID      RefID
    52  		timestamp        time.Time
    53  		amount           Float
    54  		balance          Float
    55  		lockAmount       Float
    56  		totalLocked      Float
    57  	}
    58  	tests := []struct {
    59  		name string
    60  		args args
    61  		want AccountOperation
    62  	}{
    63  		{"CheckArgsOrder", args{ref.ID, ref.AccountID, ref.SynchroneousType, ref.OperationType, ref.ReferenceID, ref.Timestamp, *ref.Amount, *ref.Balance, *ref.LockAmount, *ref.TotalLocked}, ref},
    64  	}
    65  	for _, tt := range tests {
    66  		tt := tt // capture range variable
    67  		t.Run(tt.name, func(t *testing.T) {
    68  			got := NewAccountOperation(tt.args.ID, tt.args.accountID, tt.args.synchroneousType, tt.args.operationType, tt.args.referenceID, tt.args.timestamp, tt.args.amount, tt.args.balance, tt.args.lockAmount, tt.args.totalLocked)
    69  			if !reflect.DeepEqual(got, tt.want) {
    70  				t.Errorf("NewAccountOperation() = %v, want %v", got, tt.want)
    71  			}
    72  		})
    73  	}
    74  }
    75  
    76  func TestNewInitOperation(t *testing.T) {
    77  	t.Parallel()
    78  
    79  	type args struct {
    80  		accountID   AccountID
    81  		referenceID RefID
    82  	}
    83  	tests := []struct {
    84  		name string
    85  		args args
    86  		want bool
    87  	}{
    88  		{"Init", args{42, 0}, true},
    89  	}
    90  	for _, tt := range tests {
    91  		tt := tt // capture range variable
    92  		t.Run(tt.name, func(t *testing.T) {
    93  			if got := NewInitOperation(tt.args.accountID, tt.args.referenceID); got.PreCheck() != tt.want {
    94  				t.Errorf("NewInitOperation() = %v, want %v", got.IsValid(), tt.want)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func TestAccountOperation_IsValid(t *testing.T) {
   101  	t.Parallel()
   102  
   103  	type fields struct {
   104  		p AccountOperation
   105  	}
   106  	tests := []struct {
   107  		name   string
   108  		fields fields
   109  		want   bool
   110  	}{
   111  		{"Default", fields{AccountOperation{}}, false},
   112  		{"Valid", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 1.0, 1.0)}, true},
   113  		{"Init", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeInit, 0, time.Now(), 0.0, 0.0, 0.0, 0.0)}, true},
   114  		{"NotInit", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeDeposit, 0, time.Now(), 0.0, 0.0, 0.0, 0.0)}, false},
   115  		{"ValidUTC", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now().UTC(), 1.0, 1.0, 1.0, 1.0)}, true},
   116  
   117  		{"InvalidID", fields{NewAccountOperation(0, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   118  		{"InvalidAccountID", fields{NewAccountOperation(1, 0, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   119  		{"InvalidSynchroneousType", fields{NewAccountOperation(1, 42, SynchroneousTypeInvalid, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   120  		{"InvalidOperationType", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeInvalid, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   121  
   122  		// test with amount and lock
   123  		{"ValidNegativeAmount", fields{amountAccountOperation(-1.0, 1.0, 0.0, 1.0)}, true},
   124  		{"ValidNegativeTotalLocked", fields{amountAccountOperation(0.0, 1.0, -1.0, 1.0)}, true},
   125  
   126  		{"InvalidTotalLockedAndBalance", fields{amountAccountOperation(0.0, 1.0, 0.0, 2.0)}, false},
   127  		{"InvalidBalance", fields{amountAccountOperation(0.0, -1.0, 0.0, 0.0)}, false},
   128  		{"InvalidLockTotalLocked", fields{amountAccountOperation(0.0, 1.0, 0.0, -1.0)}, false},
   129  		{"InvalidTooManyLocked", fields{amountAccountOperation(0.0, 1.0, 0.0, 2.0)}, false},
   130  
   131  		{"InvalidBalanceToLow", fields{amountAccountOperation(2.0, 1.0, 0.0, 0.0)}, false},
   132  		{"InvalidTotalLockedToLow", fields{amountAccountOperation(0.0, 0.0, 2.0, 1.0)}, false},
   133  
   134  		// test void operation
   135  		{"InvalidZero", fields{amountAccountOperation(0.0, 0.0, 0.0, 0.0)}, false},
   136  		{"InvalidVoidOperation", fields{amountAccountOperation(0.0, 1.0, 0.0, 1.0)}, false},
   137  	}
   138  	for _, tt := range tests {
   139  		tt := tt // capture range variable
   140  		t.Run(tt.name, func(t *testing.T) {
   141  			p := tt.fields.p
   142  			if got := p.IsValid(); got != tt.want {
   143  				t.Errorf("AccountOperation.IsValid() = %v, want %v", got, tt.want)
   144  			}
   145  		})
   146  	}
   147  }
   148  
   149  func TestAccountOperation_PreCheck(t *testing.T) {
   150  	t.Parallel()
   151  
   152  	type fields struct {
   153  		p AccountOperation
   154  	}
   155  	tests := []struct {
   156  		name   string
   157  		fields fields
   158  		want   bool
   159  	}{
   160  		{"Default", fields{AccountOperation{}}, false},
   161  		{"Valid", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 1.0, 1.0)}, true},
   162  		{"ValidUTC", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now().UTC(), 1.0, 1.0, 1.0, 1.0)}, true},
   163  
   164  		// Valid PreCheck
   165  		{"InvalidID", fields{NewAccountOperation(0, 42, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, true},
   166  
   167  		// Invvalid PreCheck
   168  		{"InvalidAccountID", fields{NewAccountOperation(1, 0, SynchroneousTypeSync, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   169  		{"InvalidSynchroneousType", fields{NewAccountOperation(1, 42, SynchroneousTypeInvalid, OperationTypeNone, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   170  		{"InvalidOperationType", fields{NewAccountOperation(1, 42, SynchroneousTypeSync, OperationTypeInvalid, 0, time.Now(), 1.0, 1.0, 0.0, 0.0)}, false},
   171  
   172  		// test with amount and lock
   173  		{"ValidNegativeAmount", fields{amountAccountOperation(-1.0, 1.0, 0.0, 1.0)}, true},
   174  		{"ValidNegativeTotalLocked", fields{amountAccountOperation(0.0, 1.0, -1.0, 1.0)}, true},
   175  
   176  		{"InvalidTotalLockedAndBalance", fields{amountAccountOperation(0.0, 1.0, 0.0, 2.0)}, false},
   177  		{"InvalidBalance", fields{amountAccountOperation(0.0, -1.0, 0.0, 0.0)}, false},
   178  		{"InvalidLockTotalLocked", fields{amountAccountOperation(0.0, 1.0, 0.0, -1.0)}, false},
   179  		{"InvalidTooManyLocked", fields{amountAccountOperation(0.0, 1.0, 0.0, 2.0)}, false},
   180  
   181  		{"InvalidBalanceToLow", fields{amountAccountOperation(2.0, 1.0, 0.0, 0.0)}, false},
   182  		{"InvalidTotalLockedToLow", fields{amountAccountOperation(0.0, 0.0, 2.0, 1.0)}, false},
   183  
   184  		// test void operation
   185  		{"InvalidZero", fields{amountAccountOperation(0.0, 0.0, 0.0, 0.0)}, false},
   186  		{"InvalidVoidOperation", fields{amountAccountOperation(0.0, 1.0, 0.0, 1.0)}, false},
   187  	}
   188  	for _, tt := range tests {
   189  		tt := tt // capture range variable
   190  		t.Run(tt.name, func(t *testing.T) {
   191  			p := tt.fields.p
   192  
   193  			if got := p.PreCheck(); got != tt.want {
   194  				t.Errorf("AccountOperation.PreCheck() = %v, want %v", got, tt.want)
   195  			}
   196  		})
   197  	}
   198  }