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 }