Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: third_party/grpc/src/node/interop/interop_client.js

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015-2016, Google Inc.
4 * 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
34 'use strict';
35
36 var fs = require('fs');
37 var path = require('path');
38 var grpc = require('..');
39 var testProto = grpc.load({
40 root: __dirname + '/../../..',
41 file: 'src/proto/grpc/testing/test.proto'}).grpc.testing;
42 var GoogleAuth = require('google-auth-library');
43
44 var assert = require('assert');
45
46 var SERVICE_ACCOUNT_EMAIL;
47 try {
48 SERVICE_ACCOUNT_EMAIL = require(
49 process.env.GOOGLE_APPLICATION_CREDENTIALS).client_email;
50 } catch (e) {
51 // This will cause the tests to fail if they need that string
52 SERVICE_ACCOUNT_EMAIL = null;
53 }
54
55 var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
56 var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
57
58 /**
59 * Create a buffer filled with size zeroes
60 * @param {number} size The length of the buffer
61 * @return {Buffer} The new buffer
62 */
63 function zeroBuffer(size) {
64 var zeros = new Buffer(size);
65 zeros.fill(0);
66 return zeros;
67 }
68
69 /**
70 * This is used for testing functions with multiple asynchronous calls that
71 * can happen in different orders. This should be passed the number of async
72 * function invocations that can occur last, and each of those should call this
73 * function's return value
74 * @param {function()} done The function that should be called when a test is
75 * complete.
76 * @param {number} count The number of calls to the resulting function if the
77 * test passes.
78 * @return {function()} The function that should be called at the end of each
79 * sequence of asynchronous functions.
80 */
81 function multiDone(done, count) {
82 return function() {
83 count -= 1;
84 if (count <= 0) {
85 done();
86 }
87 };
88 }
89
90 /**
91 * Run the empty_unary test
92 * @param {Client} client The client to test against
93 * @param {function} done Callback to call when the test is completed. Included
94 * primarily for use with mocha
95 */
96 function emptyUnary(client, done) {
97 client.emptyCall({}, function(err, resp) {
98 assert.ifError(err);
99 if (done) {
100 done();
101 }
102 });
103 }
104
105 /**
106 * Run the large_unary test
107 * @param {Client} client The client to test against
108 * @param {function} done Callback to call when the test is completed. Included
109 * primarily for use with mocha
110 */
111 function largeUnary(client, done) {
112 var arg = {
113 response_type: 'COMPRESSABLE',
114 response_size: 314159,
115 payload: {
116 body: zeroBuffer(271828)
117 }
118 };
119 client.unaryCall(arg, function(err, resp) {
120 assert.ifError(err);
121 assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
122 assert.strictEqual(resp.payload.body.length, 314159);
123 if (done) {
124 done();
125 }
126 });
127 }
128
129 /**
130 * Run the client_streaming test
131 * @param {Client} client The client to test against
132 * @param {function} done Callback to call when the test is completed. Included
133 * primarily for use with mocha
134 */
135 function clientStreaming(client, done) {
136 var call = client.streamingInputCall(function(err, resp) {
137 assert.ifError(err);
138 assert.strictEqual(resp.aggregated_payload_size, 74922);
139 if (done) {
140 done();
141 }
142 });
143 var payload_sizes = [27182, 8, 1828, 45904];
144 for (var i = 0; i < payload_sizes.length; i++) {
145 call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
146 }
147 call.end();
148 }
149
150 /**
151 * Run the server_streaming test
152 * @param {Client} client The client to test against
153 * @param {function} done Callback to call when the test is completed. Included
154 * primarily for use with mocha
155 */
156 function serverStreaming(client, done) {
157 var arg = {
158 response_type: 'COMPRESSABLE',
159 response_parameters: [
160 {size: 31415},
161 {size: 9},
162 {size: 2653},
163 {size: 58979}
164 ]
165 };
166 var call = client.streamingOutputCall(arg);
167 var resp_index = 0;
168 call.on('data', function(value) {
169 assert(resp_index < 4);
170 assert.strictEqual(value.payload.type, 'COMPRESSABLE');
171 assert.strictEqual(value.payload.body.length,
172 arg.response_parameters[resp_index].size);
173 resp_index += 1;
174 });
175 call.on('end', function() {
176 assert.strictEqual(resp_index, 4);
177 if (done) {
178 done();
179 }
180 });
181 call.on('status', function(status) {
182 assert.strictEqual(status.code, grpc.status.OK);
183 });
184 }
185
186 /**
187 * Run the ping_pong test
188 * @param {Client} client The client to test against
189 * @param {function} done Callback to call when the test is completed. Included
190 * primarily for use with mocha
191 */
192 function pingPong(client, done) {
193 var payload_sizes = [27182, 8, 1828, 45904];
194 var response_sizes = [31415, 9, 2653, 58979];
195 var call = client.fullDuplexCall();
196 call.on('status', function(status) {
197 assert.strictEqual(status.code, grpc.status.OK);
198 if (done) {
199 done();
200 }
201 });
202 var index = 0;
203 call.write({
204 response_type: 'COMPRESSABLE',
205 response_parameters: [
206 {size: response_sizes[index]}
207 ],
208 payload: {body: zeroBuffer(payload_sizes[index])}
209 });
210 call.on('data', function(response) {
211 assert.strictEqual(response.payload.type, 'COMPRESSABLE');
212 assert.equal(response.payload.body.length, response_sizes[index]);
213 index += 1;
214 if (index === 4) {
215 call.end();
216 } else {
217 call.write({
218 response_type: 'COMPRESSABLE',
219 response_parameters: [
220 {size: response_sizes[index]}
221 ],
222 payload: {body: zeroBuffer(payload_sizes[index])}
223 });
224 }
225 });
226 }
227
228 /**
229 * Run the empty_stream test.
230 * @param {Client} client The client to test against
231 * @param {function} done Callback to call when the test is completed. Included
232 * primarily for use with mocha
233 */
234 function emptyStream(client, done) {
235 var call = client.fullDuplexCall();
236 call.on('status', function(status) {
237 assert.strictEqual(status.code, grpc.status.OK);
238 if (done) {
239 done();
240 }
241 });
242 call.on('data', function(value) {
243 assert.fail(value, null, 'No data should have been received', '!==');
244 });
245 call.end();
246 }
247
248 /**
249 * Run the cancel_after_begin test.
250 * @param {Client} client The client to test against
251 * @param {function} done Callback to call when the test is completed. Included
252 * primarily for use with mocha
253 */
254 function cancelAfterBegin(client, done) {
255 var call = client.streamingInputCall(function(err, resp) {
256 assert.strictEqual(err.code, grpc.status.CANCELLED);
257 done();
258 });
259 call.cancel();
260 }
261
262 /**
263 * Run the cancel_after_first_response test.
264 * @param {Client} client The client to test against
265 * @param {function} done Callback to call when the test is completed. Included
266 * primarily for use with mocha
267 */
268 function cancelAfterFirstResponse(client, done) {
269 var call = client.fullDuplexCall();
270 call.write({
271 response_type: 'COMPRESSABLE',
272 response_parameters: [
273 {size: 31415}
274 ],
275 payload: {body: zeroBuffer(27182)}
276 });
277 call.on('data', function(data) {
278 call.cancel();
279 });
280 call.on('error', function(error) {
281 assert.strictEqual(error.code, grpc.status.CANCELLED);
282 done();
283 });
284 }
285
286 function timeoutOnSleepingServer(client, done) {
287 var deadline = new Date();
288 deadline.setMilliseconds(deadline.getMilliseconds() + 1);
289 var call = client.fullDuplexCall(null, {deadline: deadline});
290 call.write({
291 payload: {body: zeroBuffer(27182)}
292 });
293 call.on('data', function() {});
294 call.on('error', function(error) {
295
296 assert(error.code === grpc.status.DEADLINE_EXCEEDED ||
297 error.code === grpc.status.INTERNAL);
298 done();
299 });
300 }
301
302 function customMetadata(client, done) {
303 done = multiDone(done, 5);
304 var metadata = new grpc.Metadata();
305 metadata.set(ECHO_INITIAL_KEY, 'test_initial_metadata_value');
306 metadata.set(ECHO_TRAILING_KEY, new Buffer('ababab', 'hex'));
307 var arg = {
308 response_type: 'COMPRESSABLE',
309 response_size: 314159,
310 payload: {
311 body: zeroBuffer(271828)
312 }
313 };
314 var streaming_arg = {
315 payload: {
316 body: zeroBuffer(271828)
317 }
318 };
319 var unary = client.unaryCall(arg, function(err, resp) {
320 assert.ifError(err);
321 done();
322 }, metadata);
323 unary.on('metadata', function(metadata) {
324 assert.deepEqual(metadata.get(ECHO_INITIAL_KEY),
325 ['test_initial_metadata_value']);
326 done();
327 });
328 unary.on('status', function(status) {
329 var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
330 assert(echo_trailer.length > 0);
331 assert.strictEqual(echo_trailer[0].toString('hex'), 'ababab');
332 done();
333 });
334 var stream = client.fullDuplexCall(metadata);
335 stream.on('metadata', function(metadata) {
336 assert.deepEqual(metadata.get(ECHO_INITIAL_KEY),
337 ['test_initial_metadata_value']);
338 done();
339 });
340 stream.on('data', function() {});
341 stream.on('status', function(status) {
342 var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
343 assert(echo_trailer.length > 0);
344 assert.strictEqual(echo_trailer[0].toString('hex'), 'ababab');
345 done();
346 });
347 stream.write(streaming_arg);
348 stream.end();
349 }
350
351 function statusCodeAndMessage(client, done) {
352 done = multiDone(done, 2);
353 var arg = {
354 response_status: {
355 code: 2,
356 message: 'test status message'
357 }
358 };
359 client.unaryCall(arg, function(err, resp) {
360 assert(err);
361 assert.strictEqual(err.code, 2);
362 assert.strictEqual(err.message, 'test status message');
363 done();
364 });
365 var duplex = client.fullDuplexCall();
366 duplex.on('data', function() {});
367 duplex.on('status', function(status) {
368 assert(status);
369 assert.strictEqual(status.code, 2);
370 assert.strictEqual(status.details, 'test status message');
371 done();
372 });
373 duplex.on('error', function(){});
374 duplex.write(arg);
375 duplex.end();
376 }
377
378 function unimplementedMethod(client, done) {
379 client.unimplementedCall({}, function(err, resp) {
380 assert(err);
381 assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
382 assert(!err.message);
383 done();
384 });
385 }
386
387 /**
388 * Run one of the authentication tests.
389 * @param {string} expected_user The expected username in the response
390 * @param {Client} client The client to test against
391 * @param {?string} scope The scope to apply to the credentials
392 * @param {function} done Callback to call when the test is completed. Included
393 * primarily for use with mocha
394 */
395 function authTest(expected_user, scope, client, done) {
396 var arg = {
397 response_type: 'COMPRESSABLE',
398 response_size: 314159,
399 payload: {
400 body: zeroBuffer(271828)
401 },
402 fill_username: true,
403 fill_oauth_scope: true
404 };
405 client.unaryCall(arg, function(err, resp) {
406 assert.ifError(err);
407 assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
408 assert.strictEqual(resp.payload.body.length, 314159);
409 assert.strictEqual(resp.username, expected_user);
410 if (scope) {
411 assert(scope.indexOf(resp.oauth_scope) > -1);
412 }
413 if (done) {
414 done();
415 }
416 });
417 }
418
419 function computeEngineCreds(client, done, extra) {
420 authTest(extra.service_account, null, client, done);
421 }
422
423 function serviceAccountCreds(client, done, extra) {
424 authTest(SERVICE_ACCOUNT_EMAIL, extra.oauth_scope, client, done);
425 }
426
427 function jwtTokenCreds(client, done, extra) {
428 authTest(SERVICE_ACCOUNT_EMAIL, null, client, done);
429 }
430
431 function oauth2Test(client, done, extra) {
432 var arg = {
433 fill_username: true,
434 fill_oauth_scope: true
435 };
436 client.unaryCall(arg, function(err, resp) {
437 assert.ifError(err);
438 assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
439 assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
440 if (done) {
441 done();
442 }
443 });
444 }
445
446 function perRpcAuthTest(client, done, extra) {
447 (new GoogleAuth()).getApplicationDefault(function(err, credential) {
448 assert.ifError(err);
449 var arg = {
450 fill_username: true,
451 fill_oauth_scope: true
452 };
453 var scope = extra.oauth_scope;
454 if (credential.createScopedRequired() && scope) {
455 credential = credential.createScoped(scope);
456 }
457 var creds = grpc.credentials.createFromGoogleCredential(credential);
458 client.unaryCall(arg, function(err, resp) {
459 assert.ifError(err);
460 assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
461 assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
462 if (done) {
463 done();
464 }
465 }, null, {credentials: creds});
466 });
467 }
468
469 function getApplicationCreds(scope, callback) {
470 (new GoogleAuth()).getApplicationDefault(function(err, credential) {
471 if (err) {
472 callback(err);
473 return;
474 }
475 if (credential.createScopedRequired() && scope) {
476 credential = credential.createScoped(scope);
477 }
478 callback(null, grpc.credentials.createFromGoogleCredential(credential));
479 });
480 }
481
482 function getOauth2Creds(scope, callback) {
483 (new GoogleAuth()).getApplicationDefault(function(err, credential) {
484 if (err) {
485 callback(err);
486 return;
487 }
488 credential = credential.createScoped(scope);
489 credential.getAccessToken(function(err, token) {
490 if (err) {
491 callback(err);
492 return;
493 }
494 var updateMd = function(service_url, callback) {
495 var metadata = new grpc.Metadata();
496 metadata.add('authorization', 'Bearer ' + token);
497 callback(null, metadata);
498 };
499 callback(null, grpc.credentials.createFromMetadataGenerator(updateMd));
500 });
501 });
502 }
503
504 /**
505 * Map from test case names to test functions
506 */
507 var test_cases = {
508 empty_unary: {run: emptyUnary,
509 Client: testProto.TestService},
510 large_unary: {run: largeUnary,
511 Client: testProto.TestService},
512 client_streaming: {run: clientStreaming,
513 Client: testProto.TestService},
514 server_streaming: {run: serverStreaming,
515 Client: testProto.TestService},
516 ping_pong: {run: pingPong,
517 Client: testProto.TestService},
518 empty_stream: {run: emptyStream,
519 Client: testProto.TestService},
520 cancel_after_begin: {run: cancelAfterBegin,
521 Client: testProto.TestService},
522 cancel_after_first_response: {run: cancelAfterFirstResponse,
523 Client: testProto.TestService},
524 timeout_on_sleeping_server: {run: timeoutOnSleepingServer,
525 Client: testProto.TestService},
526 custom_metadata: {run: customMetadata,
527 Client: testProto.TestService},
528 status_code_and_message: {run: statusCodeAndMessage,
529 Client: testProto.TestService},
530 unimplemented_method: {run: unimplementedMethod,
531 Client: testProto.UnimplementedService},
532 compute_engine_creds: {run: computeEngineCreds,
533 Client: testProto.TestService,
534 getCreds: getApplicationCreds},
535 service_account_creds: {run: serviceAccountCreds,
536 Client: testProto.TestService,
537 getCreds: getApplicationCreds},
538 jwt_token_creds: {run: jwtTokenCreds,
539 Client: testProto.TestService,
540 getCreds: getApplicationCreds},
541 oauth2_auth_token: {run: oauth2Test,
542 Client: testProto.TestService,
543 getCreds: getOauth2Creds},
544 per_rpc_creds: {run: perRpcAuthTest,
545 Client: testProto.TestService}
546 };
547
548 /**
549 * Execute a single test case.
550 * @param {string} address The address of the server to connect to, in the
551 * format 'hostname:port'
552 * @param {string} host_overrirde The hostname of the server to use as an SSL
553 * override
554 * @param {string} test_case The name of the test case to run
555 * @param {bool} tls Indicates that a secure channel should be used
556 * @param {function} done Callback to call when the test is completed. Included
557 * primarily for use with mocha
558 * @param {object=} extra Extra options for some tests
559 */
560 function runTest(address, host_override, test_case, tls, test_ca, done, extra) {
561 // TODO(mlumish): enable TLS functionality
562 var options = {};
563 var creds;
564 if (tls) {
565 var ca_path;
566 if (test_ca) {
567 ca_path = path.join(__dirname, '../test/data/ca.pem');
568 var ca_data = fs.readFileSync(ca_path);
569 creds = grpc.credentials.createSsl(ca_data);
570 } else {
571 creds = grpc.credentials.createSsl();
572 }
573 if (host_override) {
574 options['grpc.ssl_target_name_override'] = host_override;
575 options['grpc.default_authority'] = host_override;
576 }
577 } else {
578 creds = grpc.credentials.createInsecure();
579 }
580 var test = test_cases[test_case];
581
582 var execute = function(err, creds) {
583 assert.ifError(err);
584 var client = new test.Client(address, creds, options);
585 test.run(client, done, extra);
586 };
587
588 if (test.getCreds) {
589 test.getCreds(extra.oauth_scope, function(err, new_creds) {
590 assert.ifError(err);
591 execute(err, grpc.credentials.combineChannelCredentials(
592 creds, new_creds));
593 });
594 } else {
595 execute(null, creds);
596 }
597 }
598
599 if (require.main === module) {
600 var parseArgs = require('minimist');
601 var argv = parseArgs(process.argv, {
602 string: ['server_host', 'server_host_override', 'server_port', 'test_case',
603 'use_tls', 'use_test_ca', 'default_service_account', 'oauth_scope',
604 'service_account_key_file']
605 });
606 var extra_args = {
607 service_account: argv.default_service_account,
608 oauth_scope: argv.oauth_scope
609 };
610 runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
611 argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
612 function () {
613 console.log('OK:', argv.test_case);
614 }, extra_args);
615 }
616
617 /**
618 * See docs for runTest
619 */
620 exports.runTest = runTest;
OLDNEW
« no previous file with comments | « third_party/grpc/src/node/interop/async_delay_queue.js ('k') | third_party/grpc/src/node/interop/interop_server.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698