aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Jan Tattermusch <jtattermusch@users.noreply.github.com>2015-10-09 16:24:44 -0700
committerGravatar Jan Tattermusch <jtattermusch@users.noreply.github.com>2015-10-09 16:24:44 -0700
commitabaf47c3a57d5f00c2e75b98ed9a52b35252c4fa (patch)
tree55581316ee2818990ac31d8f219858ce7698e08f /src
parent8aad5a07bf1c24239939e14a34b306e26169d9a8 (diff)
parent5dbbd9178db5a26b9a765534a561cf1e0cba5e94 (diff)
Merge pull request #3746 from murgatroid99/node_interop_compliance
Made node interop tests maximally compliant with the spec
Diffstat (limited to 'src')
-rw-r--r--src/node/interop/interop_client.js188
-rw-r--r--src/node/interop/interop_server.js63
-rw-r--r--src/node/src/server.js2
-rw-r--r--src/node/test/async_test.js2
-rw-r--r--src/node/test/channel_test.js2
-rw-r--r--src/node/test/credentials_test.js10
-rw-r--r--src/node/test/interop_sanity_test.js10
7 files changed, 175 insertions, 102 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'));
}
/**
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 87b5b7ad06..a974d593c9 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -629,7 +629,7 @@ function Server(options) {
(new Metadata())._getCoreRepresentation();
batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
code: grpc.status.UNIMPLEMENTED,
- details: 'This method is not available on this server.',
+ details: '',
metadata: {}
};
batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
diff --git a/src/node/test/async_test.js b/src/node/test/async_test.js
index ce3ce50a2d..6d71ea24f5 100644
--- a/src/node/test/async_test.js
+++ b/src/node/test/async_test.js
@@ -57,7 +57,7 @@ describe('Async functionality', function() {
grpc.ServerCredentials.createInsecure());
server.start();
math_client = new math.Math('localhost:' + port_num,
- grpc.Credentials.createInsecure());
+ grpc.credentials.createInsecure());
done();
});
after(function() {
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index b86f89b8a8..05269f7b6e 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -149,7 +149,7 @@ describe('channel', function() {
afterEach(function() {
channel.close();
});
- it.only('should time out if called alone', function(done) {
+ it('should time out if called alone', function(done) {
var old_state = channel.getConnectivityState();
var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 1);
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 8eb91ee69e..7fc311a888 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -130,8 +130,8 @@ describe('client credentials', function() {
callback(null, metadata);
};
var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
- var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
- creds);
+ var combined_creds = grpc.credentials.combineChannelCredentials(
+ client_ssl_creds, creds);
var client = new Client('localhost:' + port, combined_creds,
client_options);
var call = client.unary({}, function(err, data) {
@@ -150,8 +150,8 @@ describe('client credentials', function() {
callback(null, metadata);
};
var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
- var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
- creds);
+ var combined_creds = grpc.credentials.combineChannelCredentials(
+ client_ssl_creds, creds);
var client = new Client('localhost:' + port, combined_creds,
client_options);
var call = client.unary({}, function(err, data) {
@@ -231,7 +231,7 @@ describe('client credentials', function() {
updater_creds, alt_updater_creds);
var call = client.unary({}, function(err, data) {
assert.ifError(err);
- }, null, {credentials: updater_creds});
+ }, null, {credentials: combined_updater});
call.on('metadata', function(metadata) {
assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
assert.deepEqual(metadata.get('other_plugin_key'),
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index 804c1d45e4..f8c0b14137 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -71,7 +71,7 @@ describe('Interop tests', function() {
interop_client.runTest(port, name_override, 'server_streaming', true, true,
done);
});
- it('should pass ping_pong', function(done) {
+ it.only('should pass ping_pong', function(done) {
interop_client.runTest(port, name_override, 'ping_pong', true, true, done);
});
it('should pass empty_stream', function(done) {
@@ -94,4 +94,12 @@ describe('Interop tests', function() {
interop_client.runTest(port, name_override, 'custom_metadata',
true, true, done);
});
+ it('should pass status_code_and_message', function(done) {
+ interop_client.runTest(port, name_override, 'status_code_and_message',
+ true, true, done);
+ });
+ it('should pass unimplemented_method', function(done) {
+ interop_client.runTest(port, name_override, 'unimplemented_method',
+ true, true, done);
+ });
});