func GoServe(t *testing.T, tr smux.Transport, l net.Listener) (done func()) { closed := make(chan struct{}, 1) go func() { for { c1, err := l.Accept() if err != nil { select { case <-closed: return // closed naturally. default: checkErr(t, err) } } log("accepted connection") sc1, err := tr.NewConn(c1, true) checkErr(t, err) go sc1.Serve(echoStream) } }() return func() { closed <- struct{}{} } }
func SubtestWriteCloses(t *testing.T, tr smux.Transport) { a, b := net.Pipe() c1, err := tr.NewConn(a, true) if err != nil { t.Fatal(err) } c2, err := tr.NewConn(b, false) if err != nil { t.Fatal(err) } count := 1000 runners := 10 stress := func() { for i := 0; i < count; i++ { s, err := c2.OpenStream() if err != nil { t.Error(err) } s.Write([]byte("hello")) s.Write([]byte("world")) s.Close() } } for i := 0; i < runners; i++ { go stress() } wg := sync.WaitGroup{} buf := make([]byte, 20) for i := 0; i < runners*count; i++ { s, err := c1.AcceptStream() if err != nil { t.Fatal(err) } wg.Add(1) go func(s smux.Stream) { defer wg.Done() n, _ := io.ReadFull(s, buf) if !bytes.Equal(buf[:n], []byte("helloworld")) { t.Error("got wrong data!", string(buf[:n])) } s.Close() }(s) } wg.Wait() }
func SubtestStreamOpenStress(t *testing.T, tr smux.Transport) { a, b := tcpPipe(t) defer a.Close() defer b.Close() count := 10000 go func() { muxa, err := tr.NewConn(a, true) if err != nil { t.Fatal(err) } stress := func() { for i := 0; i < count; i++ { s, err := muxa.OpenStream() if err != nil { panic(err) } s.Close() } } go stress() go stress() go stress() go stress() go stress() }() muxb, err := tr.NewConn(b, false) if err != nil { t.Fatal(err) } time.Sleep(time.Millisecond * 50) recv := make(chan struct{}) go muxb.Serve(func(s smux.Stream) { recv <- struct{}{} s.Close() }) limit := time.After(time.Second * 10) for i := 0; i < count*5; i++ { select { case <-recv: case <-limit: t.Fatal("timed out receiving streams") } } }
func SubtestSimpleWrite(t *testing.T, tr smux.Transport) { l, err := net.Listen("tcp", "localhost:0") checkErr(t, err) log("listening at %s", l.Addr().String()) done := GoServe(t, tr, l) defer done() log("dialing to %s", l.Addr().String()) nc1, err := net.Dial("tcp", l.Addr().String()) checkErr(t, err) defer nc1.Close() log("wrapping conn") c1, err := tr.NewConn(nc1, false) checkErr(t, err) defer c1.Close() // serve the outgoing conn, because some muxers assume // that we _always_ call serve. (this is an error?) go c1.Serve(smux.NoOpHandler) log("creating stream") s1, err := c1.OpenStream() checkErr(t, err) defer s1.Close() buf1 := randBuf(4096) log("writing %d bytes to stream", len(buf1)) _, err = s1.Write(buf1) checkErr(t, err) buf2 := make([]byte, len(buf1)) log("reading %d bytes from stream (echoed)", len(buf2)) _, err = s1.Read(buf2) checkErr(t, err) if string(buf2) != string(buf1) { t.Error("buf1 and buf2 not equal: %s != %s", string(buf1), string(buf2)) } log("done") }