aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/node/interop
diff options
context:
space:
mode:
authorGravatar murgatroid99 <mlumish@google.com>2015-08-27 09:26:33 -0700
committerGravatar murgatroid99 <mlumish@google.com>2015-08-27 09:26:33 -0700
commit1eb113c61ed87dbc12d9e76649e206190ccd3c4a (patch)
tree11293cb8e7528dc837fcc80d3edddd149adde6f5 /src/node/interop
parent5390692976b796e7aa3069d631433f00343c1165 (diff)
Add metadata echo functionality to interop server, and corresponding interop test
Diffstat (limited to 'src/node/interop')
-rw-r--r--src/node/interop/interop_client.js73
-rw-r--r--src/node/interop/interop_server.js48
2 files changed, 116 insertions, 5 deletions
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 8fb8d66920..14ae045275 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -49,6 +49,9 @@ var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
'@developer.gserviceaccount.com');
+var ECHO_INITIAL_KEY = "x-grpc-test-echo-initial";
+var ECHO_TRAILING_KEY = "x-grpc-test-echo-trailing-bin";
+
/**
* Create a buffer filled with size zeroes
* @param {number} size The length of the buffer
@@ -61,6 +64,27 @@ function zeroBuffer(size) {
}
/**
+ * This is used for testing functions with multiple asynchronous calls that
+ * can happen in different orders. This should be passed the number of async
+ * function invocations that can occur last, and each of those should call this
+ * function's return value
+ * @param {function()} done The function that should be called when a test is
+ * complete.
+ * @param {number} count The number of calls to the resulting function if the
+ * test passes.
+ * @return {function()} The function that should be called at the end of each
+ * sequence of asynchronous functions.
+ */
+function multiDone(done, count) {
+ return function() {
+ count -= 1;
+ if (count <= 0) {
+ done();
+ }
+ };
+}
+
+/**
* Run the empty_unary test
* @param {Client} client The client to test against
* @param {function} done Callback to call when the test is completed. Included
@@ -271,6 +295,54 @@ function timeoutOnSleepingServer(client, done) {
});
}
+function customMetadata(client, done) {
+ done = multiDone(done, 5);
+ var metadata = new grpc.Metadata();
+ metadata.set(ECHO_INITIAL_KEY, 'test_initial_metadata_value');
+ metadata.set(ECHO_TRAILING_KEY, new Buffer('ababab', 'hex'));
+ var arg = {
+ response_type: 'COMPRESSABLE',
+ response_size: 314159,
+ payload: {
+ body: zeroBuffer(271828)
+ }
+ };
+ var streaming_arg = {
+ payload: {
+ body: zeroBuffer(271828)
+ }
+ };
+ var unary = client.unaryCall(arg, function(err, resp) {
+ assert.ifError(err);
+ done();
+ }, metadata);
+ unary.on('metadata', function(metadata) {
+ assert.deepEqual(metadata.get(ECHO_INITIAL_KEY),
+ ['test_initial_metadata_value']);
+ done();
+ });
+ unary.on('status', function(status) {
+ var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
+ assert(echo_trailer.length > 0);
+ assert.strictEqual(echo_trailer.toString('hex'), 'ababab');
+ done();
+ });
+ var stream = client.fullDuplexCall(metadata);
+ stream.on('metadata', function(metadata) {
+ assert.deepEqual(metadata.get(ECHO_INITIAL_KEY),
+ ['test_initial_metadata_value']);
+ done();
+ });
+ stream.on('status', function(status) {
+ var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
+ assert(echo_trailer.length > 0);
+ assert.strictEqual(echo_trailer.toString('hex'), 'ababab');
+ done();
+ });
+ stream.write(streaming_arg);
+ stream.end();
+}
+
/**
* Run one of the authentication tests.
* @param {string} expected_user The expected username in the response
@@ -358,6 +430,7 @@ var test_cases = {
cancel_after_begin: cancelAfterBegin,
cancel_after_first_response: cancelAfterFirstResponse,
timeout_on_sleeping_server: timeoutOnSleepingServer,
+ custom_metadata: customMetadata,
compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
jwt_token_creds: _.partial(authTest, AUTH_USER, null),
diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js
index 99155e9958..c23f237680 100644
--- a/src/node/interop/interop_server.js
+++ b/src/node/interop/interop_server.js
@@ -39,6 +39,9 @@ var _ = require('lodash');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
+var ECHO_INITIAL_KEY = "x-grpc-test-echo-initial";
+var ECHO_TRAILING_KEY = "x-grpc-test-echo-trailing-bin";
+
/**
* Create a buffer filled with size zeroes
* @param {number} size The length of the buffer
@@ -51,6 +54,34 @@ function zeroBuffer(size) {
}
/**
+ * Echos a header metadata item as specified in the interop spec.
+ * @param {Call} call The call to echo metadata on
+ */
+function echoHeader(call) {
+ var echo_initial = call.metadata.get(ECHO_INITIAL_KEY);
+ if (echo_initial.length > 0) {
+ var response_metadata = new grpc.Metadata();
+ response_metadata.set(ECHO_INITIAL_KEY, echo_initial[0]);
+ call.sendMetadata(response_metadata);
+ }
+}
+
+/**
+ * Gets the trailer metadata that should be echoed when the call is done,
+ * as specified in the interop spec.
+ * @param {Call} call The call to get metadata from
+ * @return {grpc.Metadata} The metadata to send as a trailer
+ */
+function getEchoTrailer(call) {
+ var echo_trailer = call.metadata.get(ECHO_TRAILING_KEY);
+ var response_trailer = new grpc.Metadata();
+ if (echo_trailer.length > 0) {
+ response_trailer.set(ECHO_TRAILING_KEY, echo_trailer[0]);
+ }
+ return response_trailer;
+}
+
+/**
* Respond to an empty parameter with an empty response.
* NOTE: this currently does not work due to issue #137
* @param {Call} call Call to handle
@@ -58,7 +89,8 @@ function zeroBuffer(size) {
* or error
*/
function handleEmpty(call, callback) {
- callback(null, {});
+ echoHeader(call);
+ callback(null, {}, getEchoTrailer(call));
}
/**
@@ -68,6 +100,7 @@ function handleEmpty(call, callback) {
* error
*/
function handleUnary(call, callback) {
+ echoHeader(call);
var req = call.request;
var zeros = zeroBuffer(req.response_size);
var payload_type = req.response_type;
@@ -75,7 +108,8 @@ function handleUnary(call, callback) {
payload_type = ['COMPRESSABLE',
'UNCOMPRESSABLE'][Math.random() < 0.5 ? 0 : 1];
}
- callback(null, {payload: {type: payload_type, body: zeros}});
+ callback(null, {payload: {type: payload_type, body: zeros}},
+ getEchoTrailer(call));
}
/**
@@ -85,12 +119,14 @@ function handleUnary(call, callback) {
* error
*/
function handleStreamingInput(call, callback) {
+ echoHeader(call);
var aggregate_size = 0;
call.on('data', function(value) {
aggregate_size += value.payload.body.length;
});
call.on('end', function() {
- callback(null, {aggregated_payload_size: aggregate_size});
+ callback(null, {aggregated_payload_size: aggregate_size},
+ getEchoTrailer(call));
});
}
@@ -99,6 +135,7 @@ function handleStreamingInput(call, callback) {
* @param {Call} call Call to handle
*/
function handleStreamingOutput(call) {
+ echoHeader(call);
var req = call.request;
var payload_type = req.response_type;
if (payload_type === 'RANDOM') {
@@ -113,7 +150,7 @@ function handleStreamingOutput(call) {
}
});
});
- call.end();
+ call.end(getEchoTrailer(call));
}
/**
@@ -122,6 +159,7 @@ function handleStreamingOutput(call) {
* @param {Call} call Call to handle
*/
function handleFullDuplex(call) {
+ echoHeader(call);
call.on('data', function(value) {
var payload_type = value.response_type;
if (payload_type === 'RANDOM') {
@@ -138,7 +176,7 @@ function handleFullDuplex(call) {
});
});
call.on('end', function() {
- call.end();
+ call.end(getEchoTrailer(call));
});
}