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