blob: fc765ed7314ff8b1239a56ca49d9e3c8ab19148a [file] [log] [blame]
murgatroid99cca5ffa2015-01-15 14:06:56 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
murgatroid99cca5ffa2015-01-15 14:06:56 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
murgatroid99dca966d2015-02-19 14:37:18 -080034'use strict';
murgatroid99cca5ffa2015-01-15 14:06:56 -080035
murgatroid99dca966d2015-02-19 14:37:18 -080036var assert = require('assert');
murgatroid99cca5ffa2015-01-15 14:06:56 -080037
murgatroid9910ac96c2015-02-12 13:28:25 -080038var surface_client = require('../src/client.js');
murgatroid9955dd2ba2015-01-26 14:11:18 -080039
murgatroid99cca5ffa2015-01-15 14:06:56 -080040var ProtoBuf = require('protobufjs');
41
42var grpc = require('..');
43
Jan Tattermusch8ef43bd2015-12-07 09:55:22 -080044var math_proto = ProtoBuf.loadProtoFile(__dirname +
45 '/../../proto/math/math.proto');
murgatroid99cca5ffa2015-01-15 14:06:56 -080046
47var mathService = math_proto.lookup('math.Math');
48
murgatroid9955739d52015-06-03 10:58:21 -070049var _ = require('lodash');
murgatroid99778c61b2015-05-18 16:52:47 -070050
murgatroid99c7f4d4f2015-07-28 15:18:57 -070051/**
52 * This is used for testing functions with multiple asynchronous calls that
53 * can happen in different orders. This should be passed the number of async
54 * function invocations that can occur last, and each of those should call this
55 * function's return value
56 * @param {function()} done The function that should be called when a test is
57 * complete.
58 * @param {number} count The number of calls to the resulting function if the
59 * test passes.
60 * @return {function()} The function that should be called at the end of each
61 * sequence of asynchronous functions.
62 */
63function multiDone(done, count) {
64 return function() {
65 count -= 1;
66 if (count <= 0) {
67 done();
68 }
69 };
70}
murgatroid9999e21042015-08-14 10:35:43 -070071
murgatroid991a7dcac2015-07-27 16:13:28 -070072var server_insecure_creds = grpc.ServerCredentials.createInsecure();
73
murgatroid9971dbb862015-04-20 11:22:51 -070074describe('File loader', function() {
75 it('Should load a proto file by default', function() {
76 assert.doesNotThrow(function() {
77 grpc.load(__dirname + '/test_service.proto');
78 });
79 });
80 it('Should load a proto file with the proto format', function() {
81 assert.doesNotThrow(function() {
82 grpc.load(__dirname + '/test_service.proto', 'proto');
83 });
84 });
85 it('Should load a json file with the json format', function() {
86 assert.doesNotThrow(function() {
87 grpc.load(__dirname + '/test_service.json', 'json');
88 });
89 });
90 it('Should fail to load a file with an unknown format', function() {
91 assert.throws(function() {
92 grpc.load(__dirname + '/test_service.proto', 'fake_format');
93 });
94 });
95});
murgatroid997cfee082015-10-13 13:49:55 -070096describe('surface Server', function() {
97 var server;
98 beforeEach(function() {
99 server = new grpc.Server();
100 });
101 afterEach(function() {
102 server.forceShutdown();
103 });
104 it('should error if started twice', function() {
105 server.start();
106 assert.throws(function() {
107 server.start();
108 });
109 });
110 it('should error if a port is bound after the server starts', function() {
111 server.start();
112 assert.throws(function() {
113 server.bind('localhost:0', grpc.ServerCredentials.createInsecure());
114 });
115 });
116 it('should successfully shutdown if tryShutdown is called', function(done) {
117 server.start();
118 server.tryShutdown(done);
119 });
120});
murgatroid99366e64d2015-07-15 17:01:49 -0700121describe('Server.prototype.addProtoService', function() {
122 var server;
123 var dummyImpls = {
124 'div': function() {},
125 'divMany': function() {},
126 'fib': function() {},
127 'sum': function() {}
128 };
129 beforeEach(function() {
130 server = new grpc.Server();
131 });
132 afterEach(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700133 server.forceShutdown();
murgatroid99cca5ffa2015-01-15 14:06:56 -0800134 });
135 it('Should succeed with a single service', function() {
136 assert.doesNotThrow(function() {
murgatroid99366e64d2015-07-15 17:01:49 -0700137 server.addProtoService(mathService, dummyImpls);
138 });
139 });
140 it('Should fail with conflicting method names', function() {
141 server.addProtoService(mathService, dummyImpls);
142 assert.throws(function() {
143 server.addProtoService(mathService, dummyImpls);
murgatroid99cca5ffa2015-01-15 14:06:56 -0800144 });
145 });
146 it('Should fail with missing handlers', function() {
murgatroid99cca5ffa2015-01-15 14:06:56 -0800147 assert.throws(function() {
murgatroid99366e64d2015-07-15 17:01:49 -0700148 server.addProtoService(mathService, {
149 'div': function() {},
150 'divMany': function() {},
151 'fib': function() {}
murgatroid99cca5ffa2015-01-15 14:06:56 -0800152 });
153 }, /math.Math.Sum/);
154 });
murgatroid99366e64d2015-07-15 17:01:49 -0700155 it('Should fail if the server has been started', function() {
156 server.start();
murgatroid99cca5ffa2015-01-15 14:06:56 -0800157 assert.throws(function() {
murgatroid99366e64d2015-07-15 17:01:49 -0700158 server.addProtoService(mathService, dummyImpls);
159 });
murgatroid99cca5ffa2015-01-15 14:06:56 -0800160 });
161});
murgatroid99e77da442015-07-29 10:09:36 -0700162describe('Client constructor building', function() {
163 var illegal_service_attrs = {
164 $method : {
165 path: '/illegal/$method',
166 requestStream: false,
167 responseStream: false,
168 requestSerialize: _.identity,
169 requestDeserialize: _.identity,
170 responseSerialize: _.identity,
171 responseDeserialize: _.identity
172 }
173 };
174 it('Should reject method names starting with $', function() {
175 assert.throws(function() {
176 grpc.makeGenericClientConstructor(illegal_service_attrs);
177 }, /\$/);
178 });
179});
murgatroid9976ba1ff2015-08-28 14:57:04 -0700180describe('waitForClientReady', function() {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700181 var server;
182 var port;
183 var Client;
184 var client;
185 before(function() {
186 server = new grpc.Server();
murgatroid99296a3692015-08-13 11:26:57 -0700187 port = server.bind('localhost:0', grpc.ServerCredentials.createInsecure());
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700188 server.start();
189 Client = surface_client.makeProtobufClientConstructor(mathService);
190 });
191 beforeEach(function() {
murgatroid99153b09d2015-09-25 16:04:03 -0700192 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700193 });
194 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700195 server.forceShutdown();
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700196 });
murgatroid9937135462015-08-13 11:24:34 -0700197 it('should complete when called alone', function(done) {
murgatroid9976ba1ff2015-08-28 14:57:04 -0700198 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid9937135462015-08-13 11:24:34 -0700199 assert.ifError(error);
200 done();
201 });
202 });
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700203 it('should complete when a call is initiated', function(done) {
murgatroid9976ba1ff2015-08-28 14:57:04 -0700204 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700205 assert.ifError(error);
206 done();
207 });
208 var call = client.div({}, function(err, response) {});
209 call.cancel();
210 });
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700211 it('should complete if called more than once', function(done) {
212 done = multiDone(done, 2);
murgatroid9976ba1ff2015-08-28 14:57:04 -0700213 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700214 assert.ifError(error);
215 done();
216 });
murgatroid9976ba1ff2015-08-28 14:57:04 -0700217 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700218 assert.ifError(error);
219 done();
220 });
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700221 });
222 it('should complete if called when already ready', function(done) {
murgatroid9976ba1ff2015-08-28 14:57:04 -0700223 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700224 assert.ifError(error);
murgatroid9976ba1ff2015-08-28 14:57:04 -0700225 grpc.waitForClientReady(client, Infinity, function(error) {
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700226 assert.ifError(error);
227 done();
228 });
229 });
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700230 });
murgatroid997cfee082015-10-13 13:49:55 -0700231 it('should time out if the server does not exist', function(done) {
232 var bad_client = new Client('nonexistent_hostname',
233 grpc.credentials.createInsecure());
234 var deadline = new Date();
235 deadline.setSeconds(deadline.getSeconds() + 1);
236 grpc.waitForClientReady(bad_client, deadline, function(error) {
237 assert(error);
238 done();
239 });
240 });
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700241});
murgatroid995828fb92015-05-11 14:27:39 -0700242describe('Echo service', function() {
243 var server;
244 var client;
245 before(function() {
246 var test_proto = ProtoBuf.loadProtoFile(__dirname + '/echo_service.proto');
247 var echo_service = test_proto.lookup('EchoService');
murgatroid99366e64d2015-07-15 17:01:49 -0700248 server = new grpc.Server();
249 server.addProtoService(echo_service, {
250 echo: function(call, callback) {
251 callback(null, call.request);
murgatroid995828fb92015-05-11 14:27:39 -0700252 }
253 });
murgatroid991a7dcac2015-07-27 16:13:28 -0700254 var port = server.bind('localhost:0', server_insecure_creds);
murgatroid995828fb92015-05-11 14:27:39 -0700255 var Client = surface_client.makeProtobufClientConstructor(echo_service);
murgatroid99153b09d2015-09-25 16:04:03 -0700256 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid99366e64d2015-07-15 17:01:49 -0700257 server.start();
murgatroid995828fb92015-05-11 14:27:39 -0700258 });
259 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700260 server.forceShutdown();
murgatroid995828fb92015-05-11 14:27:39 -0700261 });
262 it('should echo the recieved message directly', function(done) {
263 client.echo({value: 'test value', value2: 3}, function(error, response) {
264 assert.ifError(error);
265 assert.deepEqual(response, {value: 'test value', value2: 3});
266 done();
267 });
268 });
269});
murgatroid99e0f24dc2015-03-19 11:16:48 -0700270describe('Generic client and server', function() {
271 function toString(val) {
272 return val.toString();
273 }
274 function toBuffer(str) {
275 return new Buffer(str);
276 }
277 var string_service_attrs = {
278 'capitalize' : {
279 path: '/string/capitalize',
280 requestStream: false,
281 responseStream: false,
282 requestSerialize: toBuffer,
283 requestDeserialize: toString,
284 responseSerialize: toBuffer,
285 responseDeserialize: toString
286 }
287 };
288 describe('String client and server', function() {
289 var client;
290 var server;
291 before(function() {
murgatroid99366e64d2015-07-15 17:01:49 -0700292 server = new grpc.Server();
293 server.addService(string_service_attrs, {
294 capitalize: function(call, callback) {
295 callback(null, _.capitalize(call.request));
murgatroid99e0f24dc2015-03-19 11:16:48 -0700296 }
297 });
murgatroid991a7dcac2015-07-27 16:13:28 -0700298 var port = server.bind('localhost:0', server_insecure_creds);
murgatroid99366e64d2015-07-15 17:01:49 -0700299 server.start();
murgatroid99e0f24dc2015-03-19 11:16:48 -0700300 var Client = grpc.makeGenericClientConstructor(string_service_attrs);
murgatroid99893690f2015-07-27 14:56:40 -0700301 client = new Client('localhost:' + port,
murgatroid99153b09d2015-09-25 16:04:03 -0700302 grpc.credentials.createInsecure());
murgatroid99e0f24dc2015-03-19 11:16:48 -0700303 });
304 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700305 server.forceShutdown();
murgatroid99e0f24dc2015-03-19 11:16:48 -0700306 });
307 it('Should respond with a capitalized string', function(done) {
308 client.capitalize('abc', function(err, response) {
309 assert.ifError(err);
310 assert.strictEqual(response, 'Abc');
311 done();
312 });
313 });
314 });
315});
murgatroid99b4696302015-12-07 10:52:25 -0800316describe('Server-side getPeer', function() {
317 function toString(val) {
318 return val.toString();
319 }
320 function toBuffer(str) {
321 return new Buffer(str);
322 }
323 var string_service_attrs = {
324 'getPeer' : {
325 path: '/string/getPeer',
326 requestStream: false,
327 responseStream: false,
328 requestSerialize: toBuffer,
329 requestDeserialize: toString,
330 responseSerialize: toBuffer,
331 responseDeserialize: toString
332 }
333 };
334 var client;
335 var server;
336 before(function() {
337 server = new grpc.Server();
338 server.addService(string_service_attrs, {
339 getPeer: function(call, callback) {
340 try {
341 callback(null, call.getPeer());
342 } catch (e) {
343 call.emit('error', e);
344 }
345 }
346 });
347 var port = server.bind('localhost:0', server_insecure_creds);
348 server.start();
349 var Client = grpc.makeGenericClientConstructor(string_service_attrs);
350 client = new Client('localhost:' + port,
351 grpc.credentials.createInsecure());
352 });
353 after(function() {
354 server.forceShutdown();
355 });
356 it('should respond with a string representing the client', function(done) {
357 client.getPeer('', function(err, response) {
358 assert.ifError(err);
359 // We don't expect a specific value, just that it worked without error
360 done();
361 });
362 });
363});
murgatroid99ef9fd532015-07-16 13:33:23 -0700364describe('Echo metadata', function() {
365 var client;
366 var server;
murgatroid9984e3cde2015-08-20 11:27:05 -0700367 var metadata;
murgatroid99ef9fd532015-07-16 13:33:23 -0700368 before(function() {
369 var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
370 var test_service = test_proto.lookup('TestService');
371 server = new grpc.Server();
372 server.addProtoService(test_service, {
373 unary: function(call, cb) {
374 call.sendMetadata(call.metadata);
375 cb(null, {});
376 },
377 clientStream: function(stream, cb){
378 stream.on('data', function(data) {});
379 stream.on('end', function() {
380 stream.sendMetadata(stream.metadata);
381 cb(null, {});
382 });
383 },
384 serverStream: function(stream) {
385 stream.sendMetadata(stream.metadata);
386 stream.end();
387 },
388 bidiStream: function(stream) {
389 stream.on('data', function(data) {});
390 stream.on('end', function() {
391 stream.sendMetadata(stream.metadata);
392 stream.end();
393 });
394 }
395 });
murgatroid991a7dcac2015-07-27 16:13:28 -0700396 var port = server.bind('localhost:0', server_insecure_creds);
murgatroid99ef9fd532015-07-16 13:33:23 -0700397 var Client = surface_client.makeProtobufClientConstructor(test_service);
murgatroid99153b09d2015-09-25 16:04:03 -0700398 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid99ef9fd532015-07-16 13:33:23 -0700399 server.start();
murgatroid9984e3cde2015-08-20 11:27:05 -0700400 metadata = new grpc.Metadata();
401 metadata.set('key', 'value');
murgatroid99ef9fd532015-07-16 13:33:23 -0700402 });
403 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700404 server.forceShutdown();
murgatroid99ef9fd532015-07-16 13:33:23 -0700405 });
406 it('with unary call', function(done) {
407 var call = client.unary({}, function(err, data) {
408 assert.ifError(err);
murgatroid9984e3cde2015-08-20 11:27:05 -0700409 }, metadata);
murgatroid99ef9fd532015-07-16 13:33:23 -0700410 call.on('metadata', function(metadata) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700411 assert.deepEqual(metadata.get('key'), ['value']);
murgatroid99ef9fd532015-07-16 13:33:23 -0700412 done();
413 });
414 });
415 it('with client stream call', function(done) {
416 var call = client.clientStream(function(err, data) {
417 assert.ifError(err);
murgatroid9984e3cde2015-08-20 11:27:05 -0700418 }, metadata);
murgatroid99ef9fd532015-07-16 13:33:23 -0700419 call.on('metadata', function(metadata) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700420 assert.deepEqual(metadata.get('key'), ['value']);
murgatroid99ef9fd532015-07-16 13:33:23 -0700421 done();
422 });
423 call.end();
424 });
425 it('with server stream call', function(done) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700426 var call = client.serverStream({}, metadata);
murgatroid99ef9fd532015-07-16 13:33:23 -0700427 call.on('data', function() {});
428 call.on('metadata', function(metadata) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700429 assert.deepEqual(metadata.get('key'), ['value']);
murgatroid99ef9fd532015-07-16 13:33:23 -0700430 done();
431 });
432 });
433 it('with bidi stream call', function(done) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700434 var call = client.bidiStream(metadata);
murgatroid99ef9fd532015-07-16 13:33:23 -0700435 call.on('data', function() {});
436 call.on('metadata', function(metadata) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700437 assert.deepEqual(metadata.get('key'), ['value']);
murgatroid99ef9fd532015-07-16 13:33:23 -0700438 done();
439 });
440 call.end();
441 });
murgatroid99198a1ad2015-07-21 14:27:56 -0700442 it('shows the correct user-agent string', function(done) {
murgatroid992af89e42015-10-01 11:54:00 -0700443 var version = require('../../../package.json').version;
Craig Tillerb256faa2015-07-23 11:28:16 -0700444 var call = client.unary({}, function(err, data) { assert.ifError(err); },
murgatroid9984e3cde2015-08-20 11:27:05 -0700445 metadata);
murgatroid99198a1ad2015-07-21 14:27:56 -0700446 call.on('metadata', function(metadata) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700447 assert(_.startsWith(metadata.get('user-agent')[0],
448 'grpc-node/' + version));
murgatroid99198a1ad2015-07-21 14:27:56 -0700449 done();
450 });
451 });
murgatroid9971f50362015-10-12 16:12:18 -0700452 it('properly handles duplicate values', function(done) {
453 var dup_metadata = metadata.clone();
454 dup_metadata.add('key', 'value2');
455 var call = client.unary({}, function(err, data) {assert.ifError(err); },
456 dup_metadata);
457 call.on('metadata', function(resp_metadata) {
458 // Two arrays are equal iff their symmetric difference is empty
459 assert.deepEqual(_.xor(dup_metadata.get('key'), resp_metadata.get('key')),
460 []);
461 done();
462 });
463 });
murgatroid99ef9fd532015-07-16 13:33:23 -0700464});
murgatroid997cfee082015-10-13 13:49:55 -0700465describe('Client malformed response handling', function() {
466 var server;
467 var client;
468 var badArg = new Buffer([0xFF]);
469 before(function() {
470 var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
471 var test_service = test_proto.lookup('TestService');
472 var malformed_test_service = {
473 unary: {
474 path: '/TestService/Unary',
475 requestStream: false,
476 responseStream: false,
477 requestDeserialize: _.identity,
478 responseSerialize: _.identity
479 },
480 clientStream: {
481 path: '/TestService/ClientStream',
482 requestStream: true,
483 responseStream: false,
484 requestDeserialize: _.identity,
485 responseSerialize: _.identity
486 },
487 serverStream: {
488 path: '/TestService/ServerStream',
489 requestStream: false,
490 responseStream: true,
491 requestDeserialize: _.identity,
492 responseSerialize: _.identity
493 },
494 bidiStream: {
495 path: '/TestService/BidiStream',
496 requestStream: true,
497 responseStream: true,
498 requestDeserialize: _.identity,
499 responseSerialize: _.identity
500 }
501 };
502 server = new grpc.Server();
503 server.addService(malformed_test_service, {
504 unary: function(call, cb) {
505 cb(null, badArg);
506 },
507 clientStream: function(stream, cb) {
508 stream.on('data', function() {/* Ignore requests */});
509 stream.on('end', function() {
510 cb(null, badArg);
511 });
512 },
513 serverStream: function(stream) {
514 stream.write(badArg);
515 stream.end();
516 },
517 bidiStream: function(stream) {
518 stream.on('data', function() {
519 // Ignore requests
520 stream.write(badArg);
521 });
522 stream.on('end', function() {
523 stream.end();
524 });
525 }
526 });
527 var port = server.bind('localhost:0', server_insecure_creds);
528 var Client = surface_client.makeProtobufClientConstructor(test_service);
529 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
530 server.start();
531 });
532 after(function() {
533 server.forceShutdown();
534 });
535 it('should get an INTERNAL status with a unary call', function(done) {
536 client.unary({}, function(err, data) {
537 assert(err);
538 assert.strictEqual(err.code, grpc.status.INTERNAL);
539 done();
540 });
541 });
542 it('should get an INTERNAL status with a client stream call', function(done) {
543 var call = client.clientStream(function(err, data) {
544 assert(err);
545 assert.strictEqual(err.code, grpc.status.INTERNAL);
546 done();
547 });
548 call.write({});
549 call.end();
550 });
551 it('should get an INTERNAL status with a server stream call', function(done) {
552 var call = client.serverStream({});
553 call.on('data', function(){});
554 call.on('error', function(err) {
555 assert.strictEqual(err.code, grpc.status.INTERNAL);
556 done();
557 });
558 });
559 it('should get an INTERNAL status with a bidi stream call', function(done) {
560 var call = client.bidiStream();
561 call.on('data', function(){});
562 call.on('error', function(err) {
563 assert.strictEqual(err.code, grpc.status.INTERNAL);
564 done();
565 });
566 call.write({});
567 call.end();
568 });
569});
murgatroid99778c61b2015-05-18 16:52:47 -0700570describe('Other conditions', function() {
murgatroid9999e21042015-08-14 10:35:43 -0700571 var test_service;
572 var Client;
murgatroid99d07a2782015-03-26 10:07:15 -0700573 var client;
574 var server;
murgatroid99778c61b2015-05-18 16:52:47 -0700575 var port;
murgatroid99d07a2782015-03-26 10:07:15 -0700576 before(function() {
577 var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
murgatroid9999e21042015-08-14 10:35:43 -0700578 test_service = test_proto.lookup('TestService');
murgatroid99366e64d2015-07-15 17:01:49 -0700579 server = new grpc.Server();
murgatroid9984e3cde2015-08-20 11:27:05 -0700580 var trailer_metadata = new grpc.Metadata();
murgatroid99cc248a22015-08-20 14:47:15 -0700581 trailer_metadata.add('trailer-present', 'yes');
murgatroid99366e64d2015-07-15 17:01:49 -0700582 server.addProtoService(test_service, {
583 unary: function(call, cb) {
584 var req = call.request;
585 if (req.error) {
murgatroid996fe015e2015-10-12 13:18:06 -0700586 cb({code: grpc.status.UNKNOWN,
587 details: 'Requested error'}, null, trailer_metadata);
murgatroid99366e64d2015-07-15 17:01:49 -0700588 } else {
murgatroid9984e3cde2015-08-20 11:27:05 -0700589 cb(null, {count: 1}, trailer_metadata);
murgatroid99366e64d2015-07-15 17:01:49 -0700590 }
591 },
592 clientStream: function(stream, cb){
593 var count = 0;
594 var errored;
595 stream.on('data', function(data) {
596 if (data.error) {
597 errored = true;
murgatroid9984e3cde2015-08-20 11:27:05 -0700598 cb(new Error('Requested error'), null, trailer_metadata);
murgatroid99d07a2782015-03-26 10:07:15 -0700599 } else {
murgatroid99366e64d2015-07-15 17:01:49 -0700600 count += 1;
murgatroid99d07a2782015-03-26 10:07:15 -0700601 }
murgatroid99366e64d2015-07-15 17:01:49 -0700602 });
603 stream.on('end', function() {
604 if (!errored) {
murgatroid9984e3cde2015-08-20 11:27:05 -0700605 cb(null, {count: count}, trailer_metadata);
murgatroid99366e64d2015-07-15 17:01:49 -0700606 }
607 });
608 },
609 serverStream: function(stream) {
610 var req = stream.request;
611 if (req.error) {
murgatroid996fe015e2015-10-12 13:18:06 -0700612 var err = {code: grpc.status.UNKNOWN,
613 details: 'Requested error'};
murgatroid9984e3cde2015-08-20 11:27:05 -0700614 err.metadata = trailer_metadata;
murgatroid99366e64d2015-07-15 17:01:49 -0700615 stream.emit('error', err);
616 } else {
617 for (var i = 0; i < 5; i++) {
618 stream.write({count: i});
619 }
murgatroid9984e3cde2015-08-20 11:27:05 -0700620 stream.end(trailer_metadata);
murgatroid99366e64d2015-07-15 17:01:49 -0700621 }
622 },
623 bidiStream: function(stream) {
624 var count = 0;
625 stream.on('data', function(data) {
626 if (data.error) {
murgatroid99d07a2782015-03-26 10:07:15 -0700627 var err = new Error('Requested error');
murgatroid9984e3cde2015-08-20 11:27:05 -0700628 err.metadata = trailer_metadata.clone();
629 err.metadata.add('count', '' + count);
murgatroid99eb21bdd2015-03-26 15:19:54 -0700630 stream.emit('error', err);
murgatroid99d07a2782015-03-26 10:07:15 -0700631 } else {
murgatroid99366e64d2015-07-15 17:01:49 -0700632 stream.write({count: count});
633 count += 1;
murgatroid99d07a2782015-03-26 10:07:15 -0700634 }
murgatroid99366e64d2015-07-15 17:01:49 -0700635 });
636 stream.on('end', function() {
murgatroid9984e3cde2015-08-20 11:27:05 -0700637 stream.end(trailer_metadata);
murgatroid99366e64d2015-07-15 17:01:49 -0700638 });
murgatroid99d07a2782015-03-26 10:07:15 -0700639 }
640 });
murgatroid991a7dcac2015-07-27 16:13:28 -0700641 port = server.bind('localhost:0', server_insecure_creds);
murgatroid9999e21042015-08-14 10:35:43 -0700642 Client = surface_client.makeProtobufClientConstructor(test_service);
murgatroid99153b09d2015-09-25 16:04:03 -0700643 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid99366e64d2015-07-15 17:01:49 -0700644 server.start();
murgatroid99d07a2782015-03-26 10:07:15 -0700645 });
646 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -0700647 server.forceShutdown();
murgatroid99d07a2782015-03-26 10:07:15 -0700648 });
murgatroid99ea12b972015-07-24 10:43:27 -0700649 it('channel.getTarget should be available', function() {
murgatroid9976ba1ff2015-08-28 14:57:04 -0700650 assert.strictEqual(typeof grpc.getClientChannel(client).getTarget(),
651 'string');
murgatroid99ea12b972015-07-24 10:43:27 -0700652 });
murgatroid997cfee082015-10-13 13:49:55 -0700653 it('client should be able to pause and resume a stream', function(done) {
654 var call = client.bidiStream();
655 call.on('data', function(data) {
656 assert(data.count < 3);
657 call.pause();
658 setTimeout(function() {
659 call.resume();
660 }, 10);
661 });
662 call.on('end', function() {
663 done();
664 });
665 call.write({});
666 call.write({});
667 call.write({});
668 call.end();
669 });
murgatroid99778c61b2015-05-18 16:52:47 -0700670 describe('Server recieving bad input', function() {
671 var misbehavingClient;
672 var badArg = new Buffer([0xFF]);
673 before(function() {
674 var test_service_attrs = {
675 unary: {
676 path: '/TestService/Unary',
677 requestStream: false,
678 responseStream: false,
679 requestSerialize: _.identity,
680 responseDeserialize: _.identity
681 },
682 clientStream: {
683 path: '/TestService/ClientStream',
684 requestStream: true,
685 responseStream: false,
686 requestSerialize: _.identity,
687 responseDeserialize: _.identity
688 },
689 serverStream: {
690 path: '/TestService/ServerStream',
691 requestStream: false,
692 responseStream: true,
693 requestSerialize: _.identity,
694 responseDeserialize: _.identity
695 },
696 bidiStream: {
697 path: '/TestService/BidiStream',
698 requestStream: true,
699 responseStream: true,
700 requestSerialize: _.identity,
701 responseDeserialize: _.identity
702 }
703 };
704 var Client = surface_client.makeClientConstructor(test_service_attrs,
705 'TestService');
murgatroid99893690f2015-07-27 14:56:40 -0700706 misbehavingClient = new Client('localhost:' + port,
murgatroid99153b09d2015-09-25 16:04:03 -0700707 grpc.credentials.createInsecure());
murgatroid99d07a2782015-03-26 10:07:15 -0700708 });
murgatroid99778c61b2015-05-18 16:52:47 -0700709 it('should respond correctly to a unary call', function(done) {
murgatroid9904589a72015-05-19 09:51:26 -0700710 misbehavingClient.unary(badArg, function(err, data) {
murgatroid99778c61b2015-05-18 16:52:47 -0700711 assert(err);
712 assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
713 done();
714 });
715 });
716 it('should respond correctly to a client stream', function(done) {
717 var call = misbehavingClient.clientStream(function(err, data) {
718 assert(err);
719 assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
720 done();
721 });
722 call.write(badArg);
murgatroid9904589a72015-05-19 09:51:26 -0700723 // TODO(mlumish): Remove call.end()
724 call.end();
murgatroid99778c61b2015-05-18 16:52:47 -0700725 });
726 it('should respond correctly to a server stream', function(done) {
727 var call = misbehavingClient.serverStream(badArg);
728 call.on('data', function(data) {
murgatroid9904589a72015-05-19 09:51:26 -0700729 assert.fail(data, null, 'Unexpected data', '===');
murgatroid99778c61b2015-05-18 16:52:47 -0700730 });
731 call.on('error', function(err) {
732 assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
733 done();
734 });
735 });
736 it('should respond correctly to a bidi stream', function(done) {
737 var call = misbehavingClient.bidiStream();
738 call.on('data', function(data) {
murgatroid9904589a72015-05-19 09:51:26 -0700739 assert.fail(data, null, 'Unexpected data', '===');
murgatroid99778c61b2015-05-18 16:52:47 -0700740 });
741 call.on('error', function(err) {
742 assert.strictEqual(err.code, grpc.status.INVALID_ARGUMENT);
743 done();
744 });
745 call.write(badArg);
murgatroid9904589a72015-05-19 09:51:26 -0700746 // TODO(mlumish): Remove call.end()
747 call.end();
murgatroid99d07a2782015-03-26 10:07:15 -0700748 });
749 });
murgatroid99778c61b2015-05-18 16:52:47 -0700750 describe('Trailing metadata', function() {
751 it('should be present when a unary call succeeds', function(done) {
752 var call = client.unary({error: false}, function(err, data) {
753 assert.ifError(err);
754 });
755 call.on('status', function(status) {
murgatroid99cc248a22015-08-20 14:47:15 -0700756 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700757 done();
758 });
murgatroid99d07a2782015-03-26 10:07:15 -0700759 });
murgatroid99778c61b2015-05-18 16:52:47 -0700760 it('should be present when a unary call fails', function(done) {
761 var call = client.unary({error: true}, function(err, data) {
762 assert(err);
763 });
764 call.on('status', function(status) {
murgatroid99cc248a22015-08-20 14:47:15 -0700765 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700766 done();
767 });
murgatroid99d07a2782015-03-26 10:07:15 -0700768 });
murgatroid99778c61b2015-05-18 16:52:47 -0700769 it('should be present when a client stream call succeeds', function(done) {
770 var call = client.clientStream(function(err, data) {
771 assert.ifError(err);
772 });
773 call.write({error: false});
774 call.write({error: false});
775 call.end();
776 call.on('status', function(status) {
murgatroid99cc248a22015-08-20 14:47:15 -0700777 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700778 done();
779 });
murgatroid99d07a2782015-03-26 10:07:15 -0700780 });
murgatroid99778c61b2015-05-18 16:52:47 -0700781 it('should be present when a client stream call fails', function(done) {
782 var call = client.clientStream(function(err, data) {
783 assert(err);
784 });
785 call.write({error: false});
786 call.write({error: true});
787 call.end();
788 call.on('status', function(status) {
murgatroid99cc248a22015-08-20 14:47:15 -0700789 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700790 done();
791 });
murgatroid99d07a2782015-03-26 10:07:15 -0700792 });
murgatroid99778c61b2015-05-18 16:52:47 -0700793 it('should be present when a server stream call succeeds', function(done) {
794 var call = client.serverStream({error: false});
795 call.on('data', function(){});
796 call.on('status', function(status) {
797 assert.strictEqual(status.code, grpc.status.OK);
murgatroid99cc248a22015-08-20 14:47:15 -0700798 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700799 done();
800 });
murgatroid99d07a2782015-03-26 10:07:15 -0700801 });
murgatroid99778c61b2015-05-18 16:52:47 -0700802 it('should be present when a server stream call fails', function(done) {
803 var call = client.serverStream({error: true});
804 call.on('data', function(){});
805 call.on('error', function(error) {
murgatroid99cc248a22015-08-20 14:47:15 -0700806 assert.deepEqual(error.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700807 done();
808 });
murgatroid99d07a2782015-03-26 10:07:15 -0700809 });
murgatroid99778c61b2015-05-18 16:52:47 -0700810 it('should be present when a bidi stream succeeds', function(done) {
811 var call = client.bidiStream();
812 call.write({error: false});
813 call.write({error: false});
814 call.end();
815 call.on('data', function(){});
816 call.on('status', function(status) {
817 assert.strictEqual(status.code, grpc.status.OK);
murgatroid99cc248a22015-08-20 14:47:15 -0700818 assert.deepEqual(status.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700819 done();
820 });
murgatroid99eb21bdd2015-03-26 15:19:54 -0700821 });
murgatroid99778c61b2015-05-18 16:52:47 -0700822 it('should be present when a bidi stream fails', function(done) {
823 var call = client.bidiStream();
824 call.write({error: false});
825 call.write({error: true});
826 call.end();
827 call.on('data', function(){});
828 call.on('error', function(error) {
murgatroid99cc248a22015-08-20 14:47:15 -0700829 assert.deepEqual(error.metadata.get('trailer-present'), ['yes']);
murgatroid99778c61b2015-05-18 16:52:47 -0700830 done();
831 });
murgatroid99eb21bdd2015-03-26 15:19:54 -0700832 });
833 });
murgatroid9906f09722015-07-17 11:26:54 -0700834 describe('Error object should contain the status', function() {
835 it('for a unary call', function(done) {
836 client.unary({error: true}, function(err, data) {
837 assert(err);
murgatroid99560b82c2015-07-17 13:06:15 -0700838 assert.strictEqual(err.code, grpc.status.UNKNOWN);
murgatroid9906f09722015-07-17 11:26:54 -0700839 assert.strictEqual(err.message, 'Requested error');
840 done();
841 });
842 });
843 it('for a client stream call', function(done) {
844 var call = client.clientStream(function(err, data) {
845 assert(err);
murgatroid99560b82c2015-07-17 13:06:15 -0700846 assert.strictEqual(err.code, grpc.status.UNKNOWN);
murgatroid9906f09722015-07-17 11:26:54 -0700847 assert.strictEqual(err.message, 'Requested error');
848 done();
849 });
850 call.write({error: false});
851 call.write({error: true});
852 call.end();
853 });
854 it('for a server stream call', function(done) {
855 var call = client.serverStream({error: true});
856 call.on('data', function(){});
857 call.on('error', function(error) {
murgatroid99560b82c2015-07-17 13:06:15 -0700858 assert.strictEqual(error.code, grpc.status.UNKNOWN);
murgatroid9906f09722015-07-17 11:26:54 -0700859 assert.strictEqual(error.message, 'Requested error');
860 done();
861 });
862 });
863 it('for a bidi stream call', function(done) {
864 var call = client.bidiStream();
865 call.write({error: false});
866 call.write({error: true});
867 call.end();
868 call.on('data', function(){});
869 call.on('error', function(error) {
murgatroid99560b82c2015-07-17 13:06:15 -0700870 assert.strictEqual(error.code, grpc.status.UNKNOWN);
murgatroid9906f09722015-07-17 11:26:54 -0700871 assert.strictEqual(error.message, 'Requested error');
872 done();
873 });
874 });
875 });
murgatroid99ea12b972015-07-24 10:43:27 -0700876 describe('call.getPeer should return the peer', function() {
877 it('for a unary call', function(done) {
878 var call = client.unary({error: false}, function(err, data) {
879 assert.ifError(err);
880 done();
881 });
882 assert.strictEqual(typeof call.getPeer(), 'string');
883 });
884 it('for a client stream call', function(done) {
885 var call = client.clientStream(function(err, data) {
886 assert.ifError(err);
887 done();
888 });
889 assert.strictEqual(typeof call.getPeer(), 'string');
890 call.write({error: false});
891 call.end();
892 });
893 it('for a server stream call', function(done) {
894 var call = client.serverStream({error: false});
895 assert.strictEqual(typeof call.getPeer(), 'string');
896 call.on('data', function(){});
897 call.on('status', function(status) {
898 assert.strictEqual(status.code, grpc.status.OK);
899 done();
900 });
901 });
902 it('for a bidi stream call', function(done) {
903 var call = client.bidiStream();
904 assert.strictEqual(typeof call.getPeer(), 'string');
905 call.write({error: false});
906 call.end();
907 call.on('data', function(){});
908 call.on('status', function(status) {
909 done();
910 });
911 });
912 });
murgatroid997cd632c2015-10-05 15:56:18 -0700913});
914describe('Call propagation', function() {
915 var proxy;
916 var proxy_impl;
917
918 var test_service;
919 var Client;
920 var client;
921 var server;
922 before(function() {
923 var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
924 test_service = test_proto.lookup('TestService');
925 server = new grpc.Server();
926 server.addProtoService(test_service, {
927 unary: function(call) {},
928 clientStream: function(stream) {},
929 serverStream: function(stream) {},
930 bidiStream: function(stream) {}
murgatroid9999e21042015-08-14 10:35:43 -0700931 });
murgatroid997cd632c2015-10-05 15:56:18 -0700932 var port = server.bind('localhost:0', server_insecure_creds);
933 Client = surface_client.makeProtobufClientConstructor(test_service);
murgatroid99cc545462015-10-06 11:16:49 -0700934 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -0700935 server.start();
936 });
937 after(function() {
938 server.forceShutdown();
939 });
940 beforeEach(function() {
941 proxy = new grpc.Server();
942 proxy_impl = {
943 unary: function(call) {},
944 clientStream: function(stream) {},
945 serverStream: function(stream) {},
946 bidiStream: function(stream) {}
947 };
948 });
949 afterEach(function() {
950 proxy.forceShutdown();
951 });
952 describe('Cancellation', function() {
953 it('With a unary call', function(done) {
954 done = multiDone(done, 2);
955 proxy_impl.unary = function(parent, callback) {
956 client.unary(parent.request, function(err, value) {
957 try {
murgatroid9999e21042015-08-14 10:35:43 -0700958 assert(err);
959 assert.strictEqual(err.code, grpc.status.CANCELLED);
murgatroid997cd632c2015-10-05 15:56:18 -0700960 } finally {
961 callback(err, value);
murgatroid9999e21042015-08-14 10:35:43 -0700962 done();
murgatroid997cd632c2015-10-05 15:56:18 -0700963 }
964 }, null, {parent: parent});
965 call.cancel();
murgatroid9999e21042015-08-14 10:35:43 -0700966 };
murgatroid997cd632c2015-10-05 15:56:18 -0700967 proxy.addProtoService(test_service, proxy_impl);
968 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
969 proxy.start();
970 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -0700971 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -0700972 var call = proxy_client.unary({}, function(err, value) {
973 done();
murgatroid9999e21042015-08-14 10:35:43 -0700974 });
murgatroid9999e21042015-08-14 10:35:43 -0700975 });
murgatroid997cd632c2015-10-05 15:56:18 -0700976 it('With a client stream call', function(done) {
977 done = multiDone(done, 2);
978 proxy_impl.clientStream = function(parent, callback) {
979 client.clientStream(function(err, value) {
980 try {
murgatroid9999e21042015-08-14 10:35:43 -0700981 assert(err);
982 assert.strictEqual(err.code, grpc.status.CANCELLED);
murgatroid997cd632c2015-10-05 15:56:18 -0700983 } finally {
984 callback(err, value);
murgatroid9999e21042015-08-14 10:35:43 -0700985 done();
murgatroid997cd632c2015-10-05 15:56:18 -0700986 }
987 }, null, {parent: parent});
988 call.cancel();
989 };
990 proxy.addProtoService(test_service, proxy_impl);
991 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
992 proxy.start();
993 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -0700994 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -0700995 var call = proxy_client.clientStream(function(err, value) {
996 done();
murgatroid9999e21042015-08-14 10:35:43 -0700997 });
998 });
murgatroid997cd632c2015-10-05 15:56:18 -0700999 it('With a server stream call', function(done) {
1000 done = multiDone(done, 2);
1001 proxy_impl.serverStream = function(parent) {
1002 var child = client.serverStream(parent.request, null,
1003 {parent: parent});
1004 child.on('error', function(err) {
1005 assert(err);
1006 assert.strictEqual(err.code, grpc.status.CANCELLED);
murgatroid9999e21042015-08-14 10:35:43 -07001007 done();
murgatroid997cd632c2015-10-05 15:56:18 -07001008 });
1009 call.cancel();
1010 };
1011 proxy.addProtoService(test_service, proxy_impl);
1012 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
1013 proxy.start();
1014 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -07001015 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -07001016 var call = proxy_client.serverStream({});
1017 call.on('error', function(err) {
1018 done();
murgatroid9999e21042015-08-14 10:35:43 -07001019 });
murgatroid997cd632c2015-10-05 15:56:18 -07001020 });
1021 it('With a bidi stream call', function(done) {
1022 done = multiDone(done, 2);
1023 proxy_impl.bidiStream = function(parent) {
1024 var child = client.bidiStream(null, {parent: parent});
1025 child.on('error', function(err) {
1026 assert(err);
1027 assert.strictEqual(err.code, grpc.status.CANCELLED);
1028 done();
1029 });
1030 call.cancel();
1031 };
1032 proxy.addProtoService(test_service, proxy_impl);
1033 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
1034 proxy.start();
1035 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -07001036 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -07001037 var call = proxy_client.bidiStream();
1038 call.on('error', function(err) {
1039 done();
1040 });
1041 });
1042 });
1043 describe('Deadline', function() {
1044 /* jshint bitwise:false */
1045 var deadline_flags = (grpc.propagate.DEFAULTS &
1046 ~grpc.propagate.CANCELLATION);
1047 it('With a client stream call', function(done) {
1048 done = multiDone(done, 2);
1049 proxy_impl.clientStream = function(parent, callback) {
1050 client.clientStream(function(err, value) {
1051 try {
murgatroid9999e21042015-08-14 10:35:43 -07001052 assert(err);
murgatroid99aac8f142015-08-17 13:35:54 -07001053 assert(err.code === grpc.status.DEADLINE_EXCEEDED ||
1054 err.code === grpc.status.INTERNAL);
murgatroid997cd632c2015-10-05 15:56:18 -07001055 } finally {
1056 callback(err, value);
murgatroid9999e21042015-08-14 10:35:43 -07001057 done();
murgatroid997cd632c2015-10-05 15:56:18 -07001058 }
1059 }, null, {parent: parent, propagate_flags: deadline_flags});
1060 };
1061 proxy.addProtoService(test_service, proxy_impl);
1062 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
1063 proxy.start();
1064 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -07001065 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -07001066 var deadline = new Date();
1067 deadline.setSeconds(deadline.getSeconds() + 1);
1068 proxy_client.clientStream(function(err, value) {
1069 done();
1070 }, null, {deadline: deadline});
1071 });
1072 it('With a bidi stream call', function(done) {
1073 done = multiDone(done, 2);
1074 proxy_impl.bidiStream = function(parent) {
1075 var child = client.bidiStream(
1076 null, {parent: parent, propagate_flags: deadline_flags});
1077 child.on('error', function(err) {
1078 assert(err);
1079 assert(err.code === grpc.status.DEADLINE_EXCEEDED ||
1080 err.code === grpc.status.INTERNAL);
murgatroid9999e21042015-08-14 10:35:43 -07001081 done();
1082 });
murgatroid997cd632c2015-10-05 15:56:18 -07001083 };
1084 proxy.addProtoService(test_service, proxy_impl);
1085 var proxy_port = proxy.bind('localhost:0', server_insecure_creds);
1086 proxy.start();
1087 var proxy_client = new Client('localhost:' + proxy_port,
murgatroid99cc545462015-10-06 11:16:49 -07001088 grpc.credentials.createInsecure());
murgatroid997cd632c2015-10-05 15:56:18 -07001089 var deadline = new Date();
1090 deadline.setSeconds(deadline.getSeconds() + 1);
1091 var call = proxy_client.bidiStream(null, {deadline: deadline});
1092 call.on('error', function(err) {
1093 done();
murgatroid9999e21042015-08-14 10:35:43 -07001094 });
1095 });
1096 });
murgatroid99d07a2782015-03-26 10:07:15 -07001097});
murgatroid994d2d0f02015-01-29 11:44:46 -08001098describe('Cancelling surface client', function() {
murgatroid9955dd2ba2015-01-26 14:11:18 -08001099 var client;
1100 var server;
1101 before(function() {
murgatroid99366e64d2015-07-15 17:01:49 -07001102 server = new grpc.Server();
1103 server.addProtoService(mathService, {
1104 'div': function(stream) {},
1105 'divMany': function(stream) {},
1106 'fib': function(stream) {},
1107 'sum': function(stream) {}
murgatroid9955dd2ba2015-01-26 14:11:18 -08001108 });
murgatroid991a7dcac2015-07-27 16:13:28 -07001109 var port = server.bind('localhost:0', server_insecure_creds);
murgatroid99e023e982015-03-18 17:17:33 -07001110 var Client = surface_client.makeProtobufClientConstructor(mathService);
murgatroid99153b09d2015-09-25 16:04:03 -07001111 client = new Client('localhost:' + port, grpc.credentials.createInsecure());
murgatroid99366e64d2015-07-15 17:01:49 -07001112 server.start();
murgatroid9955dd2ba2015-01-26 14:11:18 -08001113 });
1114 after(function() {
murgatroid99cb951f62015-08-18 17:38:11 -07001115 server.forceShutdown();
murgatroid9955dd2ba2015-01-26 14:11:18 -08001116 });
1117 it('Should correctly cancel a unary call', function(done) {
1118 var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) {
1119 assert.strictEqual(err.code, surface_client.status.CANCELLED);
1120 done();
1121 });
1122 call.cancel();
1123 });
1124 it('Should correctly cancel a client stream call', function(done) {
1125 var call = client.sum(function(err, resp) {
1126 assert.strictEqual(err.code, surface_client.status.CANCELLED);
1127 done();
1128 });
1129 call.cancel();
1130 });
1131 it('Should correctly cancel a server stream call', function(done) {
1132 var call = client.fib({'limit': 5});
murgatroid9965b784e2015-05-06 16:46:19 -07001133 call.on('error', function(error) {
1134 assert.strictEqual(error.code, surface_client.status.CANCELLED);
murgatroid9955dd2ba2015-01-26 14:11:18 -08001135 done();
1136 });
1137 call.cancel();
1138 });
1139 it('Should correctly cancel a bidi stream call', function(done) {
1140 var call = client.divMany();
murgatroid9965b784e2015-05-06 16:46:19 -07001141 call.on('error', function(error) {
1142 assert.strictEqual(error.code, surface_client.status.CANCELLED);
murgatroid9955dd2ba2015-01-26 14:11:18 -08001143 done();
1144 });
1145 call.cancel();
1146 });
Craig Tillerce5021b2015-02-18 09:25:21 -08001147});