aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/node/interop
diff options
context:
space:
mode:
Diffstat (limited to 'src/node/interop')
-rw-r--r--src/node/interop/interop_client.js188
-rw-r--r--src/node/interop/interop_server.js63
2 files changed, 158 insertions, 93 deletions
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 14cc6c0efe..cb55083d1a 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -44,12 +44,14 @@ var GoogleAuth = require('google-auth-library');
var assert = require('assert');
-var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
-var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
-var AUTH_USER = ('155450119199-vefjjaekcc6cmsd5914v6lqufunmh9ue' +
- '@developer.gserviceaccount.com');
-var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
- '@developer.gserviceaccount.com');
+var SERVICE_ACCOUNT_EMAIL;
+try {
+ SERVICE_ACCOUNT_EMAIL = require(
+ process.env.GOOGLE_APPLICATION_CREDENTIALS).client_email;
+} catch (e) {
+ // This will cause the tests to fail if they need that string
+ SERVICE_ACCOUNT_EMAIL = null;
+}
var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
@@ -345,6 +347,41 @@ function customMetadata(client, done) {
stream.end();
}
+function statusCodeAndMessage(client, done) {
+ done = multiDone(done, 2);
+ var arg = {
+ response_status: {
+ code: 2,
+ message: 'test status message'
+ }
+ };
+ client.unaryCall(arg, function(err, resp) {
+ assert(err);
+ assert.strictEqual(err.code, 2);
+ assert.strictEqual(err.message, 'test status message');
+ done();
+ });
+ var duplex = client.fullDuplexCall();
+ duplex.on('status', function(status) {
+ assert(status);
+ assert.strictEqual(status.code, 2);
+ assert.strictEqual(status.details, 'test status message');
+ done();
+ });
+ duplex.on('error', function(){});
+ duplex.write(arg);
+ duplex.end();
+}
+
+function unimplementedMethod(client, done) {
+ client.unimplementedCall({}, function(err, resp) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
+ assert(!err.message);
+ done();
+ });
+}
+
/**
* Run one of the authentication tests.
* @param {string} expected_user The expected username in the response
@@ -369,7 +406,7 @@ function authTest(expected_user, scope, client, done) {
assert.strictEqual(resp.payload.body.length, 314159);
assert.strictEqual(resp.username, expected_user);
if (scope) {
- assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
+ assert(scope.indexOf(resp.oauth_scope) > -1);
}
if (done) {
done();
@@ -377,56 +414,49 @@ function authTest(expected_user, scope, client, done) {
});
}
-function oauth2Test(expected_user, scope, per_rpc, client, done) {
- (new GoogleAuth()).getApplicationDefault(function(err, credential) {
+function computeEngineCreds(client, done, extra) {
+ authTest(extra.service_account, null, client, done);
+}
+
+function serviceAccountCreds(client, done, extra) {
+ authTest(SERVICE_ACCOUNT_EMAIL, extra.oauth_scope, client, done);
+}
+
+function jwtTokenCreds(client, done, extra) {
+ authTest(SERVICE_ACCOUNT_EMAIL, null, client, done);
+}
+
+function oauth2Test(client, done, extra) {
+ var arg = {
+ fill_username: true,
+ fill_oauth_scope: true
+ };
+ client.unaryCall(arg, function(err, resp) {
assert.ifError(err);
- var arg = {
- fill_username: true,
- fill_oauth_scope: true
- };
- credential = credential.createScoped(scope);
- credential.getAccessToken(function(err, token) {
- assert.ifError(err);
- var updateMetadata = function(authURI, metadata, callback) {
- metadata.add('authorization', 'Bearer ' + token);
- callback(null, metadata);
- };
- var makeTestCall = function(error, client_metadata) {
- assert.ifError(error);
- client.unaryCall(arg, function(err, resp) {
- assert.ifError(err);
- assert.strictEqual(resp.username, expected_user);
- assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
- if (done) {
- done();
- }
- }, client_metadata);
- };
- if (per_rpc) {
- updateMetadata('', new grpc.Metadata(), makeTestCall);
- } else {
- client.$updateMetadata = updateMetadata;
- makeTestCall(null, new grpc.Metadata());
- }
- });
+ assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
+ assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
+ if (done) {
+ done();
+ }
});
}
-function perRpcAuthTest(expected_user, scope, per_rpc, client, done) {
+function perRpcAuthTest(client, done, extra) {
(new GoogleAuth()).getApplicationDefault(function(err, credential) {
assert.ifError(err);
var arg = {
fill_username: true,
fill_oauth_scope: true
};
+ var scope = extra.oauth_scope;
if (credential.createScopedRequired() && scope) {
credential = credential.createScoped(scope);
}
var creds = grpc.credentials.createFromGoogleCredential(credential);
client.unaryCall(arg, function(err, resp) {
assert.ifError(err);
- assert.strictEqual(resp.username, expected_user);
- assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
+ assert.strictEqual(resp.username, SERVICE_ACCOUNT_EMAIL);
+ assert(extra.oauth_scope.indexOf(resp.oauth_scope) > -1);
if (done) {
done();
}
@@ -473,25 +503,44 @@ function getOauth2Creds(scope, callback) {
* Map from test case names to test functions
*/
var test_cases = {
- empty_unary: {run: emptyUnary},
- large_unary: {run: largeUnary},
- client_streaming: {run: clientStreaming},
- server_streaming: {run: serverStreaming},
- ping_pong: {run: pingPong},
- empty_stream: {run: emptyStream},
- cancel_after_begin: {run: cancelAfterBegin},
- cancel_after_first_response: {run: cancelAfterFirstResponse},
- timeout_on_sleeping_server: {run: timeoutOnSleepingServer},
- custom_metadata: {run: customMetadata},
- compute_engine_creds: {run: _.partial(authTest, COMPUTE_ENGINE_USER, null),
- getCreds: _.partial(getApplicationCreds, null)},
- service_account_creds: {run: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
- getCreds: _.partial(getApplicationCreds, AUTH_SCOPE)},
- jwt_token_creds: {run: _.partial(authTest, AUTH_USER, null),
- getCreds: _.partial(getApplicationCreds, null)},
- oauth2_auth_token: {run: _.partial(oauth2Test, AUTH_USER, AUTH_SCOPE, false),
- getCreds: _.partial(getOauth2Creds, AUTH_SCOPE)},
- per_rpc_creds: {run: _.partial(perRpcAuthTest, AUTH_USER, AUTH_SCOPE, true)}
+ empty_unary: {run: emptyUnary,
+ Client: testProto.TestService},
+ large_unary: {run: largeUnary,
+ Client: testProto.TestService},
+ client_streaming: {run: clientStreaming,
+ Client: testProto.TestService},
+ server_streaming: {run: serverStreaming,
+ Client: testProto.TestService},
+ ping_pong: {run: pingPong,
+ Client: testProto.TestService},
+ empty_stream: {run: emptyStream,
+ Client: testProto.TestService},
+ cancel_after_begin: {run: cancelAfterBegin,
+ Client: testProto.TestService},
+ cancel_after_first_response: {run: cancelAfterFirstResponse,
+ Client: testProto.TestService},
+ timeout_on_sleeping_server: {run: timeoutOnSleepingServer,
+ Client: testProto.TestService},
+ custom_metadata: {run: customMetadata,
+ Client: testProto.TestService},
+ status_code_and_message: {run: statusCodeAndMessage,
+ Client: testProto.TestService},
+ unimplemented_method: {run: unimplementedMethod,
+ Client: testProto.UnimplementedService},
+ compute_engine_creds: {run: computeEngineCreds,
+ Client: testProto.TestService,
+ getCreds: getApplicationCreds},
+ service_account_creds: {run: serviceAccountCreds,
+ Client: testProto.TestService,
+ getCreds: getApplicationCreds},
+ jwt_token_creds: {run: jwtTokenCreds,
+ Client: testProto.TestService,
+ getCreds: getApplicationCreds},
+ oauth2_auth_token: {run: oauth2Test,
+ Client: testProto.TestService,
+ getCreds: getOauth2Creds},
+ per_rpc_creds: {run: perRpcAuthTest,
+ Client: testProto.TestService}
};
/**
@@ -504,8 +553,9 @@ var test_cases = {
* @param {bool} tls Indicates that a secure channel should be used
* @param {function} done Callback to call when the test is completed. Included
* primarily for use with mocha
+ * @param {object=} extra Extra options for some tests
*/
-function runTest(address, host_override, test_case, tls, test_ca, done) {
+function runTest(address, host_override, test_case, tls, test_ca, done, extra) {
// TODO(mlumish): enable TLS functionality
var options = {};
var creds;
@@ -529,12 +579,13 @@ function runTest(address, host_override, test_case, tls, test_ca, done) {
var execute = function(err, creds) {
assert.ifError(err);
- var client = new testProto.TestService(address, creds, options);
- test.run(client, done);
+ var client = new test.Client(address, creds, options);
+ test.run(client, done, extra);
};
if (test.getCreds) {
- test.getCreds(function(err, new_creds) {
+ test.getCreds(extra.oauth_scope, function(err, new_creds) {
+ assert.ifError(err);
execute(err, grpc.credentials.combineChannelCredentials(
creds, new_creds));
});
@@ -547,13 +598,18 @@ if (require.main === module) {
var parseArgs = require('minimist');
var argv = parseArgs(process.argv, {
string: ['server_host', 'server_host_override', 'server_port', 'test_case',
- 'use_tls', 'use_test_ca']
+ 'use_tls', 'use_test_ca', 'default_service_account', 'oauth_scope',
+ 'service_account_key_file']
});
+ var extra_args = {
+ service_account: argv.default_service_account,
+ oauth_scope: argv.oauth_scope
+ };
runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
function () {
console.log('OK:', argv.test_case);
- });
+ }, extra_args);
}
/**
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index 3e83304faa..5321005c86 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -44,6 +44,9 @@ var testProto = grpc.load({
var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
+var incompressible_data = fs.readFileSync(
+ __dirname + '/../../../test/cpp/interop/rnd.dat');
+
/**
* Create a buffer filled with size zeroes
* @param {number} size The length of the buffer
@@ -83,6 +86,19 @@ function getEchoTrailer(call) {
return response_trailer;
}
+function getPayload(payload_type, size) {
+ if (payload_type === 'RANDOM') {
+ payload_type = ['COMPRESSABLE',
+ 'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+ }
+ var body;
+ switch (payload_type) {
+ case 'COMPRESSABLE': body = zeroBuffer(size); break;
+ case 'UNCOMPRESSABLE': incompressible_data.slice(size); break;
+ }
+ return {type: payload_type, body: body};
+}
+
/**
* Respond to an empty parameter with an empty response.
* NOTE: this currently does not work due to issue #137
@@ -104,13 +120,14 @@ function handleEmpty(call, callback) {
function handleUnary(call, callback) {
echoHeader(call);
var req = call.request;
- var zeros = zeroBuffer(req.response_size);
- var payload_type = req.response_type;
- if (payload_type === 'RANDOM') {
- payload_type = ['COMPRESSABLE',
- 'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+ if (req.response_status) {
+ var status = req.response_status;
+ status.metadata = getEchoTrailer(call);
+ callback(status);
+ return;
}
- callback(null, {payload: {type: payload_type, body: zeros}},
+ var payload = getPayload(req.response_type, req.response_size);
+ callback(null, {payload: payload},
getEchoTrailer(call));
}
@@ -139,18 +156,14 @@ function handleStreamingInput(call, callback) {
function handleStreamingOutput(call) {
echoHeader(call);
var req = call.request;
- var payload_type = req.response_type;
- if (payload_type === 'RANDOM') {
- payload_type = ['COMPRESSABLE',
- 'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+ if (req.response_status) {
+ var status = req.response_status;
+ status.metadata = getEchoTrailer(call);
+ call.emit('error', status);
+ return;
}
_.each(req.response_parameters, function(resp_param) {
- call.write({
- payload: {
- body: zeroBuffer(resp_param.size),
- type: payload_type
- }
- });
+ call.write({payload: getPayload(req.response_type, resp_param.size)});
});
call.end(getEchoTrailer(call));
}
@@ -163,18 +176,14 @@ function handleStreamingOutput(call) {
function handleFullDuplex(call) {
echoHeader(call);
call.on('data', function(value) {
- var payload_type = value.response_type;
- if (payload_type === 'RANDOM') {
- payload_type = ['COMPRESSABLE',
- 'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
+ if (value.response_status) {
+ var status = value.response_status;
+ status.metadata = getEchoTrailer(call);
+ call.emit('error', status);
+ return;
}
_.each(value.response_parameters, function(resp_param) {
- call.write({
- payload: {
- body: zeroBuffer(resp_param.size),
- type: payload_type
- }
- });
+ call.write({payload: getPayload(value.response_type, resp_param.size)});
});
});
call.on('end', function() {
@@ -188,7 +197,7 @@ function handleFullDuplex(call) {
* @param {Call} call Call to handle
*/
function handleHalfDuplex(call) {
- throw new Error('HalfDuplexCall not yet implemented');
+ call.emit('error', Error('HalfDuplexCall not yet implemented'));
}
/**