msgnotfound_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 "github.com/p9c/p9/pkg/chainhash"
12 )
13
14 // TestNotFound tests the MsgNotFound API.
15 func TestNotFound(t *testing.T) {
16 pver := ProtocolVersion
17 // Ensure the command is expected value.
18 wantCmd := "notfound"
19 msg := NewMsgNotFound()
20 if cmd := msg.Command(); cmd != wantCmd {
21 t.Errorf(
22 "NewMsgNotFound: wrong command - got %v want %v",
23 cmd, wantCmd,
24 )
25 }
26 // Ensure max payload is expected value for latest protocol version. Num inventory vectors (varInt) + max allowed
27 // inventory vectors.
28 wantPayload := uint32(1800009)
29 maxPayload := msg.MaxPayloadLength(pver)
30 if maxPayload != wantPayload {
31 t.Errorf(
32 "MaxPayloadLength: wrong max payload length for "+
33 "protocol version %d - got %v, want %v", pver,
34 maxPayload, wantPayload,
35 )
36 }
37 // Ensure inventory vectors are added properly.
38 hash := chainhash.Hash{}
39 iv := NewInvVect(InvTypeBlock, &hash)
40 var e error
41 if e = msg.AddInvVect(iv); E.Chk(e) {
42 t.Errorf("AddInvVect: %v", e)
43 }
44 if msg.InvList[0] != iv {
45 t.Errorf(
46 "AddInvVect: wrong invvect added - got %v, want %v",
47 spew.Sprint(msg.InvList[0]), spew.Sprint(iv),
48 )
49 }
50 // Ensure adding more than the max allowed inventory vectors per message returns an error.
51 for i := 0; i < MaxInvPerMsg; i++ {
52 e = msg.AddInvVect(iv)
53 }
54 if e == nil {
55 t.Errorf(
56 "AddInvVect: expected error on too many inventory " +
57 "vectors not received",
58 )
59 }
60 }
61
62 // TestNotFoundWire tests the MsgNotFound wire encode and decode for various numbers of inventory vectors and protocol
63 // versions.
64 func TestNotFoundWire(t *testing.T) {
65 // Block 203707 hash.
66 hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
67 blockHash, e := chainhash.NewHashFromStr(hashStr)
68 if e != nil {
69 t.Errorf("NewHashFromStr: %v", e)
70 }
71 // Transaction 1 of Block 203707 hash.
72 hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
73 txHash, e := chainhash.NewHashFromStr(hashStr)
74 if e != nil {
75 t.Errorf("NewHashFromStr: %v", e)
76 }
77 iv := NewInvVect(InvTypeBlock, blockHash)
78 iv2 := NewInvVect(InvTypeTx, txHash)
79 // Empty notfound message.
80 NoInv := NewMsgNotFound()
81 NoInvEncoded := []byte{
82 0x00, // Varint for number of inventory vectors
83 }
84 // NotFound message with multiple inventory vectors.
85 MultiInv := NewMsgNotFound()
86 e = MultiInv.AddInvVect(iv)
87 if e != nil {
88 t.Log(e)
89 }
90 e = MultiInv.AddInvVect(iv2)
91 if e != nil {
92 t.Log(e)
93 }
94 MultiInvEncoded := []byte{
95 0x02, // Varint for number of inv vectors
96 0x02, 0x00, 0x00, 0x00, // InvTypeBlock
97 0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
98 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
99 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
100 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
101 0x01, 0x00, 0x00, 0x00, // InvTypeTx
102 0xf0, 0xfa, 0xcc, 0x7a, 0x48, 0x1b, 0xe7, 0xcf,
103 0x42, 0xbd, 0x7f, 0xe5, 0x4f, 0x2c, 0x2a, 0xf8,
104 0xef, 0x81, 0x9a, 0xdd, 0x93, 0xee, 0x55, 0x98,
105 0x0a, 0xf0, 0x2b, 0x39, 0xc7, 0x3d, 0x8a, 0xd2, // Tx 1 of block 203707 hash
106 }
107 tests := []struct {
108 in *MsgNotFound // Message to encode
109 out *MsgNotFound // Expected decoded message
110 buf []byte // Wire encoding
111 pver uint32 // Protocol version for wire encoding
112 enc MessageEncoding // Message encoding format
113 }{
114 // Latest protocol version with no inv vectors.
115 {
116 NoInv,
117 NoInv,
118 NoInvEncoded,
119 ProtocolVersion,
120 BaseEncoding,
121 },
122 // Latest protocol version with multiple inv vectors.
123 {
124 MultiInv,
125 MultiInv,
126 MultiInvEncoded,
127 ProtocolVersion,
128 BaseEncoding,
129 },
130 // Protocol version BIP0035Version no inv vectors.
131 {
132 NoInv,
133 NoInv,
134 NoInvEncoded,
135 BIP0035Version,
136 BaseEncoding,
137 },
138 // Protocol version BIP0035Version with multiple inv vectors.
139 {
140 MultiInv,
141 MultiInv,
142 MultiInvEncoded,
143 BIP0035Version,
144 BaseEncoding,
145 },
146 // Protocol version BIP0031Version no inv vectors.
147 {
148 NoInv,
149 NoInv,
150 NoInvEncoded,
151 BIP0031Version,
152 BaseEncoding,
153 },
154 // Protocol version BIP0031Version with multiple inv vectors.
155 {
156 MultiInv,
157 MultiInv,
158 MultiInvEncoded,
159 BIP0031Version,
160 BaseEncoding,
161 },
162 // Protocol version NetAddressTimeVersion no inv vectors.
163 {
164 NoInv,
165 NoInv,
166 NoInvEncoded,
167 NetAddressTimeVersion,
168 BaseEncoding,
169 },
170 // Protocol version NetAddressTimeVersion with multiple inv vectors.
171 {
172 MultiInv,
173 MultiInv,
174 MultiInvEncoded,
175 NetAddressTimeVersion,
176 BaseEncoding,
177 },
178 // Protocol version MultipleAddressVersion no inv vectors.
179 {
180 NoInv,
181 NoInv,
182 NoInvEncoded,
183 MultipleAddressVersion,
184 BaseEncoding,
185 },
186 // Protocol version MultipleAddressVersion with multiple inv vectors.
187 {
188 MultiInv,
189 MultiInv,
190 MultiInvEncoded,
191 MultipleAddressVersion,
192 BaseEncoding,
193 },
194 }
195 t.Logf("Running %d tests", len(tests))
196 for i, test := range tests {
197 // Encode the message to wire format.
198 var buf bytes.Buffer
199 e := test.in.BtcEncode(&buf, test.pver, test.enc)
200 if e != nil {
201 t.Errorf("BtcEncode #%d error %v", i, e)
202 continue
203 }
204 if !bytes.Equal(buf.Bytes(), test.buf) {
205 t.Errorf(
206 "BtcEncode #%d\n got: %s want: %s", i,
207 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf),
208 )
209 continue
210 }
211 // Decode the message from wire format.
212 var msg MsgNotFound
213 rbuf := bytes.NewReader(test.buf)
214 e = msg.BtcDecode(rbuf, test.pver, test.enc)
215 if e != nil {
216 t.Errorf("BtcDecode #%d error %v", i, e)
217 continue
218 }
219 if !reflect.DeepEqual(&msg, test.out) {
220 t.Errorf(
221 "BtcDecode #%d\n got: %s want: %s", i,
222 spew.Sdump(msg), spew.Sdump(test.out),
223 )
224 continue
225 }
226 }
227 }
228
229 // TestNotFoundWireErrors performs negative tests against wire encode and decode of MsgNotFound to confirm error paths
230 // work correctly.
231 func TestNotFoundWireErrors(t *testing.T) {
232 pver := ProtocolVersion
233 wireErr := &MessageError{}
234 // Block 203707 hash.
235 hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
236 blockHash, e := chainhash.NewHashFromStr(hashStr)
237 if e != nil {
238 t.Errorf("NewHashFromStr: %v", e)
239 }
240 iv := NewInvVect(InvTypeBlock, blockHash)
241 // Base message used to induce errors.
242 baseNotFound := NewMsgNotFound()
243 e = baseNotFound.AddInvVect(iv)
244 if e != nil {
245 t.Log(e)
246 }
247 baseNotFoundEncoded := []byte{
248 0x02, // Varint for number of inv vectors
249 0x02, 0x00, 0x00, 0x00, // InvTypeBlock
250 0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
251 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
252 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
253 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
254 }
255 // Message that forces an error by having more than the max allowed inv vectors.
256 maxNotFound := NewMsgNotFound()
257 for i := 0; i < MaxInvPerMsg; i++ {
258 e = maxNotFound.AddInvVect(iv)
259 if e != nil {
260 t.Log(e)
261 }
262 }
263 maxNotFound.InvList = append(maxNotFound.InvList, iv)
264 maxNotFoundEncoded := []byte{
265 0xfd, 0x51, 0xc3, // Varint for number of inv vectors (50001)
266 }
267 tests := []struct {
268 in *MsgNotFound // value to encode
269 buf []byte // Wire encoding
270 pver uint32 // Protocol version for wire encoding
271 enc MessageEncoding // Message encoding format
272 max int // Max size of fixed buffer to induce errors
273 writeErr error // Expected write error
274 readErr error // Expected read error
275 }{
276 // Force error in inventory vector count
277 {baseNotFound, baseNotFoundEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
278 // Force error in inventory list.
279 {baseNotFound, baseNotFoundEncoded, pver, BaseEncoding, 1, io.ErrShortWrite, io.EOF},
280 // Force error with greater than max inventory vectors.
281 {maxNotFound, maxNotFoundEncoded, pver, BaseEncoding, 3, wireErr, wireErr},
282 }
283 t.Logf("Running %d tests", len(tests))
284 for i, test := range tests {
285 // Encode to wire format.
286 w := newFixedWriter(test.max)
287 if e = test.in.BtcEncode(w, test.pver, test.enc); E.Chk(e) {
288 }
289 if reflect.TypeOf(e) != reflect.TypeOf(test.writeErr) {
290 t.Errorf(
291 "BtcEncode #%d wrong error got: %v, want: %v",
292 i, e, test.writeErr,
293 )
294 continue
295 }
296 // For errors which are not of type MessageError, check them for equality.
297 if _, ok := e.(*MessageError); !ok {
298 if e != test.writeErr {
299 t.Errorf(
300 "BtcEncode #%d wrong error got: %v, want: %v",
301 i, e, test.writeErr,
302 )
303 continue
304 }
305 }
306 // Decode from wire format.
307 var msg MsgNotFound
308 r := newFixedReader(test.max, test.buf)
309 e = msg.BtcDecode(r, test.pver, test.enc)
310 if reflect.TypeOf(e) != reflect.TypeOf(test.readErr) {
311 t.Errorf(
312 "BtcDecode #%d wrong error got: %v, want: %v",
313 i, e, test.readErr,
314 )
315 continue
316 }
317 // For errors which are not of type MessageError, check them for equality.
318 if _, ok := e.(*MessageError); !ok {
319 if e != test.readErr {
320 t.Errorf(
321 "BtcDecode #%d wrong error got: %v, "+
322 "want: %v", i, e, test.readErr,
323 )
324 continue
325 }
326 }
327 }
328 }
329