2015-07-30 01:45:57 +08:00
|
|
|
package cmux
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"net/rpc"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
testHTTP1Resp = "http1"
|
|
|
|
rpcVal = 1234
|
|
|
|
)
|
|
|
|
|
2016-02-21 04:43:18 +08:00
|
|
|
func testListener(t *testing.T) (net.Listener, func()) {
|
|
|
|
l, err := net.Listen("tcp", ":0")
|
2015-07-30 01:45:57 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-02-21 04:43:18 +08:00
|
|
|
return l, func() {
|
|
|
|
if err := l.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type testHTTP1Handler struct{}
|
|
|
|
|
|
|
|
func (h *testHTTP1Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintf(w, testHTTP1Resp)
|
|
|
|
}
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
func runTestHTTPServer(t *testing.T, l net.Listener) {
|
2015-07-30 01:45:57 +08:00
|
|
|
s := &http.Server{
|
|
|
|
Handler: &testHTTP1Handler{},
|
|
|
|
}
|
2016-02-21 04:43:18 +08:00
|
|
|
if err := s.Serve(l); err != nil && err != ErrListenerClosed {
|
2016-01-07 23:15:03 +08:00
|
|
|
t.Log(err)
|
|
|
|
}
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
|
2016-02-21 04:43:18 +08:00
|
|
|
func runTestHTTP1Client(t *testing.T, addr net.Addr) {
|
2016-02-04 12:49:21 +08:00
|
|
|
var r *http.Response
|
2016-02-21 04:43:18 +08:00
|
|
|
if resp, err := http.Get("http://" + addr.String()); err != nil {
|
2015-07-30 01:45:57 +08:00
|
|
|
t.Fatal(err)
|
2016-02-04 12:49:21 +08:00
|
|
|
} else {
|
|
|
|
r = resp
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
defer func() {
|
|
|
|
if err := r.Body.Close(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-07-30 01:45:57 +08:00
|
|
|
b, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if string(b) != testHTTP1Resp {
|
|
|
|
t.Errorf("invalid response: want=%s got=%s", testHTTP1Resp, b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestRPCRcvr struct{}
|
|
|
|
|
|
|
|
func (r TestRPCRcvr) Test(i int, j *int) error {
|
|
|
|
*j = i
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
func runTestRPCServer(t *testing.T, l net.Listener) {
|
2015-07-30 01:45:57 +08:00
|
|
|
s := rpc.NewServer()
|
2016-01-07 23:15:03 +08:00
|
|
|
if err := s.Register(TestRPCRcvr{}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-30 01:45:57 +08:00
|
|
|
for {
|
|
|
|
c, err := l.Accept()
|
|
|
|
if err != nil {
|
2016-01-07 23:15:03 +08:00
|
|
|
t.Log(err)
|
2015-07-30 01:45:57 +08:00
|
|
|
return
|
|
|
|
}
|
2016-01-07 23:15:03 +08:00
|
|
|
go s.ServeConn(c)
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-21 04:43:18 +08:00
|
|
|
func runTestRPCClient(t *testing.T, addr net.Addr) {
|
|
|
|
c, err := rpc.Dial(addr.Network(), addr.String())
|
2015-07-30 01:45:57 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var num int
|
|
|
|
if err := c.Call("TestRPCRcvr.Test", rpcVal, &num); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if num != rpcVal {
|
|
|
|
t.Errorf("wrong rpc response: want=%d got=%v", rpcVal, num)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAny(t *testing.T) {
|
2016-02-21 04:43:18 +08:00
|
|
|
l, cleanup := testListener(t)
|
|
|
|
defer cleanup()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
|
|
|
muxl := New(l)
|
|
|
|
httpl := muxl.Match(Any())
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
go runTestHTTPServer(t, httpl)
|
|
|
|
go func() {
|
|
|
|
if err := muxl.Serve(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
2016-02-04 12:49:21 +08:00
|
|
|
var r *http.Response
|
2016-02-21 04:43:18 +08:00
|
|
|
if resp, err := http.Get("http://" + l.Addr().String()); err != nil {
|
2015-07-30 01:45:57 +08:00
|
|
|
t.Fatal(err)
|
2016-02-04 12:49:21 +08:00
|
|
|
} else {
|
|
|
|
r = resp
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
defer func() {
|
|
|
|
if err := r.Body.Close(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-07-30 01:45:57 +08:00
|
|
|
b, err := ioutil.ReadAll(r.Body)
|
2016-02-04 12:49:21 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
2015-07-30 01:45:57 +08:00
|
|
|
if string(b) != testHTTP1Resp {
|
|
|
|
t.Errorf("invalid response: want=%s got=%s", testHTTP1Resp, b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHTTPGoRPC(t *testing.T) {
|
2016-02-21 04:43:18 +08:00
|
|
|
l, cleanup := testListener(t)
|
|
|
|
defer cleanup()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
|
|
|
muxl := New(l)
|
|
|
|
httpl := muxl.Match(HTTP2(), HTTP1Fast())
|
|
|
|
rpcl := muxl.Match(Any())
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
go runTestHTTPServer(t, httpl)
|
|
|
|
go runTestRPCServer(t, rpcl)
|
|
|
|
go func() {
|
|
|
|
if err := muxl.Serve(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
2016-02-21 04:43:18 +08:00
|
|
|
runTestHTTP1Client(t, l.Addr())
|
|
|
|
runTestRPCClient(t, l.Addr())
|
2015-07-30 01:45:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestErrorHandler(t *testing.T) {
|
2016-02-21 04:43:18 +08:00
|
|
|
l, cleanup := testListener(t)
|
|
|
|
defer cleanup()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
|
|
|
muxl := New(l)
|
|
|
|
httpl := muxl.Match(HTTP2(), HTTP1Fast())
|
|
|
|
|
2016-01-07 23:15:03 +08:00
|
|
|
go runTestHTTPServer(t, httpl)
|
|
|
|
go func() {
|
|
|
|
if err := muxl.Serve(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-07-30 01:45:57 +08:00
|
|
|
|
|
|
|
firstErr := true
|
|
|
|
muxl.HandleError(func(err error) bool {
|
|
|
|
if !firstErr {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if _, ok := err.(ErrNotMatched); !ok {
|
|
|
|
t.Errorf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
firstErr = false
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
2016-02-21 04:43:18 +08:00
|
|
|
addr := l.Addr()
|
|
|
|
c, err := rpc.Dial(addr.Network(), addr.String())
|
2015-07-30 01:45:57 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var num int
|
|
|
|
if err := c.Call("TestRPCRcvr.Test", rpcVal, &num); err == nil {
|
|
|
|
t.Error("rpc got a response")
|
|
|
|
}
|
|
|
|
}
|
2015-08-31 09:07:48 +08:00
|
|
|
|
|
|
|
type closerConn struct {
|
|
|
|
net.Conn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c closerConn) Close() error { return nil }
|
|
|
|
|
|
|
|
func TestClosed(t *testing.T) {
|
|
|
|
mux := &cMux{}
|
|
|
|
lis := mux.Match(Any()).(muxListener)
|
|
|
|
close(lis.donec)
|
|
|
|
mux.serve(closerConn{})
|
2015-12-20 11:28:37 +08:00
|
|
|
_, err := lis.Accept()
|
|
|
|
if _, ok := err.(errListenerClosed); !ok {
|
|
|
|
t.Errorf("expected errListenerClosed got %v", err)
|
|
|
|
}
|
2015-08-31 09:07:48 +08:00
|
|
|
}
|