github.com/anthdm/go-ethereum@v1.8.4-0.20180412101906-60516c83b011/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  }