github.com/homburg/packer@v0.6.1-0.20140528012651-1dcaf1716848/packer/rpc/muxconn_test.go (about)

     1  package rpc
     2  
     3  import (
     4  	"io"
     5  	"net"
     6  	"sync"
     7  	"testing"
     8  )
     9  
    10  func readStream(t *testing.T, s io.Reader) string {
    11  	var data [1024]byte
    12  	n, err := s.Read(data[:])
    13  	if err != nil {
    14  		t.Fatalf("err: %s", err)
    15  	}
    16  
    17  	return string(data[0:n])
    18  }
    19  
    20  func testMux(t *testing.T) (client *MuxConn, server *MuxConn) {
    21  	l, err := net.Listen("tcp", "127.0.0.1:0")
    22  	if err != nil {
    23  		t.Fatalf("err: %s", err)
    24  	}
    25  
    26  	// Server side
    27  	doneCh := make(chan struct{})
    28  	go func() {
    29  		defer close(doneCh)
    30  		conn, err := l.Accept()
    31  		l.Close()
    32  		if err != nil {
    33  			t.Fatalf("err: %s", err)
    34  		}
    35  
    36  		server = NewMuxConn(conn)
    37  	}()
    38  
    39  	// Client side
    40  	conn, err := net.Dial("tcp", l.Addr().String())
    41  	if err != nil {
    42  		t.Fatalf("err: %s", err)
    43  	}
    44  	client = NewMuxConn(conn)
    45  
    46  	// Wait for the server
    47  	<-doneCh
    48  
    49  	return
    50  }
    51  
    52  func TestMuxConn(t *testing.T) {
    53  	client, server := testMux(t)
    54  	defer client.Close()
    55  	defer server.Close()
    56  
    57  	// When the server is done
    58  	doneCh := make(chan struct{})
    59  
    60  	// The server side
    61  	go func() {
    62  		defer close(doneCh)
    63  
    64  		s0, err := server.Accept(0)
    65  		if err != nil {
    66  			t.Fatalf("err: %s", err)
    67  		}
    68  
    69  		s1, err := server.Dial(1)
    70  		if err != nil {
    71  			t.Fatalf("err: %s", err)
    72  		}
    73  
    74  		var wg sync.WaitGroup
    75  		wg.Add(2)
    76  
    77  		go func() {
    78  			defer wg.Done()
    79  			defer s1.Close()
    80  			data := readStream(t, s1)
    81  			if data != "another" {
    82  				t.Fatalf("bad: %#v", data)
    83  			}
    84  		}()
    85  
    86  		go func() {
    87  			defer wg.Done()
    88  			defer s0.Close()
    89  			data := readStream(t, s0)
    90  			if data != "hello" {
    91  				t.Fatalf("bad: %#v", data)
    92  			}
    93  		}()
    94  
    95  		wg.Wait()
    96  	}()
    97  
    98  	s0, err := client.Dial(0)
    99  	if err != nil {
   100  		t.Fatalf("err: %s", err)
   101  	}
   102  
   103  	s1, err := client.Accept(1)
   104  	if err != nil {
   105  		t.Fatalf("err: %s", err)
   106  	}
   107  
   108  	if _, err := s0.Write([]byte("hello")); err != nil {
   109  		t.Fatalf("err: %s", err)
   110  	}
   111  	if _, err := s1.Write([]byte("another")); err != nil {
   112  		t.Fatalf("err: %s", err)
   113  	}
   114  
   115  	s0.Close()
   116  	s1.Close()
   117  
   118  	// Wait for the server to be done
   119  	<-doneCh
   120  }
   121  
   122  func TestMuxConn_lotsOfData(t *testing.T) {
   123  	client, server := testMux(t)
   124  	defer client.Close()
   125  	defer server.Close()
   126  
   127  	// When the server is done
   128  	doneCh := make(chan struct{})
   129  
   130  	// The server side
   131  	go func() {
   132  		defer close(doneCh)
   133  
   134  		s0, err := server.Accept(0)
   135  		if err != nil {
   136  			t.Fatalf("err: %s", err)
   137  		}
   138  
   139  		var data [1024]byte
   140  		for {
   141  			n, err := s0.Read(data[:])
   142  			if err == io.EOF {
   143  				break
   144  			}
   145  
   146  			dataString := string(data[0:n])
   147  			if dataString != "hello" {
   148  				t.Fatalf("bad: %#v", dataString)
   149  			}
   150  		}
   151  
   152  		s0.Close()
   153  	}()
   154  
   155  	s0, err := client.Dial(0)
   156  	if err != nil {
   157  		t.Fatalf("err: %s", err)
   158  	}
   159  
   160  	for i := 0; i < 4096*4; i++ {
   161  		if _, err := s0.Write([]byte("hello")); err != nil {
   162  			t.Fatalf("err: %s", err)
   163  		}
   164  	}
   165  
   166  	if err := s0.Close(); err != nil {
   167  		t.Fatalf("err: %s", err)
   168  	}
   169  
   170  	// Wait for the server to be done
   171  	<-doneCh
   172  }
   173  
   174  // This tests that even when the client end is closed, data can be
   175  // read from the server.
   176  func TestMuxConn_clientCloseRead(t *testing.T) {
   177  	client, server := testMux(t)
   178  	defer client.Close()
   179  	defer server.Close()
   180  
   181  	// This channel will be closed when we close
   182  	waitCh := make(chan struct{})
   183  
   184  	go func() {
   185  		conn, err := server.Accept(0)
   186  		if err != nil {
   187  			t.Fatalf("err: %s", err)
   188  		}
   189  
   190  		<-waitCh
   191  
   192  		_, err = conn.Write([]byte("foo"))
   193  		if err != nil {
   194  			t.Fatalf("err: %s", err)
   195  		}
   196  
   197  		conn.Close()
   198  	}()
   199  
   200  	s0, err := client.Dial(0)
   201  	if err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  
   205  	if err := s0.Close(); err != nil {
   206  		t.Fatalf("bad: %s", err)
   207  	}
   208  
   209  	// Close this to continue on on the server-side
   210  	close(waitCh)
   211  
   212  	var data [1024]byte
   213  	n, err := s0.Read(data[:])
   214  	if string(data[:n]) != "foo" {
   215  		t.Fatalf("bad: %#v", string(data[:n]))
   216  	}
   217  }
   218  
   219  func TestMuxConn_socketClose(t *testing.T) {
   220  	client, server := testMux(t)
   221  	defer client.Close()
   222  	defer server.Close()
   223  
   224  	go func() {
   225  		_, err := server.Accept(0)
   226  		if err != nil {
   227  			t.Fatalf("err: %s", err)
   228  		}
   229  
   230  		server.rwc.Close()
   231  	}()
   232  
   233  	s0, err := client.Dial(0)
   234  	if err != nil {
   235  		t.Fatalf("err: %s", err)
   236  	}
   237  
   238  	var data [1024]byte
   239  	_, err = s0.Read(data[:])
   240  	if err != io.EOF {
   241  		t.Fatalf("err: %s", err)
   242  	}
   243  }
   244  
   245  func TestMuxConn_clientClosesStreams(t *testing.T) {
   246  	client, server := testMux(t)
   247  	defer client.Close()
   248  	defer server.Close()
   249  
   250  	go func() {
   251  		conn, err := server.Accept(0)
   252  		if err != nil {
   253  			t.Fatalf("err: %s", err)
   254  		}
   255  		conn.Close()
   256  	}()
   257  
   258  	s0, err := client.Dial(0)
   259  	if err != nil {
   260  		t.Fatalf("err: %s", err)
   261  	}
   262  
   263  	var data [1024]byte
   264  	_, err = s0.Read(data[:])
   265  	if err != io.EOF {
   266  		t.Fatalf("err: %s", err)
   267  	}
   268  }
   269  
   270  func TestMuxConn_serverClosesStreams(t *testing.T) {
   271  	client, server := testMux(t)
   272  	defer client.Close()
   273  	defer server.Close()
   274  	go server.Accept(0)
   275  
   276  	s0, err := client.Dial(0)
   277  	if err != nil {
   278  		t.Fatalf("err: %s", err)
   279  	}
   280  
   281  	if err := server.Close(); err != nil {
   282  		t.Fatalf("err: %s", err)
   283  	}
   284  
   285  	// This should block forever since we never write onto this stream.
   286  	var data [1024]byte
   287  	_, err = s0.Read(data[:])
   288  	if err != io.EOF {
   289  		t.Fatalf("err: %s", err)
   290  	}
   291  }
   292  
   293  func TestMuxConnNextId(t *testing.T) {
   294  	client, server := testMux(t)
   295  	defer client.Close()
   296  	defer server.Close()
   297  
   298  	a := client.NextId()
   299  	b := client.NextId()
   300  
   301  	if a != 1 || b != 2 {
   302  		t.Fatalf("IDs should increment")
   303  	}
   304  
   305  	a = server.NextId()
   306  	b = server.NextId()
   307  
   308  	if a != 1 || b != 2 {
   309  		t.Fatalf("IDs should increment: %d %d", a, b)
   310  	}
   311  }