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 }