msgreject_test.go raw

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