github.com/btcsuite/btcd@v0.24.0/wire/msgalert_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 ) 15 16 // TestMsgAlert tests the MsgAlert API. 17 func TestMsgAlert(t *testing.T) { 18 pver := ProtocolVersion 19 encoding := BaseEncoding 20 serializedpayload := []byte("some message") 21 signature := []byte("some sig") 22 23 // Ensure we get the same payload and signature back out. 24 msg := NewMsgAlert(serializedpayload, signature) 25 if !reflect.DeepEqual(msg.SerializedPayload, serializedpayload) { 26 t.Errorf("NewMsgAlert: wrong serializedpayload - got %v, want %v", 27 msg.SerializedPayload, serializedpayload) 28 } 29 if !reflect.DeepEqual(msg.Signature, signature) { 30 t.Errorf("NewMsgAlert: wrong signature - got %v, want %v", 31 msg.Signature, signature) 32 } 33 34 // Ensure the command is expected value. 35 wantCmd := "alert" 36 if cmd := msg.Command(); cmd != wantCmd { 37 t.Errorf("NewMsgAlert: wrong command - got %v want %v", 38 cmd, wantCmd) 39 } 40 41 // Ensure max payload is expected value. 42 wantPayload := uint32(1024 * 1024 * 32) 43 maxPayload := msg.MaxPayloadLength(pver) 44 if maxPayload != wantPayload { 45 t.Errorf("MaxPayloadLength: wrong max payload length for "+ 46 "protocol version %d - got %v, want %v", pver, 47 maxPayload, wantPayload) 48 } 49 50 // Test BtcEncode with Payload == nil 51 var buf bytes.Buffer 52 err := msg.BtcEncode(&buf, pver, encoding) 53 if err != nil { 54 t.Error(err.Error()) 55 } 56 // expected = 0x0c + serializedpayload + 0x08 + signature 57 expectedBuf := append([]byte{0x0c}, serializedpayload...) 58 expectedBuf = append(expectedBuf, []byte{0x08}...) 59 expectedBuf = append(expectedBuf, signature...) 60 if !bytes.Equal(buf.Bytes(), expectedBuf) { 61 t.Errorf("BtcEncode got: %s want: %s", 62 spew.Sdump(buf.Bytes()), spew.Sdump(expectedBuf)) 63 } 64 65 // Test BtcEncode with Payload != nil 66 // note: Payload is an empty Alert but not nil 67 msg.Payload = new(Alert) 68 buf = *new(bytes.Buffer) 69 err = msg.BtcEncode(&buf, pver, encoding) 70 if err != nil { 71 t.Error(err.Error()) 72 } 73 // empty Alert is 45 null bytes, see Alert comments 74 // for details 75 // expected = 0x2d + 45*0x00 + 0x08 + signature 76 expectedBuf = append([]byte{0x2d}, bytes.Repeat([]byte{0x00}, 45)...) 77 expectedBuf = append(expectedBuf, []byte{0x08}...) 78 expectedBuf = append(expectedBuf, signature...) 79 if !bytes.Equal(buf.Bytes(), expectedBuf) { 80 t.Errorf("BtcEncode got: %s want: %s", 81 spew.Sdump(buf.Bytes()), spew.Sdump(expectedBuf)) 82 } 83 } 84 85 // TestMsgAlertWire tests the MsgAlert wire encode and decode for various protocol 86 // versions. 87 func TestMsgAlertWire(t *testing.T) { 88 baseMsgAlert := NewMsgAlert([]byte("some payload"), []byte("somesig")) 89 baseMsgAlertEncoded := []byte{ 90 0x0c, // Varint for payload length 91 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x61, 0x79, 92 0x6c, 0x6f, 0x61, 0x64, // "some payload" 93 0x07, // Varint for signature length 94 0x73, 0x6f, 0x6d, 0x65, 0x73, 0x69, 0x67, // "somesig" 95 } 96 97 tests := []struct { 98 in *MsgAlert // Message to encode 99 out *MsgAlert // Expected decoded message 100 buf []byte // Wire encoding 101 pver uint32 // Protocol version for wire encoding 102 enc MessageEncoding // Message encoding format 103 }{ 104 // Latest protocol version. 105 { 106 baseMsgAlert, 107 baseMsgAlert, 108 baseMsgAlertEncoded, 109 ProtocolVersion, 110 BaseEncoding, 111 }, 112 113 // Protocol version BIP0035Version. 114 { 115 baseMsgAlert, 116 baseMsgAlert, 117 baseMsgAlertEncoded, 118 BIP0035Version, 119 BaseEncoding, 120 }, 121 122 // Protocol version BIP0031Version. 123 { 124 baseMsgAlert, 125 baseMsgAlert, 126 baseMsgAlertEncoded, 127 BIP0031Version, 128 BaseEncoding, 129 }, 130 131 // Protocol version NetAddressTimeVersion. 132 { 133 baseMsgAlert, 134 baseMsgAlert, 135 baseMsgAlertEncoded, 136 NetAddressTimeVersion, 137 BaseEncoding, 138 }, 139 140 // Protocol version MultipleAddressVersion. 141 { 142 baseMsgAlert, 143 baseMsgAlert, 144 baseMsgAlertEncoded, 145 MultipleAddressVersion, 146 BaseEncoding, 147 }, 148 } 149 150 t.Logf("Running %d tests", len(tests)) 151 for i, test := range tests { 152 // Encode the message to wire format. 153 var buf bytes.Buffer 154 err := test.in.BtcEncode(&buf, test.pver, test.enc) 155 if err != nil { 156 t.Errorf("BtcEncode #%d error %v", i, err) 157 continue 158 } 159 if !bytes.Equal(buf.Bytes(), test.buf) { 160 t.Errorf("BtcEncode #%d\n got: %s want: %s", i, 161 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) 162 continue 163 } 164 165 // Decode the message from wire format. 166 var msg MsgAlert 167 rbuf := bytes.NewReader(test.buf) 168 err = msg.BtcDecode(rbuf, test.pver, test.enc) 169 if err != nil { 170 t.Errorf("BtcDecode #%d error %v", i, err) 171 continue 172 } 173 if !reflect.DeepEqual(&msg, test.out) { 174 t.Errorf("BtcDecode #%d\n got: %s want: %s", i, 175 spew.Sdump(msg), spew.Sdump(test.out)) 176 continue 177 } 178 } 179 } 180 181 // TestMsgAlertWireErrors performs negative tests against wire encode and decode 182 // of MsgAlert to confirm error paths work correctly. 183 func TestMsgAlertWireErrors(t *testing.T) { 184 pver := ProtocolVersion 185 encoding := BaseEncoding 186 187 baseMsgAlert := NewMsgAlert([]byte("some payload"), []byte("somesig")) 188 baseMsgAlertEncoded := []byte{ 189 0x0c, // Varint for payload length 190 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x61, 0x79, 191 0x6c, 0x6f, 0x61, 0x64, // "some payload" 192 0x07, // Varint for signature length 193 0x73, 0x6f, 0x6d, 0x65, 0x73, 0x69, 0x67, // "somesig" 194 } 195 196 tests := []struct { 197 in *MsgAlert // Value to encode 198 buf []byte // Wire encoding 199 pver uint32 // Protocol version for wire encoding 200 enc MessageEncoding // Message encoding format 201 max int // Max size of fixed buffer to induce errors 202 writeErr error // Expected write error 203 readErr error // Expected read error 204 }{ 205 // Force error in payload length. 206 {baseMsgAlert, baseMsgAlertEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF}, 207 // Force error in payload. 208 {baseMsgAlert, baseMsgAlertEncoded, pver, BaseEncoding, 1, io.ErrShortWrite, io.EOF}, 209 // Force error in signature length. 210 {baseMsgAlert, baseMsgAlertEncoded, pver, BaseEncoding, 13, io.ErrShortWrite, io.EOF}, 211 // Force error in signature. 212 {baseMsgAlert, baseMsgAlertEncoded, pver, BaseEncoding, 14, io.ErrShortWrite, io.EOF}, 213 } 214 215 t.Logf("Running %d tests", len(tests)) 216 for i, test := range tests { 217 // Encode to wire format. 218 w := newFixedWriter(test.max) 219 err := test.in.BtcEncode(w, test.pver, test.enc) 220 if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) { 221 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v", 222 i, err, test.writeErr) 223 continue 224 } 225 226 // For errors which are not of type MessageError, check them for 227 // equality. 228 if _, ok := err.(*MessageError); !ok { 229 if err != test.writeErr { 230 t.Errorf("BtcEncode #%d wrong error got: %v, "+ 231 "want: %v", i, err, test.writeErr) 232 continue 233 } 234 } 235 236 // Decode from wire format. 237 var msg MsgAlert 238 r := newFixedReader(test.max, test.buf) 239 err = msg.BtcDecode(r, test.pver, test.enc) 240 if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { 241 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v", 242 i, err, test.readErr) 243 continue 244 } 245 246 // For errors which are not of type MessageError, check them for 247 // equality. 248 if _, ok := err.(*MessageError); !ok { 249 if err != test.readErr { 250 t.Errorf("BtcDecode #%d wrong error got: %v, "+ 251 "want: %v", i, err, test.readErr) 252 continue 253 } 254 } 255 } 256 257 // Test Error on empty Payload 258 baseMsgAlert.SerializedPayload = []byte{} 259 w := new(bytes.Buffer) 260 err := baseMsgAlert.BtcEncode(w, pver, encoding) 261 if _, ok := err.(*MessageError); !ok { 262 t.Errorf("MsgAlert.BtcEncode wrong error got: %T, want: %T", 263 err, MessageError{}) 264 } 265 266 // Test Payload Serialize error 267 // overflow the max number of elements in SetCancel 268 baseMsgAlert.Payload = new(Alert) 269 baseMsgAlert.Payload.SetCancel = make([]int32, maxCountSetCancel+1) 270 buf := *new(bytes.Buffer) 271 err = baseMsgAlert.BtcEncode(&buf, pver, encoding) 272 if _, ok := err.(*MessageError); !ok { 273 t.Errorf("MsgAlert.BtcEncode wrong error got: %T, want: %T", 274 err, MessageError{}) 275 } 276 277 // overflow the max number of elements in SetSubVer 278 baseMsgAlert.Payload = new(Alert) 279 baseMsgAlert.Payload.SetSubVer = make([]string, maxCountSetSubVer+1) 280 buf = *new(bytes.Buffer) 281 err = baseMsgAlert.BtcEncode(&buf, pver, encoding) 282 if _, ok := err.(*MessageError); !ok { 283 t.Errorf("MsgAlert.BtcEncode wrong error got: %T, want: %T", 284 err, MessageError{}) 285 } 286 } 287 288 // TestAlert tests serialization and deserialization 289 // of the payload to Alert 290 func TestAlert(t *testing.T) { 291 pver := ProtocolVersion 292 alert := NewAlert( 293 1, 1337093712, 1368628812, 1015, 294 1013, []int32{1014}, 0, 40599, []string{"/Satoshi:0.7.2/"}, 5000, "", 295 "URGENT: upgrade required, see http://bitcoin.org/dos for details", 296 ) 297 w := new(bytes.Buffer) 298 err := alert.Serialize(w, pver) 299 if err != nil { 300 t.Error(err.Error()) 301 } 302 serializedpayload := w.Bytes() 303 newAlert, err := NewAlertFromPayload(serializedpayload, pver) 304 if err != nil { 305 t.Error(err.Error()) 306 } 307 308 if alert.Version != newAlert.Version { 309 t.Errorf("NewAlertFromPayload: wrong Version - got %v, want %v ", 310 alert.Version, newAlert.Version) 311 } 312 if alert.RelayUntil != newAlert.RelayUntil { 313 t.Errorf("NewAlertFromPayload: wrong RelayUntil - got %v, want %v ", 314 alert.RelayUntil, newAlert.RelayUntil) 315 } 316 if alert.Expiration != newAlert.Expiration { 317 t.Errorf("NewAlertFromPayload: wrong Expiration - got %v, want %v ", 318 alert.Expiration, newAlert.Expiration) 319 } 320 if alert.ID != newAlert.ID { 321 t.Errorf("NewAlertFromPayload: wrong ID - got %v, want %v ", 322 alert.ID, newAlert.ID) 323 } 324 if alert.Cancel != newAlert.Cancel { 325 t.Errorf("NewAlertFromPayload: wrong Cancel - got %v, want %v ", 326 alert.Cancel, newAlert.Cancel) 327 } 328 if len(alert.SetCancel) != len(newAlert.SetCancel) { 329 t.Errorf("NewAlertFromPayload: wrong number of SetCancel - got %v, want %v ", 330 len(alert.SetCancel), len(newAlert.SetCancel)) 331 } 332 for i := 0; i < len(alert.SetCancel); i++ { 333 if alert.SetCancel[i] != newAlert.SetCancel[i] { 334 t.Errorf("NewAlertFromPayload: wrong SetCancel[%v] - got %v, want %v ", 335 len(alert.SetCancel), alert.SetCancel[i], newAlert.SetCancel[i]) 336 } 337 } 338 if alert.MinVer != newAlert.MinVer { 339 t.Errorf("NewAlertFromPayload: wrong MinVer - got %v, want %v ", 340 alert.MinVer, newAlert.MinVer) 341 } 342 if alert.MaxVer != newAlert.MaxVer { 343 t.Errorf("NewAlertFromPayload: wrong MaxVer - got %v, want %v ", 344 alert.MaxVer, newAlert.MaxVer) 345 } 346 if len(alert.SetSubVer) != len(newAlert.SetSubVer) { 347 t.Errorf("NewAlertFromPayload: wrong number of SetSubVer - got %v, want %v ", 348 len(alert.SetSubVer), len(newAlert.SetSubVer)) 349 } 350 for i := 0; i < len(alert.SetSubVer); i++ { 351 if alert.SetSubVer[i] != newAlert.SetSubVer[i] { 352 t.Errorf("NewAlertFromPayload: wrong SetSubVer[%v] - got %v, want %v ", 353 len(alert.SetSubVer), alert.SetSubVer[i], newAlert.SetSubVer[i]) 354 } 355 } 356 if alert.Priority != newAlert.Priority { 357 t.Errorf("NewAlertFromPayload: wrong Priority - got %v, want %v ", 358 alert.Priority, newAlert.Priority) 359 } 360 if alert.Comment != newAlert.Comment { 361 t.Errorf("NewAlertFromPayload: wrong Comment - got %v, want %v ", 362 alert.Comment, newAlert.Comment) 363 } 364 if alert.StatusBar != newAlert.StatusBar { 365 t.Errorf("NewAlertFromPayload: wrong StatusBar - got %v, want %v ", 366 alert.StatusBar, newAlert.StatusBar) 367 } 368 if alert.Reserved != newAlert.Reserved { 369 t.Errorf("NewAlertFromPayload: wrong Reserved - got %v, want %v ", 370 alert.Reserved, newAlert.Reserved) 371 } 372 } 373 374 // TestAlertErrors performs negative tests against payload serialization, 375 // deserialization of Alert to confirm error paths work correctly. 376 func TestAlertErrors(t *testing.T) { 377 pver := ProtocolVersion 378 379 baseAlert := NewAlert( 380 1, 1337093712, 1368628812, 1015, 381 1013, []int32{1014}, 0, 40599, []string{"/Satoshi:0.7.2/"}, 5000, "", 382 "URGENT", 383 ) 384 baseAlertEncoded := []byte{ 385 0x01, 0x00, 0x00, 0x00, 0x50, 0x6e, 0xb2, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x9e, 0x93, 0x51, //|....Pn.O....L..Q| 386 0x00, 0x00, 0x00, 0x00, 0xf7, 0x03, 0x00, 0x00, 0xf5, 0x03, 0x00, 0x00, 0x01, 0xf6, 0x03, 0x00, //|................| 387 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x9e, 0x00, 0x00, 0x01, 0x0f, 0x2f, 0x53, 0x61, 0x74, 0x6f, //|.........../Sato| 388 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x37, 0x2e, 0x32, 0x2f, 0x88, 0x13, 0x00, 0x00, 0x00, 0x06, //|shi:0.7.2/......| 389 0x55, 0x52, 0x47, 0x45, 0x4e, 0x54, 0x00, //|URGENT.| 390 } 391 tests := []struct { 392 in *Alert // Value to encode 393 buf []byte // Wire encoding 394 pver uint32 // Protocol version for wire encoding 395 max int // Max size of fixed buffer to induce errors 396 writeErr error // Expected write error 397 readErr error // Expected read error 398 }{ 399 // Force error in Version 400 {baseAlert, baseAlertEncoded, pver, 0, io.ErrShortWrite, io.EOF}, 401 // Force error in SetCancel VarInt. 402 {baseAlert, baseAlertEncoded, pver, 28, io.ErrShortWrite, io.EOF}, 403 // Force error in SetCancel ints. 404 {baseAlert, baseAlertEncoded, pver, 29, io.ErrShortWrite, io.EOF}, 405 // Force error in MinVer 406 {baseAlert, baseAlertEncoded, pver, 40, io.ErrShortWrite, io.EOF}, 407 // Force error in SetSubVer string VarInt. 408 {baseAlert, baseAlertEncoded, pver, 41, io.ErrShortWrite, io.EOF}, 409 // Force error in SetSubVer strings. 410 {baseAlert, baseAlertEncoded, pver, 48, io.ErrShortWrite, io.EOF}, 411 // Force error in Priority 412 {baseAlert, baseAlertEncoded, pver, 60, io.ErrShortWrite, io.EOF}, 413 // Force error in Comment string. 414 {baseAlert, baseAlertEncoded, pver, 62, io.ErrShortWrite, io.EOF}, 415 // Force error in StatusBar string. 416 {baseAlert, baseAlertEncoded, pver, 64, io.ErrShortWrite, io.EOF}, 417 // Force error in Reserved string. 418 {baseAlert, baseAlertEncoded, pver, 70, io.ErrShortWrite, io.EOF}, 419 } 420 421 t.Logf("Running %d tests", len(tests)) 422 for i, test := range tests { 423 w := newFixedWriter(test.max) 424 err := test.in.Serialize(w, test.pver) 425 if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) { 426 t.Errorf("Alert.Serialize #%d wrong error got: %v, want: %v", 427 i, err, test.writeErr) 428 continue 429 } 430 431 var alert Alert 432 r := newFixedReader(test.max, test.buf) 433 err = alert.Deserialize(r, test.pver) 434 if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { 435 t.Errorf("Alert.Deserialize #%d wrong error got: %v, want: %v", 436 i, err, test.readErr) 437 continue 438 } 439 } 440 441 // overflow the max number of elements in SetCancel 442 // maxCountSetCancel + 1 == 8388575 == \xdf\xff\x7f\x00 443 // replace bytes 29-33 444 badAlertEncoded := []byte{ 445 0x01, 0x00, 0x00, 0x00, 0x50, 0x6e, 0xb2, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x9e, 0x93, 0x51, //|....Pn.O....L..Q| 446 0x00, 0x00, 0x00, 0x00, 0xf7, 0x03, 0x00, 0x00, 0xf5, 0x03, 0x00, 0x00, 0xfe, 0xdf, 0xff, 0x7f, //|................| 447 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x9e, 0x00, 0x00, 0x01, 0x0f, 0x2f, 0x53, 0x61, 0x74, 0x6f, //|.........../Sato| 448 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x37, 0x2e, 0x32, 0x2f, 0x88, 0x13, 0x00, 0x00, 0x00, 0x06, //|shi:0.7.2/......| 449 0x55, 0x52, 0x47, 0x45, 0x4e, 0x54, 0x00, //|URGENT.| 450 } 451 var alert Alert 452 r := bytes.NewReader(badAlertEncoded) 453 err := alert.Deserialize(r, pver) 454 if _, ok := err.(*MessageError); !ok { 455 t.Errorf("Alert.Deserialize wrong error got: %T, want: %T", 456 err, MessageError{}) 457 } 458 459 // overflow the max number of elements in SetSubVer 460 // maxCountSetSubVer + 1 == 131071 + 1 == \x00\x00\x02\x00 461 // replace bytes 42-46 462 badAlertEncoded = []byte{ 463 0x01, 0x00, 0x00, 0x00, 0x50, 0x6e, 0xb2, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x9e, 0x93, 0x51, //|....Pn.O....L..Q| 464 0x00, 0x00, 0x00, 0x00, 0xf7, 0x03, 0x00, 0x00, 0xf5, 0x03, 0x00, 0x00, 0x01, 0xf6, 0x03, 0x00, //|................| 465 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x9e, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x74, 0x6f, //|.........../Sato| 466 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x37, 0x2e, 0x32, 0x2f, 0x88, 0x13, 0x00, 0x00, 0x00, 0x06, //|shi:0.7.2/......| 467 0x55, 0x52, 0x47, 0x45, 0x4e, 0x54, 0x00, //|URGENT.| 468 } 469 r = bytes.NewReader(badAlertEncoded) 470 err = alert.Deserialize(r, pver) 471 if _, ok := err.(*MessageError); !ok { 472 t.Errorf("Alert.Deserialize wrong error got: %T, want: %T", 473 err, MessageError{}) 474 } 475 }