github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/protocols/accounting_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:41</date> 10 //</624450105902108672> 11 12 13 package protocols 14 15 import ( 16 "testing" 17 18 "github.com/ethereum/go-ethereum/p2p" 19 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 20 "github.com/ethereum/go-ethereum/rlp" 21 ) 22 23 //虚拟平衡实现 24 type dummyBalance struct { 25 amount int64 26 peer *Peer 27 } 28 29 //虚拟价格实施 30 type dummyPrices struct{} 31 32 //需要基于大小的记帐的虚拟消息 33 //发送者付费 34 type perBytesMsgSenderPays struct { 35 Content string 36 } 37 38 //需要基于大小的记帐的虚拟消息 39 //接收者付费 40 type perBytesMsgReceiverPays struct { 41 Content string 42 } 43 44 //按单位付费的假消息 45 //发送者付费 46 type perUnitMsgSenderPays struct{} 47 48 //接收者付费 49 type perUnitMsgReceiverPays struct{} 50 51 //价格为零的假消息 52 type zeroPriceMsg struct{} 53 54 //没有记帐的虚拟消息 55 type nilPriceMsg struct{} 56 57 //返回已定义消息的价格 58 func (d *dummyPrices) Price(msg interface{}) *Price { 59 switch msg.(type) { 60 //基于大小的消息成本,接收者支付 61 case *perBytesMsgReceiverPays: 62 return &Price{ 63 PerByte: true, 64 Value: uint64(100), 65 Payer: Receiver, 66 } 67 //基于大小的邮件成本,发件人支付 68 case *perBytesMsgSenderPays: 69 return &Price{ 70 PerByte: true, 71 Value: uint64(100), 72 Payer: Sender, 73 } 74 //单一成本,收款人支付 75 case *perUnitMsgReceiverPays: 76 return &Price{ 77 PerByte: false, 78 Value: uint64(99), 79 Payer: Receiver, 80 } 81 //单一成本,寄件人支付 82 case *perUnitMsgSenderPays: 83 return &Price{ 84 PerByte: false, 85 Value: uint64(99), 86 Payer: Sender, 87 } 88 case *zeroPriceMsg: 89 return &Price{ 90 PerByte: false, 91 Value: uint64(0), 92 Payer: Sender, 93 } 94 case *nilPriceMsg: 95 return nil 96 } 97 return nil 98 } 99 100 //虚拟会计实现,只存储值供以后检查 101 func (d *dummyBalance) Add(amount int64, peer *Peer) error { 102 d.amount = amount 103 d.peer = peer 104 return nil 105 } 106 107 type testCase struct { 108 msg interface{} 109 size uint32 110 sendResult int64 111 recvResult int64 112 } 113 114 //最低水平单元测试 115 func TestBalance(t *testing.T) { 116 //创建实例 117 balance := &dummyBalance{} 118 prices := &dummyPrices{} 119 //创建规格 120 spec := createTestSpec() 121 //为规范创建记帐挂钩 122 acc := NewAccounting(balance, prices) 123 //创建对等体 124 id := adapters.RandomNodeConfig().ID 125 p := p2p.NewPeer(id, "testPeer", nil) 126 peer := NewPeer(p, &dummyRW{}, spec) 127 //价格取决于尺寸,接收者支付 128 msg := &perBytesMsgReceiverPays{Content: "testBalance"} 129 size, _ := rlp.EncodeToBytes(msg) 130 131 testCases := []testCase{ 132 { 133 msg, 134 uint32(len(size)), 135 int64(len(size) * 100), 136 int64(len(size) * -100), 137 }, 138 { 139 &perBytesMsgSenderPays{Content: "testBalance"}, 140 uint32(len(size)), 141 int64(len(size) * -100), 142 int64(len(size) * 100), 143 }, 144 { 145 &perUnitMsgSenderPays{}, 146 0, 147 int64(-99), 148 int64(99), 149 }, 150 { 151 &perUnitMsgReceiverPays{}, 152 0, 153 int64(99), 154 int64(-99), 155 }, 156 { 157 &zeroPriceMsg{}, 158 0, 159 int64(0), 160 int64(0), 161 }, 162 { 163 &nilPriceMsg{}, 164 0, 165 int64(0), 166 int64(0), 167 }, 168 } 169 checkAccountingTestCases(t, testCases, acc, peer, balance, true) 170 checkAccountingTestCases(t, testCases, acc, peer, balance, false) 171 } 172 173 func checkAccountingTestCases(t *testing.T, cases []testCase, acc *Accounting, peer *Peer, balance *dummyBalance, send bool) { 174 for _, c := range cases { 175 var err error 176 var expectedResult int64 177 //每次检查前重置平衡 178 balance.amount = 0 179 if send { 180 err = acc.Send(peer, c.size, c.msg) 181 expectedResult = c.sendResult 182 } else { 183 err = acc.Receive(peer, c.size, c.msg) 184 expectedResult = c.recvResult 185 } 186 187 checkResults(t, err, balance, peer, expectedResult) 188 } 189 } 190 191 func checkResults(t *testing.T, err error, balance *dummyBalance, peer *Peer, result int64) { 192 if err != nil { 193 t.Fatal(err) 194 } 195 if balance.peer != peer { 196 t.Fatalf("expected Add to be called with peer %v, got %v", peer, balance.peer) 197 } 198 if balance.amount != result { 199 t.Fatalf("Expected balance to be %d but is %d", result, balance.amount) 200 } 201 } 202 203 //创建测试规范 204 func createTestSpec() *Spec { 205 spec := &Spec{ 206 Name: "test", 207 Version: 42, 208 MaxMsgSize: 10 * 1024, 209 Messages: []interface{}{ 210 &perBytesMsgReceiverPays{}, 211 &perBytesMsgSenderPays{}, 212 &perUnitMsgReceiverPays{}, 213 &perUnitMsgSenderPays{}, 214 &zeroPriceMsg{}, 215 &nilPriceMsg{}, 216 }, 217 } 218 return spec 219 } 220