google.golang.org/grpc@v1.62.1/internal/testutils/pipe_listener_test.go (about)

     1  /*
     2   *
     3   * Copyright 2018 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package testutils_test
    20  
    21  import (
    22  	"testing"
    23  	"time"
    24  
    25  	"google.golang.org/grpc/internal/grpctest"
    26  	"google.golang.org/grpc/internal/testutils"
    27  )
    28  
    29  type s struct {
    30  	grpctest.Tester
    31  }
    32  
    33  func Test(t *testing.T) {
    34  	grpctest.RunSubTests(t, s{})
    35  }
    36  
    37  func (s) TestPipeListener(t *testing.T) {
    38  	pl := testutils.NewPipeListener()
    39  	recvdBytes := make(chan []byte, 1)
    40  	const want = "hello world"
    41  
    42  	go func() {
    43  		c, err := pl.Accept()
    44  		if err != nil {
    45  			t.Error(err)
    46  		}
    47  
    48  		read := make([]byte, len(want))
    49  		_, err = c.Read(read)
    50  		if err != nil {
    51  			t.Error(err)
    52  		}
    53  		recvdBytes <- read
    54  	}()
    55  
    56  	dl := pl.Dialer()
    57  	conn, err := dl("", time.Duration(0))
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  
    62  	_, err = conn.Write([]byte(want))
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	select {
    68  	case gotBytes := <-recvdBytes:
    69  		got := string(gotBytes)
    70  		if got != want {
    71  			t.Fatalf("expected to get %s, got %s", got, want)
    72  		}
    73  	case <-time.After(100 * time.Millisecond):
    74  		t.Fatal("timed out waiting for server to receive bytes")
    75  	}
    76  }
    77  
    78  func (s) TestUnblocking(t *testing.T) {
    79  	for _, test := range []struct {
    80  		desc                 string
    81  		blockFuncShouldError bool
    82  		blockFunc            func(*testutils.PipeListener, chan struct{}) error
    83  		unblockFunc          func(*testutils.PipeListener) error
    84  	}{
    85  		{
    86  			desc: "Accept unblocks Dial",
    87  			blockFunc: func(pl *testutils.PipeListener, done chan struct{}) error {
    88  				dl := pl.Dialer()
    89  				_, err := dl("", time.Duration(0))
    90  				close(done)
    91  				return err
    92  			},
    93  			unblockFunc: func(pl *testutils.PipeListener) error {
    94  				_, err := pl.Accept()
    95  				return err
    96  			},
    97  		},
    98  		{
    99  			desc:                 "Close unblocks Dial",
   100  			blockFuncShouldError: true, // because pl.Close will be called
   101  			blockFunc: func(pl *testutils.PipeListener, done chan struct{}) error {
   102  				dl := pl.Dialer()
   103  				_, err := dl("", time.Duration(0))
   104  				close(done)
   105  				return err
   106  			},
   107  			unblockFunc: func(pl *testutils.PipeListener) error {
   108  				return pl.Close()
   109  			},
   110  		},
   111  		{
   112  			desc: "Dial unblocks Accept",
   113  			blockFunc: func(pl *testutils.PipeListener, done chan struct{}) error {
   114  				_, err := pl.Accept()
   115  				close(done)
   116  				return err
   117  			},
   118  			unblockFunc: func(pl *testutils.PipeListener) error {
   119  				dl := pl.Dialer()
   120  				_, err := dl("", time.Duration(0))
   121  				return err
   122  			},
   123  		},
   124  		{
   125  			desc:                 "Close unblocks Accept",
   126  			blockFuncShouldError: true, // because pl.Close will be called
   127  			blockFunc: func(pl *testutils.PipeListener, done chan struct{}) error {
   128  				_, err := pl.Accept()
   129  				close(done)
   130  				return err
   131  			},
   132  			unblockFunc: func(pl *testutils.PipeListener) error {
   133  				return pl.Close()
   134  			},
   135  		},
   136  	} {
   137  		t.Log(test.desc)
   138  		testUnblocking(t, test.blockFunc, test.unblockFunc, test.blockFuncShouldError)
   139  	}
   140  }
   141  
   142  func testUnblocking(t *testing.T, blockFunc func(*testutils.PipeListener, chan struct{}) error, unblockFunc func(*testutils.PipeListener) error, blockFuncShouldError bool) {
   143  	pl := testutils.NewPipeListener()
   144  	dialFinished := make(chan struct{})
   145  
   146  	go func() {
   147  		err := blockFunc(pl, dialFinished)
   148  		if blockFuncShouldError && err == nil {
   149  			t.Error("expected blocking func to return error because pl.Close was called, but got nil")
   150  		}
   151  
   152  		if !blockFuncShouldError && err != nil {
   153  			t.Error(err)
   154  		}
   155  	}()
   156  
   157  	select {
   158  	case <-dialFinished:
   159  		t.Fatal("expected Dial to block until pl.Close or pl.Accept")
   160  	default:
   161  	}
   162  
   163  	if err := unblockFunc(pl); err != nil {
   164  		t.Fatal(err)
   165  	}
   166  
   167  	select {
   168  	case <-dialFinished:
   169  	case <-time.After(100 * time.Millisecond):
   170  		t.Fatal("expected Accept to unblock after pl.Accept was called")
   171  	}
   172  }