Add basic tests for C# interceptors
diff --git a/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs b/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs
new file mode 100644
index 0000000..0904c51
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs
@@ -0,0 +1,76 @@
+#region Copyright notice and license
+
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Interceptors;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using Grpc.Core.Tests;
+using NUnit.Framework;
+
+namespace Grpc.Core.Interceptors.Tests
+{
+    public class ClientInterceptorTest
+    {
+        private class AddHeaderClientInterceptor : Interceptor
+        {
+            readonly Metadata.Entry header;
+            public AddHeaderClientInterceptor(string key, string value)
+            {
+                this.header = new Metadata.Entry(key, value);
+            }
+            public override TResponse BlockingUnaryCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, BlockingUnaryCallContinuation<TRequest, TResponse> continuation)
+            {
+                context.Options.Headers.Add(this.header);
+                return continuation(request, context);
+            }
+
+            public Metadata.Entry Header
+            {
+                get
+                {
+                    return this.header;
+                }
+            }
+        }
+
+        const string Host = "127.0.0.1";
+
+        [Test]
+        public void AddRequestHeaderInClientInterceptor()
+        {
+            var helper = new MockServiceHelper(Host);
+            var interceptor = new AddHeaderClientInterceptor("x-client-interceptor", "hello world");
+            helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+            {
+                var interceptorHeader = context.RequestHeaders.Last(m => (m.Key == interceptor.Header.Key)).Value;
+                Assert.AreEqual(interceptorHeader, interceptor.Header.Value);
+                return Task.FromResult("PASS");
+            });
+            var server = helper.GetServer();
+            server.Start();
+            var callInvoker = helper.GetChannel().Intercept(interceptor);
+            Assert.AreEqual("PASS", callInvoker.BlockingUnaryCall(new Method<string, string>(MethodType.Unary, MockServiceHelper.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), Host, new CallOptions().WithHeaders(new Metadata()), ""));
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs b/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs
new file mode 100644
index 0000000..57ea3e3
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs
@@ -0,0 +1,79 @@
+#region Copyright notice and license
+
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Interceptors;
+using Grpc.Core.Internal;
+using Grpc.Core.Tests;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Interceptors.Tests
+{
+    public class ServerInterceptorTest
+    {
+        const string Host = "127.0.0.1";
+
+        private class AddRequestHeaderServerInterceptor : Interceptor
+        {
+            readonly Metadata.Entry header;
+
+            public AddRequestHeaderServerInterceptor(string key, string value)
+            {
+                this.header = new Metadata.Entry(key, value);
+            }
+
+            public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
+            {
+                context.RequestHeaders.Add(header);
+                return await continuation(request, context).ConfigureAwait(false);
+            }
+
+            public Metadata.Entry Header
+            {
+                get
+                {
+                    return header;
+                }
+            }
+        }
+
+        [Test]
+        public void AddRequestHeaderInServerInterceptor()
+        {
+            var helper = new MockServiceHelper(Host);
+            var interceptor = new AddRequestHeaderServerInterceptor("x-interceptor", "hello world");
+            helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
+            {
+                var interceptorHeader = context.RequestHeaders.Last(m => (m.Key == interceptor.Header.Key)).Value;
+                Assert.AreEqual(interceptorHeader, interceptor.Header.Value);
+                return Task.FromResult("PASS");
+            });
+            helper.ServiceDefinition = helper.ServiceDefinition.Intercept(interceptor);
+            var server = helper.GetServer();
+            server.Start();
+            var channel = helper.GetChannel();
+            Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), ""));
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
index 7f4677d..a925f86 100644
--- a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
+++ b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs
@@ -37,7 +37,6 @@
         public const string ServiceName = "tests.Test";
 
         readonly string host;
-        readonly ServerServiceDefinition serviceDefinition;
         readonly IEnumerable<ChannelOption> channelOptions;
 
         readonly Method<string, string> unaryMethod;
@@ -87,7 +86,7 @@
                 marshaller,
                 marshaller);
 
-            serviceDefinition = ServerServiceDefinition.CreateBuilder()
+            ServiceDefinition = ServerServiceDefinition.CreateBuilder()
                 .AddMethod(unaryMethod, (request, context) => unaryHandler(request, context))
                 .AddMethod(clientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context))
                 .AddMethod(serverStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context))
@@ -131,7 +130,7 @@
                 // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
                 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
                 {
-                    Services = { serviceDefinition },
+                    Services = { ServiceDefinition },
                     Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
                 };
             }
@@ -178,13 +177,7 @@
             }
         }
 
-        public ServerServiceDefinition ServiceDefinition
-        {
-            get
-            {
-                return this.serviceDefinition;
-            }
-        }
+        public ServerServiceDefinition ServiceDefinition { get; set; }
       
         public UnaryServerMethod<string, string> UnaryHandler
         {
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
index 469328a..60f67ff 100644
--- a/src/csharp/tests.json
+++ b/src/csharp/tests.json
@@ -1,5 +1,7 @@
 {
   "Grpc.Core.Tests": [
+    "Grpc.Core.Interceptors.Tests.ClientInterceptorTest",
+    "Grpc.Core.Interceptors.Tests.ServerInterceptorTest",
     "Grpc.Core.Internal.Tests.AsyncCallServerTest",
     "Grpc.Core.Internal.Tests.AsyncCallTest",
     "Grpc.Core.Internal.Tests.ChannelArgsSafeHandleTest",
@@ -59,4 +61,4 @@
     "Grpc.Reflection.Tests.ReflectionClientServerTest",
     "Grpc.Reflection.Tests.SymbolRegistryTest"
   ]
-}
\ No newline at end of file
+}