github.com/ethersphere/bee/v2@v2.2.0/pkg/api/settlements_test.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package api_test 6 7 import ( 8 "errors" 9 "math/big" 10 "net/http" 11 "reflect" 12 "testing" 13 14 "github.com/ethersphere/bee/v2/pkg/api" 15 "github.com/ethersphere/bee/v2/pkg/bigint" 16 "github.com/ethersphere/bee/v2/pkg/jsonhttp" 17 "github.com/ethersphere/bee/v2/pkg/jsonhttp/jsonhttptest" 18 "github.com/ethersphere/bee/v2/pkg/settlement" 19 "github.com/ethersphere/bee/v2/pkg/settlement/swap/mock" 20 "github.com/ethersphere/bee/v2/pkg/swarm" 21 ) 22 23 func TestSettlements(t *testing.T) { 24 t.Parallel() 25 26 settlementsSentFunc := func() (ret map[string]*big.Int, err error) { 27 ret = make(map[string]*big.Int) 28 ret["DEAD"] = big.NewInt(10000) 29 ret["BEEF"] = big.NewInt(20000) 30 ret["FFFF"] = big.NewInt(50000) 31 return ret, err 32 } 33 34 settlementsRecvFunc := func() (ret map[string]*big.Int, err error) { 35 ret = make(map[string]*big.Int) 36 ret["BEEF"] = big.NewInt(10000) 37 ret["EEEE"] = big.NewInt(5000) 38 return ret, err 39 } 40 41 testServer, _, _, _ := newTestServer(t, testServerOptions{ 42 SwapOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc), mock.WithSettlementsRecvFunc(settlementsRecvFunc)}, 43 }) 44 45 expected := &api.SettlementsResponse{ 46 TotalSettlementReceived: bigint.Wrap(big.NewInt(15000)), 47 TotalSettlementSent: bigint.Wrap(big.NewInt(80000)), 48 Settlements: []api.SettlementResponse{ 49 { 50 Peer: "DEAD", 51 SettlementReceived: bigint.Wrap(big.NewInt(0)), 52 SettlementSent: bigint.Wrap(big.NewInt(10000)), 53 }, 54 { 55 Peer: "BEEF", 56 SettlementReceived: bigint.Wrap(big.NewInt(10000)), 57 SettlementSent: bigint.Wrap(big.NewInt(20000)), 58 }, 59 { 60 Peer: "FFFF", 61 SettlementReceived: bigint.Wrap(big.NewInt(0)), 62 SettlementSent: bigint.Wrap(big.NewInt(50000)), 63 }, 64 { 65 Peer: "EEEE", 66 SettlementReceived: bigint.Wrap(big.NewInt(5000)), 67 SettlementSent: bigint.Wrap(big.NewInt(0)), 68 }, 69 }, 70 } 71 72 // We expect a list of items unordered by peer: 73 var got *api.SettlementsResponse 74 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements", http.StatusOK, 75 jsonhttptest.WithUnmarshalJSONResponse(&got), 76 ) 77 78 if !equalSettlements(got, expected) { 79 t.Errorf("got settlements: %+v, expected: %+v", got, expected) 80 } 81 82 } 83 84 func TestSettlementsError(t *testing.T) { 85 t.Parallel() 86 87 wantErr := errors.New("New errors") 88 settlementsSentFunc := func() (map[string]*big.Int, error) { 89 return nil, wantErr 90 } 91 testServer, _, _, _ := newTestServer(t, testServerOptions{ 92 SwapOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc)}, 93 }) 94 95 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements", http.StatusInternalServerError, 96 jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ 97 Message: api.ErrCantSettlements, 98 Code: http.StatusInternalServerError, 99 }), 100 ) 101 } 102 103 func TestSettlementsPeers(t *testing.T) { 104 t.Parallel() 105 106 peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" 107 settlementSentFunc := func(swarm.Address) (*big.Int, error) { 108 return big.NewInt(1000000000000000000), nil 109 } 110 testServer, _, _, _ := newTestServer(t, testServerOptions{ 111 SwapOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, 112 }) 113 114 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements/"+peer, http.StatusOK, 115 jsonhttptest.WithExpectedJSONResponse(api.SettlementResponse{ 116 Peer: peer, 117 SettlementSent: bigint.Wrap(big.NewInt(1000000000000000000)), 118 SettlementReceived: bigint.Wrap(big.NewInt(0)), 119 }), 120 ) 121 } 122 123 func TestSettlementsPeersNoSettlements(t *testing.T) { 124 t.Parallel() 125 126 peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" 127 noErrFunc := func(swarm.Address) (*big.Int, error) { 128 return big.NewInt(1000000000000000000), nil 129 } 130 errFunc := func(swarm.Address) (*big.Int, error) { 131 return nil, settlement.ErrPeerNoSettlements 132 } 133 134 t.Run("no sent", func(t *testing.T) { 135 t.Parallel() 136 137 testServer, _, _, _ := newTestServer(t, testServerOptions{ 138 SwapOpts: []mock.Option{ 139 mock.WithSettlementSentFunc(errFunc), 140 mock.WithSettlementRecvFunc(noErrFunc), 141 }, 142 }) 143 144 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements/"+peer, http.StatusOK, 145 jsonhttptest.WithExpectedJSONResponse(api.SettlementResponse{ 146 Peer: peer, 147 SettlementSent: bigint.Wrap(big.NewInt(0)), 148 SettlementReceived: bigint.Wrap(big.NewInt(1000000000000000000)), 149 }), 150 ) 151 }) 152 153 t.Run("no received", func(t *testing.T) { 154 t.Parallel() 155 156 testServer, _, _, _ := newTestServer(t, testServerOptions{ 157 SwapOpts: []mock.Option{ 158 mock.WithSettlementSentFunc(noErrFunc), 159 mock.WithSettlementRecvFunc(errFunc), 160 }, 161 }) 162 163 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements/"+peer, http.StatusOK, 164 jsonhttptest.WithExpectedJSONResponse(api.SettlementResponse{ 165 Peer: peer, 166 SettlementSent: bigint.Wrap(big.NewInt(1000000000000000000)), 167 SettlementReceived: bigint.Wrap(big.NewInt(0)), 168 }), 169 ) 170 }) 171 } 172 173 func Test_peerSettlementsHandler_invalidInputs(t *testing.T) { 174 t.Parallel() 175 176 client, _, _, _ := newTestServer(t, testServerOptions{}) 177 178 tests := []struct { 179 name string 180 peer string 181 want jsonhttp.StatusResponse 182 }{{ 183 name: "peer - odd hex string", 184 peer: "123", 185 want: jsonhttp.StatusResponse{ 186 Code: http.StatusBadRequest, 187 Message: "invalid path params", 188 Reasons: []jsonhttp.Reason{ 189 { 190 Field: "peer", 191 Error: api.ErrHexLength.Error(), 192 }, 193 }, 194 }, 195 }, { 196 name: "peer - invalid hex character", 197 peer: "123G", 198 want: jsonhttp.StatusResponse{ 199 Code: http.StatusBadRequest, 200 Message: "invalid path params", 201 Reasons: []jsonhttp.Reason{ 202 { 203 Field: "peer", 204 Error: api.HexInvalidByteError('G').Error(), 205 }, 206 }, 207 }, 208 }} 209 210 for _, tc := range tests { 211 tc := tc 212 t.Run(tc.name, func(t *testing.T) { 213 t.Parallel() 214 215 jsonhttptest.Request(t, client, http.MethodGet, "/settlements/"+tc.peer, tc.want.Code, 216 jsonhttptest.WithExpectedJSONResponse(tc.want), 217 ) 218 }) 219 } 220 } 221 222 func TestSettlementsPeersError(t *testing.T) { 223 t.Parallel() 224 225 peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" 226 wantErr := errors.New("Error") 227 settlementSentFunc := func(swarm.Address) (*big.Int, error) { 228 return nil, wantErr 229 } 230 testServer, _, _, _ := newTestServer(t, testServerOptions{ 231 SwapOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, 232 }) 233 234 jsonhttptest.Request(t, testServer, http.MethodGet, "/settlements/"+peer, http.StatusInternalServerError, 235 jsonhttptest.WithExpectedJSONResponse(jsonhttp.StatusResponse{ 236 Message: api.ErrCantSettlementsPeer, 237 Code: http.StatusInternalServerError, 238 }), 239 ) 240 } 241 242 func equalSettlements(a, b *api.SettlementsResponse) bool { 243 var state bool 244 245 for akeys := range a.Settlements { 246 state = false 247 for bkeys := range b.Settlements { 248 if reflect.DeepEqual(a.Settlements[akeys], b.Settlements[bkeys]) { 249 state = true 250 break 251 } 252 } 253 if !state { 254 return false 255 } 256 } 257 258 for bkeys := range b.Settlements { 259 state = false 260 for akeys := range a.Settlements { 261 if reflect.DeepEqual(a.Settlements[akeys], b.Settlements[bkeys]) { 262 state = true 263 break 264 } 265 } 266 if !state { 267 return false 268 } 269 } 270 271 if a.TotalSettlementReceived.Cmp(b.TotalSettlementReceived.Int) != 0 { 272 return false 273 } 274 275 if a.TotalSettlementSent.Cmp(b.TotalSettlementSent.Int) != 0 { 276 return false 277 } 278 279 return true 280 }