1*61c4878aSAndroid Build Coastguard Worker// Copyright 2024 The Pigweed Authors 2*61c4878aSAndroid Build Coastguard Worker// 3*61c4878aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4*61c4878aSAndroid Build Coastguard Worker// use this file except in compliance with the License. You may obtain a copy of 5*61c4878aSAndroid Build Coastguard Worker// the License at 6*61c4878aSAndroid Build Coastguard Worker// 7*61c4878aSAndroid Build Coastguard Worker// https://www.apache.org/licenses/LICENSE-2.0 8*61c4878aSAndroid Build Coastguard Worker// 9*61c4878aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*61c4878aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11*61c4878aSAndroid Build Coastguard Worker// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12*61c4878aSAndroid Build Coastguard Worker// License for the specific language governing permissions and limitations under 13*61c4878aSAndroid Build Coastguard Worker// the License. 14*61c4878aSAndroid Build Coastguard Worker// 15*61c4878aSAndroid Build Coastguard Worker// Package integration_test implements a client to exercise the pw_grpc server implementation 16*61c4878aSAndroid Build Coastguard Workerpackage integration_test 17*61c4878aSAndroid Build Coastguard Worker 18*61c4878aSAndroid Build Coastguard Workerimport ( 19*61c4878aSAndroid Build Coastguard Worker "bufio" 20*61c4878aSAndroid Build Coastguard Worker "context" 21*61c4878aSAndroid Build Coastguard Worker "fmt" 22*61c4878aSAndroid Build Coastguard Worker "hash/crc32" 23*61c4878aSAndroid Build Coastguard Worker "io" 24*61c4878aSAndroid Build Coastguard Worker "os/exec" 25*61c4878aSAndroid Build Coastguard Worker "strconv" 26*61c4878aSAndroid Build Coastguard Worker "strings" 27*61c4878aSAndroid Build Coastguard Worker "testing" 28*61c4878aSAndroid Build Coastguard Worker "time" 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard Worker "google.golang.org/grpc" 31*61c4878aSAndroid Build Coastguard Worker "google.golang.org/grpc/codes" 32*61c4878aSAndroid Build Coastguard Worker "google.golang.org/grpc/credentials/insecure" 33*61c4878aSAndroid Build Coastguard Worker pb "google.golang.org/grpc/examples/features/proto/echo" 34*61c4878aSAndroid Build Coastguard Worker "google.golang.org/grpc/status" 35*61c4878aSAndroid Build Coastguard Worker) 36*61c4878aSAndroid Build Coastguard Worker 37*61c4878aSAndroid Build Coastguard Workerconst port = "3402" 38*61c4878aSAndroid Build Coastguard Worker 39*61c4878aSAndroid Build Coastguard Workerfunc TestUnaryEcho(t *testing.T) { 40*61c4878aSAndroid Build Coastguard Worker const num_connections = 1 41*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 42*61c4878aSAndroid Build Coastguard Worker if err != nil { 43*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 44*61c4878aSAndroid Build Coastguard Worker } 45*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 46*61c4878aSAndroid Build Coastguard Worker 47*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 48*61c4878aSAndroid Build Coastguard Worker if err != nil { 49*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 50*61c4878aSAndroid Build Coastguard Worker } 51*61c4878aSAndroid Build Coastguard Worker defer conn.Close() 52*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard Worker testRPC(t, func(t *testing.T, ctx context.Context, msg string) { 55*61c4878aSAndroid Build Coastguard Worker t.Logf("call UnaryEcho(%v)", msg) 56*61c4878aSAndroid Build Coastguard Worker resp, err := echo_client.UnaryEcho(ctx, &pb.EchoRequest{Message: msg}) 57*61c4878aSAndroid Build Coastguard Worker if err != nil { 58*61c4878aSAndroid Build Coastguard Worker t.Logf("... failed with error: %v", err.Error()) 59*61c4878aSAndroid Build Coastguard Worker if msg != "quiet" || status.Convert(err).Code() != codes.Canceled { 60*61c4878aSAndroid Build Coastguard Worker t.Errorf("Error unexpected %v", err) 61*61c4878aSAndroid Build Coastguard Worker } 62*61c4878aSAndroid Build Coastguard Worker } else { 63*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv %v", resp) 64*61c4878aSAndroid Build Coastguard Worker if resp.Message != msg { 65*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 66*61c4878aSAndroid Build Coastguard Worker } 67*61c4878aSAndroid Build Coastguard Worker } 68*61c4878aSAndroid Build Coastguard Worker }) 69*61c4878aSAndroid Build Coastguard Worker} 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard Workerfunc TestFragmentedMessage(t *testing.T) { 72*61c4878aSAndroid Build Coastguard Worker // Test sending successively larger messages, larger than the maximum 73*61c4878aSAndroid Build Coastguard Worker // HTTP2 data frame size (16384), ensuring messages are fragmented across 74*61c4878aSAndroid Build Coastguard Worker // frames. 75*61c4878aSAndroid Build Coastguard Worker const num_connections = 1 76*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 77*61c4878aSAndroid Build Coastguard Worker if err != nil { 78*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 79*61c4878aSAndroid Build Coastguard Worker } 80*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 81*61c4878aSAndroid Build Coastguard Worker 82*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 83*61c4878aSAndroid Build Coastguard Worker if err != nil { 84*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 85*61c4878aSAndroid Build Coastguard Worker } 86*61c4878aSAndroid Build Coastguard Worker defer conn.Close() 87*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 88*61c4878aSAndroid Build Coastguard Worker 89*61c4878aSAndroid Build Coastguard Worker const num_calls = 4 90*61c4878aSAndroid Build Coastguard Worker for i := 0; i < num_calls; i++ { 91*61c4878aSAndroid Build Coastguard Worker t.Run(fmt.Sprintf("%d of %d", i+1, num_calls), func(t *testing.T) { 92*61c4878aSAndroid Build Coastguard Worker ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 93*61c4878aSAndroid Build Coastguard Worker defer cancel() 94*61c4878aSAndroid Build Coastguard Worker 95*61c4878aSAndroid Build Coastguard Worker msg := "crc32:" + strings.Repeat("testmessage!", 1500*(i+1)) 96*61c4878aSAndroid Build Coastguard Worker checksum := strconv.FormatUint(uint64(crc32.ChecksumIEEE([]byte(msg))), 10) 97*61c4878aSAndroid Build Coastguard Worker 98*61c4878aSAndroid Build Coastguard Worker done := make(chan struct{}) 99*61c4878aSAndroid Build Coastguard Worker go func() { 100*61c4878aSAndroid Build Coastguard Worker t.Logf("call UnaryChecksum") 101*61c4878aSAndroid Build Coastguard Worker resp, err := echo_client.UnaryEcho(ctx, &pb.EchoRequest{Message: msg}) 102*61c4878aSAndroid Build Coastguard Worker if err != nil { 103*61c4878aSAndroid Build Coastguard Worker t.Logf("... failed with error: %v", err.Error()) 104*61c4878aSAndroid Build Coastguard Worker if msg != "quiet" || status.Convert(err).Code() != codes.Canceled { 105*61c4878aSAndroid Build Coastguard Worker t.Errorf("Error unexpected %v", err) 106*61c4878aSAndroid Build Coastguard Worker } 107*61c4878aSAndroid Build Coastguard Worker } else { 108*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv %v", resp) 109*61c4878aSAndroid Build Coastguard Worker if resp.Message != checksum { 110*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 111*61c4878aSAndroid Build Coastguard Worker } 112*61c4878aSAndroid Build Coastguard Worker } 113*61c4878aSAndroid Build Coastguard Worker close(done) 114*61c4878aSAndroid Build Coastguard Worker }() 115*61c4878aSAndroid Build Coastguard Worker <-done 116*61c4878aSAndroid Build Coastguard Worker }) 117*61c4878aSAndroid Build Coastguard Worker } 118*61c4878aSAndroid Build Coastguard Worker} 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard Workerfunc TestMultipleConnections(t *testing.T) { 121*61c4878aSAndroid Build Coastguard Worker const num_connections = 3 122*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 123*61c4878aSAndroid Build Coastguard Worker if err != nil { 124*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 125*61c4878aSAndroid Build Coastguard Worker } 126*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 127*61c4878aSAndroid Build Coastguard Worker 128*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 129*61c4878aSAndroid Build Coastguard Worker 130*61c4878aSAndroid Build Coastguard Worker for i := 0; i < num_connections; i++ { 131*61c4878aSAndroid Build Coastguard Worker t.Run(fmt.Sprintf("connection %d of %d", i+1, num_connections), func(t *testing.T) { 132*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 133*61c4878aSAndroid Build Coastguard Worker if err != nil { 134*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 135*61c4878aSAndroid Build Coastguard Worker } 136*61c4878aSAndroid Build Coastguard Worker 137*61c4878aSAndroid Build Coastguard Worker ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 138*61c4878aSAndroid Build Coastguard Worker defer cancel() 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard Worker resp, err := echo_client.UnaryEcho(ctx, &pb.EchoRequest{Message: "message0"}) 141*61c4878aSAndroid Build Coastguard Worker if err != nil { 142*61c4878aSAndroid Build Coastguard Worker t.Errorf("... failed with error: %v", err.Error()) 143*61c4878aSAndroid Build Coastguard Worker } else { 144*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv %v", resp) 145*61c4878aSAndroid Build Coastguard Worker if resp.Message != "message0" { 146*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 147*61c4878aSAndroid Build Coastguard Worker } 148*61c4878aSAndroid Build Coastguard Worker } 149*61c4878aSAndroid Build Coastguard Worker 150*61c4878aSAndroid Build Coastguard Worker conn.Close() 151*61c4878aSAndroid Build Coastguard Worker }) 152*61c4878aSAndroid Build Coastguard Worker } 153*61c4878aSAndroid Build Coastguard Worker} 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard Workerfunc TestServerStreamingEcho(t *testing.T) { 156*61c4878aSAndroid Build Coastguard Worker const num_connections = 1 157*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 158*61c4878aSAndroid Build Coastguard Worker if err != nil { 159*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 160*61c4878aSAndroid Build Coastguard Worker } 161*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 162*61c4878aSAndroid Build Coastguard Worker 163*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 164*61c4878aSAndroid Build Coastguard Worker if err != nil { 165*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 166*61c4878aSAndroid Build Coastguard Worker } 167*61c4878aSAndroid Build Coastguard Worker defer conn.Close() 168*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 169*61c4878aSAndroid Build Coastguard Worker 170*61c4878aSAndroid Build Coastguard Worker testRPC(t, func(t *testing.T, ctx context.Context, msg string) { 171*61c4878aSAndroid Build Coastguard Worker t.Logf("call ServerStreamingEcho(%v)", msg) 172*61c4878aSAndroid Build Coastguard Worker client, err := echo_client.ServerStreamingEcho(ctx, &pb.EchoRequest{Message: msg}) 173*61c4878aSAndroid Build Coastguard Worker if err != nil { 174*61c4878aSAndroid Build Coastguard Worker t.Errorf("... failed with error: %v", err) 175*61c4878aSAndroid Build Coastguard Worker return 176*61c4878aSAndroid Build Coastguard Worker } 177*61c4878aSAndroid Build Coastguard Worker for { 178*61c4878aSAndroid Build Coastguard Worker resp, err := client.Recv() 179*61c4878aSAndroid Build Coastguard Worker if err == io.EOF { 180*61c4878aSAndroid Build Coastguard Worker t.Logf("... completed") 181*61c4878aSAndroid Build Coastguard Worker return 182*61c4878aSAndroid Build Coastguard Worker } 183*61c4878aSAndroid Build Coastguard Worker if err != nil { 184*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv failed with error: %v", err) 185*61c4878aSAndroid Build Coastguard Worker if msg != "quiet" || status.Convert(err).Code() != codes.Canceled { 186*61c4878aSAndroid Build Coastguard Worker t.Errorf("Error unexpected %v", err) 187*61c4878aSAndroid Build Coastguard Worker } 188*61c4878aSAndroid Build Coastguard Worker return 189*61c4878aSAndroid Build Coastguard Worker } 190*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv %v", resp) 191*61c4878aSAndroid Build Coastguard Worker if resp.Message != msg && resp.Message != "done" { 192*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 193*61c4878aSAndroid Build Coastguard Worker } 194*61c4878aSAndroid Build Coastguard Worker } 195*61c4878aSAndroid Build Coastguard Worker }) 196*61c4878aSAndroid Build Coastguard Worker} 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard Workerfunc TestClientStreamingEcho(t *testing.T) { 199*61c4878aSAndroid Build Coastguard Worker const num_connections = 1 200*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 201*61c4878aSAndroid Build Coastguard Worker if err != nil { 202*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 203*61c4878aSAndroid Build Coastguard Worker } 204*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 205*61c4878aSAndroid Build Coastguard Worker 206*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 207*61c4878aSAndroid Build Coastguard Worker if err != nil { 208*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 209*61c4878aSAndroid Build Coastguard Worker } 210*61c4878aSAndroid Build Coastguard Worker defer conn.Close() 211*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 212*61c4878aSAndroid Build Coastguard Worker 213*61c4878aSAndroid Build Coastguard Worker testRPC(t, func(t *testing.T, ctx context.Context, msg string) { 214*61c4878aSAndroid Build Coastguard Worker t.Logf("call ClientStreamingEcho()") 215*61c4878aSAndroid Build Coastguard Worker client, err := echo_client.ClientStreamingEcho(ctx) 216*61c4878aSAndroid Build Coastguard Worker if err != nil { 217*61c4878aSAndroid Build Coastguard Worker t.Errorf("... failed with error: %v", err) 218*61c4878aSAndroid Build Coastguard Worker return 219*61c4878aSAndroid Build Coastguard Worker } 220*61c4878aSAndroid Build Coastguard Worker for i := 0; i < 3; i++ { 221*61c4878aSAndroid Build Coastguard Worker t.Logf("... Send %v", msg) 222*61c4878aSAndroid Build Coastguard Worker if err := client.Send(&pb.EchoRequest{Message: msg}); err != nil { 223*61c4878aSAndroid Build Coastguard Worker t.Errorf("... Send failed with error: %v", err) 224*61c4878aSAndroid Build Coastguard Worker return 225*61c4878aSAndroid Build Coastguard Worker } 226*61c4878aSAndroid Build Coastguard Worker } 227*61c4878aSAndroid Build Coastguard Worker if err := client.CloseSend(); err != nil { 228*61c4878aSAndroid Build Coastguard Worker t.Errorf("... CloseSend failed with error: %v", err) 229*61c4878aSAndroid Build Coastguard Worker return 230*61c4878aSAndroid Build Coastguard Worker } 231*61c4878aSAndroid Build Coastguard Worker resp, err := client.CloseAndRecv() 232*61c4878aSAndroid Build Coastguard Worker if err != nil { 233*61c4878aSAndroid Build Coastguard Worker t.Logf("... CloseAndRecv failed with error: %v", err) 234*61c4878aSAndroid Build Coastguard Worker if msg != "quiet" || status.Convert(err).Code() != codes.Canceled { 235*61c4878aSAndroid Build Coastguard Worker t.Errorf("Error unexpected %v", err) 236*61c4878aSAndroid Build Coastguard Worker } 237*61c4878aSAndroid Build Coastguard Worker } else { 238*61c4878aSAndroid Build Coastguard Worker t.Logf("... CloseAndRecv %v", resp) 239*61c4878aSAndroid Build Coastguard Worker if resp.Message != "done" { 240*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 241*61c4878aSAndroid Build Coastguard Worker } 242*61c4878aSAndroid Build Coastguard Worker } 243*61c4878aSAndroid Build Coastguard Worker }) 244*61c4878aSAndroid Build Coastguard Worker} 245*61c4878aSAndroid Build Coastguard Worker 246*61c4878aSAndroid Build Coastguard Workerfunc TestBidirectionalStreamingEcho(t *testing.T) { 247*61c4878aSAndroid Build Coastguard Worker const num_connections = 1 248*61c4878aSAndroid Build Coastguard Worker cmd, reader, err := launchServer(t, num_connections) 249*61c4878aSAndroid Build Coastguard Worker if err != nil { 250*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch %v", err) 251*61c4878aSAndroid Build Coastguard Worker } 252*61c4878aSAndroid Build Coastguard Worker defer cmd.Wait() 253*61c4878aSAndroid Build Coastguard Worker 254*61c4878aSAndroid Build Coastguard Worker conn, echo_client, err := connectServer() 255*61c4878aSAndroid Build Coastguard Worker if err != nil { 256*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to connect %v", err) 257*61c4878aSAndroid Build Coastguard Worker } 258*61c4878aSAndroid Build Coastguard Worker defer conn.Close() 259*61c4878aSAndroid Build Coastguard Worker go logServer(t, reader) 260*61c4878aSAndroid Build Coastguard Worker 261*61c4878aSAndroid Build Coastguard Worker testRPC(t, func(t *testing.T, ctx context.Context, msg string) { 262*61c4878aSAndroid Build Coastguard Worker t.Logf("call BidirectionalStreamingEcho()") 263*61c4878aSAndroid Build Coastguard Worker client, err := echo_client.BidirectionalStreamingEcho(ctx) 264*61c4878aSAndroid Build Coastguard Worker if err != nil { 265*61c4878aSAndroid Build Coastguard Worker t.Logf("... failed with error: %v", err) 266*61c4878aSAndroid Build Coastguard Worker return 267*61c4878aSAndroid Build Coastguard Worker } 268*61c4878aSAndroid Build Coastguard Worker for i := 0; i < 3; i++ { 269*61c4878aSAndroid Build Coastguard Worker t.Logf("... Send %v", msg) 270*61c4878aSAndroid Build Coastguard Worker if err := client.Send(&pb.EchoRequest{Message: msg}); err != nil { 271*61c4878aSAndroid Build Coastguard Worker t.Errorf("... Send failed with error: %v", err) 272*61c4878aSAndroid Build Coastguard Worker return 273*61c4878aSAndroid Build Coastguard Worker } 274*61c4878aSAndroid Build Coastguard Worker } 275*61c4878aSAndroid Build Coastguard Worker if err := client.CloseSend(); err != nil { 276*61c4878aSAndroid Build Coastguard Worker t.Logf("... CloseSend failed with error: %v", err) 277*61c4878aSAndroid Build Coastguard Worker return 278*61c4878aSAndroid Build Coastguard Worker } 279*61c4878aSAndroid Build Coastguard Worker for { 280*61c4878aSAndroid Build Coastguard Worker resp, err := client.Recv() 281*61c4878aSAndroid Build Coastguard Worker if err == io.EOF { 282*61c4878aSAndroid Build Coastguard Worker t.Logf("... completed") 283*61c4878aSAndroid Build Coastguard Worker return 284*61c4878aSAndroid Build Coastguard Worker } 285*61c4878aSAndroid Build Coastguard Worker if err != nil { 286*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv failed with error: %v", err) 287*61c4878aSAndroid Build Coastguard Worker if msg != "quiet" || status.Convert(err).Code() != codes.Canceled { 288*61c4878aSAndroid Build Coastguard Worker t.Errorf("Error unexpected %v", err) 289*61c4878aSAndroid Build Coastguard Worker } 290*61c4878aSAndroid Build Coastguard Worker return 291*61c4878aSAndroid Build Coastguard Worker } 292*61c4878aSAndroid Build Coastguard Worker t.Logf("... Recv %v", resp) 293*61c4878aSAndroid Build Coastguard Worker if resp.Message != msg { 294*61c4878aSAndroid Build Coastguard Worker t.Errorf("Unexpected response %v", resp) 295*61c4878aSAndroid Build Coastguard Worker } 296*61c4878aSAndroid Build Coastguard Worker } 297*61c4878aSAndroid Build Coastguard Worker }) 298*61c4878aSAndroid Build Coastguard Worker} 299*61c4878aSAndroid Build Coastguard Worker 300*61c4878aSAndroid Build Coastguard Workerfunc logServer(t *testing.T, reader *bufio.Reader) { 301*61c4878aSAndroid Build Coastguard Worker for { 302*61c4878aSAndroid Build Coastguard Worker line, err := reader.ReadString('\n') 303*61c4878aSAndroid Build Coastguard Worker if err != nil { 304*61c4878aSAndroid Build Coastguard Worker break 305*61c4878aSAndroid Build Coastguard Worker } 306*61c4878aSAndroid Build Coastguard Worker t.Logf("SERVER: %v", line) 307*61c4878aSAndroid Build Coastguard Worker } 308*61c4878aSAndroid Build Coastguard Worker} 309*61c4878aSAndroid Build Coastguard Worker 310*61c4878aSAndroid Build Coastguard Workerfunc launchServer(t *testing.T, num_connections int) (*exec.Cmd, *bufio.Reader, error) { 311*61c4878aSAndroid Build Coastguard Worker cmd := exec.Command("./test_pw_rpc_server", port, strconv.Itoa(num_connections)) 312*61c4878aSAndroid Build Coastguard Worker 313*61c4878aSAndroid Build Coastguard Worker output, err := cmd.StdoutPipe() 314*61c4878aSAndroid Build Coastguard Worker if err != nil { 315*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to get stdout of server %v", err) 316*61c4878aSAndroid Build Coastguard Worker return nil, nil, err 317*61c4878aSAndroid Build Coastguard Worker } 318*61c4878aSAndroid Build Coastguard Worker 319*61c4878aSAndroid Build Coastguard Worker if err := cmd.Start(); err != nil { 320*61c4878aSAndroid Build Coastguard Worker t.Errorf("Failed to launch server %v", err) 321*61c4878aSAndroid Build Coastguard Worker return nil, nil, err 322*61c4878aSAndroid Build Coastguard Worker } 323*61c4878aSAndroid Build Coastguard Worker 324*61c4878aSAndroid Build Coastguard Worker reader := bufio.NewReader(output) 325*61c4878aSAndroid Build Coastguard Worker for { 326*61c4878aSAndroid Build Coastguard Worker line, _ := reader.ReadString('\n') 327*61c4878aSAndroid Build Coastguard Worker if strings.Contains(line, "Accept") { 328*61c4878aSAndroid Build Coastguard Worker break 329*61c4878aSAndroid Build Coastguard Worker } 330*61c4878aSAndroid Build Coastguard Worker } 331*61c4878aSAndroid Build Coastguard Worker 332*61c4878aSAndroid Build Coastguard Worker return cmd, reader, nil 333*61c4878aSAndroid Build Coastguard Worker} 334*61c4878aSAndroid Build Coastguard Worker 335*61c4878aSAndroid Build Coastguard Workerfunc connectServer() (*grpc.ClientConn, pb.EchoClient, error) { 336*61c4878aSAndroid Build Coastguard Worker addr := "localhost:" + port 337*61c4878aSAndroid Build Coastguard Worker 338*61c4878aSAndroid Build Coastguard Worker conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) 339*61c4878aSAndroid Build Coastguard Worker if err != nil { 340*61c4878aSAndroid Build Coastguard Worker return nil, nil, err 341*61c4878aSAndroid Build Coastguard Worker } 342*61c4878aSAndroid Build Coastguard Worker 343*61c4878aSAndroid Build Coastguard Worker echo_client := pb.NewEchoClient(conn) 344*61c4878aSAndroid Build Coastguard Worker return conn, echo_client, nil 345*61c4878aSAndroid Build Coastguard Worker} 346*61c4878aSAndroid Build Coastguard Worker 347*61c4878aSAndroid Build Coastguard Workerfunc testRPC(t *testing.T, call func(t *testing.T, ctx context.Context, msg string)) { 348*61c4878aSAndroid Build Coastguard Worker const num_calls = 30 349*61c4878aSAndroid Build Coastguard Worker for i := 0; i < num_calls; i++ { 350*61c4878aSAndroid Build Coastguard Worker t.Run(fmt.Sprintf("%d of %d", i+1, num_calls), func(t *testing.T) { 351*61c4878aSAndroid Build Coastguard Worker ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 352*61c4878aSAndroid Build Coastguard Worker defer cancel() 353*61c4878aSAndroid Build Coastguard Worker 354*61c4878aSAndroid Build Coastguard Worker msg := fmt.Sprintf("message%d", i) 355*61c4878aSAndroid Build Coastguard Worker if i == num_calls-1 { 356*61c4878aSAndroid Build Coastguard Worker msg = "quiet" 357*61c4878aSAndroid Build Coastguard Worker } 358*61c4878aSAndroid Build Coastguard Worker 359*61c4878aSAndroid Build Coastguard Worker done := make(chan struct{}) 360*61c4878aSAndroid Build Coastguard Worker go func() { 361*61c4878aSAndroid Build Coastguard Worker call(t, ctx, msg) 362*61c4878aSAndroid Build Coastguard Worker close(done) 363*61c4878aSAndroid Build Coastguard Worker }() 364*61c4878aSAndroid Build Coastguard Worker // Test cancellation. When we sent "quiet", the server won't echo anything 365*61c4878aSAndroid Build Coastguard Worker // back and instead will hold onto the request. Sleep a bit to make sure 366*61c4878aSAndroid Build Coastguard Worker // the server doesn't respond. Then cancel the request, which should 367*61c4878aSAndroid Build Coastguard Worker // complete the RPC. 368*61c4878aSAndroid Build Coastguard Worker if msg == "quiet" { 369*61c4878aSAndroid Build Coastguard Worker time.Sleep(100 * time.Millisecond) 370*61c4878aSAndroid Build Coastguard Worker cancel() 371*61c4878aSAndroid Build Coastguard Worker } 372*61c4878aSAndroid Build Coastguard Worker <-done 373*61c4878aSAndroid Build Coastguard Worker }) 374*61c4878aSAndroid Build Coastguard Worker } 375*61c4878aSAndroid Build Coastguard Worker} 376