1<?php
2/*
3 *
4 * Copyright 2015-2016 gRPC authors.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19require_once realpath(dirname(__FILE__).'/../../vendor/autoload.php');
20
21// The following includes are needed when using protobuf 3.1.0
22// and will suppress warnings when using protobuf 3.2.0+
23@include_once 'src/proto/grpc/testing/test.pb.php';
24@include_once 'src/proto/grpc/testing/test_grpc_pb.php';
25
26use Google\Auth\CredentialsLoader;
27use Google\Auth\ApplicationDefaultCredentials;
28use GuzzleHttp\ClientInterface;
29
30/**
31 * Assertion function that always exits with an error code if the assertion is
32 * falsy.
33 *
34 * @param $value Assertion value. Should be true.
35 * @param $error_message Message to display if the assertion is false
36 */
37function hardAssert($value, $error_message)
38{
39    if (!$value) {
40        echo $error_message."\n";
41        exit(1);
42    }
43}
44
45function hardAssertIfStatusOk($status)
46{
47    if ($status->code !== Grpc\STATUS_OK) {
48        echo "Call did not complete successfully. Status object:\n";
49        var_dump($status);
50        exit(1);
51    }
52}
53
54/**
55 * Run the empty_unary test.
56 *
57 * @param $stub Stub object that has service methods
58 */
59function emptyUnary($stub)
60{
61    list($result, $status) =
62        $stub->EmptyCall(new Grpc\Testing\EmptyMessage())->wait();
63    hardAssertIfStatusOk($status);
64    hardAssert($result !== null, 'Call completed with a null response');
65}
66
67/**
68 * Run the large_unary test.
69 *
70 * @param $stub Stub object that has service methods
71 */
72function largeUnary($stub)
73{
74    performLargeUnary($stub);
75}
76
77/**
78 * Shared code between large unary test and auth test.
79 *
80 * @param $stub Stub object that has service methods
81 * @param $fillUsername boolean whether to fill result with username
82 * @param $fillOauthScope boolean whether to fill result with oauth scope
83 */
84function performLargeUnary($stub, $fillUsername = false,
85                           $fillOauthScope = false, $callback = false)
86{
87    $request_len = 271828;
88    $response_len = 314159;
89
90    $request = new Grpc\Testing\SimpleRequest();
91    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
92    $request->setResponseSize($response_len);
93    $payload = new Grpc\Testing\Payload();
94    $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE);
95    $payload->setBody(str_repeat("\0", $request_len));
96    $request->setPayload($payload);
97    $request->setFillUsername($fillUsername);
98    $request->setFillOauthScope($fillOauthScope);
99
100    $options = [];
101    if ($callback) {
102        $options['call_credentials_callback'] = $callback;
103    }
104
105    list($result, $status) = $stub->UnaryCall($request, [], $options)->wait();
106    hardAssertIfStatusOk($status);
107    hardAssert($result !== null, 'Call returned a null response');
108    $payload = $result->getPayload();
109    hardAssert($payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
110               'Payload had the wrong type');
111    hardAssert(strlen($payload->getBody()) === $response_len,
112               'Payload had the wrong length');
113    hardAssert($payload->getBody() === str_repeat("\0", $response_len),
114               'Payload had the wrong content');
115
116    return $result;
117}
118
119/**
120 * Run the client_compressed_unary test.
121 *
122 * @param $stub Stub object that has service methods
123 */
124function clientCompressedUnary($stub)
125{
126    $request_len = 271828;
127    $response_len = 314159;
128    $falseBoolValue = new Grpc\Testing\BoolValue(['value' => false]);
129    $trueBoolValue = new Grpc\Testing\BoolValue(['value' => true]);
130    // 1. Probing for compression-checks support
131    $payload = new Grpc\Testing\Payload([
132        'body' => str_repeat("\0", $request_len),
133    ]);
134    $request = new Grpc\Testing\SimpleRequest([
135        'payload' => $payload,
136        'response_size' => $response_len,
137        'expect_compressed' => $trueBoolValue, // lie
138    ]);
139    list($result, $status) = $stub->UnaryCall($request, [], [])->wait();
140    hardAssert(
141        $status->code === GRPC\STATUS_INVALID_ARGUMENT,
142        'Received unexpected UnaryCall status code: ' .
143            $status->code
144    );
145    // 2. with/without compressed message
146    foreach ([true, false] as $compression) {
147        $request->setExpectCompressed($compression ? $trueBoolValue : $falseBoolValue);
148        $metadata = $compression ? [
149            'grpc-internal-encoding-request' => ['gzip'],
150        ] : [];
151        list($result, $status) = $stub->UnaryCall($request, $metadata, [])->wait();
152        hardAssertIfStatusOk($status);
153        hardAssert($result !== null, 'Call returned a null response');
154        $payload = $result->getPayload();
155        hardAssert(
156            strlen($payload->getBody()) === $response_len,
157            'Payload had the wrong length'
158        );
159        hardAssert(
160            $payload->getBody() === str_repeat("\0", $response_len),
161            'Payload had the wrong content'
162        );
163    }
164}
165
166/**
167 * Run the service account credentials auth test.
168 *
169 * @param $stub Stub object that has service methods
170 * @param $args array command line args
171 */
172function serviceAccountCreds($stub, $args)
173{
174    if (!array_key_exists('oauth_scope', $args)) {
175        throw new Exception('Missing oauth scope');
176    }
177    $jsonKey = json_decode(
178        file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
179        true);
180    $result = performLargeUnary($stub, $fillUsername = true,
181                                $fillOauthScope = true);
182    hardAssert($result->getUsername() === $jsonKey['client_email'],
183               'invalid email returned');
184    hardAssert(strpos($args['oauth_scope'], $result->getOauthScope()) !== false,
185               'invalid oauth scope returned');
186}
187
188/**
189 * Run the compute engine credentials auth test.
190 * Has not been run from gcloud as of 2015-05-05.
191 *
192 * @param $stub Stub object that has service methods
193 * @param $args array command line args
194 */
195function computeEngineCreds($stub, $args)
196{
197    if (!array_key_exists('oauth_scope', $args)) {
198        throw new Exception('Missing oauth scope');
199    }
200    if (!array_key_exists('default_service_account', $args)) {
201        throw new Exception('Missing default_service_account');
202    }
203    $result = performLargeUnary($stub, $fillUsername = true,
204                                $fillOauthScope = true);
205    hardAssert($args['default_service_account'] === $result->getUsername(),
206               'invalid email returned');
207}
208
209/**
210 * Run the jwt token credentials auth test.
211 *
212 * @param $stub Stub object that has service methods
213 * @param $args array command line args
214 */
215function jwtTokenCreds($stub, $args)
216{
217    $jsonKey = json_decode(
218        file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
219        true);
220    $result = performLargeUnary($stub, $fillUsername = true,
221                                $fillOauthScope = true);
222    hardAssert($result->getUsername() === $jsonKey['client_email'],
223               'invalid email returned');
224}
225
226/**
227 * Run the oauth2_auth_token auth test.
228 *
229 * @param $stub Stub object that has service methods
230 * @param $args array command line args
231 */
232function oauth2AuthToken($stub, $args)
233{
234    $jsonKey = json_decode(
235        file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
236        true);
237    $result = performLargeUnary($stub, $fillUsername = true,
238                                $fillOauthScope = true);
239    hardAssert($result->getUsername() === $jsonKey['client_email'],
240               'invalid email returned');
241}
242
243function updateAuthMetadataCallback($context)
244{
245    $authUri = $context->service_url;
246    $methodName = $context->method_name;
247    $auth_credentials = ApplicationDefaultCredentials::getCredentials();
248
249    $metadata = [];
250    $result = $auth_credentials->updateMetadata([], $authUri);
251    foreach ($result as $key => $value) {
252        $metadata[strtolower($key)] = $value;
253    }
254
255    return $metadata;
256}
257
258/**
259 * Run the per_rpc_creds auth test.
260 *
261 * @param $stub Stub object that has service methods
262 * @param $args array command line args
263 */
264function perRpcCreds($stub, $args)
265{
266    $jsonKey = json_decode(
267        file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
268        true);
269
270    $result = performLargeUnary($stub, $fillUsername = true,
271                                $fillOauthScope = true,
272                                'updateAuthMetadataCallback');
273    hardAssert($result->getUsername() === $jsonKey['client_email'],
274               'invalid email returned');
275}
276
277/**
278 * Run the client_streaming test.
279 *
280 * @param $stub Stub object that has service methods
281 */
282function clientStreaming($stub)
283{
284    $request_lengths = [27182, 8, 1828, 45904];
285
286    $requests = array_map(
287        function ($length) {
288            $request = new Grpc\Testing\StreamingInputCallRequest();
289            $payload = new Grpc\Testing\Payload();
290            $payload->setBody(str_repeat("\0", $length));
291            $request->setPayload($payload);
292
293            return $request;
294        }, $request_lengths);
295
296    $call = $stub->StreamingInputCall();
297    foreach ($requests as $request) {
298        $call->write($request);
299    }
300    list($result, $status) = $call->wait();
301    hardAssertIfStatusOk($status);
302    hardAssert($result->getAggregatedPayloadSize() === 74922,
303               'aggregated_payload_size was incorrect');
304}
305
306/**
307 * Run the client_compressed_streaming test.
308 *
309 * @param $stub Stub object that has service methods
310 */
311function clientCompressedStreaming($stub)
312{
313    $request_len = 27182;
314    $request2_len = 45904;
315    $response_len = 73086;
316    $falseBoolValue = new Grpc\Testing\BoolValue(['value' => false]);
317    $trueBoolValue = new Grpc\Testing\BoolValue(['value' => true]);
318
319    // 1. Probing for compression-checks support
320
321    $payload = new Grpc\Testing\Payload([
322        'body' => str_repeat("\0", $request_len),
323    ]);
324    $request = new Grpc\Testing\StreamingInputCallRequest([
325        'payload' => $payload,
326        'expect_compressed' => $trueBoolValue, // lie
327    ]);
328
329    $call = $stub->StreamingInputCall();
330    $call->write($request);
331    list($result, $status) = $call->wait();
332    hardAssert(
333        $status->code === GRPC\STATUS_INVALID_ARGUMENT,
334        'Received unexpected StreamingInputCall status code: ' .
335            $status->code
336    );
337
338    // 2. write compressed message
339
340    $call = $stub->StreamingInputCall([
341        'grpc-internal-encoding-request' => ['gzip'],
342    ]);
343    $request->setExpectCompressed($trueBoolValue);
344    $call->write($request);
345
346    // 3. write uncompressed message
347
348    $payload2 = new Grpc\Testing\Payload([
349        'body' => str_repeat("\0", $request2_len),
350    ]);
351    $request->setPayload($payload2);
352    $request->setExpectCompressed($falseBoolValue);
353    $call->write($request, [
354        'flags' => 0x02 // GRPC_WRITE_NO_COMPRESS
355    ]);
356
357    // 4. verify response
358
359    list($result, $status) = $call->wait();
360
361    hardAssertIfStatusOk($status);
362    hardAssert(
363        $result->getAggregatedPayloadSize() === $response_len,
364        'aggregated_payload_size was incorrect'
365    );
366}
367
368/**
369 * Run the server_streaming test.
370 *
371 * @param $stub Stub object that has service methods.
372 */
373function serverStreaming($stub)
374{
375    $sizes = [31415, 9, 2653, 58979];
376
377    $request = new Grpc\Testing\StreamingOutputCallRequest();
378    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
379    foreach ($sizes as $size) {
380        $response_parameters = new Grpc\Testing\ResponseParameters();
381        $response_parameters->setSize($size);
382        $request->getResponseParameters()[] = $response_parameters;
383    }
384
385    $call = $stub->StreamingOutputCall($request);
386    $i = 0;
387    foreach ($call->responses() as $value) {
388        hardAssert($i < 4, 'Too many responses');
389        $payload = $value->getPayload();
390        hardAssert(
391            $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
392            'Payload '.$i.' had the wrong type');
393        hardAssert(strlen($payload->getBody()) === $sizes[$i],
394                   'Response '.$i.' had the wrong length');
395        $i += 1;
396    }
397    hardAssertIfStatusOk($call->getStatus());
398}
399
400/**
401 * Run the ping_pong test.
402 *
403 * @param $stub Stub object that has service methods.
404 */
405function pingPong($stub)
406{
407    $request_lengths = [27182, 8, 1828, 45904];
408    $response_lengths = [31415, 9, 2653, 58979];
409
410    $call = $stub->FullDuplexCall();
411    for ($i = 0; $i < 4; ++$i) {
412        $request = new Grpc\Testing\StreamingOutputCallRequest();
413        $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
414        $response_parameters = new Grpc\Testing\ResponseParameters();
415        $response_parameters->setSize($response_lengths[$i]);
416        $request->getResponseParameters()[] = $response_parameters;
417        $payload = new Grpc\Testing\Payload();
418        $payload->setBody(str_repeat("\0", $request_lengths[$i]));
419        $request->setPayload($payload);
420
421        $call->write($request);
422        $response = $call->read();
423
424        hardAssert($response !== null, 'Server returned too few responses');
425        $payload = $response->getPayload();
426        hardAssert(
427            $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
428            'Payload '.$i.' had the wrong type');
429        hardAssert(strlen($payload->getBody()) === $response_lengths[$i],
430                   'Payload '.$i.' had the wrong length');
431    }
432    $call->writesDone();
433    hardAssert($call->read() === null, 'Server returned too many responses');
434    hardAssertIfStatusOk($call->getStatus());
435}
436
437/**
438 * Run the empty_stream test.
439 *
440 * @param $stub Stub object that has service methods.
441 */
442function emptyStream($stub)
443{
444    $call = $stub->FullDuplexCall();
445    $call->writesDone();
446    hardAssert($call->read() === null, 'Server returned too many responses');
447    hardAssertIfStatusOk($call->getStatus());
448}
449
450/**
451 * Run the cancel_after_begin test.
452 *
453 * @param $stub Stub object that has service methods.
454 */
455function cancelAfterBegin($stub)
456{
457    $call = $stub->StreamingInputCall();
458    $call->cancel();
459    list($result, $status) = $call->wait();
460    hardAssert($status->code === Grpc\STATUS_CANCELLED,
461               'Call status was not CANCELLED');
462}
463
464/**
465 * Run the cancel_after_first_response test.
466 *
467 * @param $stub Stub object that has service methods.
468 */
469function cancelAfterFirstResponse($stub)
470{
471    $call = $stub->FullDuplexCall();
472    $request = new Grpc\Testing\StreamingOutputCallRequest();
473    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
474    $response_parameters = new Grpc\Testing\ResponseParameters();
475    $response_parameters->setSize(31415);
476    $request->getResponseParameters()[] = $response_parameters;
477    $payload = new Grpc\Testing\Payload();
478    $payload->setBody(str_repeat("\0", 27182));
479    $request->setPayload($payload);
480
481    $call->write($request);
482    $response = $call->read();
483
484    $call->cancel();
485    hardAssert($call->getStatus()->code === Grpc\STATUS_CANCELLED,
486               'Call status was not CANCELLED');
487}
488
489function timeoutOnSleepingServer($stub)
490{
491    $call = $stub->FullDuplexCall([], ['timeout' => 1000]);
492    $request = new Grpc\Testing\StreamingOutputCallRequest();
493    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
494    $response_parameters = new Grpc\Testing\ResponseParameters();
495    $response_parameters->setSize(8);
496    $request->getResponseParameters()[] = $response_parameters;
497    $payload = new Grpc\Testing\Payload();
498    $payload->setBody(str_repeat("\0", 9));
499    $request->setPayload($payload);
500
501    $call->write($request);
502    $response = $call->read();
503
504    hardAssert($call->getStatus()->code === Grpc\STATUS_DEADLINE_EXCEEDED,
505               'Call status was not DEADLINE_EXCEEDED');
506}
507
508function customMetadata($stub)
509{
510    $ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
511    $ECHO_INITIAL_VALUE = 'test_initial_metadata_value';
512    $ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
513    $ECHO_TRAILING_VALUE = 'ababab';
514    $request_len = 271828;
515    $response_len = 314159;
516
517    $request = new Grpc\Testing\SimpleRequest();
518    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
519    $request->setResponseSize($response_len);
520    $payload = new Grpc\Testing\Payload();
521    $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE);
522    $payload->setBody(str_repeat("\0", $request_len));
523    $request->setPayload($payload);
524
525    $metadata = [
526        $ECHO_INITIAL_KEY => [$ECHO_INITIAL_VALUE],
527        $ECHO_TRAILING_KEY => [$ECHO_TRAILING_VALUE],
528    ];
529    $call = $stub->UnaryCall($request, $metadata);
530
531    $initial_metadata = $call->getMetadata();
532    hardAssert(array_key_exists($ECHO_INITIAL_KEY, $initial_metadata),
533               'Initial metadata does not contain expected key');
534    hardAssert(
535        $initial_metadata[$ECHO_INITIAL_KEY][0] === $ECHO_INITIAL_VALUE,
536        'Incorrect initial metadata value');
537
538    list($result, $status) = $call->wait();
539    hardAssertIfStatusOk($status);
540
541    $trailing_metadata = $call->getTrailingMetadata();
542    hardAssert(array_key_exists($ECHO_TRAILING_KEY, $trailing_metadata),
543               'Trailing metadata does not contain expected key');
544    hardAssert(
545        $trailing_metadata[$ECHO_TRAILING_KEY][0] === $ECHO_TRAILING_VALUE,
546        'Incorrect trailing metadata value');
547
548    $streaming_call = $stub->FullDuplexCall($metadata);
549
550    $streaming_request = new Grpc\Testing\StreamingOutputCallRequest();
551    $streaming_request->setPayload($payload);
552    $response_parameters = new Grpc\Testing\ResponseParameters();
553    $response_parameters->setSize($response_len);
554    $streaming_request->getResponseParameters()[] = $response_parameters;
555    $streaming_call->write($streaming_request);
556    $streaming_call->writesDone();
557    $result = $streaming_call->read();
558
559    hardAssertIfStatusOk($streaming_call->getStatus());
560
561    $streaming_initial_metadata = $streaming_call->getMetadata();
562    hardAssert(array_key_exists($ECHO_INITIAL_KEY, $streaming_initial_metadata),
563               'Initial metadata does not contain expected key');
564    hardAssert(
565        $streaming_initial_metadata[$ECHO_INITIAL_KEY][0] === $ECHO_INITIAL_VALUE,
566        'Incorrect initial metadata value');
567
568    $streaming_trailing_metadata = $streaming_call->getTrailingMetadata();
569    hardAssert(array_key_exists($ECHO_TRAILING_KEY,
570                                $streaming_trailing_metadata),
571               'Trailing metadata does not contain expected key');
572    hardAssert($streaming_trailing_metadata[$ECHO_TRAILING_KEY][0] ===
573               $ECHO_TRAILING_VALUE, 'Incorrect trailing metadata value');
574}
575
576function statusCodeAndMessage($stub)
577{
578    $echo_status = new Grpc\Testing\EchoStatus();
579    $echo_status->setCode(2);
580    $echo_status->setMessage('test status message');
581
582    $request = new Grpc\Testing\SimpleRequest();
583    $request->setResponseStatus($echo_status);
584
585    $call = $stub->UnaryCall($request);
586    list($result, $status) = $call->wait();
587
588    hardAssert($status->code === 2,
589               'Received unexpected UnaryCall status code: '.
590               $status->code);
591    hardAssert($status->details === 'test status message',
592               'Received unexpected UnaryCall status details: '.
593               $status->details);
594
595    $streaming_call = $stub->FullDuplexCall();
596
597    $streaming_request = new Grpc\Testing\StreamingOutputCallRequest();
598    $streaming_request->setResponseStatus($echo_status);
599    $streaming_call->write($streaming_request);
600    $streaming_call->writesDone();
601    $result = $streaming_call->read();
602
603    $status = $streaming_call->getStatus();
604    hardAssert($status->code === 2,
605               'Received unexpected FullDuplexCall status code: '.
606               $status->code);
607    hardAssert($status->details === 'test status message',
608               'Received unexpected FullDuplexCall status details: '.
609               $status->details);
610}
611
612# NOTE: the stub input to this function is from UnimplementedService
613function unimplementedService($stub)
614{
615    $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage());
616    list($result, $status) = $call->wait();
617    hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED,
618               'Received unexpected status code');
619}
620
621# NOTE: the stub input to this function is from TestService
622function unimplementedMethod($stub)
623{
624    $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage());
625    list($result, $status) = $call->wait();
626    hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED,
627               'Received unexpected status code');
628}
629
630function _makeStub($args)
631{
632    if (!array_key_exists('server_host', $args)) {
633        throw new Exception('Missing argument: --server_host is required');
634    }
635    if (!array_key_exists('server_port', $args)) {
636        throw new Exception('Missing argument: --server_port is required');
637    }
638    if (!array_key_exists('test_case', $args)) {
639        throw new Exception('Missing argument: --test_case is required');
640    }
641
642    $server_address = $args['server_host'].':'.$args['server_port'];
643    $test_case = $args['test_case'];
644
645    $host_override = '';
646    if (array_key_exists('server_host_override', $args)) {
647        $host_override = $args['server_host_override'];
648    }
649
650    $use_tls = false;
651    if (array_key_exists('use_tls', $args) &&
652        $args['use_tls'] != 'false') {
653        $use_tls = true;
654    }
655
656    $use_test_ca = false;
657    if (array_key_exists('use_test_ca', $args) &&
658        $args['use_test_ca'] != 'false') {
659        $use_test_ca = true;
660    }
661
662    $opts = [];
663
664    if ($use_tls) {
665        if ($use_test_ca) {
666            $ssl_credentials = Grpc\ChannelCredentials::createSsl(
667                file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
668        } else {
669            $ssl_credentials = Grpc\ChannelCredentials::createSsl();
670        }
671        $opts['credentials'] = $ssl_credentials;
672        if (!empty($host_override)) {
673            $opts['grpc.ssl_target_name_override'] = $host_override;
674        }
675    } else {
676        $opts['credentials'] = Grpc\ChannelCredentials::createInsecure();
677    }
678
679    if (in_array($test_case, ['service_account_creds',
680                              'compute_engine_creds', 'jwt_token_creds', ])) {
681        if ($test_case === 'jwt_token_creds') {
682            $auth_credentials = ApplicationDefaultCredentials::getCredentials();
683        } else {
684            $auth_credentials = ApplicationDefaultCredentials::getCredentials(
685                $args['oauth_scope']
686            );
687        }
688        $opts['update_metadata'] = $auth_credentials->getUpdateMetadataFunc();
689    }
690
691    if ($test_case === 'oauth2_auth_token') {
692        $auth_credentials = ApplicationDefaultCredentials::getCredentials(
693            $args['oauth_scope']
694        );
695        $token = $auth_credentials->fetchAuthToken();
696        $update_metadata =
697            function ($metadata,
698                      $authUri = null,
699                      ClientInterface $client = null) use ($token) {
700                $metadata_copy = $metadata;
701                $metadata_copy[CredentialsLoader::AUTH_METADATA_KEY] =
702                    [sprintf('%s %s',
703                             $token['token_type'],
704                             $token['access_token'])];
705
706                return $metadata_copy;
707            };
708        $opts['update_metadata'] = $update_metadata;
709    }
710
711    if ($test_case === 'unimplemented_service') {
712        $stub = new Grpc\Testing\UnimplementedServiceClient($server_address,
713                                                            $opts);
714    } else {
715        $stub = new Grpc\Testing\TestServiceClient($server_address, $opts);
716    }
717
718    return $stub;
719}
720
721function interop_main($args, $stub = false)
722{
723    if (!$stub) {
724        $stub = _makeStub($args);
725    }
726
727    $test_case = $args['test_case'];
728    echo "Running test case $test_case\n";
729
730    switch ($test_case) {
731        case 'empty_unary':
732            emptyUnary($stub);
733            break;
734        case 'large_unary':
735            largeUnary($stub);
736            break;
737        case 'client_streaming':
738            clientStreaming($stub);
739            break;
740        case 'server_streaming':
741            serverStreaming($stub);
742            break;
743        case 'ping_pong':
744            pingPong($stub);
745            break;
746        case 'empty_stream':
747            emptyStream($stub);
748            break;
749        case 'cancel_after_begin':
750            cancelAfterBegin($stub);
751            break;
752        case 'cancel_after_first_response':
753            cancelAfterFirstResponse($stub);
754            break;
755        case 'timeout_on_sleeping_server':
756            timeoutOnSleepingServer($stub);
757            break;
758        case 'custom_metadata':
759            customMetadata($stub);
760            break;
761        case 'status_code_and_message':
762            statusCodeAndMessage($stub);
763            break;
764        case 'unimplemented_service':
765            unimplementedService($stub);
766            break;
767        case 'unimplemented_method':
768            unimplementedMethod($stub);
769            break;
770        case 'service_account_creds':
771            serviceAccountCreds($stub, $args);
772            break;
773        case 'compute_engine_creds':
774            computeEngineCreds($stub, $args);
775            break;
776        case 'jwt_token_creds':
777            jwtTokenCreds($stub, $args);
778            break;
779        case 'oauth2_auth_token':
780            oauth2AuthToken($stub, $args);
781            break;
782        case 'per_rpc_creds':
783            perRpcCreds($stub, $args);
784            break;
785        case 'client_compressed_unary':
786            clientCompressedUnary($stub);
787            break;
788        case 'client_compressed_streaming':
789            clientCompressedStreaming($stub);
790            break;
791        default:
792            echo "Unsupported test case $test_case\n";
793            exit(1);
794    }
795
796    return $stub;
797}
798
799if (isset($_SERVER['PHP_SELF']) &&
800    preg_match('/interop_client/', $_SERVER['PHP_SELF'])) {
801    $args = getopt('', ['server_host:', 'server_port:', 'test_case:',
802                        'use_tls::', 'use_test_ca::',
803                        'server_host_override:', 'oauth_scope:',
804                        'default_service_account:', ]);
805    interop_main($args);
806}
807