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 }