aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/node
diff options
context:
space:
mode:
Diffstat (limited to 'src/node')
-rw-r--r--src/node/.gitignore2
-rw-r--r--src/node/.jshintignore1
-rw-r--r--src/node/.jshintrc28
-rw-r--r--src/node/ext/node_grpc.cc35
-rw-r--r--src/node/ext/server_credentials.cc4
-rw-r--r--src/node/index.js7
-rw-r--r--src/node/src/client.js3
-rw-r--r--src/node/src/server.js34
-rw-r--r--src/node/test/math/math_grpc_pb.js99
-rw-r--r--src/node/test/math/math_pb.js866
-rw-r--r--src/node/test/math/math_server.js40
-rw-r--r--src/node/test/math/node_modules/grpc.js37
-rw-r--r--src/node/test/math_client_test.js45
-rw-r--r--src/node/test/surface_test.js56
-rwxr-xr-xsrc/node/tools/bin/protoc.js4
-rwxr-xr-xsrc/node/tools/bin/protoc_plugin.js56
-rw-r--r--src/node/tools/package.json4
17 files changed, 1236 insertions, 85 deletions
diff --git a/src/node/.gitignore b/src/node/.gitignore
deleted file mode 100644
index e3fbd98336..0000000000
--- a/src/node/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build
-node_modules
diff --git a/src/node/.jshintignore b/src/node/.jshintignore
new file mode 100644
index 0000000000..0a73e1e2b6
--- /dev/null
+++ b/src/node/.jshintignore
@@ -0,0 +1 @@
+**/*_pb.js \ No newline at end of file
diff --git a/src/node/.jshintrc b/src/node/.jshintrc
deleted file mode 100644
index 8237e0d2b6..0000000000
--- a/src/node/.jshintrc
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "bitwise": true,
- "curly": true,
- "eqeqeq": true,
- "esnext": true,
- "freeze": true,
- "immed": true,
- "indent": 2,
- "latedef": "nofunc",
- "maxlen": 80,
- "newcap": true,
- "node": true,
- "noarg": true,
- "quotmark": "single",
- "strict": true,
- "trailing": true,
- "undef": true,
- "unused": "vars",
- "globals": {
- /* Mocha-provided globals */
- "describe": false,
- "it": false,
- "before": false,
- "beforeEach": false,
- "after": false,
- "afterEach": false
- }
-}
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index b988f29878..6b6e42737b 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -35,6 +35,8 @@
#include <nan.h>
#include <v8.h>
#include "grpc/grpc.h"
+#include "grpc/grpc_security.h"
+#include "grpc/support/alloc.h"
#include "call.h"
#include "call_credentials.h"
@@ -51,6 +53,8 @@ using v8::Object;
using v8::Uint32;
using v8::String;
+static char *pem_root_certs = NULL;
+
void InitStatusConstants(Local<Object> exports) {
Nan::HandleScope scope;
Local<Object> status = Nan::New<Object>();
@@ -268,9 +272,36 @@ NAN_METHOD(MetadataKeyIsBinary) {
grpc_is_binary_header(key_str, static_cast<size_t>(key->Length()))));
}
+static grpc_ssl_roots_override_result get_ssl_roots_override(
+ char **pem_root_certs_ptr) {
+ *pem_root_certs_ptr = pem_root_certs;
+ if (pem_root_certs == NULL) {
+ return GRPC_SSL_ROOTS_OVERRIDE_FAIL;
+ } else {
+ return GRPC_SSL_ROOTS_OVERRIDE_OK;
+ }
+}
+
+/* This should only be called once, and only before creating any
+ *ServerCredentials */
+NAN_METHOD(SetDefaultRootsPem) {
+ if (!info[0]->IsString()) {
+ return Nan::ThrowTypeError(
+ "setDefaultRootsPem's argument must be a string");
+ }
+ Nan::Utf8String utf8_roots(info[0]);
+ size_t length = static_cast<size_t>(utf8_roots.length());
+ if (length > 0) {
+ const char *data = *utf8_roots;
+ pem_root_certs = (char *)gpr_malloc((length + 1) * sizeof(char));
+ memcpy(pem_root_certs, data, length + 1);
+ }
+}
+
void init(Local<Object> exports) {
Nan::HandleScope scope;
grpc_init();
+ grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
InitStatusConstants(exports);
InitCallErrorConstants(exports);
InitOpTypeConstants(exports);
@@ -298,6 +329,10 @@ void init(Local<Object> exports) {
Nan::GetFunction(
Nan::New<FunctionTemplate>(MetadataKeyIsBinary)
).ToLocalChecked());
+ Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(),
+ Nan::GetFunction(
+ Nan::New<FunctionTemplate>(SetDefaultRootsPem)
+ ).ToLocalChecked());
}
NODE_MODULE(grpc_node, init)
diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc
index cff821aafc..a817ade518 100644
--- a/src/node/ext/server_credentials.cc
+++ b/src/node/ext/server_credentials.cc
@@ -146,7 +146,9 @@ NAN_METHOD(ServerCredentials::CreateSsl) {
"createSsl's second argument must be a list of objects");
}
- grpc_ssl_client_certificate_request_type client_certificate_request;
+ // Default to not requesting the client certificate
+ grpc_ssl_client_certificate_request_type client_certificate_request =
+ GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
if (info[2]->IsBoolean()) {
client_certificate_request =
Nan::To<bool>(info[2]).FromJust()
diff --git a/src/node/index.js b/src/node/index.js
index d345a5142d..66664d94b5 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -34,13 +34,10 @@
'use strict';
var path = require('path');
+var fs = require('fs');
var SSL_ROOTS_PATH = path.resolve(__dirname, '..', '..', 'etc', 'roots.pem');
-if (!process.env.GRPC_DEFAULT_SSL_ROOTS_FILE_PATH) {
- process.env.GRPC_DEFAULT_SSL_ROOTS_FILE_PATH = SSL_ROOTS_PATH;
-}
-
var _ = require('lodash');
var ProtoBuf = require('protobufjs');
@@ -53,6 +50,8 @@ var Metadata = require('./src/metadata.js');
var grpc = require('./src/grpc_extension');
+grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
+
/**
* Load a gRPC object from an existing ProtoBuf.Reflect object.
* @param {ProtoBuf.Reflect.Namespace} value The ProtoBuf object to load.
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 5e07046fc6..f75f951eb8 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -815,8 +815,7 @@ exports.waitForClientReady = function(client, deadline, callback) {
* @return {function(string, Object)} New client constructor
*/
exports.makeProtobufClientConstructor = function(service, options) {
- var method_attrs = common.getProtobufServiceAttrs(service, service.name,
- options);
+ var method_attrs = common.getProtobufServiceAttrs(service, options);
var deprecatedArgumentOrder = false;
if (options) {
deprecatedArgumentOrder = options.deprecatedArgumentOrder;
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 22128343a9..fd5153f124 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -684,6 +684,26 @@ Server.prototype.register = function(name, handler, serialize, deserialize,
return true;
};
+var unimplementedStatusResponse = {
+ code: grpc.status.UNIMPLEMENTED,
+ details: 'The server does not implement this method'
+};
+
+var defaultHandler = {
+ unary: function(call, callback) {
+ callback(unimplementedStatusResponse);
+ },
+ client_stream: function(call, callback) {
+ callback(unimplementedStatusResponse);
+ },
+ server_stream: function(call) {
+ call.emit('error', unimplementedStatusResponse);
+ },
+ bidi: function(call) {
+ call.emit('error', unimplementedStatusResponse);
+ }
+};
+
/**
* Add a service to the server, with a corresponding implementation. If you are
* generating this from a proto file, you should instead use
@@ -713,16 +733,18 @@ Server.prototype.addService = function(service, implementation) {
method_type = 'unary';
}
}
+ var impl;
if (implementation[name] === undefined) {
- throw new Error('Method handler for ' + attrs.path +
- ' not provided.');
+ console.warn('Method handler for %s expected but not provided',
+ attrs.path);
+ impl = defaultHandler[method_type];
+ } else {
+ impl = _.bind(implementation[name], implementation);
}
var serialize = attrs.responseSerialize;
var deserialize = attrs.requestDeserialize;
- var register_success = self.register(attrs.path,
- _.bind(implementation[name],
- implementation),
- serialize, deserialize, method_type);
+ var register_success = self.register(attrs.path, impl, serialize,
+ deserialize, method_type);
if (!register_success) {
throw new Error('Method handler for ' + attrs.path +
' already provided.');
diff --git a/src/node/test/math/math_grpc_pb.js b/src/node/test/math/math_grpc_pb.js
new file mode 100644
index 0000000000..083ed66913
--- /dev/null
+++ b/src/node/test/math/math_grpc_pb.js
@@ -0,0 +1,99 @@
+// GENERATED CODE -- DO NOT EDIT!
+
+'use strict';
+var grpc = require('grpc');
+var math_pb = require('./math_pb.js');
+
+function serialize_DivArgs(arg) {
+ if (!(arg instanceof math_pb.DivArgs)) {
+ throw new Error('Expected argument of type DivArgs');
+ }
+ return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_DivArgs(buffer_arg) {
+ return math_pb.DivArgs.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_DivReply(arg) {
+ if (!(arg instanceof math_pb.DivReply)) {
+ throw new Error('Expected argument of type DivReply');
+ }
+ return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_DivReply(buffer_arg) {
+ return math_pb.DivReply.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_FibArgs(arg) {
+ if (!(arg instanceof math_pb.FibArgs)) {
+ throw new Error('Expected argument of type FibArgs');
+ }
+ return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_FibArgs(buffer_arg) {
+ return math_pb.FibArgs.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_Num(arg) {
+ if (!(arg instanceof math_pb.Num)) {
+ throw new Error('Expected argument of type Num');
+ }
+ return new Buffer(arg.serializeBinary());
+}
+
+function deserialize_Num(buffer_arg) {
+ return math_pb.Num.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+
+var MathService = exports.MathService = {
+ div: {
+ path: '/math.Math/Div',
+ requestStream: false,
+ responseStream: false,
+ requestType: math_pb.DivArgs,
+ responseType: math_pb.DivReply,
+ requestSerialize: serialize_DivArgs,
+ requestDeserialize: deserialize_DivArgs,
+ responseSerialize: serialize_DivReply,
+ responseDeserialize: deserialize_DivReply,
+ },
+ divMany: {
+ path: '/math.Math/DivMany',
+ requestStream: true,
+ responseStream: true,
+ requestType: math_pb.DivArgs,
+ responseType: math_pb.DivReply,
+ requestSerialize: serialize_DivArgs,
+ requestDeserialize: deserialize_DivArgs,
+ responseSerialize: serialize_DivReply,
+ responseDeserialize: deserialize_DivReply,
+ },
+ fib: {
+ path: '/math.Math/Fib',
+ requestStream: false,
+ responseStream: true,
+ requestType: math_pb.FibArgs,
+ responseType: math_pb.Num,
+ requestSerialize: serialize_FibArgs,
+ requestDeserialize: deserialize_FibArgs,
+ responseSerialize: serialize_Num,
+ responseDeserialize: deserialize_Num,
+ },
+ sum: {
+ path: '/math.Math/Sum',
+ requestStream: true,
+ responseStream: false,
+ requestType: math_pb.Num,
+ responseType: math_pb.Num,
+ requestSerialize: serialize_Num,
+ requestDeserialize: deserialize_Num,
+ responseSerialize: serialize_Num,
+ responseDeserialize: deserialize_Num,
+ },
+};
+
+exports.MathClient = grpc.makeGenericClientConstructor(MathService);
diff --git a/src/node/test/math/math_pb.js b/src/node/test/math/math_pb.js
new file mode 100644
index 0000000000..3489143bec
--- /dev/null
+++ b/src/node/test/math/math_pb.js
@@ -0,0 +1,866 @@
+/**
+ * @fileoverview
+ * @enhanceable
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+goog.exportSymbol('proto.math.DivArgs', null, global);
+goog.exportSymbol('proto.math.DivReply', null, global);
+goog.exportSymbol('proto.math.FibArgs', null, global);
+goog.exportSymbol('proto.math.FibReply', null, global);
+goog.exportSymbol('proto.math.Num', null, global);
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.DivArgs = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.DivArgs, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.math.DivArgs.displayName = 'proto.math.DivArgs';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.DivArgs.prototype.toObject = function(opt_includeInstance) {
+ return proto.math.DivArgs.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.math.DivArgs} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.DivArgs.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ dividend: msg.getDividend(),
+ divisor: msg.getDivisor()
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.DivArgs}
+ */
+proto.math.DivArgs.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.math.DivArgs;
+ return proto.math.DivArgs.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.DivArgs} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.DivArgs}
+ */
+proto.math.DivArgs.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setDividend(value);
+ break;
+ case 2:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setDivisor(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.DivArgs} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivArgs.serializeBinaryToWriter = function(message, writer) {
+ message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.DivArgs.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ this.serializeBinaryToWriter(writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivArgs.prototype.serializeBinaryToWriter = function (writer) {
+ var f = undefined;
+ f = this.getDividend();
+ if (f !== 0) {
+ writer.writeInt64(
+ 1,
+ f
+ );
+ }
+ f = this.getDivisor();
+ if (f !== 0) {
+ writer.writeInt64(
+ 2,
+ f
+ );
+ }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.DivArgs} The clone.
+ */
+proto.math.DivArgs.prototype.cloneMessage = function() {
+ return /** @type {!proto.math.DivArgs} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 dividend = 1;
+ * @return {number}
+ */
+proto.math.DivArgs.prototype.getDividend = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value */
+proto.math.DivArgs.prototype.setDividend = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+/**
+ * optional int64 divisor = 2;
+ * @return {number}
+ */
+proto.math.DivArgs.prototype.getDivisor = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
+};
+
+
+/** @param {number} value */
+proto.math.DivArgs.prototype.setDivisor = function(value) {
+ jspb.Message.setField(this, 2, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.DivReply = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.DivReply, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.math.DivReply.displayName = 'proto.math.DivReply';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.DivReply.prototype.toObject = function(opt_includeInstance) {
+ return proto.math.DivReply.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.math.DivReply} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.DivReply.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ quotient: msg.getQuotient(),
+ remainder: msg.getRemainder()
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.DivReply}
+ */
+proto.math.DivReply.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.math.DivReply;
+ return proto.math.DivReply.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.DivReply} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.DivReply}
+ */
+proto.math.DivReply.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setQuotient(value);
+ break;
+ case 2:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setRemainder(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.DivReply} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivReply.serializeBinaryToWriter = function(message, writer) {
+ message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.DivReply.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ this.serializeBinaryToWriter(writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.DivReply.prototype.serializeBinaryToWriter = function (writer) {
+ var f = undefined;
+ f = this.getQuotient();
+ if (f !== 0) {
+ writer.writeInt64(
+ 1,
+ f
+ );
+ }
+ f = this.getRemainder();
+ if (f !== 0) {
+ writer.writeInt64(
+ 2,
+ f
+ );
+ }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.DivReply} The clone.
+ */
+proto.math.DivReply.prototype.cloneMessage = function() {
+ return /** @type {!proto.math.DivReply} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 quotient = 1;
+ * @return {number}
+ */
+proto.math.DivReply.prototype.getQuotient = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value */
+proto.math.DivReply.prototype.setQuotient = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+/**
+ * optional int64 remainder = 2;
+ * @return {number}
+ */
+proto.math.DivReply.prototype.getRemainder = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
+};
+
+
+/** @param {number} value */
+proto.math.DivReply.prototype.setRemainder = function(value) {
+ jspb.Message.setField(this, 2, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.FibArgs = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.FibArgs, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.math.FibArgs.displayName = 'proto.math.FibArgs';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.FibArgs.prototype.toObject = function(opt_includeInstance) {
+ return proto.math.FibArgs.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.math.FibArgs} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.FibArgs.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ limit: msg.getLimit()
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.FibArgs}
+ */
+proto.math.FibArgs.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.math.FibArgs;
+ return proto.math.FibArgs.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.FibArgs} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.FibArgs}
+ */
+proto.math.FibArgs.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setLimit(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.FibArgs} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibArgs.serializeBinaryToWriter = function(message, writer) {
+ message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.FibArgs.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ this.serializeBinaryToWriter(writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibArgs.prototype.serializeBinaryToWriter = function (writer) {
+ var f = undefined;
+ f = this.getLimit();
+ if (f !== 0) {
+ writer.writeInt64(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.FibArgs} The clone.
+ */
+proto.math.FibArgs.prototype.cloneMessage = function() {
+ return /** @type {!proto.math.FibArgs} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 limit = 1;
+ * @return {number}
+ */
+proto.math.FibArgs.prototype.getLimit = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value */
+proto.math.FibArgs.prototype.setLimit = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.Num = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.Num, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.math.Num.displayName = 'proto.math.Num';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.Num.prototype.toObject = function(opt_includeInstance) {
+ return proto.math.Num.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.math.Num} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.Num.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ num: msg.getNum()
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.Num}
+ */
+proto.math.Num.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.math.Num;
+ return proto.math.Num.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.Num} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.Num}
+ */
+proto.math.Num.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setNum(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.Num} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.Num.serializeBinaryToWriter = function(message, writer) {
+ message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.Num.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ this.serializeBinaryToWriter(writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.Num.prototype.serializeBinaryToWriter = function (writer) {
+ var f = undefined;
+ f = this.getNum();
+ if (f !== 0) {
+ writer.writeInt64(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.Num} The clone.
+ */
+proto.math.Num.prototype.cloneMessage = function() {
+ return /** @type {!proto.math.Num} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 num = 1;
+ * @return {number}
+ */
+proto.math.Num.prototype.getNum = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value */
+proto.math.Num.prototype.setNum = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.math.FibReply = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.math.FibReply, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.math.FibReply.displayName = 'proto.math.FibReply';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.math.FibReply.prototype.toObject = function(opt_includeInstance) {
+ return proto.math.FibReply.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.math.FibReply} msg The msg instance to transform.
+ * @return {!Object}
+ */
+proto.math.FibReply.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ count: msg.getCount()
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.math.FibReply}
+ */
+proto.math.FibReply.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.math.FibReply;
+ return proto.math.FibReply.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.math.FibReply} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.math.FibReply}
+ */
+proto.math.FibReply.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setCount(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Class method variant: serializes the given message to binary data
+ * (in protobuf wire format), writing to the given BinaryWriter.
+ * @param {!proto.math.FibReply} message
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibReply.serializeBinaryToWriter = function(message, writer) {
+ message.serializeBinaryToWriter(writer);
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.math.FibReply.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ this.serializeBinaryToWriter(writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format),
+ * writing to the given BinaryWriter.
+ * @param {!jspb.BinaryWriter} writer
+ */
+proto.math.FibReply.prototype.serializeBinaryToWriter = function (writer) {
+ var f = undefined;
+ f = this.getCount();
+ if (f !== 0) {
+ writer.writeInt64(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * Creates a deep clone of this proto. No data is shared with the original.
+ * @return {!proto.math.FibReply} The clone.
+ */
+proto.math.FibReply.prototype.cloneMessage = function() {
+ return /** @type {!proto.math.FibReply} */ (jspb.Message.cloneMessage(this));
+};
+
+
+/**
+ * optional int64 count = 1;
+ * @return {number}
+ */
+proto.math.FibReply.prototype.getCount = function() {
+ return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
+};
+
+
+/** @param {number} value */
+proto.math.FibReply.prototype.setCount = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+goog.object.extend(exports, proto.math);
diff --git a/src/node/test/math/math_server.js b/src/node/test/math/math_server.js
index 9f67c52ab0..fa05ed0165 100644
--- a/src/node/test/math/math_server.js
+++ b/src/node/test/math/math_server.js
@@ -34,8 +34,8 @@
'use strict';
var grpc = require('../..');
-var math = grpc.load(__dirname + '/../../../proto/math/math.proto').math;
-
+var grpcMath = require('./math_grpc_pb');
+var math = require('./math_pb');
/**
* Server function for division. Provides the /Math/DivMany and /Math/Div
@@ -46,14 +46,16 @@ var math = grpc.load(__dirname + '/../../../proto/math/math.proto').math;
*/
function mathDiv(call, cb) {
var req = call.request;
+ var divisor = req.getDivisor();
+ var dividend = req.getDividend();
// Unary + is explicit coersion to integer
- if (+req.divisor === 0) {
+ if (req.getDivisor() === 0) {
cb(new Error('cannot divide by zero'));
} else {
- cb(null, {
- quotient: req.dividend / req.divisor,
- remainder: req.dividend % req.divisor
- });
+ var response = new math.DivReply();
+ response.setQuotient(Math.floor(dividend / divisor));
+ response.setRemainder(dividend % divisor);
+ cb(null, response);
}
}
@@ -67,7 +69,9 @@ function mathFib(stream) {
// Here, call is a standard writable Node object Stream
var previous = 0, current = 1;
for (var i = 0; i < stream.request.limit; i++) {
- stream.write({num: current});
+ var response = new math.Num();
+ response.setNum(current);
+ stream.write(response);
var temp = current;
current += previous;
previous = temp;
@@ -85,22 +89,26 @@ function mathSum(call, cb) {
// Here, call is a standard readable Node object Stream
var sum = 0;
call.on('data', function(data) {
- sum += (+data.num);
+ sum += data.getNum();
});
call.on('end', function() {
- cb(null, {num: sum});
+ var response = new math.Num();
+ response.setNum(sum);
+ cb(null, response);
});
}
function mathDivMany(stream) {
stream.on('data', function(div_args) {
- if (+div_args.divisor === 0) {
+ var divisor = div_args.getDivisor();
+ var dividend = div_args.getDividend();
+ if (divisor === 0) {
stream.emit('error', new Error('cannot divide by zero'));
} else {
- stream.write({
- quotient: div_args.dividend / div_args.divisor,
- remainder: div_args.dividend % div_args.divisor
- });
+ var response = new math.DivReply();
+ response.setQuotient(Math.floor(dividend / divisor));
+ response.setRemainder(dividend % divisor);
+ stream.write(response);
}
});
stream.on('end', function() {
@@ -110,7 +118,7 @@ function mathDivMany(stream) {
function getMathServer() {
var server = new grpc.Server();
- server.addProtoService(math.Math.service, {
+ server.addService(grpcMath.MathService, {
div: mathDiv,
fib: mathFib,
sum: mathSum,
diff --git a/src/node/test/math/node_modules/grpc.js b/src/node/test/math/node_modules/grpc.js
new file mode 100644
index 0000000000..17c8fd96d9
--- /dev/null
+++ b/src/node/test/math/node_modules/grpc.js
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* This exists solely to allow the generated code to import the grpc module
+ * without using a relative path */
+
+module.exports = require('../../..');
diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js
index 3d44610536..34c16e070b 100644
--- a/src/node/test/math_client_test.js
+++ b/src/node/test/math_client_test.js
@@ -36,7 +36,8 @@
var assert = require('assert');
var grpc = require('..');
-var math = grpc.load(__dirname + '/../../proto/math/math.proto').math;
+var math = require('./math/math_pb');
+var MathClient = require('./math/math_grpc_pb').MathClient;
/**
* Client to use to make requests to a running server.
@@ -55,35 +56,41 @@ describe('Math client', function() {
var port_num = server.bind('0.0.0.0:0',
grpc.ServerCredentials.createInsecure());
server.start();
- math_client = new math.Math('localhost:' + port_num,
- grpc.credentials.createInsecure());
+ math_client = new MathClient('localhost:' + port_num,
+ grpc.credentials.createInsecure());
done();
});
after(function() {
server.forceShutdown();
});
it('should handle a single request', function(done) {
- var arg = {dividend: 7, divisor: 4};
+ var arg = new math.DivArgs();
+ arg.setDividend(7);
+ arg.setDivisor(4);
math_client.div(arg, function handleDivResult(err, value) {
assert.ifError(err);
- assert.equal(value.quotient, 1);
- assert.equal(value.remainder, 3);
+ assert.equal(value.getQuotient(), 1);
+ assert.equal(value.getRemainder(), 3);
done();
});
});
it('should handle an error from a unary request', function(done) {
- var arg = {dividend: 7, divisor: 0};
+ var arg = new math.DivArgs();
+ arg.setDividend(7);
+ arg.setDivisor(0);
math_client.div(arg, function handleDivResult(err, value) {
assert(err);
done();
});
});
it('should handle a server streaming request', function(done) {
- var call = math_client.fib({limit: 7});
+ var arg = new math.FibArgs();
+ arg.setLimit(7);
+ var call = math_client.fib(arg);
var expected_results = [1, 1, 2, 3, 5, 8, 13];
var next_expected = 0;
call.on('data', function checkResponse(value) {
- assert.equal(value.num, expected_results[next_expected]);
+ assert.equal(value.getNum(), expected_results[next_expected]);
next_expected += 1;
});
call.on('status', function checkStatus(status) {
@@ -94,10 +101,12 @@ describe('Math client', function() {
it('should handle a client streaming request', function(done) {
var call = math_client.sum(function handleSumResult(err, value) {
assert.ifError(err);
- assert.equal(value.num, 21);
+ assert.equal(value.getNum(), 21);
});
for (var i = 0; i < 7; i++) {
- call.write({'num': i});
+ var arg = new math.Num();
+ arg.setNum(i);
+ call.write(arg);
}
call.end();
call.on('status', function checkStatus(status) {
@@ -107,8 +116,8 @@ describe('Math client', function() {
});
it('should handle a bidirectional streaming request', function(done) {
function checkResponse(index, value) {
- assert.equal(value.quotient, index);
- assert.equal(value.remainder, 1);
+ assert.equal(value.getQuotient(), index);
+ assert.equal(value.getRemainder(), 1);
}
var call = math_client.divMany();
var response_index = 0;
@@ -117,7 +126,10 @@ describe('Math client', function() {
response_index += 1;
});
for (var i = 0; i < 7; i++) {
- call.write({dividend: 2 * i + 1, divisor: 2});
+ var arg = new math.DivArgs();
+ arg.setDividend(2 * i + 1);
+ arg.setDivisor(2);
+ call.write(arg);
}
call.end();
call.on('status', function checkStatus(status) {
@@ -131,7 +143,10 @@ describe('Math client', function() {
assert.fail(value, undefined, 'Unexpected data response on failing call',
'!=');
});
- call.write({dividend: 7, divisor: 0});
+ var arg = new math.DivArgs();
+ arg.setDividend(7);
+ arg.setDivisor(0);
+ call.write(arg);
call.end();
call.on('error', function checkStatus(status) {
done();
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index b96e8e487c..d8b36dc55c 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -143,21 +143,59 @@ describe('Server.prototype.addProtoService', function() {
server.addProtoService(mathService, dummyImpls);
});
});
- it('Should fail with missing handlers', function() {
- assert.throws(function() {
- server.addProtoService(mathService, {
- 'div': function() {},
- 'divMany': function() {},
- 'fib': function() {}
- });
- }, /math.Math.Sum/);
- });
it('Should fail if the server has been started', function() {
server.start();
assert.throws(function() {
server.addProtoService(mathService, dummyImpls);
});
});
+ describe('Default handlers', function() {
+ var client;
+ beforeEach(function() {
+ server.addProtoService(mathService, {});
+ var port = server.bind('localhost:0', server_insecure_creds);
+ var Client = surface_client.makeProtobufClientConstructor(mathService);
+ client = new Client('localhost:' + port,
+ grpc.credentials.createInsecure());
+ server.start();
+ });
+ it('should respond to a unary call with UNIMPLEMENTED', function(done) {
+ client.div({divisor: 4, dividend: 3}, function(error, response) {
+ assert(error);
+ assert.strictEqual(error.code, grpc.status.UNIMPLEMENTED);
+ done();
+ });
+ });
+ it('should respond to a client stream with UNIMPLEMENTED', function(done) {
+ var call = client.sum(function(error, respones) {
+ assert(error);
+ assert.strictEqual(error.code, grpc.status.UNIMPLEMENTED);
+ done();
+ });
+ call.end();
+ });
+ it('should respond to a server stream with UNIMPLEMENTED', function(done) {
+ var call = client.fib({limit: 5});
+ call.on('data', function(value) {
+ assert.fail('No messages expected');
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.UNIMPLEMENTED);
+ done();
+ });
+ });
+ it('should respond to a bidi call with UNIMPLEMENTED', function(done) {
+ var call = client.divMany();
+ call.on('data', function(value) {
+ assert.fail('No messages expected');
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.UNIMPLEMENTED);
+ done();
+ });
+ call.end();
+ });
+ });
});
describe('Client constructor building', function() {
var illegal_service_attrs = {
diff --git a/src/node/tools/bin/protoc.js b/src/node/tools/bin/protoc.js
index 0c6d7ce017..4d50c94b0f 100755
--- a/src/node/tools/bin/protoc.js
+++ b/src/node/tools/bin/protoc.js
@@ -43,7 +43,9 @@
var path = require('path');
var execFile = require('child_process').execFile;
-var protoc = path.resolve(__dirname, 'protoc');
+var exe_ext = process.platform === 'win32' ? '.exe' : '';
+
+var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
if (error) {
diff --git a/src/node/tools/bin/protoc_plugin.js b/src/node/tools/bin/protoc_plugin.js
new file mode 100755
index 0000000000..281ec0d85e
--- /dev/null
+++ b/src/node/tools/bin/protoc_plugin.js
@@ -0,0 +1,56 @@
+#!/usr/bin/env node
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * This file is required because package.json cannot reference a file that
+ * is not distributed with the package, and we use node-pre-gyp to distribute
+ * the plugin binary
+ */
+
+'use strict';
+
+var path = require('path');
+var execFile = require('child_process').execFile;
+
+var exe_ext = process.platform === 'win32' ? '.exe' : '';
+
+var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
+
+execFile(plugin, process.argv.slice(2), function(error, stdout, stderr) {
+ if (error) {
+ throw error;
+ }
+ console.log(stdout);
+ console.log(stderr);
+});
diff --git a/src/node/tools/package.json b/src/node/tools/package.json
index 4b3499f2f9..d98ed0b1fc 100644
--- a/src/node/tools/package.json
+++ b/src/node/tools/package.json
@@ -16,7 +16,8 @@
}
],
"bin": {
- "grpc-tools-protoc": "./bin/protoc.js"
+ "grpc-tools-protoc": "./bin/protoc.js",
+ "grpc-tools-plugin": "./bin/protoc_plugin.js"
},
"scripts": {
"install": "./node_modules/.bin/node-pre-gyp install"
@@ -32,6 +33,7 @@
"files": [
"index.js",
"bin/protoc.js",
+ "bin/protoc_plugin.js",
"LICENSE"
],
"main": "index.js"