github.com/snowblossomcoin/go-ethereum@v1.9.25/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  	"fmt"
    22  	"io"
    23  	"runtime"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  func ExampleMsgPipe() {
    29  	rw1, rw2 := MsgPipe()
    30  	go func() {
    31  		Send(rw1, 8, [][]byte{{0, 0}})
    32  		Send(rw1, 5, [][]byte{{1, 1}})
    33  		rw1.Close()
    34  	}()
    35  
    36  	for {
    37  		msg, err := rw2.ReadMsg()
    38  		if err != nil {
    39  			break
    40  		}
    41  		var data [][]byte
    42  		msg.Decode(&data)
    43  		fmt.Printf("msg: %d, %x\n", msg.Code, data[0])
    44  	}
    45  	// Output:
    46  	// msg: 8, 0000
    47  	// msg: 5, 0101
    48  }
    49  
    50  func TestMsgPipeUnblockWrite(t *testing.T) {
    51  loop:
    52  	for i := 0; i < 100; i++ {
    53  		rw1, rw2 := MsgPipe()
    54  		done := make(chan struct{})
    55  		go func() {
    56  			if err := SendItems(rw1, 1); err == nil {
    57  				t.Error("EncodeMsg returned nil error")
    58  			} else if err != ErrPipeClosed {
    59  				t.Errorf("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed)
    60  			}
    61  			close(done)
    62  		}()
    63  
    64  		// this call should ensure that EncodeMsg is waiting to
    65  		// deliver sometimes. if this isn't done, Close is likely to
    66  		// be executed before EncodeMsg starts and then we won't test
    67  		// all the cases.
    68  		runtime.Gosched()
    69  
    70  		rw2.Close()
    71  		select {
    72  		case <-done:
    73  		case <-time.After(200 * time.Millisecond):
    74  			t.Errorf("write didn't unblock")
    75  			break loop
    76  		}
    77  	}
    78  }
    79  
    80  // This test should panic if concurrent close isn't implemented correctly.
    81  func TestMsgPipeConcurrentClose(t *testing.T) {
    82  	rw1, _ := MsgPipe()
    83  	for i := 0; i < 10; i++ {
    84  		go rw1.Close()
    85  	}
    86  }
    87  
    88  func TestEOFSignal(t *testing.T) {
    89  	rb := make([]byte, 10)
    90  
    91  	// empty reader
    92  	eof := make(chan struct{}, 1)
    93  	sig := &eofSignal{new(bytes.Buffer), 0, eof}
    94  	if n, err := sig.Read(rb); n != 0 || err != io.EOF {
    95  		t.Errorf("Read returned unexpected values: (%v, %v)", n, err)
    96  	}
    97  	select {
    98  	case <-eof:
    99  	default:
   100  		t.Error("EOF chan not signaled")
   101  	}
   102  
   103  	// count before error
   104  	eof = make(chan struct{}, 1)
   105  	sig = &eofSignal{bytes.NewBufferString("aaaaaaaa"), 4, eof}
   106  	if n, err := sig.Read(rb); n != 4 || err != nil {
   107  		t.Errorf("Read returned unexpected values: (%v, %v)", n, err)
   108  	}
   109  	select {
   110  	case <-eof:
   111  	default:
   112  		t.Error("EOF chan not signaled")
   113  	}
   114  
   115  	// error before count
   116  	eof = make(chan struct{}, 1)
   117  	sig = &eofSignal{bytes.NewBufferString("aaaa"), 999, eof}
   118  	if n, err := sig.Read(rb); n != 4 || err != nil {
   119  		t.Errorf("Read returned unexpected values: (%v, %v)", n, err)
   120  	}
   121  	if n, err := sig.Read(rb); n != 0 || err != io.EOF {
   122  		t.Errorf("Read returned unexpected values: (%v, %v)", n, err)
   123  	}
   124  	select {
   125  	case <-eof:
   126  	default:
   127  		t.Error("EOF chan not signaled")
   128  	}
   129  
   130  	// no signal if neither occurs
   131  	eof = make(chan struct{}, 1)
   132  	sig = &eofSignal{bytes.NewBufferString("aaaaaaaaaaaaaaaaaaaaa"), 999, eof}
   133  	if n, err := sig.Read(rb); n != 10 || err != nil {
   134  		t.Errorf("Read returned unexpected values: (%v, %v)", n, err)
   135  	}
   136  	select {
   137  	case <-eof:
   138  		t.Error("unexpected EOF signal")
   139  	default:
   140  	}
   141  }