github.com/btcsuite/btcd@v0.24.0/wire/msgpong_test.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package wire
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  	"reflect"
    11  	"testing"
    12  
    13  	"github.com/davecgh/go-spew/spew"
    14  )
    15  
    16  // TestPongLatest tests the MsgPong API against the latest protocol version.
    17  func TestPongLatest(t *testing.T) {
    18  	enc := BaseEncoding
    19  	pver := ProtocolVersion
    20  
    21  	nonce, err := RandomUint64()
    22  	if err != nil {
    23  		t.Errorf("RandomUint64: error generating nonce: %v", err)
    24  	}
    25  	msg := NewMsgPong(nonce)
    26  	if msg.Nonce != nonce {
    27  		t.Errorf("NewMsgPong: wrong nonce - got %v, want %v",
    28  			msg.Nonce, nonce)
    29  	}
    30  
    31  	// Ensure the command is expected value.
    32  	wantCmd := "pong"
    33  	if cmd := msg.Command(); cmd != wantCmd {
    34  		t.Errorf("NewMsgPong: wrong command - got %v want %v",
    35  			cmd, wantCmd)
    36  	}
    37  
    38  	// Ensure max payload is expected value for latest protocol version.
    39  	wantPayload := uint32(8)
    40  	maxPayload := msg.MaxPayloadLength(pver)
    41  	if maxPayload != wantPayload {
    42  		t.Errorf("MaxPayloadLength: wrong max payload length for "+
    43  			"protocol version %d - got %v, want %v", pver,
    44  			maxPayload, wantPayload)
    45  	}
    46  
    47  	// Test encode with latest protocol version.
    48  	var buf bytes.Buffer
    49  	err = msg.BtcEncode(&buf, pver, enc)
    50  	if err != nil {
    51  		t.Errorf("encode of MsgPong failed %v err <%v>", msg, err)
    52  	}
    53  
    54  	// Test decode with latest protocol version.
    55  	readmsg := NewMsgPong(0)
    56  	err = readmsg.BtcDecode(&buf, pver, enc)
    57  	if err != nil {
    58  		t.Errorf("decode of MsgPong failed [%v] err <%v>", buf, err)
    59  	}
    60  
    61  	// Ensure nonce is the same.
    62  	if msg.Nonce != readmsg.Nonce {
    63  		t.Errorf("Should get same nonce for protocol version %d", pver)
    64  	}
    65  }
    66  
    67  // TestPongBIP0031 tests the MsgPong API against the protocol version
    68  // BIP0031Version.
    69  func TestPongBIP0031(t *testing.T) {
    70  	// Use the protocol version just prior to BIP0031Version changes.
    71  	pver := BIP0031Version
    72  	enc := BaseEncoding
    73  
    74  	nonce, err := RandomUint64()
    75  	if err != nil {
    76  		t.Errorf("Error generating nonce: %v", err)
    77  	}
    78  	msg := NewMsgPong(nonce)
    79  	if msg.Nonce != nonce {
    80  		t.Errorf("Should get same nonce back out.")
    81  	}
    82  
    83  	// Ensure max payload is expected value for old protocol version.
    84  	size := msg.MaxPayloadLength(pver)
    85  	if size != 0 {
    86  		t.Errorf("Max length should be 0 for pong protocol version %d.",
    87  			pver)
    88  	}
    89  
    90  	// Test encode with old protocol version.
    91  	var buf bytes.Buffer
    92  	err = msg.BtcEncode(&buf, pver, enc)
    93  	if err == nil {
    94  		t.Errorf("encode of MsgPong succeeded when it shouldn't have %v",
    95  			msg)
    96  	}
    97  
    98  	// Test decode with old protocol version.
    99  	readmsg := NewMsgPong(0)
   100  	err = readmsg.BtcDecode(&buf, pver, enc)
   101  	if err == nil {
   102  		t.Errorf("decode of MsgPong succeeded when it shouldn't have %v",
   103  			spew.Sdump(buf))
   104  	}
   105  
   106  	// Since this protocol version doesn't support pong, make sure the
   107  	// nonce didn't get encoded and decoded back out.
   108  	if msg.Nonce == readmsg.Nonce {
   109  		t.Errorf("Should not get same nonce for protocol version %d", pver)
   110  	}
   111  }
   112  
   113  // TestPongCrossProtocol tests the MsgPong API when encoding with the latest
   114  // protocol version and decoding with BIP0031Version.
   115  func TestPongCrossProtocol(t *testing.T) {
   116  	nonce, err := RandomUint64()
   117  	if err != nil {
   118  		t.Errorf("Error generating nonce: %v", err)
   119  	}
   120  	msg := NewMsgPong(nonce)
   121  	if msg.Nonce != nonce {
   122  		t.Errorf("Should get same nonce back out.")
   123  	}
   124  
   125  	// Encode with latest protocol version.
   126  	var buf bytes.Buffer
   127  	err = msg.BtcEncode(&buf, ProtocolVersion, BaseEncoding)
   128  	if err != nil {
   129  		t.Errorf("encode of MsgPong failed %v err <%v>", msg, err)
   130  	}
   131  
   132  	// Decode with old protocol version.
   133  	readmsg := NewMsgPong(0)
   134  	err = readmsg.BtcDecode(&buf, BIP0031Version, BaseEncoding)
   135  	if err == nil {
   136  		t.Errorf("encode of MsgPong succeeded when it shouldn't have %v",
   137  			msg)
   138  	}
   139  
   140  	// Since one of the protocol versions doesn't support the pong message,
   141  	// make sure the nonce didn't get encoded and decoded back out.
   142  	if msg.Nonce == readmsg.Nonce {
   143  		t.Error("Should not get same nonce for cross protocol")
   144  	}
   145  }
   146  
   147  // TestPongWire tests the MsgPong wire encode and decode for various protocol
   148  // versions.
   149  func TestPongWire(t *testing.T) {
   150  	tests := []struct {
   151  		in   MsgPong         // Message to encode
   152  		out  MsgPong         // Expected decoded message
   153  		buf  []byte          // Wire encoding
   154  		pver uint32          // Protocol version for wire encoding
   155  		enc  MessageEncoding // Message encoding format
   156  	}{
   157  		// Latest protocol version.
   158  		{
   159  			MsgPong{Nonce: 123123}, // 0x1e0f3
   160  			MsgPong{Nonce: 123123}, // 0x1e0f3
   161  			[]byte{0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
   162  			ProtocolVersion,
   163  			BaseEncoding,
   164  		},
   165  
   166  		// Protocol version BIP0031Version+1
   167  		{
   168  			MsgPong{Nonce: 456456}, // 0x6f708
   169  			MsgPong{Nonce: 456456}, // 0x6f708
   170  			[]byte{0x08, 0xf7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
   171  			BIP0031Version + 1,
   172  			BaseEncoding,
   173  		},
   174  	}
   175  
   176  	t.Logf("Running %d tests", len(tests))
   177  	for i, test := range tests {
   178  		// Encode the message to wire format.
   179  		var buf bytes.Buffer
   180  		err := test.in.BtcEncode(&buf, test.pver, test.enc)
   181  		if err != nil {
   182  			t.Errorf("BtcEncode #%d error %v", i, err)
   183  			continue
   184  		}
   185  		if !bytes.Equal(buf.Bytes(), test.buf) {
   186  			t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
   187  				spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
   188  			continue
   189  		}
   190  
   191  		// Decode the message from wire format.
   192  		var msg MsgPong
   193  		rbuf := bytes.NewReader(test.buf)
   194  		err = msg.BtcDecode(rbuf, test.pver, test.enc)
   195  		if err != nil {
   196  			t.Errorf("BtcDecode #%d error %v", i, err)
   197  			continue
   198  		}
   199  		if !reflect.DeepEqual(msg, test.out) {
   200  			t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
   201  				spew.Sdump(msg), spew.Sdump(test.out))
   202  			continue
   203  		}
   204  	}
   205  }
   206  
   207  // TestPongWireErrors performs negative tests against wire encode and decode
   208  // of MsgPong to confirm error paths work correctly.
   209  func TestPongWireErrors(t *testing.T) {
   210  	pver := ProtocolVersion
   211  	pverNoPong := BIP0031Version
   212  	wireErr := &MessageError{}
   213  
   214  	basePong := NewMsgPong(123123) // 0x1e0f3
   215  	basePongEncoded := []byte{
   216  		0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
   217  	}
   218  
   219  	tests := []struct {
   220  		in       *MsgPong        // Value to encode
   221  		buf      []byte          // Wire encoding
   222  		pver     uint32          // Protocol version for wire encoding
   223  		enc      MessageEncoding // Message encoding format
   224  		max      int             // Max size of fixed buffer to induce errors
   225  		writeErr error           // Expected write error
   226  		readErr  error           // Expected read error
   227  	}{
   228  		// Latest protocol version with intentional read/write errors.
   229  		// Force error in nonce.
   230  		{basePong, basePongEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
   231  		// Force error due to unsupported protocol version.
   232  		{basePong, basePongEncoded, pverNoPong, BaseEncoding, 4, wireErr, wireErr},
   233  	}
   234  
   235  	t.Logf("Running %d tests", len(tests))
   236  	for i, test := range tests {
   237  		// Encode to wire format.
   238  		w := newFixedWriter(test.max)
   239  		err := test.in.BtcEncode(w, test.pver, test.enc)
   240  		if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
   241  			t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
   242  				i, err, test.writeErr)
   243  			continue
   244  		}
   245  
   246  		// For errors which are not of type MessageError, check them for
   247  		// equality.
   248  		if _, ok := err.(*MessageError); !ok {
   249  			if err != test.writeErr {
   250  				t.Errorf("BtcEncode #%d wrong error got: %v, "+
   251  					"want: %v", i, err, test.writeErr)
   252  				continue
   253  			}
   254  		}
   255  
   256  		// Decode from wire format.
   257  		var msg MsgPong
   258  		r := newFixedReader(test.max, test.buf)
   259  		err = msg.BtcDecode(r, test.pver, test.enc)
   260  		if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
   261  			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
   262  				i, err, test.readErr)
   263  			continue
   264  		}
   265  
   266  		// For errors which are not of type MessageError, check them for
   267  		// equality.
   268  		if _, ok := err.(*MessageError); !ok {
   269  			if err != test.readErr {
   270  				t.Errorf("BtcDecode #%d wrong error got: %v, "+
   271  					"want: %v", i, err, test.readErr)
   272  				continue
   273  			}
   274  		}
   275  
   276  	}
   277  }