1<?php
2/*
3 *
4 * Copyright 2015 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 */
19
20class CallCredentials2Test extends PHPUnit_Framework_TestCase
21{
22    public function setUp()
23    {
24        $credentials = Grpc\ChannelCredentials::createSsl(
25            file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
26        $server_credentials = Grpc\ServerCredentials::createSsl(
27            null,
28            file_get_contents(dirname(__FILE__).'/../data/server1.key'),
29            file_get_contents(dirname(__FILE__).'/../data/server1.pem'));
30        $this->server = new Grpc\Server();
31        $this->port = $this->server->addSecureHttp2Port('0.0.0.0:0',
32                                              $server_credentials);
33        $this->server->start();
34        $this->host_override = 'foo.test.google.fr';
35        $this->channel = new Grpc\Channel(
36            'localhost:'.$this->port,
37            [
38            'force_new' => true,
39            'grpc.ssl_target_name_override' => $this->host_override,
40            'grpc.default_authority' => $this->host_override,
41            'credentials' => $credentials,
42            ]
43        );
44    }
45
46    public function tearDown()
47    {
48        unset($this->channel);
49        unset($this->server);
50    }
51
52    public function callbackFunc($context)
53    {
54        $this->assertTrue(is_string($context->service_url));
55        $this->assertTrue(is_string($context->method_name));
56
57        return ['k1' => ['v1'], 'k2' => ['v2']];
58    }
59
60    public function testCreateFromPlugin()
61    {
62        $deadline = Grpc\Timeval::infFuture();
63        $status_text = 'xyz';
64        $call = new Grpc\Call($this->channel,
65                              '/abc/dummy_method',
66                              $deadline,
67                              $this->host_override);
68
69        $call_credentials = Grpc\CallCredentials::createFromPlugin(
70            array($this, 'callbackFunc'));
71        $call->setCredentials($call_credentials);
72
73        $event = $call->startBatch([
74            Grpc\OP_SEND_INITIAL_METADATA => [],
75            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
76        ]);
77
78        $this->assertTrue($event->send_metadata);
79        $this->assertTrue($event->send_close);
80
81        $event = $this->server->requestCall();
82
83        $this->assertTrue(is_array($event->metadata));
84        $metadata = $event->metadata;
85        $this->assertTrue(array_key_exists('k1', $metadata));
86        $this->assertTrue(array_key_exists('k2', $metadata));
87        $this->assertSame($metadata['k1'], ['v1']);
88        $this->assertSame($metadata['k2'], ['v2']);
89
90        $this->assertSame('/abc/dummy_method', $event->method);
91        $server_call = $event->call;
92
93        $event = $server_call->startBatch([
94            Grpc\OP_SEND_INITIAL_METADATA => [],
95            Grpc\OP_SEND_STATUS_FROM_SERVER => [
96                'metadata' => [],
97                'code' => Grpc\STATUS_OK,
98                'details' => $status_text,
99            ],
100            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
101        ]);
102
103        $this->assertTrue($event->send_metadata);
104        $this->assertTrue($event->send_status);
105        $this->assertFalse($event->cancelled);
106
107        $event = $call->startBatch([
108            Grpc\OP_RECV_INITIAL_METADATA => true,
109            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
110        ]);
111
112        $this->assertSame([], $event->metadata);
113        $status = $event->status;
114        $this->assertSame([], $status->metadata);
115        $this->assertSame(Grpc\STATUS_OK, $status->code);
116        $this->assertSame($status_text, $status->details);
117
118        unset($call);
119        unset($server_call);
120    }
121
122    public function invalidKeyCallbackFunc($context)
123    {
124        $this->assertTrue(is_string($context->service_url));
125        $this->assertTrue(is_string($context->method_name));
126
127        return ['K1' => ['v1']];
128    }
129
130    public function testCallbackWithInvalidKey()
131    {
132        $deadline = Grpc\Timeval::infFuture();
133        $status_text = 'xyz';
134        $call = new Grpc\Call($this->channel,
135                              '/abc/dummy_method',
136                              $deadline,
137                              $this->host_override);
138
139        $call_credentials = Grpc\CallCredentials::createFromPlugin(
140            array($this, 'invalidKeyCallbackFunc'));
141        $call->setCredentials($call_credentials);
142
143        $event = $call->startBatch([
144            Grpc\OP_SEND_INITIAL_METADATA => [],
145            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
146            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
147        ]);
148
149        $this->assertTrue($event->send_metadata);
150        $this->assertTrue($event->send_close);
151        $this->assertTrue($event->status->code == Grpc\STATUS_UNAVAILABLE);
152    }
153
154    public function invalidReturnCallbackFunc($context)
155    {
156        $this->assertTrue(is_string($context->service_url));
157        $this->assertTrue(is_string($context->method_name));
158
159        return 'a string';
160    }
161
162    public function testCallbackWithInvalidReturnValue()
163    {
164        $deadline = Grpc\Timeval::infFuture();
165        $status_text = 'xyz';
166        $call = new Grpc\Call($this->channel,
167                              '/abc/dummy_method',
168                              $deadline,
169                              $this->host_override);
170
171        $call_credentials = Grpc\CallCredentials::createFromPlugin(
172            array($this, 'invalidReturnCallbackFunc'));
173        $call->setCredentials($call_credentials);
174
175        $event = $call->startBatch([
176            Grpc\OP_SEND_INITIAL_METADATA => [],
177            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
178            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
179        ]);
180
181        $this->assertTrue($event->send_metadata);
182        $this->assertTrue($event->send_close);
183        $this->assertTrue($event->status->code == Grpc\STATUS_UNAVAILABLE);
184    }
185}
186