github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/old/netchan/netchan_test.go (about)

     1  // Copyright 2010 The Go Authors. 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 netchan
     6  
     7  import (
     8  	"net"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  const count = 10     // number of items in most tests
    15  const closeCount = 5 // number of items when sender closes early
    16  
    17  const base = 23
    18  
    19  func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) {
    20  	ch := make(chan int)
    21  	err := exp.Export("exportedSend", ch, Send)
    22  	if err != nil {
    23  		t.Fatal("exportSend:", err)
    24  	}
    25  	go func() {
    26  		for i := 0; i < n; i++ {
    27  			ch <- base + i
    28  		}
    29  		close(ch)
    30  		if done != nil {
    31  			done <- true
    32  		}
    33  	}()
    34  }
    35  
    36  func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
    37  	ch := make(chan int)
    38  	err := exp.Export("exportedRecv", ch, Recv)
    39  	expDone <- true
    40  	if err != nil {
    41  		t.Fatal("exportReceive:", err)
    42  	}
    43  	for i := 0; i < count; i++ {
    44  		v, ok := <-ch
    45  		if !ok {
    46  			if i != closeCount {
    47  				t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
    48  			}
    49  			break
    50  		}
    51  		if v != base+i {
    52  			t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v)
    53  		}
    54  	}
    55  }
    56  
    57  func importSend(imp *Importer, n int, t *testing.T, done chan bool) {
    58  	ch := make(chan int)
    59  	err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1)
    60  	if err != nil {
    61  		t.Fatal("importSend:", err)
    62  	}
    63  	go func() {
    64  		for i := 0; i < n; i++ {
    65  			ch <- base + i
    66  		}
    67  		close(ch)
    68  		if done != nil {
    69  			done <- true
    70  		}
    71  	}()
    72  }
    73  
    74  func importReceive(imp *Importer, t *testing.T, done chan bool) {
    75  	ch := make(chan int)
    76  	err := imp.ImportNValues("exportedSend", ch, Recv, 3, count)
    77  	if err != nil {
    78  		t.Fatal("importReceive:", err)
    79  	}
    80  	for i := 0; i < count; i++ {
    81  		v, ok := <-ch
    82  		if !ok {
    83  			if i != closeCount {
    84  				t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
    85  			}
    86  			break
    87  		}
    88  		if v != base+i {
    89  			t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
    90  		}
    91  	}
    92  	if done != nil {
    93  		done <- true
    94  	}
    95  }
    96  
    97  func TestExportSendImportReceive(t *testing.T) {
    98  	exp, imp := pair(t)
    99  	exportSend(exp, count, t, nil)
   100  	importReceive(imp, t, nil)
   101  }
   102  
   103  func TestExportReceiveImportSend(t *testing.T) {
   104  	exp, imp := pair(t)
   105  	expDone := make(chan bool)
   106  	done := make(chan bool)
   107  	go func() {
   108  		exportReceive(exp, t, expDone)
   109  		done <- true
   110  	}()
   111  	<-expDone
   112  	importSend(imp, count, t, nil)
   113  	<-done
   114  }
   115  
   116  func TestClosingExportSendImportReceive(t *testing.T) {
   117  	exp, imp := pair(t)
   118  	exportSend(exp, closeCount, t, nil)
   119  	importReceive(imp, t, nil)
   120  }
   121  
   122  func TestClosingImportSendExportReceive(t *testing.T) {
   123  	exp, imp := pair(t)
   124  	expDone := make(chan bool)
   125  	done := make(chan bool)
   126  	go func() {
   127  		exportReceive(exp, t, expDone)
   128  		done <- true
   129  	}()
   130  	<-expDone
   131  	importSend(imp, closeCount, t, nil)
   132  	<-done
   133  }
   134  
   135  func TestErrorForIllegalChannel(t *testing.T) {
   136  	exp, imp := pair(t)
   137  	// Now export a channel.
   138  	ch := make(chan int, 1)
   139  	err := exp.Export("aChannel", ch, Send)
   140  	if err != nil {
   141  		t.Fatal("export:", err)
   142  	}
   143  	ch <- 1234
   144  	close(ch)
   145  	// Now try to import a different channel.
   146  	ch = make(chan int)
   147  	err = imp.Import("notAChannel", ch, Recv, 1)
   148  	if err != nil {
   149  		t.Fatal("import:", err)
   150  	}
   151  	// Expect an error now.  Start a timeout.
   152  	timeout := make(chan bool, 1) // buffered so closure will not hang around.
   153  	go func() {
   154  		time.Sleep(10 * time.Second) // very long, to give even really slow machines a chance.
   155  		timeout <- true
   156  	}()
   157  	select {
   158  	case err = <-imp.Errors():
   159  		if strings.Index(err.Error(), "no such channel") < 0 {
   160  			t.Error("wrong error for nonexistent channel:", err)
   161  		}
   162  	case <-timeout:
   163  		t.Error("import of nonexistent channel did not receive an error")
   164  	}
   165  }
   166  
   167  // Not a great test but it does at least invoke Drain.
   168  func TestExportDrain(t *testing.T) {
   169  	exp, imp := pair(t)
   170  	done := make(chan bool)
   171  	go func() {
   172  		exportSend(exp, closeCount, t, nil)
   173  		done <- true
   174  	}()
   175  	<-done
   176  	go importReceive(imp, t, done)
   177  	exp.Drain(0)
   178  	<-done
   179  }
   180  
   181  // Not a great test but it does at least invoke Drain.
   182  func TestImportDrain(t *testing.T) {
   183  	exp, imp := pair(t)
   184  	expDone := make(chan bool)
   185  	go exportReceive(exp, t, expDone)
   186  	<-expDone
   187  	importSend(imp, closeCount, t, nil)
   188  	imp.Drain(0)
   189  }
   190  
   191  // Not a great test but it does at least invoke Sync.
   192  func TestExportSync(t *testing.T) {
   193  	exp, imp := pair(t)
   194  	done := make(chan bool)
   195  	exportSend(exp, closeCount, t, nil)
   196  	go importReceive(imp, t, done)
   197  	exp.Sync(0)
   198  	<-done
   199  }
   200  
   201  // Test hanging up the send side of an export.
   202  // TODO: test hanging up the receive side of an export.
   203  func TestExportHangup(t *testing.T) {
   204  	exp, imp := pair(t)
   205  	ech := make(chan int)
   206  	err := exp.Export("exportedSend", ech, Send)
   207  	if err != nil {
   208  		t.Fatal("export:", err)
   209  	}
   210  	// Prepare to receive two values. We'll actually deliver only one.
   211  	ich := make(chan int)
   212  	err = imp.ImportNValues("exportedSend", ich, Recv, 1, 2)
   213  	if err != nil {
   214  		t.Fatal("import exportedSend:", err)
   215  	}
   216  	// Send one value, receive it.
   217  	const Value = 1234
   218  	ech <- Value
   219  	v := <-ich
   220  	if v != Value {
   221  		t.Fatal("expected", Value, "got", v)
   222  	}
   223  	// Now hang up the channel.  Importer should see it close.
   224  	exp.Hangup("exportedSend")
   225  	v, ok := <-ich
   226  	if ok {
   227  		t.Fatal("expected channel to be closed; got value", v)
   228  	}
   229  }
   230  
   231  // Test hanging up the send side of an import.
   232  // TODO: test hanging up the receive side of an import.
   233  func TestImportHangup(t *testing.T) {
   234  	exp, imp := pair(t)
   235  	ech := make(chan int)
   236  	err := exp.Export("exportedRecv", ech, Recv)
   237  	if err != nil {
   238  		t.Fatal("export:", err)
   239  	}
   240  	// Prepare to Send two values. We'll actually deliver only one.
   241  	ich := make(chan int)
   242  	err = imp.ImportNValues("exportedRecv", ich, Send, 1, 2)
   243  	if err != nil {
   244  		t.Fatal("import exportedRecv:", err)
   245  	}
   246  	// Send one value, receive it.
   247  	const Value = 1234
   248  	ich <- Value
   249  	v := <-ech
   250  	if v != Value {
   251  		t.Fatal("expected", Value, "got", v)
   252  	}
   253  	// Now hang up the channel.  Exporter should see it close.
   254  	imp.Hangup("exportedRecv")
   255  	v, ok := <-ech
   256  	if ok {
   257  		t.Fatal("expected channel to be closed; got value", v)
   258  	}
   259  }
   260  
   261  // loop back exportedRecv to exportedSend,
   262  // but receive a value from ctlch before starting the loop.
   263  func exportLoopback(exp *Exporter, t *testing.T) {
   264  	inch := make(chan int)
   265  	if err := exp.Export("exportedRecv", inch, Recv); err != nil {
   266  		t.Fatal("exportRecv")
   267  	}
   268  
   269  	outch := make(chan int)
   270  	if err := exp.Export("exportedSend", outch, Send); err != nil {
   271  		t.Fatal("exportSend")
   272  	}
   273  
   274  	ctlch := make(chan int)
   275  	if err := exp.Export("exportedCtl", ctlch, Recv); err != nil {
   276  		t.Fatal("exportRecv")
   277  	}
   278  
   279  	go func() {
   280  		<-ctlch
   281  		for i := 0; i < count; i++ {
   282  			x := <-inch
   283  			if x != base+i {
   284  				t.Errorf("exportLoopback expected %d; got %d", i, x)
   285  			}
   286  			outch <- x
   287  		}
   288  	}()
   289  }
   290  
   291  // This test checks that channel operations can proceed
   292  // even when other concurrent operations are blocked.
   293  func TestIndependentSends(t *testing.T) {
   294  	if testing.Short() {
   295  		t.Logf("disabled test during -short")
   296  		return
   297  	}
   298  	exp, imp := pair(t)
   299  
   300  	exportLoopback(exp, t)
   301  
   302  	importSend(imp, count, t, nil)
   303  	done := make(chan bool)
   304  	go importReceive(imp, t, done)
   305  
   306  	// wait for export side to try to deliver some values.
   307  	time.Sleep(250 * time.Millisecond)
   308  
   309  	ctlch := make(chan int)
   310  	if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
   311  		t.Fatal("importSend:", err)
   312  	}
   313  	ctlch <- 0
   314  
   315  	<-done
   316  }
   317  
   318  // This test cross-connects a pair of exporter/importer pairs.
   319  type value struct {
   320  	I      int
   321  	Source string
   322  }
   323  
   324  func TestCrossConnect(t *testing.T) {
   325  	e1, i1 := pair(t)
   326  	e2, i2 := pair(t)
   327  
   328  	crossExport(e1, e2, t)
   329  	crossImport(i1, i2, t)
   330  }
   331  
   332  // Export side of cross-traffic.
   333  func crossExport(e1, e2 *Exporter, t *testing.T) {
   334  	s := make(chan value)
   335  	err := e1.Export("exportedSend", s, Send)
   336  	if err != nil {
   337  		t.Fatal("exportSend:", err)
   338  	}
   339  
   340  	r := make(chan value)
   341  	err = e2.Export("exportedReceive", r, Recv)
   342  	if err != nil {
   343  		t.Fatal("exportReceive:", err)
   344  	}
   345  
   346  	go crossLoop("export", s, r, t)
   347  }
   348  
   349  // Import side of cross-traffic.
   350  func crossImport(i1, i2 *Importer, t *testing.T) {
   351  	s := make(chan value)
   352  	err := i2.Import("exportedReceive", s, Send, 2)
   353  	if err != nil {
   354  		t.Fatal("import of exportedReceive:", err)
   355  	}
   356  
   357  	r := make(chan value)
   358  	err = i1.Import("exportedSend", r, Recv, 2)
   359  	if err != nil {
   360  		t.Fatal("import of exported Send:", err)
   361  	}
   362  
   363  	crossLoop("import", s, r, t)
   364  }
   365  
   366  // Cross-traffic: send and receive 'count' numbers.
   367  func crossLoop(name string, s, r chan value, t *testing.T) {
   368  	for si, ri := 0, 0; si < count && ri < count; {
   369  		select {
   370  		case s <- value{si, name}:
   371  			si++
   372  		case v := <-r:
   373  			if v.I != ri {
   374  				t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
   375  			}
   376  			ri++
   377  		}
   378  	}
   379  }
   380  
   381  const flowCount = 100
   382  
   383  // test flow control from exporter to importer.
   384  func TestExportFlowControl(t *testing.T) {
   385  	if testing.Short() {
   386  		t.Logf("disabled test during -short")
   387  		return
   388  	}
   389  	exp, imp := pair(t)
   390  
   391  	sendDone := make(chan bool, 1)
   392  	exportSend(exp, flowCount, t, sendDone)
   393  
   394  	ch := make(chan int)
   395  	err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
   396  	if err != nil {
   397  		t.Fatal("importReceive:", err)
   398  	}
   399  
   400  	testFlow(sendDone, ch, flowCount, t)
   401  }
   402  
   403  // test flow control from importer to exporter.
   404  func TestImportFlowControl(t *testing.T) {
   405  	if testing.Short() {
   406  		t.Logf("disabled test during -short")
   407  		return
   408  	}
   409  	exp, imp := pair(t)
   410  
   411  	ch := make(chan int)
   412  	err := exp.Export("exportedRecv", ch, Recv)
   413  	if err != nil {
   414  		t.Fatal("importReceive:", err)
   415  	}
   416  
   417  	sendDone := make(chan bool, 1)
   418  	importSend(imp, flowCount, t, sendDone)
   419  	testFlow(sendDone, ch, flowCount, t)
   420  }
   421  
   422  func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
   423  	go func() {
   424  		time.Sleep(500 * time.Millisecond)
   425  		sendDone <- false
   426  	}()
   427  
   428  	if <-sendDone {
   429  		t.Fatal("send did not block")
   430  	}
   431  	n := 0
   432  	for i := range ch {
   433  		t.Log("after blocking, got value ", i)
   434  		n++
   435  	}
   436  	if n != N {
   437  		t.Fatalf("expected %d values; got %d", N, n)
   438  	}
   439  }
   440  
   441  func pair(t *testing.T) (*Exporter, *Importer) {
   442  	c0, c1 := net.Pipe()
   443  	exp := NewExporter()
   444  	go exp.ServeConn(c0)
   445  	imp := NewImporter(c1)
   446  	return exp, imp
   447  }