Add fake credentials to the test and verify it actually works
diff --git a/Makefile b/Makefile
index 93b5f8b..74e3d1c 100644
--- a/Makefile
+++ b/Makefile
@@ -3009,6 +3009,7 @@
     $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc \
     test/cpp/util/cli_call.cc \
     test/cpp/util/create_test_channel.cc \
+    test/cpp/util/fake_credentials.cc \
 
 
 LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC))))
@@ -3054,6 +3055,7 @@
 endif
 $(OBJDIR)/$(CONFIG)/test/cpp/util/cli_call.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc
 $(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/fake_credentials.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/messages.grpc.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo.grpc.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.grpc.pb.cc
 
 
 LIBGRPC++_UNSECURE_SRC = \
diff --git a/build.json b/build.json
index 28a5b4b..ed7769a 100644
--- a/build.json
+++ b/build.json
@@ -540,7 +540,8 @@
         "test/cpp/util/echo.proto",
         "test/cpp/util/echo_duplicate.proto",
         "test/cpp/util/cli_call.cc",
-        "test/cpp/util/create_test_channel.cc"
+        "test/cpp/util/create_test_channel.cc",
+        "test/cpp/util/fake_credentials.cc"
       ]
     },
     {
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index d425c2e..9017641 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -33,11 +33,13 @@
 
 #include <thread>
 
+#include "src/core/security/credentials.h"
+#include "src/cpp/server/thread_pool.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/echo_duplicate.grpc.pb.h"
 #include "test/cpp/util/echo.grpc.pb.h"
-#include "src/cpp/server/thread_pool.h"
+#include "test/cpp/util/fake_credentials.h"
 #include <grpc++/channel_arguments.h>
 #include <grpc++/channel_interface.h>
 #include <grpc++/client_context.h>
@@ -106,6 +108,16 @@
     } else {
       EXPECT_FALSE(context->IsCancelled());
     }
+
+    if (request->has_param() && request->param().echo_metadata()) {
+      const std::multimap<grpc::string, grpc::string>& client_metadata =
+          context->client_metadata();
+      for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+               client_metadata.begin();
+           iter != client_metadata.end(); ++iter) {
+        context->AddTrailingMetadata((*iter).first, (*iter).second);
+      }
+    }
     return Status::OK;
   }
 
@@ -179,8 +191,7 @@
     server_address_ << "localhost:" << port;
     // Setup server
     ServerBuilder builder;
-    builder.AddListeningPort(server_address_.str(),
-                             InsecureServerCredentials());
+    builder.AddListeningPort(server_address_.str(), FakeServerCredentials());
     builder.RegisterService(&service_);
     builder.SetMaxMessageSize(
         kMaxMessageSize_);  // For testing max message size.
@@ -193,7 +204,7 @@
 
   void ResetStub() {
     std::shared_ptr<ChannelInterface> channel = CreateChannel(
-        server_address_.str(), InsecureCredentials(), ChannelArguments());
+        server_address_.str(), FakeCredentials(), ChannelArguments());
     stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel));
   }
 
@@ -405,7 +416,7 @@
 // The two stubs are created on the same channel.
 TEST_F(End2endTest, DiffPackageServices) {
   std::shared_ptr<ChannelInterface> channel = CreateChannel(
-      server_address_.str(), InsecureCredentials(), ChannelArguments());
+      server_address_.str(), FakeCredentials(), ChannelArguments());
 
   EchoRequest request;
   EchoResponse response;
@@ -438,7 +449,7 @@
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
-  grpc::string msg("hello");
+  request.set_message("Hello");
 
   Status s = stub->Echo(&context, request, &response);
   EXPECT_EQ("", response.message());
@@ -588,6 +599,20 @@
   EXPECT_FALSE(s.IsOk());
 }
 
+bool MetadataContains(const std::multimap<grpc::string, grpc::string>& metadata,
+                      const grpc::string& key, const grpc::string& value) {
+  int count = 0;
+
+  for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+           metadata.begin();
+       iter != metadata.end(); ++iter) {
+    if ((*iter).first == key && (*iter).second == value) {
+      count++;
+    }
+  }
+  return count == 1;
+}
+
 TEST_F(End2endTest, SetPerCallCredentials) {
   ResetStub();
   EchoRequest request;
@@ -596,12 +621,18 @@
   std::shared_ptr<Credentials> creds =
       IAMCredentials("fake_token", "fake_selector");
   context.set_credentials(creds);
-  grpc::string msg("Hello");
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
 
   Status s = stub_->Echo(&context, request, &response);
-  // TODO(yangg) verify creds at the server side.
   EXPECT_EQ(request.message(), response.message());
   EXPECT_TRUE(s.IsOk());
+  EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(),
+                               GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
+                               "fake_token"));
+  EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(),
+                               GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
+                               "fake_selector"));
 }
 
 TEST_F(End2endTest, InsecurePerCallCredentials) {
@@ -611,7 +642,8 @@
   ClientContext context;
   std::shared_ptr<Credentials> creds = InsecureCredentials();
   context.set_credentials(creds);
-  grpc::string msg("Hello");
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
 
   Status s = stub_->Echo(&context, request, &response);
   EXPECT_EQ(StatusCode::CANCELLED, s.code());
@@ -623,15 +655,22 @@
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
-  std::shared_ptr<Credentials> creds1 = SslCredentials(SslCredentialsOptions());
+  std::shared_ptr<Credentials> creds1 =
+      IAMCredentials("fake_token1", "fake_selector1");
   context.set_credentials(creds1);
   std::shared_ptr<Credentials> creds2 =
-      IAMCredentials("fake_token", "fake_selector");
+      IAMCredentials("fake_token2", "fake_selector2");
   context.set_credentials(creds2);
-  grpc::string msg("Hello");
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
 
   Status s = stub_->Echo(&context, request, &response);
-  // TODO(yangg) verify creds at the server side.
+  EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(),
+                               GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
+                               "fake_token2"));
+  EXPECT_TRUE(MetadataContains(context.GetServerTrailingMetadata(),
+                               GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
+                               "fake_selector2"));
   EXPECT_EQ(request.message(), response.message());
   EXPECT_TRUE(s.IsOk());
 }
diff --git a/test/cpp/util/fake_credentials.cc b/test/cpp/util/fake_credentials.cc
new file mode 100644
index 0000000..6b89e2f
--- /dev/null
+++ b/test/cpp/util/fake_credentials.cc
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/grpc_security.h>
+#include <grpc++/channel_arguments.h>
+#include <grpc++/credentials.h>
+#include <grpc++/server_credentials.h>
+#include "src/cpp/client/channel.h"
+#include "src/cpp/server/secure_server_credentials.h"
+
+namespace grpc {
+namespace testing {
+
+namespace {
+class FakeCredentialsImpl GRPC_FINAL : public Credentials {
+ public:
+  FakeCredentialsImpl()
+      : c_creds_(grpc_fake_transport_security_credentials_create()) {}
+  ~FakeCredentialsImpl() { grpc_credentials_release(c_creds_); }
+  SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return nullptr; }
+  std::shared_ptr<ChannelInterface> CreateChannel(
+      const grpc::string& target, const ChannelArguments& args) GRPC_OVERRIDE {
+    grpc_channel_args channel_args;
+    args.SetChannelArgs(&channel_args);
+    return std::shared_ptr<ChannelInterface>(new Channel(
+        target,
+        grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
+  }
+  bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE { return false; }
+
+ private:
+  grpc_credentials* const c_creds_;
+};
+
+}  // namespace
+
+std::shared_ptr<Credentials> FakeCredentials() {
+  return std::shared_ptr<Credentials>(new FakeCredentialsImpl());
+}
+
+std::shared_ptr<ServerCredentials> FakeServerCredentials() {
+  grpc_server_credentials* c_creds =
+      grpc_fake_transport_security_server_credentials_create();
+  return std::shared_ptr<ServerCredentials>(
+      new SecureServerCredentials(c_creds));
+}
+
+}  // namespace testing
+}  // namespace grpc
diff --git a/test/cpp/util/fake_credentials.h b/test/cpp/util/fake_credentials.h
new file mode 100644
index 0000000..7e134ce
--- /dev/null
+++ b/test/cpp/util/fake_credentials.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H
+#define GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H
+
+#include <memory>
+
+namespace grpc {
+class Credentials;
+class ServerCredentials;
+
+namespace testing {
+
+std::shared_ptr<Credentials> FakeCredentials();
+std::shared_ptr<ServerCredentials> FakeServerCredentials();
+
+}  // namespace testing
+}  // namespace grpc
+
+#endif  // GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H
diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto
index a79bce1..062f66c 100644
--- a/test/cpp/util/messages.proto
+++ b/test/cpp/util/messages.proto
@@ -36,6 +36,7 @@
   optional bool echo_deadline = 1;
   optional int32 client_cancel_after_us = 2;
   optional int32 server_cancel_after_us = 3;
+  optional bool echo_metadata = 4;
 }
 
 message EchoRequest {