github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/les/lespay/server/prioritypool_test.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package server 18 19 import ( 20 "math/rand" 21 "reflect" 22 "testing" 23 24 "github.com/cryptogateway/go-paymex/common/mclock" 25 "github.com/cryptogateway/go-paymex/p2p/enode" 26 "github.com/cryptogateway/go-paymex/p2p/enr" 27 "github.com/cryptogateway/go-paymex/p2p/nodestate" 28 ) 29 30 var ( 31 testSetup = &nodestate.Setup{} 32 ppTestClientFlag = testSetup.NewFlag("ppTestClientFlag") 33 ppTestClientField = testSetup.NewField("ppTestClient", reflect.TypeOf(&ppTestClient{})) 34 ppUpdateFlag = testSetup.NewFlag("ppUpdateFlag") 35 ppTestSetup = NewPriorityPoolSetup(testSetup) 36 ) 37 38 func init() { 39 ppTestSetup.Connect(ppTestClientField, ppUpdateFlag) 40 } 41 42 const ( 43 testCapacityStepDiv = 100 44 testCapacityToleranceDiv = 10 45 ) 46 47 type ppTestClient struct { 48 node *enode.Node 49 balance, cap uint64 50 } 51 52 func (c *ppTestClient) Priority(now mclock.AbsTime, cap uint64) int64 { 53 return int64(c.balance / cap) 54 } 55 56 func (c *ppTestClient) EstMinPriority(until mclock.AbsTime, cap uint64, update bool) int64 { 57 return int64(c.balance / cap) 58 } 59 60 func TestPriorityPool(t *testing.T) { 61 clock := &mclock.Simulated{} 62 ns := nodestate.NewNodeStateMachine(nil, nil, clock, testSetup) 63 64 ns.SubscribeField(ppTestSetup.CapacityField, func(node *enode.Node, state nodestate.Flags, oldValue, newValue interface{}) { 65 if n := ns.GetField(node, ppTestSetup.priorityField); n != nil { 66 c := n.(*ppTestClient) 67 c.cap = newValue.(uint64) 68 } 69 }) 70 pp := NewPriorityPool(ns, ppTestSetup, clock, 100, 0, testCapacityStepDiv) 71 ns.Start() 72 pp.SetLimits(100, 1000000) 73 clients := make([]*ppTestClient, 100) 74 raise := func(c *ppTestClient) { 75 for { 76 var ok bool 77 ns.Operation(func() { 78 _, ok = pp.RequestCapacity(c.node, c.cap+c.cap/testCapacityStepDiv, 0, true) 79 }) 80 if !ok { 81 return 82 } 83 } 84 } 85 var sumBalance uint64 86 check := func(c *ppTestClient) { 87 expCap := 1000000 * c.balance / sumBalance 88 capTol := expCap / testCapacityToleranceDiv 89 if c.cap < expCap-capTol || c.cap > expCap+capTol { 90 t.Errorf("Wrong node capacity (expected %d, got %d)", expCap, c.cap) 91 } 92 } 93 94 for i := range clients { 95 c := &ppTestClient{ 96 node: enode.SignNull(&enr.Record{}, enode.ID{byte(i)}), 97 balance: 1000000000, 98 cap: 1000, 99 } 100 sumBalance += c.balance 101 clients[i] = c 102 ns.SetState(c.node, ppTestClientFlag, nodestate.Flags{}, 0) 103 ns.SetField(c.node, ppTestSetup.priorityField, c) 104 ns.SetState(c.node, ppTestSetup.InactiveFlag, nodestate.Flags{}, 0) 105 raise(c) 106 check(c) 107 } 108 109 for count := 0; count < 100; count++ { 110 c := clients[rand.Intn(len(clients))] 111 oldBalance := c.balance 112 c.balance = uint64(rand.Int63n(1000000000) + 1000000000) 113 sumBalance += c.balance - oldBalance 114 pp.ns.SetState(c.node, ppUpdateFlag, nodestate.Flags{}, 0) 115 pp.ns.SetState(c.node, nodestate.Flags{}, ppUpdateFlag, 0) 116 if c.balance > oldBalance { 117 raise(c) 118 } else { 119 for _, c := range clients { 120 raise(c) 121 } 122 } 123 for _, c := range clients { 124 check(c) 125 } 126 } 127 128 ns.Stop() 129 }