github.com/Inphi/go-ethereum@v1.9.7/p2p/message_test.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package p2p 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 "fmt" 23 "io" 24 "runtime" 25 "strings" 26 "testing" 27 "time" 28 ) 29 30 func ExampleMsgPipe() { 31 rw1, rw2 := MsgPipe() 32 go func() { 33 Send(rw1, 8, [][]byte{{0, 0}}) 34 Send(rw1, 5, [][]byte{{1, 1}}) 35 rw1.Close() 36 }() 37 38 for { 39 msg, err := rw2.ReadMsg() 40 if err != nil { 41 break 42 } 43 var data [][]byte 44 msg.Decode(&data) 45 fmt.Printf("msg: %d, %x\n", msg.Code, data[0]) 46 } 47 // Output: 48 // msg: 8, 0000 49 // msg: 5, 0101 50 } 51 52 func TestMsgPipeUnblockWrite(t *testing.T) { 53 loop: 54 for i := 0; i < 100; i++ { 55 rw1, rw2 := MsgPipe() 56 done := make(chan struct{}) 57 go func() { 58 if err := SendItems(rw1, 1); err == nil { 59 t.Error("EncodeMsg returned nil error") 60 } else if err != ErrPipeClosed { 61 t.Errorf("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed) 62 } 63 close(done) 64 }() 65 66 // this call should ensure that EncodeMsg is waiting to 67 // deliver sometimes. if this isn't done, Close is likely to 68 // be executed before EncodeMsg starts and then we won't test 69 // all the cases. 70 runtime.Gosched() 71 72 rw2.Close() 73 select { 74 case <-done: 75 case <-time.After(200 * time.Millisecond): 76 t.Errorf("write didn't unblock") 77 break loop 78 } 79 } 80 } 81 82 // This test should panic if concurrent close isn't implemented correctly. 83 func TestMsgPipeConcurrentClose(t *testing.T) { 84 rw1, _ := MsgPipe() 85 for i := 0; i < 10; i++ { 86 go rw1.Close() 87 } 88 } 89 90 func TestEOFSignal(t *testing.T) { 91 rb := make([]byte, 10) 92 93 // empty reader 94 eof := make(chan struct{}, 1) 95 sig := &eofSignal{new(bytes.Buffer), 0, eof} 96 if n, err := sig.Read(rb); n != 0 || err != io.EOF { 97 t.Errorf("Read returned unexpected values: (%v, %v)", n, err) 98 } 99 select { 100 case <-eof: 101 default: 102 t.Error("EOF chan not signaled") 103 } 104 105 // count before error 106 eof = make(chan struct{}, 1) 107 sig = &eofSignal{bytes.NewBufferString("aaaaaaaa"), 4, eof} 108 if n, err := sig.Read(rb); n != 4 || err != nil { 109 t.Errorf("Read returned unexpected values: (%v, %v)", n, err) 110 } 111 select { 112 case <-eof: 113 default: 114 t.Error("EOF chan not signaled") 115 } 116 117 // error before count 118 eof = make(chan struct{}, 1) 119 sig = &eofSignal{bytes.NewBufferString("aaaa"), 999, eof} 120 if n, err := sig.Read(rb); n != 4 || err != nil { 121 t.Errorf("Read returned unexpected values: (%v, %v)", n, err) 122 } 123 if n, err := sig.Read(rb); n != 0 || err != io.EOF { 124 t.Errorf("Read returned unexpected values: (%v, %v)", n, err) 125 } 126 select { 127 case <-eof: 128 default: 129 t.Error("EOF chan not signaled") 130 } 131 132 // no signal if neither occurs 133 eof = make(chan struct{}, 1) 134 sig = &eofSignal{bytes.NewBufferString("aaaaaaaaaaaaaaaaaaaaa"), 999, eof} 135 if n, err := sig.Read(rb); n != 10 || err != nil { 136 t.Errorf("Read returned unexpected values: (%v, %v)", n, err) 137 } 138 select { 139 case <-eof: 140 t.Error("unexpected EOF signal") 141 default: 142 } 143 } 144 145 func unhex(str string) []byte { 146 r := strings.NewReplacer("\t", "", " ", "", "\n", "") 147 b, err := hex.DecodeString(r.Replace(str)) 148 if err != nil { 149 panic(fmt.Sprintf("invalid hex string: %q", str)) 150 } 151 return b 152 }