message_test.go 3 KB
Newer Older
zelig's avatar
zelig committed
1 2 3
package p2p

import (
Felix Lange's avatar
Felix Lange committed
4
	"bytes"
5
	"fmt"
Felix Lange's avatar
Felix Lange committed
6
	"io/ioutil"
7
	"runtime"
zelig's avatar
zelig committed
8
	"testing"
9
	"time"
Felix Lange's avatar
Felix Lange committed
10 11

	"github.com/ethereum/go-ethereum/ethutil"
zelig's avatar
zelig committed
12 13 14
)

func TestNewMsg(t *testing.T) {
Felix Lange's avatar
Felix Lange committed
15 16 17
	msg := NewMsg(3, 1, "000")
	if msg.Code != 3 {
		t.Errorf("incorrect code %d, want %d", msg.Code)
zelig's avatar
zelig committed
18
	}
Felix Lange's avatar
Felix Lange committed
19 20
	if msg.Size != 5 {
		t.Errorf("incorrect size %d, want %d", msg.Size, 5)
zelig's avatar
zelig committed
21
	}
Felix Lange's avatar
Felix Lange committed
22 23 24 25
	pl, _ := ioutil.ReadAll(msg.Payload)
	expect := []byte{0x01, 0x83, 0x30, 0x30, 0x30}
	if !bytes.Equal(pl, expect) {
		t.Errorf("incorrect payload content, got %x, want %x", pl, expect)
zelig's avatar
zelig committed
26 27 28 29
	}
}

func TestEncodeDecodeMsg(t *testing.T) {
Felix Lange's avatar
Felix Lange committed
30 31 32 33 34
	msg := NewMsg(3, 1, "000")
	buf := new(bytes.Buffer)
	if err := writeMsg(buf, msg); err != nil {
		t.Fatalf("encodeMsg error: %v", err)
	}
35
	// t.Logf("encoded: %x", buf.Bytes())
Felix Lange's avatar
Felix Lange committed
36 37 38 39 40 41 42 43 44 45 46

	decmsg, err := readMsg(buf)
	if err != nil {
		t.Fatalf("readMsg error: %v", err)
	}
	if decmsg.Code != 3 {
		t.Errorf("incorrect code %d, want %d", decmsg.Code, 3)
	}
	if decmsg.Size != 5 {
		t.Errorf("incorrect size %d, want %d", decmsg.Size, 5)
	}
47 48

	var data struct {
obscuren's avatar
obscuren committed
49
		I uint
50
		S string
Felix Lange's avatar
Felix Lange committed
51
	}
52 53
	if err := decmsg.Decode(&data); err != nil {
		t.Fatalf("Decode error: %v", err)
Felix Lange's avatar
Felix Lange committed
54
	}
55 56
	if data.I != 1 {
		t.Errorf("incorrect data.I: got %v, expected %d", data.I, 1)
Felix Lange's avatar
Felix Lange committed
57
	}
58 59
	if data.S != "000" {
		t.Errorf("incorrect data.S: got %q, expected %q", data.S, "000")
Felix Lange's avatar
Felix Lange committed
60 61 62 63 64 65 66 67 68 69 70 71
	}
}

func TestDecodeRealMsg(t *testing.T) {
	data := ethutil.Hex2Bytes("2240089100000080f87e8002b5457468657265756d282b2b292f5065657220536572766572204f6e652f76302e372e382f52656c656173652f4c696e75782f672b2bc082765fb84086dd80b7aefd6a6d2e3b93f4f300a86bfb6ef7bdc97cb03f793db6bb")
	msg, err := readMsg(bytes.NewReader(data))
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if msg.Code != 0 {
		t.Errorf("incorrect code %d, want %d", msg.Code, 0)
zelig's avatar
zelig committed
72 73
	}
}
74 75 76 77

func ExampleMsgPipe() {
	rw1, rw2 := MsgPipe()
	go func() {
78 79
		EncodeMsg(rw1, 8, []byte{0, 0})
		EncodeMsg(rw1, 5, []byte{1, 1})
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
		rw1.Close()
	}()

	for {
		msg, err := rw2.ReadMsg()
		if err != nil {
			break
		}
		var data [1][]byte
		msg.Decode(&data)
		fmt.Printf("msg: %d, %x\n", msg.Code, data[0])
	}
	// Output:
	// msg: 8, 0000
	// msg: 5, 0101
}

func TestMsgPipeUnblockWrite(t *testing.T) {
loop:
	for i := 0; i < 100; i++ {
		rw1, rw2 := MsgPipe()
		done := make(chan struct{})
		go func() {
103
			if err := EncodeMsg(rw1, 1); err == nil {
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
				t.Error("EncodeMsg returned nil error")
			} else if err != ErrPipeClosed {
				t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed)
			}
			close(done)
		}()

		// this call should ensure that EncodeMsg is waiting to
		// deliver sometimes. if this isn't done, Close is likely to
		// be executed before EncodeMsg starts and then we won't test
		// all the cases.
		runtime.Gosched()

		rw2.Close()
		select {
		case <-done:
		case <-time.After(200 * time.Millisecond):
			t.Errorf("write didn't unblock")
			break loop
		}
	}
}

// This test should panic if concurrent close isn't implemented correctly.
func TestMsgPipeConcurrentClose(t *testing.T) {
	rw1, _ := MsgPipe()
	for i := 0; i < 10; i++ {
		go rw1.Close()
	}
}