github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/netpoll/netpoll_unix_test.go (about)

     1  // +build linux darwin dragonfly freebsd netbsd openbsd
     2  
     3  package netpoll
     4  
     5  import (
     6  	"bytes"
     7  	"io"
     8  	"log"
     9  	"net"
    10  	"os"
    11  	"sync"
    12  	"sync/atomic"
    13  	"syscall"
    14  	"testing"
    15  	"time"
    16  
    17  	"golang.org/x/sys/unix"
    18  )
    19  
    20  func TestPollerReadOnce(t *testing.T) {
    21  	poller, err := New(config(t))
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  
    26  	r, w, err := socketPair()
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	conn, err := net.FileConn(os.NewFile(uintptr(r), "|0"))
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	var (
    37  		data     = []byte("hello")
    38  		done     = make(chan struct{})
    39  		received = make([]byte, 0, len(data))
    40  	)
    41  
    42  	var (
    43  		mu     sync.Mutex
    44  		events []Event
    45  	)
    46  	desc := Must(HandleReadOnce(conn))
    47  	err = poller.Start(desc, func(event Event) {
    48  		mu.Lock()
    49  		events = append(events, event)
    50  		mu.Unlock()
    51  
    52  		if event&EventRead == 0 {
    53  			return
    54  		}
    55  
    56  		bts := make([]byte, 128)
    57  		n, err := conn.Read(bts)
    58  		switch {
    59  		case err == io.EOF:
    60  			defer close(done)
    61  			if err = poller.Stop(desc); err != nil {
    62  				t.Fatalf("poller.Stop() error: %v", err)
    63  			}
    64  
    65  		case err != nil:
    66  			t.Fatal(err)
    67  
    68  		default:
    69  			received = append(received, bts[:n]...)
    70  			if err := poller.Resume(desc); err != nil {
    71  				t.Fatalf("poller.Resume() error: %v", err)
    72  			}
    73  		}
    74  	})
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	// Write data by a single byte.
    80  	for i := 0; i < len(data); i++ {
    81  		_, err = unix.Write(w, data[i:i+1])
    82  		if err != nil {
    83  			t.Fatal(err)
    84  		}
    85  		time.Sleep(time.Millisecond)
    86  	}
    87  
    88  	if err = unix.Close(w); err != nil {
    89  		t.Fatalf("unix.Close() error: %v", err)
    90  	}
    91  
    92  	<-done
    93  
    94  	if count, exp := len(events), len(data)+1; count != exp { // expect +1 for EPOLLRDHUP or EPOLLHUP
    95  		t.Errorf("callback called %d times (%v); want %d", count, events, exp)
    96  		return
    97  	}
    98  
    99  	if last, want := events[len(events)-1], EventRead|EventHup|EventReadHup; last != want {
   100  		t.Errorf("last callback call was made with %s; want %s", last, want)
   101  	}
   102  	for i, m := range events[:len(events)-1] {
   103  		if m != EventRead {
   104  			t.Errorf("callback call #%d was made with %s; want %s", i, m, EventRead)
   105  		}
   106  	}
   107  	if !bytes.Equal(data, received) {
   108  		t.Errorf("bytes are not equal:\ngot:  %v\nwant: %v\n", received, data)
   109  	}
   110  }
   111  
   112  func TestPollerWriteOnce(t *testing.T) {
   113  	poller, err := New(config(t))
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	r, w, err := socketPair()
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	sendLoWat, err := unix.GetsockoptInt(w, unix.SOL_SOCKET, unix.SO_SNDLOWAT)
   124  	if err != nil {
   125  		t.Fatalf("get SO_SNDLOWAT error: %v", err)
   126  	}
   127  	sendBuf, err := unix.GetsockoptInt(w, unix.SOL_SOCKET, unix.SO_SNDBUF)
   128  	if err != nil {
   129  		t.Fatalf("get SO_SNDBUF error: %v", err)
   130  	}
   131  
   132  	log.Printf("send buf is %d", sendBuf)
   133  	log.Printf("send low watermark is %d", sendLoWat)
   134  
   135  	filled, err := fillSendBuffer(w)
   136  	if err != nil {
   137  		t.Fatalf("fill send buffer error: %v", err)
   138  	}
   139  	log.Printf("filled send buffer: %d", filled)
   140  
   141  	var (
   142  		writeEvents = new(uint32)
   143  		writeHup    = new(uint32)
   144  	)
   145  
   146  	wc, err := net.FileConn(os.NewFile(uintptr(w), "w"))
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	desc := Must(HandleWriteOnce(wc))
   152  	err = poller.Start(desc, func(e Event) {
   153  		log.Printf("received event from poller: %s", e)
   154  		atomic.AddUint32(writeEvents, 1)
   155  
   156  		if e&EventHup != 0 {
   157  			atomic.AddUint32(writeHup, 1)
   158  			return
   159  		}
   160  		if e&EventErr != 0 {
   161  			return
   162  		}
   163  
   164  		filled, err := fillSendBuffer(w)
   165  		if err != nil {
   166  			t.Fatalf("fill send buffer error: %v", err)
   167  		}
   168  		log.Printf("filled send buffer: %d", filled)
   169  
   170  		if err := poller.Resume(desc); err != nil {
   171  			t.Fatalf("poller.Resume() error %v", err)
   172  		}
   173  	})
   174  	if err != nil {
   175  		t.Fatalf("poller.Start(w) error: %v", err)
   176  	}
   177  
   178  	// Read sendLoWat-1 bytes such that next read will trigger write event.
   179  	if n, err := unix.Read(r, make([]byte, sendLoWat-1)); err != nil {
   180  		t.Fatalf("unix.Read() error: %v", err)
   181  	} else {
   182  		log.Printf("read %d (from %d: SNDLOWAT-1)", n, sendLoWat-1)
   183  	}
   184  
   185  	time.Sleep(time.Millisecond * 50)
   186  	if n := atomic.LoadUint32(writeEvents); n > 0 {
   187  		t.Fatalf("write events: %v; want 0", n)
   188  	}
   189  
   190  	if n, err := unix.Read(r, make([]byte, filled)); err != nil {
   191  		t.Fatalf("empty receive buffer error: %v", err)
   192  	} else {
   193  		log.Printf("emptied receive buffer: %d", n)
   194  	}
   195  	time.Sleep(time.Millisecond * 50)
   196  	if n := atomic.LoadUint32(writeEvents); n != 1 {
   197  		t.Errorf("write events: %v; want 1", n)
   198  	}
   199  
   200  	if err := unix.Close(r); err != nil {
   201  		t.Fatalf("unix.Close() error: %v", err)
   202  	}
   203  	log.Println("closed read-end of pair")
   204  	time.Sleep(time.Millisecond * 50)
   205  	if n := atomic.LoadUint32(writeHup); n != 1 {
   206  		t.Errorf("hup events: %v; want 1", n)
   207  	}
   208  }
   209  
   210  func emptyRecvBuffer(fd int, k int) (n int, err error) {
   211  	for eagain := 0; eagain < 10; {
   212  		var x int
   213  		p := make([]byte, k+1)
   214  		x, err = unix.Read(fd, p)
   215  		if err != nil {
   216  			if err == syscall.EAGAIN {
   217  				err = nil
   218  				eagain++
   219  				continue
   220  			}
   221  			return
   222  		}
   223  		n += x
   224  	}
   225  	return
   226  }
   227  
   228  func fillSendBuffer(fd int) (n int, err error) {
   229  	p := bytes.Repeat([]byte{'x'}, 1)
   230  	for eagain := 0; eagain < 10; {
   231  		var x int
   232  		x, err = unix.Write(fd, p)
   233  		if err != nil {
   234  			if err == syscall.EAGAIN {
   235  				err = nil
   236  				eagain++
   237  				continue
   238  			}
   239  			return
   240  		}
   241  		n += x
   242  	}
   243  	return
   244  }
   245  
   246  func socketPair() (r, w int, err error) {
   247  	fd, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0)
   248  	if err != nil {
   249  		return
   250  	}
   251  
   252  	if err = unix.SetNonblock(fd[0], true); err != nil {
   253  		return
   254  	}
   255  	if err = unix.SetNonblock(fd[1], true); err != nil {
   256  		return
   257  	}
   258  
   259  	buf := 4096
   260  	if err = unix.SetsockoptInt(fd[0], unix.SOL_SOCKET, unix.SO_SNDBUF, buf); err != nil {
   261  		return
   262  	}
   263  	if err = unix.SetsockoptInt(fd[1], unix.SOL_SOCKET, unix.SO_SNDBUF, buf); err != nil {
   264  		return
   265  	}
   266  	if err = unix.SetsockoptInt(fd[0], unix.SOL_SOCKET, unix.SO_RCVBUF, buf); err != nil {
   267  		return
   268  	}
   269  	if err = unix.SetsockoptInt(fd[1], unix.SOL_SOCKET, unix.SO_RCVBUF, buf); err != nil {
   270  		return
   271  	}
   272  	return fd[0], fd[1], nil
   273  }
   274  
   275  func config(tb testing.TB) *Config {
   276  	return &Config{
   277  		OnWaitError: func(err error) {
   278  			tb.Fatal(err)
   279  		},
   280  	}
   281  }
   282  
   283  type stubConn struct{}
   284  
   285  func (s stubConn) Read(b []byte) (n int, err error)   { return 0, nil }
   286  func (s stubConn) Write(b []byte) (n int, err error)  { return 0, nil }
   287  func (s stubConn) Close() error                       { return nil }
   288  func (s stubConn) LocalAddr() (addr net.Addr)         { return }
   289  func (s stubConn) RemoteAddr() (addr net.Addr)        { return }
   290  func (s stubConn) SetDeadline(t time.Time) error      { return nil }
   291  func (s stubConn) SetReadDeadline(t time.Time) error  { return nil }
   292  func (s stubConn) SetWriteDeadline(t time.Time) error { return nil }