github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/lib/srpc/call_test.go (about)

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