github.com/searKing/golang/go@v1.2.74/net/mux/server_test.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mux_test
     6  
     7  import (
     8  	"context"
     9  	"io"
    10  	"log"
    11  	"net"
    12  	"strings"
    13  	"sync"
    14  	"sync/atomic"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/searKing/golang/go/net/mux"
    19  	"github.com/searKing/golang/go/testing/leakcheck"
    20  
    21  	"golang.org/x/net/http2"
    22  )
    23  
    24  const (
    25  	handleHTTP1Close   = 1
    26  	handleHTTP1Request = 2
    27  	handleAnyClose     = 3
    28  	handleAnyRequest   = 4
    29  )
    30  
    31  func TestTimeout(t *testing.T) {
    32  	defer leakcheck.Check(t)
    33  	loopbackLis := testListener(t)
    34  	defer loopbackLis.Close()
    35  	result := make(chan int, 5)
    36  	testDuration := time.Millisecond * 500
    37  	srv := mux.NewServer()
    38  
    39  	mux.DefaultServeMux.SetReadTimeout(testDuration)
    40  
    41  	http1Listener := mux.HandleListener(mux.HTTP1Fast())
    42  	defer http1Listener.Close()
    43  	anyListener := mux.HandleListener(mux.Any())
    44  	defer anyListener.Close()
    45  
    46  	ctx, cancelFn := context.WithCancel(context.TODO())
    47  	defer cancelFn()
    48  	go func() {
    49  		_ = srv.Serve(loopbackLis)
    50  	}()
    51  	go func() {
    52  		for {
    53  			select {
    54  			case <-ctx.Done():
    55  				return
    56  			default:
    57  			}
    58  			con, err := http1Listener.Accept()
    59  			if err != nil {
    60  				result <- handleHTTP1Close
    61  			} else {
    62  				_, _ = con.Write([]byte("http1Listener"))
    63  				result <- handleHTTP1Request
    64  				select {
    65  				case <-ctx.Done():
    66  					break
    67  				}
    68  				_ = con.Close()
    69  			}
    70  			select {
    71  			case <-ctx.Done():
    72  				return
    73  			}
    74  		}
    75  	}()
    76  	go func() {
    77  		for {
    78  			select {
    79  			case <-ctx.Done():
    80  				return
    81  			default:
    82  			}
    83  			con, err := anyListener.Accept()
    84  			if err != nil {
    85  				result <- handleAnyClose
    86  			} else {
    87  				_, err = con.Write([]byte("any"))
    88  				result <- handleAnyRequest
    89  				select {
    90  				case <-ctx.Done():
    91  					break
    92  				}
    93  				_ = con.Close()
    94  			}
    95  		}
    96  	}()
    97  	time.Sleep(testDuration) // wait to prevent timeouts on slow test-runners
    98  	client, err := net.Dial("tcp", loopbackLis.Addr().String())
    99  	if err != nil {
   100  		log.Fatal("testTimeout client failed: ", err)
   101  	}
   102  	defer client.Close()
   103  	time.Sleep(testDuration / 2)
   104  	if len(result) != 0 {
   105  		log.Print("tcp ")
   106  		t.Fatal("testTimeout failed: accepted to fast: ", len(result))
   107  	}
   108  	//_ = client.SetReadDeadline(time.Now().Add(testDuration * 3))
   109  	buffer := make([]byte, 10)
   110  	rl, err := client.Read(buffer)
   111  	if err != nil {
   112  		t.Fatal("testTimeout failed: client error: ", err, rl)
   113  	}
   114  	_ = srv.Close()
   115  	if rl != len("any") {
   116  		log.Print("testTimeout failed: response from wrong service ", rl)
   117  	}
   118  	if string(buffer[0:3]) != "any" {
   119  		log.Print("testTimeout failed: response from wrong service ")
   120  	}
   121  	time.Sleep(testDuration * 2)
   122  	if len(result) != 2 {
   123  		t.Fatal("testTimeout failed: accepted to less: ", len(result))
   124  	}
   125  	if a := <-result; a != handleAnyRequest {
   126  		t.Fatal("testTimeout failed: anyListener rule did not match")
   127  	}
   128  	if a := <-result; a != handleHTTP1Close {
   129  		t.Fatal("testTimeout failed: no close an http rule")
   130  	}
   131  }
   132  
   133  func TestRead(t *testing.T) {
   134  	defer leakcheck.Check(t)
   135  	errCh := make(chan error)
   136  	defer func() {
   137  		select {
   138  		case err := <-errCh:
   139  			t.Fatal(err)
   140  		default:
   141  		}
   142  	}()
   143  	const payload = "hello world\r\n"
   144  	const mult = 2
   145  
   146  	writer, reader := net.Pipe()
   147  	go func() {
   148  		if _, err := io.WriteString(writer, strings.Repeat(payload, mult)); err != nil {
   149  			t.Fatal(err)
   150  		}
   151  		if err := writer.Close(); err != nil {
   152  			t.Fatal(err)
   153  		}
   154  	}()
   155  
   156  	l := newChanListener()
   157  	l.Notify(reader)
   158  	defer l.Close()
   159  	srv := mux.NewServer()
   160  	defer srv.Close()
   161  
   162  	// Register a bogus matcher to force buffering exactly the right amount.
   163  	// Before this fix, this would trigger a bug where `Read` would incorrectly
   164  	// report `io.EOF` when only the buffer had been consumed.
   165  	_ = mux.HandleListener(mux.MatcherFunc(func(w io.Writer, r io.Reader) bool {
   166  		var b [len(payload)]byte
   167  		_, _ = r.Read(b[:])
   168  		return false
   169  	}))
   170  	anyl := mux.HandleListener(mux.Any())
   171  	go safeServe(errCh, srv, l)
   172  	muxedConn, err := anyl.Accept()
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  	for i := 0; i < mult; i++ {
   177  		var b [len(payload)]byte
   178  		n, err := muxedConn.Read(b[:])
   179  		if err != nil {
   180  			t.Error(err)
   181  			continue
   182  		}
   183  		if e := len(b); n != e {
   184  			t.Errorf("expected to read %d bytes, but read %d bytes", e, n)
   185  		}
   186  	}
   187  	var b [1]byte
   188  	if _, err := muxedConn.Read(b[:]); err != io.EOF {
   189  		t.Errorf("unexpected error %v, expected %v", err, io.EOF)
   190  	}
   191  
   192  }
   193  
   194  func TestAny(t *testing.T) {
   195  	defer leakcheck.Check(t)
   196  	errCh := make(chan error, 5)
   197  	defer func() {
   198  		for {
   199  			select {
   200  			case err, ok := <-errCh:
   201  				if !ok {
   202  					return
   203  				}
   204  				t.Fatal(err)
   205  			default:
   206  				close(errCh)
   207  				return
   208  			}
   209  		}
   210  	}()
   211  	l := testListener(t)
   212  	defer l.Close()
   213  
   214  	var wg sync.WaitGroup
   215  	func() {
   216  		srv := mux.NewServer()
   217  		defer srv.Close()
   218  
   219  		httpl := mux.HandleListener(mux.Any())
   220  		wg.Add(1)
   221  		go func() {
   222  			defer wg.Done()
   223  			runTestHTTPServer(errCh, httpl)
   224  		}()
   225  		wg.Add(1)
   226  		go func() {
   227  			defer wg.Done()
   228  			safeServe(errCh, srv, l)
   229  		}()
   230  		runTestHTTP1Client(t, l.Addr())
   231  	}()
   232  	wg.Wait()
   233  }
   234  
   235  func TestTLS(t *testing.T) {
   236  	generateTLSCert(t)
   237  	defer cleanupTLSCert(t)
   238  	defer leakcheck.Check(t)
   239  	errCh := make(chan error)
   240  	defer func() {
   241  		for {
   242  			select {
   243  			case err, ok := <-errCh:
   244  				if !ok {
   245  					return
   246  				}
   247  				t.Fatal(err)
   248  			default:
   249  				close(errCh)
   250  				return
   251  			}
   252  		}
   253  	}()
   254  	l := testListener(t)
   255  	defer l.Close()
   256  
   257  	srv := mux.NewServer()
   258  	defer srv.Close()
   259  
   260  	tlsl := mux.HandleListener(mux.TLS())
   261  	httpl := mux.HandleListener(mux.Any())
   262  
   263  	go runTestTLSServer(errCh, tlsl)
   264  	go runTestHTTPServer(errCh, httpl)
   265  	go safeServe(errCh, srv, l)
   266  
   267  	runTestHTTP1Client(t, l.Addr())
   268  	runTestTLSClient(t, l.Addr())
   269  }
   270  
   271  func TestHTTP2(t *testing.T) {
   272  	defer leakcheck.Check(t)
   273  	errCh := make(chan error)
   274  	defer func() {
   275  		for {
   276  			select {
   277  			case err, ok := <-errCh:
   278  				if !ok {
   279  					return
   280  				}
   281  				t.Fatal(err)
   282  			default:
   283  				close(errCh)
   284  				return
   285  			}
   286  		}
   287  	}()
   288  	writer, reader := net.Pipe()
   289  	go func() {
   290  		if _, err := io.WriteString(writer, http2.ClientPreface); err != nil {
   291  			t.Fatal(err)
   292  		}
   293  		if err := writer.Close(); err != nil {
   294  			t.Fatal(err)
   295  		}
   296  	}()
   297  
   298  	l := newChanListener()
   299  	l.Notify(reader)
   300  	srv := mux.NewServer()
   301  	defer srv.Close()
   302  
   303  	// Register a bogus matcher that only reads one byte.
   304  	mux.HandleListener(mux.MatcherFunc(func(w io.Writer, r io.Reader) bool {
   305  		var b [1]byte
   306  		_, _ = r.Read(b[:])
   307  		return false
   308  	}))
   309  	h2l := mux.HandleListener(mux.HTTP2())
   310  	go safeServe(errCh, srv, l)
   311  	muxedConn, err := h2l.Accept()
   312  	_ = l.Close()
   313  	if err != nil {
   314  		t.Fatal(err)
   315  	}
   316  	var b [len(http2.ClientPreface)]byte
   317  	var n int
   318  	// We have the sniffed buffer first...
   319  	if n, err = muxedConn.Read(b[:]); err == io.EOF {
   320  		t.Fatal(err)
   321  	}
   322  	// and then we read from the source.
   323  	if _, err = muxedConn.Read(b[n:]); err != nil && err != io.EOF {
   324  		t.Fatal(err)
   325  	}
   326  	if string(b[:]) != http2.ClientPreface {
   327  		t.Errorf("got unexpected read %s, expected %s", b, http2.ClientPreface)
   328  	}
   329  }
   330  
   331  func TestHTTP2MatchHeaderField(t *testing.T) {
   332  	testHTTP2HeaderField(t, mux.HTTP2HeaderFieldEqual, "value", "value", "anothervalue")
   333  }
   334  
   335  func TestHTTP2MatchHeaderFieldPrefix(t *testing.T) {
   336  	testHTTP2HeaderField(t, mux.HTTP2HeaderFieldPrefix, "application/grpc+proto", "application/grpc", "application/json")
   337  }
   338  
   339  func TestHTTPGoRPC(t *testing.T) {
   340  	defer leakcheck.Check(t)
   341  	errCh := make(chan error)
   342  	defer func() {
   343  		for {
   344  			select {
   345  			case err, ok := <-errCh:
   346  				if !ok {
   347  					return
   348  				}
   349  				t.Fatal(err)
   350  			default:
   351  				close(errCh)
   352  				return
   353  			}
   354  		}
   355  	}()
   356  	l := testListener(t)
   357  	defer l.Close()
   358  
   359  	srv := mux.NewServer()
   360  	defer srv.Close()
   361  
   362  	httpl := mux.HandleListener(mux.MatcherAny(mux.HTTP2(), mux.HTTP1Fast()))
   363  
   364  	rpcl := mux.HandleListener(mux.Any())
   365  
   366  	go runTestHTTPServer(errCh, httpl)
   367  	go runTestRPCServer(errCh, rpcl)
   368  	go safeServe(errCh, srv, l)
   369  
   370  	runTestHTTP1Client(t, l.Addr())
   371  	runTestRPCClient(t, l.Addr())
   372  }
   373  
   374  func TestErrorHandler(t *testing.T) {
   375  	defer leakcheck.Check(t)
   376  	errCh := make(chan error)
   377  	defer func() {
   378  		for {
   379  			select {
   380  			case err, ok := <-errCh:
   381  				if !ok {
   382  					return
   383  				}
   384  				t.Fatal(err)
   385  			default:
   386  				close(errCh)
   387  				return
   388  			}
   389  		}
   390  	}()
   391  	l := testListener(t)
   392  
   393  	srv := mux.NewServer()
   394  	defer srv.Close()
   395  
   396  	httpl := mux.HandleListener(mux.MatcherAny(mux.HTTP2(), mux.HTTP1Fast()))
   397  
   398  	go runTestHTTPServer(errCh, httpl)
   399  	go safeServe(errCh, srv, l)
   400  
   401  	var errCount uint32
   402  	srv.HandleError(mux.ErrorHandlerFunc(func(err error) bool {
   403  		if atomic.AddUint32(&errCount, 1) == 1 {
   404  			t.Logf("expected error: %v", err)
   405  		}
   406  		return true
   407  	}))
   408  
   409  	//runTestRPCClient(t, l.Addr())
   410  	c, clean := safeDial(t, l.Addr())
   411  	defer clean()
   412  
   413  	l.Close()
   414  
   415  	var num int
   416  	for atomic.LoadUint32(&errCount) == 0 {
   417  		if err := c.Call("TestRPCRcvr.Test", rpcVal, &num); err == nil {
   418  			// The connection is simply closed.
   419  			t.Errorf("unexpected rpc success after %d errors", atomic.LoadUint32(&errCount))
   420  		}
   421  	}
   422  }
   423  
   424  func TestMultipleMatchers(t *testing.T) {
   425  	defer leakcheck.Check(t)
   426  	errCh := make(chan error)
   427  	defer func() {
   428  		for {
   429  			select {
   430  			case err, ok := <-errCh:
   431  				if !ok {
   432  					return
   433  				}
   434  				t.Fatal(err)
   435  			default:
   436  				close(errCh)
   437  				return
   438  			}
   439  		}
   440  	}()
   441  	l := testListener(t)
   442  	defer l.Close()
   443  
   444  	matcher := func(w io.Writer, r io.Reader) bool {
   445  		return true
   446  	}
   447  	unmatcher := func(w io.Writer, r io.Reader) bool {
   448  		return false
   449  	}
   450  
   451  	srv := mux.NewServer()
   452  	defer srv.Close()
   453  
   454  	lis := mux.HandleListener(mux.MatcherAny(mux.MatcherFunc(unmatcher), mux.MatcherFunc(matcher), mux.MatcherFunc(unmatcher)))
   455  
   456  	go runTestHTTPServer(errCh, lis)
   457  	go safeServe(errCh, srv, l)
   458  
   459  	runTestHTTP1Client(t, l.Addr())
   460  }
   461  
   462  func TestClose(t *testing.T) {
   463  	defer leakcheck.Check(t)
   464  	errCh := make(chan error)
   465  	defer func() {
   466  		for {
   467  			select {
   468  			case err, ok := <-errCh:
   469  				if !ok {
   470  					return
   471  				}
   472  				t.Fatal(err)
   473  			default:
   474  				close(errCh)
   475  				return
   476  			}
   477  		}
   478  	}()
   479  	l := newChanListener()
   480  
   481  	c1, c2 := net.Pipe()
   482  
   483  	srv := mux.NewServer()
   484  	defer srv.Close()
   485  
   486  	anyl := mux.HandleListener(mux.Any())
   487  
   488  	go safeServe(errCh, srv, l)
   489  
   490  	l.Notify(c1)
   491  
   492  	// First connection goes through.
   493  	if _, err := anyl.Accept(); err != nil {
   494  		t.Fatal(err)
   495  	}
   496  
   497  	// Second connection is sent
   498  	l.Notify(c2)
   499  
   500  	// Listener is closed.
   501  	l.Close()
   502  
   503  	// Second connection either goes through or it is closed.
   504  	if _, err := anyl.Accept(); err != nil {
   505  		if err != mux.ErrListenerClosed {
   506  			t.Fatal(err)
   507  		}
   508  		// The error is either io.ErrClosedPipe or net.OpError wrapping
   509  		// a net.pipeError depending on the go version.
   510  		if _, err := c2.Read([]byte{}); !strings.Contains(err.Error(), "closed") {
   511  			t.Fatalf("connection is not closed and is leaked: %v", err)
   512  		}
   513  	}
   514  }