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