github.com/palcoin-project/palcd@v1.0.0/wire/msgreject_test.go (about)

     1  // Copyright (c) 2014-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  // TestRejectCodeStringer tests the stringized output for the reject code type.
    17  func TestRejectCodeStringer(t *testing.T) {
    18  	tests := []struct {
    19  		in   RejectCode
    20  		want string
    21  	}{
    22  		{RejectMalformed, "REJECT_MALFORMED"},
    23  		{RejectInvalid, "REJECT_INVALID"},
    24  		{RejectObsolete, "REJECT_OBSOLETE"},
    25  		{RejectDuplicate, "REJECT_DUPLICATE"},
    26  		{RejectNonstandard, "REJECT_NONSTANDARD"},
    27  		{RejectDust, "REJECT_DUST"},
    28  		{RejectInsufficientFee, "REJECT_INSUFFICIENTFEE"},
    29  		{RejectCheckpoint, "REJECT_CHECKPOINT"},
    30  		{0xff, "Unknown RejectCode (255)"},
    31  	}
    32  
    33  	t.Logf("Running %d tests", len(tests))
    34  	for i, test := range tests {
    35  		result := test.in.String()
    36  		if result != test.want {
    37  			t.Errorf("String #%d\n got: %s want: %s", i, result,
    38  				test.want)
    39  			continue
    40  		}
    41  	}
    42  
    43  }
    44  
    45  // TestRejectLatest tests the MsgPong API against the latest protocol version.
    46  func TestRejectLatest(t *testing.T) {
    47  	pver := ProtocolVersion
    48  	enc := BaseEncoding
    49  
    50  	// Create reject message data.
    51  	rejCommand := (&MsgBlock{}).Command()
    52  	rejCode := RejectDuplicate
    53  	rejReason := "duplicate block"
    54  	rejHash := mainNetGenesisHash
    55  
    56  	// Ensure we get the correct data back out.
    57  	msg := NewMsgReject(rejCommand, rejCode, rejReason)
    58  	msg.Hash = rejHash
    59  	if msg.Cmd != rejCommand {
    60  		t.Errorf("NewMsgReject: wrong rejected command - got %v, "+
    61  			"want %v", msg.Cmd, rejCommand)
    62  	}
    63  	if msg.Code != rejCode {
    64  		t.Errorf("NewMsgReject: wrong rejected code - got %v, "+
    65  			"want %v", msg.Code, rejCode)
    66  	}
    67  	if msg.Reason != rejReason {
    68  		t.Errorf("NewMsgReject: wrong rejected reason - got %v, "+
    69  			"want %v", msg.Reason, rejReason)
    70  	}
    71  
    72  	// Ensure the command is expected value.
    73  	wantCmd := "reject"
    74  	if cmd := msg.Command(); cmd != wantCmd {
    75  		t.Errorf("NewMsgReject: wrong command - got %v want %v",
    76  			cmd, wantCmd)
    77  	}
    78  
    79  	// Ensure max payload is expected value for latest protocol version.
    80  	wantPayload := uint32(MaxMessagePayload)
    81  	maxPayload := msg.MaxPayloadLength(pver)
    82  	if maxPayload != wantPayload {
    83  		t.Errorf("MaxPayloadLength: wrong max payload length for "+
    84  			"protocol version %d - got %v, want %v", pver,
    85  			maxPayload, wantPayload)
    86  	}
    87  
    88  	// Test encode with latest protocol version.
    89  	var buf bytes.Buffer
    90  	err := msg.BtcEncode(&buf, pver, enc)
    91  	if err != nil {
    92  		t.Errorf("encode of MsgReject failed %v err <%v>", msg, err)
    93  	}
    94  
    95  	// Test decode with latest protocol version.
    96  	readMsg := MsgReject{}
    97  	err = readMsg.BtcDecode(&buf, pver, enc)
    98  	if err != nil {
    99  		t.Errorf("decode of MsgReject failed %v err <%v>", buf.Bytes(),
   100  			err)
   101  	}
   102  
   103  	// Ensure decoded data is the same.
   104  	if msg.Cmd != readMsg.Cmd {
   105  		t.Errorf("Should get same reject command - got %v, want %v",
   106  			readMsg.Cmd, msg.Cmd)
   107  	}
   108  	if msg.Code != readMsg.Code {
   109  		t.Errorf("Should get same reject code - got %v, want %v",
   110  			readMsg.Code, msg.Code)
   111  	}
   112  	if msg.Reason != readMsg.Reason {
   113  		t.Errorf("Should get same reject reason - got %v, want %v",
   114  			readMsg.Reason, msg.Reason)
   115  	}
   116  	if msg.Hash != readMsg.Hash {
   117  		t.Errorf("Should get same reject hash - got %v, want %v",
   118  			readMsg.Hash, msg.Hash)
   119  	}
   120  }
   121  
   122  // TestRejectBeforeAdded tests the MsgReject API against a protocol version
   123  // before the version which introduced it (RejectVersion).
   124  func TestRejectBeforeAdded(t *testing.T) {
   125  	// Use the protocol version just prior to RejectVersion.
   126  	pver := RejectVersion - 1
   127  	enc := BaseEncoding
   128  
   129  	// Create reject message data.
   130  	rejCommand := (&MsgBlock{}).Command()
   131  	rejCode := RejectDuplicate
   132  	rejReason := "duplicate block"
   133  	rejHash := mainNetGenesisHash
   134  
   135  	msg := NewMsgReject(rejCommand, rejCode, rejReason)
   136  	msg.Hash = rejHash
   137  
   138  	// Ensure max payload is expected value for old protocol version.
   139  	size := msg.MaxPayloadLength(pver)
   140  	if size != 0 {
   141  		t.Errorf("Max length should be 0 for reject protocol version %d.",
   142  			pver)
   143  	}
   144  
   145  	// Test encode with old protocol version.
   146  	var buf bytes.Buffer
   147  	err := msg.BtcEncode(&buf, pver, enc)
   148  	if err == nil {
   149  		t.Errorf("encode of MsgReject succeeded when it shouldn't "+
   150  			"have %v", msg)
   151  	}
   152  
   153  	//	// Test decode with old protocol version.
   154  	readMsg := MsgReject{}
   155  	err = readMsg.BtcDecode(&buf, pver, enc)
   156  	if err == nil {
   157  		t.Errorf("decode of MsgReject succeeded when it shouldn't "+
   158  			"have %v", spew.Sdump(buf.Bytes()))
   159  	}
   160  
   161  	// Since this protocol version doesn't support reject, make sure various
   162  	// fields didn't get encoded and decoded back out.
   163  	if msg.Cmd == readMsg.Cmd {
   164  		t.Errorf("Should not get same reject command for protocol "+
   165  			"version %d", pver)
   166  	}
   167  	if msg.Code == readMsg.Code {
   168  		t.Errorf("Should not get same reject code for protocol "+
   169  			"version %d", pver)
   170  	}
   171  	if msg.Reason == readMsg.Reason {
   172  		t.Errorf("Should not get same reject reason for protocol "+
   173  			"version %d", pver)
   174  	}
   175  	if msg.Hash == readMsg.Hash {
   176  		t.Errorf("Should not get same reject hash for protocol "+
   177  			"version %d", pver)
   178  	}
   179  }
   180  
   181  // TestRejectCrossProtocol tests the MsgReject API when encoding with the latest
   182  // protocol version and decoded with a version before the version which
   183  // introduced it (RejectVersion).
   184  func TestRejectCrossProtocol(t *testing.T) {
   185  	// Create reject message data.
   186  	rejCommand := (&MsgBlock{}).Command()
   187  	rejCode := RejectDuplicate
   188  	rejReason := "duplicate block"
   189  	rejHash := mainNetGenesisHash
   190  
   191  	msg := NewMsgReject(rejCommand, rejCode, rejReason)
   192  	msg.Hash = rejHash
   193  
   194  	// Encode with latest protocol version.
   195  	var buf bytes.Buffer
   196  	err := msg.BtcEncode(&buf, ProtocolVersion, BaseEncoding)
   197  	if err != nil {
   198  		t.Errorf("encode of MsgReject failed %v err <%v>", msg, err)
   199  	}
   200  
   201  	// Decode with old protocol version.
   202  	readMsg := MsgReject{}
   203  	err = readMsg.BtcDecode(&buf, RejectVersion-1, BaseEncoding)
   204  	if err == nil {
   205  		t.Errorf("encode of MsgReject succeeded when it shouldn't "+
   206  			"have %v", msg)
   207  	}
   208  
   209  	// Since one of the protocol versions doesn't support the reject
   210  	// message, make sure the various fields didn't get encoded and decoded
   211  	// back out.
   212  	if msg.Cmd == readMsg.Cmd {
   213  		t.Errorf("Should not get same reject command for cross protocol")
   214  	}
   215  	if msg.Code == readMsg.Code {
   216  		t.Errorf("Should not get same reject code for cross protocol")
   217  	}
   218  	if msg.Reason == readMsg.Reason {
   219  		t.Errorf("Should not get same reject reason for cross protocol")
   220  	}
   221  	if msg.Hash == readMsg.Hash {
   222  		t.Errorf("Should not get same reject hash for cross protocol")
   223  	}
   224  }
   225  
   226  // TestRejectWire tests the MsgReject wire encode and decode for various
   227  // protocol versions.
   228  func TestRejectWire(t *testing.T) {
   229  	tests := []struct {
   230  		msg  MsgReject       // Message to encode
   231  		buf  []byte          // Wire encoding
   232  		pver uint32          // Protocol version for wire encoding
   233  		enc  MessageEncoding // Message encoding format
   234  	}{
   235  		// Latest protocol version rejected command version (no hash).
   236  		{
   237  			MsgReject{
   238  				Cmd:    "version",
   239  				Code:   RejectDuplicate,
   240  				Reason: "duplicate version",
   241  			},
   242  			[]byte{
   243  				0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // "version"
   244  				0x12, // RejectDuplicate
   245  				0x11, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
   246  				0x74, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
   247  				0x6f, 0x6e, // "duplicate version"
   248  			},
   249  			ProtocolVersion,
   250  			BaseEncoding,
   251  		},
   252  		// Latest protocol version rejected command block (has hash).
   253  		{
   254  			MsgReject{
   255  				Cmd:    "block",
   256  				Code:   RejectDuplicate,
   257  				Reason: "duplicate block",
   258  				Hash:   mainNetGenesisHash,
   259  			},
   260  			[]byte{
   261  				0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, // "block"
   262  				0x12, // RejectDuplicate
   263  				0x0f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
   264  				0x74, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, // "duplicate block"
   265  				0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
   266  				0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
   267  				0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
   268  				0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // mainNetGenesisHash
   269  			},
   270  			ProtocolVersion,
   271  			BaseEncoding,
   272  		},
   273  	}
   274  
   275  	t.Logf("Running %d tests", len(tests))
   276  	for i, test := range tests {
   277  		// Encode the message to wire format.
   278  		var buf bytes.Buffer
   279  		err := test.msg.BtcEncode(&buf, test.pver, test.enc)
   280  		if err != nil {
   281  			t.Errorf("BtcEncode #%d error %v", i, err)
   282  			continue
   283  		}
   284  		if !bytes.Equal(buf.Bytes(), test.buf) {
   285  			t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
   286  				spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
   287  			continue
   288  		}
   289  
   290  		// Decode the message from wire format.
   291  		var msg MsgReject
   292  		rbuf := bytes.NewReader(test.buf)
   293  		err = msg.BtcDecode(rbuf, test.pver, test.enc)
   294  		if err != nil {
   295  			t.Errorf("BtcDecode #%d error %v", i, err)
   296  			continue
   297  		}
   298  		if !reflect.DeepEqual(msg, test.msg) {
   299  			t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
   300  				spew.Sdump(msg), spew.Sdump(test.msg))
   301  			continue
   302  		}
   303  	}
   304  }
   305  
   306  // TestRejectWireErrors performs negative tests against wire encode and decode
   307  // of MsgReject to confirm error paths work correctly.
   308  func TestRejectWireErrors(t *testing.T) {
   309  	pver := ProtocolVersion
   310  	pverNoReject := RejectVersion - 1
   311  	wireErr := &MessageError{}
   312  
   313  	baseReject := NewMsgReject("block", RejectDuplicate, "duplicate block")
   314  	baseReject.Hash = mainNetGenesisHash
   315  	baseRejectEncoded := []byte{
   316  		0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, // "block"
   317  		0x12, // RejectDuplicate
   318  		0x0f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61,
   319  		0x74, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, // "duplicate block"
   320  		0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
   321  		0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
   322  		0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
   323  		0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // mainNetGenesisHash
   324  	}
   325  
   326  	tests := []struct {
   327  		in       *MsgReject      // Value to encode
   328  		buf      []byte          // Wire encoding
   329  		pver     uint32          // Protocol version for wire encoding
   330  		enc      MessageEncoding // Message encoding format
   331  		max      int             // Max size of fixed buffer to induce errors
   332  		writeErr error           // Expected write error
   333  		readErr  error           // Expected read error
   334  	}{
   335  		// Latest protocol version with intentional read/write errors.
   336  		// Force error in reject command.
   337  		{baseReject, baseRejectEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
   338  		// Force error in reject code.
   339  		{baseReject, baseRejectEncoded, pver, BaseEncoding, 6, io.ErrShortWrite, io.EOF},
   340  		// Force error in reject reason.
   341  		{baseReject, baseRejectEncoded, pver, BaseEncoding, 7, io.ErrShortWrite, io.EOF},
   342  		// Force error in reject hash.
   343  		{baseReject, baseRejectEncoded, pver, BaseEncoding, 23, io.ErrShortWrite, io.EOF},
   344  		// Force error due to unsupported protocol version.
   345  		{baseReject, baseRejectEncoded, pverNoReject, BaseEncoding, 6, wireErr, wireErr},
   346  	}
   347  
   348  	t.Logf("Running %d tests", len(tests))
   349  	for i, test := range tests {
   350  		// Encode to wire format.
   351  		w := newFixedWriter(test.max)
   352  		err := test.in.BtcEncode(w, test.pver, test.enc)
   353  		if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
   354  			t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
   355  				i, err, test.writeErr)
   356  			continue
   357  		}
   358  
   359  		// For errors which are not of type MessageError, check them for
   360  		// equality.
   361  		if _, ok := err.(*MessageError); !ok {
   362  			if err != test.writeErr {
   363  				t.Errorf("BtcEncode #%d wrong error got: %v, "+
   364  					"want: %v", i, err, test.writeErr)
   365  				continue
   366  			}
   367  		}
   368  
   369  		// Decode from wire format.
   370  		var msg MsgReject
   371  		r := newFixedReader(test.max, test.buf)
   372  		err = msg.BtcDecode(r, test.pver, test.enc)
   373  		if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
   374  			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
   375  				i, err, test.readErr)
   376  			continue
   377  		}
   378  
   379  		// For errors which are not of type MessageError, check them for
   380  		// equality.
   381  		if _, ok := err.(*MessageError); !ok {
   382  			if err != test.readErr {
   383  				t.Errorf("BtcDecode #%d wrong error got: %v, "+
   384  					"want: %v", i, err, test.readErr)
   385  				continue
   386  			}
   387  		}
   388  	}
   389  }