github.com/Cloud-Foundations/Dominator@v0.3.4/lib/srpc/call_test.go (about)

     1  package srpc
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/Cloud-Foundations/Dominator/proto/test"
    13  )
    14  
    15  type serverType struct{}
    16  
    17  func init() {
    18  	attemptTransportUpgrade = false
    19  	RegisterName("Test", &serverType{})
    20  }
    21  
    22  func makeClientServer(makeCoder coderMaker) (*Client, error) {
    23  	serverPipe, clientPipe := net.Pipe()
    24  	go handleConnection(&Conn{
    25  		ReadWriter: bufio.NewReadWriter(bufio.NewReader(serverPipe),
    26  			bufio.NewWriter(serverPipe)),
    27  	},
    28  		makeCoder)
    29  	return newClient(clientPipe, clientPipe, false, makeCoder)
    30  }
    31  
    32  func makeListener(gob, json bool) (net.Addr, error) {
    33  	if listener, err := net.Listen("tcp", "localhost:"); err != nil {
    34  		return nil, err
    35  	} else {
    36  		serveMux := http.NewServeMux()
    37  		if gob {
    38  			serveMux.HandleFunc(rpcPath, gobUnsecuredHttpHandler)
    39  		}
    40  		if json {
    41  			serveMux.HandleFunc(jsonRpcPath, jsonUnsecuredHttpHandler)
    42  		}
    43  		go func() {
    44  			if err := http.Serve(listener, serveMux); err != nil {
    45  				panic(err)
    46  			}
    47  		}()
    48  		time.Sleep(time.Millisecond * 10) // Give the server time to start.
    49  		return listener.Addr(), nil
    50  	}
    51  }
    52  
    53  func makeListenerAndConnect(gob, json bool) (*Client, error) {
    54  	if addr, err := makeListener(gob, json); err != nil {
    55  		return nil, err
    56  	} else {
    57  		return DialHTTP(addr.Network(), addr.String(), 0)
    58  	}
    59  }
    60  
    61  func testCallPlain(t *testing.T, makeCoder coderMaker) {
    62  	client, err := makeClientServer(makeCoder)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	defer client.Close()
    67  	// Call# 0.
    68  	if err := testDoCallPlain(t, client, "plain0"); err != nil {
    69  		t.Fatal(err)
    70  	}
    71  	// Call# 1.
    72  	if err := testDoCallPlain(t, client, "plain1"); err != nil {
    73  		t.Fatal(err)
    74  	}
    75  }
    76  
    77  func testCallRequestReply(t *testing.T, makeCoder coderMaker) {
    78  	serverPipe, clientPipe := net.Pipe()
    79  	go handleConnection(&Conn{
    80  		ReadWriter: bufio.NewReadWriter(bufio.NewReader(serverPipe),
    81  			bufio.NewWriter(serverPipe)),
    82  	},
    83  		makeCoder)
    84  	client, err := newClient(clientPipe, clientPipe, false, makeCoder)
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	defer client.Close()
    89  	// Call# 0.
    90  	var response test.EchoResponse
    91  	err = client.RequestReply("Test.RequestReply",
    92  		test.EchoRequest{Request: "test0"}, &response)
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  	if response.Response != "test0" {
    97  		t.Errorf("Response: %s != test0\n", response.Response)
    98  	}
    99  	// Call# 1.
   100  	err = client.RequestReply("Test.RequestReply",
   101  		test.EchoRequest{Request: "test1"}, &response)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	if response.Response != "test1" {
   106  		t.Errorf("Response: %s != test1\n", response.Response)
   107  	}
   108  	// Call missing service.
   109  	if _, err := client.Call("NoService.None"); err == nil {
   110  		t.Fatal("no failure when calling unknown service")
   111  	} else if !strings.Contains(err.Error(), "unknown service") {
   112  		t.Fatal(err)
   113  	}
   114  	// Call missing method.
   115  	if _, err := client.Call("Test.None"); err == nil {
   116  		t.Fatal("no failure when calling unknown method")
   117  	} else if !strings.Contains(err.Error(), "unknown method") {
   118  		t.Fatal(err)
   119  	}
   120  }
   121  
   122  func testCallReceiver(t *testing.T, makeCoder coderMaker) {
   123  	client, err := makeClientServer(makeCoder)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	defer client.Close()
   128  	// Call# 0.
   129  	conn, err := client.Call("Test.Receiver")
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	if err := conn.Encode(test.EchoRequest{Request: "receiver0"}); err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	if err := conn.Flush(); err != nil {
   137  		t.Fatal(err)
   138  	}
   139  	if err := conn.Close(); err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	// Call# 1. No explicit flush.
   143  	conn, err = client.Call("Test.Receiver")
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	if err := conn.Encode(test.EchoRequest{Request: "receiver1"}); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	if err := conn.Close(); err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	// Call# 2.
   154  	conn, err = client.Call("Test.Receiver")
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	if err := conn.Encode(test.EchoRequest{Request: "receiver2"}); err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	if err := conn.Flush(); err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	if err := conn.Close(); err != nil {
   165  		t.Fatal(err)
   166  	}
   167  }
   168  
   169  func testDoCallPlain(t *testing.T, client *Client, data string) error {
   170  	conn, err := client.Call("Test.Plain")
   171  	if err != nil {
   172  		return err
   173  	}
   174  	doClose := true
   175  	defer func() {
   176  		if doClose {
   177  			conn.Close()
   178  		}
   179  	}()
   180  	if err := conn.Encode(test.EchoRequest{Request: data}); err != nil {
   181  		return err
   182  	}
   183  	if err := conn.Flush(); err != nil {
   184  		return err
   185  	}
   186  	var response test.EchoResponse
   187  	if err := conn.Decode(&response); err != nil {
   188  		return err
   189  	}
   190  	if response.Response != data {
   191  		return fmt.Errorf("response: %s != %s\n", response.Response, data)
   192  	}
   193  	doClose = false
   194  	if err := conn.Close(); err != nil {
   195  		return err
   196  	}
   197  	return nil
   198  }
   199  
   200  func TestDialCallCloseCall(t *testing.T) {
   201  	client, err := makeListenerAndConnect(true, false)
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	if err := testDoCallPlain(t, client, "dial+plain"); err != nil {
   206  		t.Fatal(err)
   207  		client.Close()
   208  	}
   209  	if err := client.Close(); err != nil {
   210  		t.Fatal(err)
   211  	}
   212  	defer func() {
   213  		if err := recover(); err == nil {
   214  			t.Fatal("call on closed client did not panic")
   215  		}
   216  	}()
   217  	if err := testDoCallPlain(t, client, "dial+close+plain"); err == nil {
   218  		t.Fatal("call on close client did not fail")
   219  	}
   220  }
   221  
   222  func TestGobCallPlain(t *testing.T) {
   223  	testCallPlain(t, &gobCoder{})
   224  }
   225  
   226  func TestJsonCallPlain(t *testing.T) {
   227  	testCallPlain(t, &jsonCoder{})
   228  }
   229  
   230  func TestGobCallRequestReply(t *testing.T) {
   231  	testCallRequestReply(t, &gobCoder{})
   232  }
   233  
   234  func TestJsonCallRequestReply(t *testing.T) {
   235  	testCallRequestReply(t, &jsonCoder{})
   236  }
   237  
   238  func TestGobCallReceiver(t *testing.T) {
   239  	testCallReceiver(t, &gobCoder{})
   240  }
   241  
   242  func TestJsonCallReceiver(t *testing.T) {
   243  	testCallReceiver(t, &jsonCoder{})
   244  }
   245  
   246  func TestDualListener(t *testing.T) {
   247  	if client, err := makeListenerAndConnect(true, true); err != nil {
   248  		t.Fatal(err)
   249  	} else {
   250  		if _, ok := client.makeCoder.(*gobCoder); !ok {
   251  			t.Fatal("GOB coder not default for dual listener")
   252  		}
   253  	}
   254  }
   255  
   256  func TestGobListener(t *testing.T) {
   257  	if client, err := makeListenerAndConnect(true, false); err != nil {
   258  		t.Fatal(err)
   259  	} else {
   260  		if _, ok := client.makeCoder.(*gobCoder); !ok {
   261  			t.Fatal("GOB coder not available for GOB listener")
   262  		}
   263  	}
   264  }
   265  
   266  func TestJsonListener(t *testing.T) {
   267  	if client, err := makeListenerAndConnect(false, true); err != nil {
   268  		t.Fatal(err)
   269  	} else {
   270  		if _, ok := client.makeCoder.(*jsonCoder); !ok {
   271  			t.Fatal("JSON coder not available for JSON listener")
   272  		}
   273  	}
   274  }
   275  
   276  func TestSilentListener(t *testing.T) {
   277  	_, err := makeListenerAndConnect(false, false)
   278  	if err != ErrorNoSrpcEndpoint {
   279  		t.Fatalf("Silent listener error: %s != %s", err, ErrorNoSrpcEndpoint)
   280  	}
   281  }
   282  
   283  func (t *serverType) Plain(conn *Conn) error {
   284  	var request test.EchoRequest
   285  	if err := conn.Decode(&request); err != nil {
   286  		return err
   287  	}
   288  	err := conn.Encode(test.EchoResponse{Response: request.Request})
   289  	if err != nil {
   290  		return err
   291  	}
   292  	return nil
   293  }
   294  
   295  func (t *serverType) RequestReply(conn *Conn, request test.EchoRequest,
   296  	response *test.EchoResponse) error {
   297  	*response = test.EchoResponse{Response: request.Request}
   298  	return nil
   299  }
   300  
   301  func (t *serverType) Receiver(conn *Conn) error {
   302  	var request test.EchoRequest
   303  	if err := conn.Decode(&request); err != nil {
   304  		return err
   305  	}
   306  	if !strings.HasPrefix(request.Request, "receiver") {
   307  		panic("bad request string: " + request.Request)
   308  	}
   309  	return nil
   310  }