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