Fixed some issues with new credential code
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index e2a0baf..fccb30f 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -729,13 +729,17 @@
 
 NAN_METHOD(Call::SetCredentials) {
   Nan::HandleScope scope;
+  if (!HasInstance(info.This())) {
+    return Nan::ThrowTypeError(
+        "setCredentials can only be called on Call objects");
+  }
   if (!Credentials::HasInstance(info[0])) {
     return Nan::ThrowTypeError(
         "setCredentials' first argument must be a credential");
   }
   Call *call = ObjectWrap::Unwrap<Call>(info.This());
   Credentials *creds_object = ObjectWrap::Unwrap<Credentials>(
-      Nan::To<Object>(info[1]).ToLocalChecked());
+      Nan::To<Object>(info[0]).ToLocalChecked());
   grpc_credentials *creds = creds_object->GetWrappedCredentials();
   grpc_call_error error = GRPC_CALL_ERROR;
   if (creds) {
diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc
index eb8c3ea..ec5cc5c 100644
--- a/src/node/ext/credentials.cc
+++ b/src/node/ext/credentials.cc
@@ -288,12 +288,16 @@
     return Nan::ThrowTypeError(
         "The callback's third argument must be an object");
   }
+  shared_ptr<Resources> resources(new Resources);
   grpc_status_code code = static_cast<grpc_status_code>(
       Nan::To<uint32_t>(info[0]).FromJust());
-  char *details = *Nan::Utf8String(info[1]);
+  //Utf8String details_str(info[1]);
+  //char *details = static_cast<char*>(calloc(details_str.length(), sizeof(char)));
+  //memcpy(details, *details_str, details_str.length());
+  char *details = *Utf8String(info[1]);
   grpc_metadata_array array;
   if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
-                           &array, shared_ptr<Resources>(new Resources))){
+                           &array, resources)){
     return Nan::ThrowError("Failed to parse metadata");
   }
   grpc_credentials_plugin_metadata_cb cb =
@@ -305,7 +309,6 @@
       Nan::Get(info.Callee(),
                Nan::New("user_data").ToLocalChecked()
                ).ToLocalChecked().As<External>()->Value();
-  gpr_log(GPR_DEBUG, "Calling plugin metadata callback");
   cb(user_data, array.metadata, array.count, code, details);
 }
 
@@ -329,13 +332,13 @@
   callback->Call(argc, argv);
   delete data;
   uv_unref((uv_handle_t *)async);
-  delete async;
+  uv_close((uv_handle_t *)async, (uv_close_cb)free);
 }
 
 void plugin_get_metadata(void *state, const char *service_url,
                          grpc_credentials_plugin_metadata_cb cb,
                          void *user_data) {
-  uv_async_t *async = new uv_async_t;
+  uv_async_t *async = static_cast<uv_async_t*>(malloc(sizeof(uv_async_t)));
   uv_async_init(uv_default_loop(),
                 async,
                 SendPluginCallback);
@@ -345,6 +348,8 @@
   data->cb = cb;
   data->user_data = user_data;
   async->data = data;
+  /* libuv says that it will coalesce calls to uv_async_send. If there is ever a
+   * problem with a callback not getting called, that is probably the reason */
   uv_async_send(async);
 }
 
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 0fae0fa..84cd7af 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -345,7 +345,9 @@
       fill_username: true,
       fill_oauth_scope: true
     };
-    credential = credential.createScoped(scope);
+    if (credential.createScopedRequired() && scope) {
+      credential = credential.createScoped(scope);
+    }
     var creds = grpc.credentials.createFromGoogleCredential(credential);
     client.unaryCall(arg, function(err, resp) {
       assert.ifError(err);
diff --git a/src/node/test/channel_test.js b/src/node/test/channel_test.js
index d81df2a..2e43622 100644
--- a/src/node/test/channel_test.js
+++ b/src/node/test/channel_test.js
@@ -149,12 +149,13 @@
     afterEach(function() {
       channel.close();
     });
-    it('should time out if called alone', function(done) {
+    it.only('should time out if called alone', function(done) {
       var old_state = channel.getConnectivityState();
       var deadline = new Date();
       deadline.setSeconds(deadline.getSeconds() + 1);
       channel.watchConnectivityState(old_state, deadline, function(err, value) {
         assert(err);
+        console.log('Callback from watchConnectivityState');
         done();
       });
     });
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index b18c267..23f01f8 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -39,7 +39,28 @@
 
 var grpc = require('..');
 
-describe('client credentials', function() {
+/**
+ * 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();
+    }
+  };
+}
+
+describe.only('client credentials', function() {
   var Client;
   var server;
   var port;
@@ -94,7 +115,15 @@
   after(function() {
     server.forceShutdown();
   });
-  it.only('Should update metadata with SSL creds', function(done) {
+  it('Should accept SSL creds for a client', function(done) {
+    var client = new Client('localhost:' + port, client_ssl_creds,
+                            client_options);
+    client.unary({}, function(err, data) {
+      assert.ifError(err);
+      done();
+    });
+  });
+  it('Should update metadata with SSL creds', function(done) {
     var metadataUpdater = function(service_url, callback) {
       var metadata = new grpc.Metadata();
       metadata.set('plugin_key', 'plugin_value');
@@ -103,16 +132,92 @@
     var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
     var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
                                                              creds);
-    //combined_creds = grpc.credentials.createInsecure();
     var client = new Client('localhost:' + port, combined_creds,
                             client_options);
     var call = client.unary({}, function(err, data) {
       assert.ifError(err);
-      console.log('Received response');
     });
     call.on('metadata', function(metadata) {
       assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
       done();
     });
   });
+  it('Should update metadata for two simultaneous calls', function(done) {
+    done = multiDone(done, 2);
+    var metadataUpdater = function(service_url, callback) {
+      var metadata = new grpc.Metadata();
+      metadata.set('plugin_key', 'plugin_value');
+      callback(null, metadata);
+    };
+    var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
+    var combined_creds = grpc.credentials.combineCredentials(client_ssl_creds,
+                                                             creds);
+    var client = new Client('localhost:' + port, combined_creds,
+                            client_options);
+    var call = client.unary({}, function(err, data) {
+      assert.ifError(err);
+    });
+    call.on('metadata', function(metadata) {
+      assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+      done();
+    });
+    var call2 = client.unary({}, function(err, data) {
+      assert.ifError(err);
+    });
+    call2.on('metadata', function(metadata) {
+      assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+      done();
+    });
+  });
+  describe('Per-rpc creds', function() {
+    var client;
+    var updater_creds;
+    before(function() {
+      client = new Client('localhost:' + port, client_ssl_creds,
+                          client_options);
+      var metadataUpdater = function(service_url, callback) {
+        var metadata = new grpc.Metadata();
+        metadata.set('plugin_key', 'plugin_value');
+        callback(null, metadata);
+      };
+      updater_creds = grpc.credentials.createFromMetadataGenerator(
+          metadataUpdater);
+    });
+    it('Should update metadata on a unary call', function(done) {
+      var call = client.unary({}, function(err, data) {
+        assert.ifError(err);
+      }, null, {credentials: updater_creds});
+      call.on('metadata', function(metadata) {
+        assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+        done();
+      });
+    });
+    it('should update metadata on a client streaming call', function(done) {
+      var call = client.clientStream(function(err, data) {
+        assert.ifError(err);
+      }, null, {credentials: updater_creds});
+      call.on('metadata', function(metadata) {
+        assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+        done();
+      });
+      call.end();
+    });
+    it('should update metadata on a server streaming call', function(done) {
+      var call = client.serverStream({}, null, {credentials: updater_creds});
+      call.on('data', function() {});
+      call.on('metadata', function(metadata) {
+        assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+        done();
+      });
+    });
+    it('should update metadata on a bidi streaming call', function(done) {
+      var call = client.bidiStream(null, {credentials: updater_creds});
+      call.on('data', function() {});
+      call.on('metadata', function(metadata) {
+        assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
+        done();
+      });
+      call.end();
+    });
+  });
 });