OLD | NEW |
(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; |
OLD | NEW |