Merge pull request #1268 from murgatroid99/node_response_error_test

Fixed bugs in trailing metadata handling and math server example
diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js
index ae548c8..3fac193 100644
--- a/src/node/examples/math_server.js
+++ b/src/node/examples/math_server.js
@@ -33,10 +33,6 @@
 
 'use strict';
 
-var util = require('util');
-
-var Transform = require('stream').Transform;
-
 var grpc = require('..');
 var math = grpc.load(__dirname + '/math.proto').math;
 
@@ -54,11 +50,12 @@
   // Unary + is explicit coersion to integer
   if (+req.divisor === 0) {
     cb(new Error('cannot divide by zero'));
+  } else {
+    cb(null, {
+      quotient: req.dividend / req.divisor,
+      remainder: req.dividend % req.divisor
+    });
   }
-  cb(null, {
-    quotient: req.dividend / req.divisor,
-    remainder: req.dividend % req.divisor
-  });
 }
 
 /**
@@ -97,24 +94,19 @@
 }
 
 function mathDivMany(stream) {
-  // Here, call is a standard duplex Node object Stream
-  util.inherits(DivTransform, Transform);
-  function DivTransform() {
-    var options = {objectMode: true};
-    Transform.call(this, options);
-  }
-  DivTransform.prototype._transform = function(div_args, encoding, callback) {
+  stream.on('data', function(div_args) {
     if (+div_args.divisor === 0) {
-      callback(new Error('cannot divide by zero'));
+      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
+      });
     }
-    callback(null, {
-      quotient: div_args.dividend / div_args.divisor,
-      remainder: div_args.dividend % div_args.divisor
-    });
-  };
-  var transform = new DivTransform();
-  stream.pipe(transform);
-  transform.pipe(stream);
+  });
+  stream.on('end', function() {
+    stream.end();
+  });
 }
 
 var server = new Server({
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 05de162..eef705c 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -360,7 +360,9 @@
     }
     handler.func(emitter, function sendUnaryData(err, value, trailer) {
       if (err) {
-        err.metadata = trailer;
+        if (trailer) {
+          err.metadata = trailer;
+        }
         handleError(call, err);
       } else {
         sendUnaryResponse(call, value, handler.serialize, trailer);
@@ -406,7 +408,9 @@
   handler.func(stream, function(err, value, trailer) {
     stream.terminate();
     if (err) {
-      err.metadata = trailer;
+      if (trailer) {
+        err.metadata = trailer;
+      }
       handleError(call, err);
     } else {
       sendUnaryResponse(call, value, handler.serialize, trailer);
diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js
index d83f641..79df978 100644
--- a/src/node/test/math_client_test.js
+++ b/src/node/test/math_client_test.js
@@ -68,6 +68,13 @@
       done();
     });
   });
+  it('should handle an error from a unary request', function(done) {
+    var arg = {dividend: 7, divisor: 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 expected_results = [1, 1, 2, 3, 5, 8, 13];
@@ -115,4 +122,17 @@
       done();
     });
   });
+  it('should handle an error from a bidi request', function(done) {
+    var call = math_client.divMany();
+    call.on('data', function(value) {
+      assert.fail(value, undefined, 'Unexpected data response on failing call',
+                  '!=');
+    });
+    call.write({dividend: 7, divisor: 0});
+    call.end();
+    call.on('status', function checkStatus(status) {
+      assert.notEqual(status.code, grpc.status.OK);
+      done();
+    });
+  });
 });