Merge pull request #7008 from jtattermusch/csharp_no_new_client

Remove generated NewClient factory method for C#.
diff --git a/Rakefile b/Rakefile
index f208a24..f44946f 100755
--- a/Rakefile
+++ b/Rakefile
@@ -77,7 +77,7 @@
   grpc_config = ENV['GRPC_CONFIG'] || 'opt'
   verbose = ENV['V'] || '0'
 
-  env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE" '
+  env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result" '
   env += 'LDFLAGS=-static '
   env += 'SYSTEM=MINGW32 '
   env += 'EMBED_ZLIB=true '
diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md
index 357ea72..31d694b 100644
--- a/doc/PROTOCOL-HTTP2.md
+++ b/doc/PROTOCOL-HTTP2.md
@@ -38,7 +38,7 @@
 * **Nanosecond** → "n"
 * **Content-Type** → "content-type" "application/grpc" [("+proto" / "+json" / {_custom_})]
 * **Content-Coding** → "identity" / "gzip" / "deflate" / "snappy" / {_custom_}
-* **Message-Encoding** → "grpc-encoding" Content-Coding
+* <a name="message-encoding"></a>**Message-Encoding** → "grpc-encoding" Content-Coding
 * **Message-Accept-Encoding** → "grpc-accept-encoding" Content-Coding \*("," Content-Coding)
 * **User-Agent** → "user-agent" {_structured user-agent string_}
 * **Message-Type** → "grpc-message-type" {_type name for message schema_}
@@ -83,7 +83,7 @@
 The repeated sequence of **Length-Prefixed-Message** items is delivered in DATA frames
 
 * **Length-Prefixed-Message** → Compressed-Flag Message-Length Message
-* **Compressed-Flag** → 0 / 1   # encoded as 1 byte unsigned integer
+* <a name="compressed-flag"></a>**Compressed-Flag** → 0 / 1   # encoded as 1 byte unsigned integer
 * **Message-Length** → {_length of Message_}  # encoded as 4 byte unsigned integer
 * **Message** → \*{binary octet}
 
diff --git a/doc/compression.md b/doc/compression.md
new file mode 100644
index 0000000..15fae4d
--- /dev/null
+++ b/doc/compression.md
@@ -0,0 +1,111 @@
+## **gRPC Compression**
+
+The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
+"SHOULD NOT", "RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to be
+interpreted as described in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt).
+
+### Intent
+
+Compression is used to reduce the amount of bandwidth used between peers. The
+compression supported by gRPC acts _at the individual message level_, taking
+_message_ [as defined in the wire format
+document](PROTOCOL-HTTP2.md).
+
+The implementation supports different compression algorithms. A _default
+compression level_, to be used in the absence of message-specific settings, MAY
+be specified for during channel creation.
+
+The ability to control compression settings per call and to enable/disable
+compression on a per message basis MAY be used to prevent CRIME/BEAST attacks.
+It also allows for asymmetric compression communication, whereby a response MAY
+be compressed differently, if at all.
+
+### Specification
+
+Compression MAY be configured by the Client Application by calling the
+appropriate API method. There are two scenarios where compression MAY be
+configured:
+
++  At channel creation time, which sets the channel default compression and
+   therefore the compression that SHALL be used in the absence of per-RPC
+   compression configuration.
++  At response time, via:
+   +  For unary RPCs, the {Client,Server}Context instance. 
+   +  For streaming RPCs, the {Client,Server}Writer instance. In this case,
+      configuration is reduced to disabling compression altogether.
+
+### Compression Method Asymmetry Between Peers
+
+A gRPC peer MAY choose to respond using a different compression method to that
+of the request, including not performing any compression, regardless of channel
+and RPC settings (for example, if compression would result in small or negative
+gains).
+
+When a message from a client compressed with an unsupported algorithm is
+processed by a server, it WILL result in an INVALID\_ARGUMENT error on the
+server. The server will then include in its response a `grpc-accept-encoding`
+header specifying the algorithms it does accept. If an INTERNAL error is
+returned from the server despite having used one of the algorithms from the
+`grpc-accept-encoding` header, the cause MUST NOT be related to compression.
+Data sent from a server compressed with an algorithm not supported by the client
+WILL result in an INTERNAL error on the client side.
+
+Note that a peer MAY choose to not disclose all the encodings it supports.
+However, if it receives a message compressed in an undisclosed but supported
+encoding, it MUST include said encoding in the response's `grpc-accept-encoding
+h`eader.
+
+For every message a server is requested to compress using an algorithm it knows
+the client doesn't support (as indicated by the last `grpc-accept-encoding`
+header received from the client), it SHALL send the message uncompressed. 
+
+### Specific Disabling of Compression
+
+If the user (through the previously described mechanisms) requests to disable
+compression the next message MUST be sent uncompressed. This is instrumental in
+preventing BEAST/CRIME attacks. This applies to both the the unary and streaming
+cases.
+
+### Compression Levels and Algorithms
+
+The set of supported algorithm is implementation dependent. In order to simplify
+the public API and to operate seamlessly across implementations (both in terms
+of languages but also different version of the same one), we introduce the idea
+of _compression levels_ (such as "low", "medium", "high").
+
+Levels map to concrete algorithms and/or their settings (such as "low" mapping
+to "gzip -3" and "high" mapping to "gzip -9") automatically depending on what a
+peer is known to support. A server is always aware of what its clients support,
+as clients disclose it in their Message-Accept-Encoding header as part of their
+initial call. A client doesn't a priori (presently) know which algorithms a
+server supports. This issue can be addressed with an initial negotiation of
+capabilities or an automatic retry mechanism. These features will be implemented
+in the future. Currently however, compression levels are only supported at the
+server side, which is aware of the client's capabilities through the incoming
+Message-Accept-Encoding header.
+
+### Propagation to child RPCs
+
+The inheritance of the compression configuration by child RPCs is left up to the
+implementation. Note that in the absence of changes to the parent channel, its
+configuration will be used.
+
+### Test cases
+
+1. When a compression level is not specified for either the channel or the
+message, the default channel level _none_ is considered: data MUST NOT be
+compressed.
+1. When per-RPC compression configuration isn't present for a message, the
+channel compression configuration MUST be used.
+1. When a compression method (including no compression) is specified for an
+outgoing message, the message MUST be compressed accordingly.
+1. A message compressed in a way not supported by its endpoint MUST fail with
+INVALID\_ARGUMENT status, its associated description indicating the unsupported
+condition as well as the supported ones. The returned `grpc-accept-encoding`
+header MUST NOT contain the compression method (encoding) used.
+1. An ill-constructed message with its [Compressed-Flag
+bit](PROTOCOL-HTTP2.md#compressed-flag)
+set but lacking a
+"[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding)"
+entry different from _identity_ in its metadata MUST fail with INTERNAL status,
+its associated description indicating the invalid Compressed-Flag condition.
diff --git a/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj b/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj
index 51a39c5..ab7419c 100644
--- a/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj
+++ b/examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj
@@ -116,11 +116,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 63E1E9A21B28CB2100EF0978 /* Build configuration list for PBXNativeTarget "AuthSample" */;
 			buildPhases = (
-				DAABBA7B5788A39108D7CA83 /* Check Pods Manifest.lock */,
+				DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */,
 				63E1E9781B28CB2000EF0978 /* Sources */,
 				63E1E9791B28CB2000EF0978 /* Frameworks */,
 				63E1E97A1B28CB2000EF0978 /* Resources */,
-				AEFCCC69DD59CE8F6EB769D7 /* Copy Pods Resources */,
+				AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */,
+				D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -177,14 +178,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		AEFCCC69DD59CE8F6EB769D7 /* Copy Pods Resources */ = {
+		AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Copy Pods Resources";
+			name = "[CP] Copy Pods Resources";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -192,14 +193,29 @@
 			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		DAABBA7B5788A39108D7CA83 /* Check Pods Manifest.lock */ = {
+		D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Check Pods Manifest.lock";
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/examples/objective-c/auth_sample/AuthTestService.podspec b/examples/objective-c/auth_sample/AuthTestService.podspec
index e935626..d246653 100644
--- a/examples/objective-c/auth_sample/AuthTestService.podspec
+++ b/examples/objective-c/auth_sample/AuthTestService.podspec
@@ -2,6 +2,10 @@
   s.name     = "AuthTestService"
   s.version  = "0.0.1"
   s.license  = "New BSD"
+  s.authors  = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
+  s.homepage = "http://www.grpc.io/"
+  s.summary = "AuthTestService example"
+  s.source = { :git => 'https://github.com/grpc/grpc.git' }
 
   s.ios.deployment_target = "7.1"
   s.osx.deployment_target = "10.9"
diff --git a/examples/objective-c/helloworld/HelloWorld.podspec b/examples/objective-c/helloworld/HelloWorld.podspec
index bdf782f..17b016b 100644
--- a/examples/objective-c/helloworld/HelloWorld.podspec
+++ b/examples/objective-c/helloworld/HelloWorld.podspec
@@ -2,6 +2,10 @@
   s.name     = "HelloWorld"
   s.version  = "0.0.1"
   s.license  = "New BSD"
+  s.authors  = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
+  s.homepage = "http://www.grpc.io/"
+  s.summary = "HelloWorld example"
+  s.source = { :git => 'https://github.com/grpc/grpc.git' }
 
   s.ios.deployment_target = "7.1"
   s.osx.deployment_target = "10.9"
diff --git a/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj b/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj
index 250f009..df5c40c 100644
--- a/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj
+++ b/examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj
@@ -7,7 +7,6 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		3EF35C14BDC2B65E21837F02 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43AB08B32839A6700EA00DD4 /* libPods.a */; };
 		5E3690661B2A23800040F884 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690651B2A23800040F884 /* main.m */; };
 		5E3690691B2A23800040F884 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690681B2A23800040F884 /* AppDelegate.m */; };
 		5E36906C1B2A23800040F884 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E36906B1B2A23800040F884 /* ViewController.m */; };
@@ -18,7 +17,6 @@
 
 /* Begin PBXFileReference section */
 		0C432EF610DB15C0F47A66BB /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = "<group>"; };
-		43AB08B32839A6700EA00DD4 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		5E3690601B2A23800040F884 /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		5E3690641B2A23800040F884 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		5E3690651B2A23800040F884 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -37,7 +35,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				EF61CF6AE2536A31D47F0E63 /* libPods-HelloWorld.a in Frameworks */,
-				3EF35C14BDC2B65E21837F02 /* libPods.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -88,7 +85,6 @@
 			isa = PBXGroup;
 			children = (
 				6B4E1F55F8A2EC95A0E7EE88 /* libPods-HelloWorld.a */,
-				43AB08B32839A6700EA00DD4 /* libPods.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -109,12 +105,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 5E3690831B2A23810040F884 /* Build configuration list for PBXNativeTarget "HelloWorld" */;
 			buildPhases = (
-				ACF9162361FB8F24C70657DE /* Check Pods Manifest.lock */,
+				ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */,
 				5E36905C1B2A23800040F884 /* Sources */,
 				5E36905D1B2A23800040F884 /* Frameworks */,
 				5E36905E1B2A23800040F884 /* Resources */,
-				4C7D815378D98AB3BFC1A7D5 /* Copy Pods Resources */,
-				BB76529986A8BFAF19A385B1 /* Embed Pods Frameworks */,
+				4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */,
+				BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -170,14 +166,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		4C7D815378D98AB3BFC1A7D5 /* Copy Pods Resources */ = {
+		4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Copy Pods Resources";
+			name = "[CP] Copy Pods Resources";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -185,14 +181,14 @@
 			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		ACF9162361FB8F24C70657DE /* Check Pods Manifest.lock */ = {
+		ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Check Pods Manifest.lock";
+			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -200,19 +196,19 @@
 			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
 			showEnvVarsInLog = 0;
 		};
-		BB76529986A8BFAF19A385B1 /* Embed Pods Frameworks */ = {
+		BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Embed Pods Frameworks";
+			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */
diff --git a/examples/objective-c/route_guide/RouteGuide.podspec b/examples/objective-c/route_guide/RouteGuide.podspec
index 4bc2c42..97a61ff 100644
--- a/examples/objective-c/route_guide/RouteGuide.podspec
+++ b/examples/objective-c/route_guide/RouteGuide.podspec
@@ -2,6 +2,10 @@
   s.name     = "RouteGuide"
   s.version  = "0.0.1"
   s.license  = "New BSD"
+  s.authors  = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
+  s.homepage = "http://www.grpc.io/"
+  s.summary = "RouteGuide example"
+  s.source = { :git => 'https://github.com/grpc/grpc.git' }
 
   s.ios.deployment_target = "7.1"
   s.osx.deployment_target = "10.9"
diff --git a/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj b/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj
index f997755..0bb84b3 100644
--- a/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj
+++ b/examples/objective-c/route_guide/RouteGuideClient.xcodeproj/project.pbxproj
@@ -116,12 +116,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 632527A31B1D0396003073D9 /* Build configuration list for PBXNativeTarget "RouteGuideClient" */;
 			buildPhases = (
-				C6FC30AD2376EC04317237C5 /* Check Pods Manifest.lock */,
+				C6FC30AD2376EC04317237C5 /* [CP] Check Pods Manifest.lock */,
 				632527791B1D0395003073D9 /* Sources */,
 				6325277A1B1D0395003073D9 /* Frameworks */,
 				6325277B1B1D0395003073D9 /* Resources */,
-				FFE0BCF30339E7A50A989EAB /* Copy Pods Resources */,
-				B5388EC5A25E89021740B916 /* Embed Pods Frameworks */,
+				FFE0BCF30339E7A50A989EAB /* [CP] Copy Pods Resources */,
+				B5388EC5A25E89021740B916 /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -178,14 +178,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		B5388EC5A25E89021740B916 /* Embed Pods Frameworks */ = {
+		B5388EC5A25E89021740B916 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Embed Pods Frameworks";
+			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -193,14 +193,14 @@
 			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RouteGuideClient/Pods-RouteGuideClient-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		C6FC30AD2376EC04317237C5 /* Check Pods Manifest.lock */ = {
+		C6FC30AD2376EC04317237C5 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Check Pods Manifest.lock";
+			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -208,14 +208,14 @@
 			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
 			showEnvVarsInLog = 0;
 		};
-		FFE0BCF30339E7A50A989EAB /* Copy Pods Resources */ = {
+		FFE0BCF30339E7A50A989EAB /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Copy Pods Resources";
+			name = "[CP] Copy Pods Resources";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index e23fd4e..a132c9a 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -193,7 +193,7 @@
   ///
   /// \return A multimap of initial metadata key-value pairs from the server.
   const std::multimap<grpc::string_ref, grpc::string_ref>&
-  GetServerInitialMetadata() {
+  GetServerInitialMetadata() const {
     GPR_CODEGEN_ASSERT(initial_metadata_received_);
     return recv_initial_metadata_;
   }
@@ -205,7 +205,7 @@
   ///
   /// \return A multimap of metadata trailing key-value pairs from the server.
   const std::multimap<grpc::string_ref, grpc::string_ref>&
-  GetServerTrailingMetadata() {
+  GetServerTrailingMetadata() const {
     // TODO(yangg) check finished
     return trailing_metadata_;
   }
@@ -230,13 +230,13 @@
 
 #ifndef GRPC_CXX0X_NO_CHRONO
   /// Return the deadline for the client call.
-  std::chrono::system_clock::time_point deadline() {
+  std::chrono::system_clock::time_point deadline() const {
     return Timespec2Timepoint(deadline_);
   }
 #endif  // !GRPC_CXX0X_NO_CHRONO
 
   /// Return a \a gpr_timespec representation of the client call's deadline.
-  gpr_timespec raw_deadline() { return deadline_; }
+  gpr_timespec raw_deadline() const { return deadline_; }
 
   /// Set the per call authority header (see
   /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3).
@@ -337,7 +337,7 @@
                                   const InputMessage& request,
                                   OutputMessage* result);
 
-  grpc_call* call() { return call_; }
+  grpc_call* call() const { return call_; }
   void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
 
   uint32_t initial_metadata_flags() const {
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index a1e1ed1..cea13a5 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -94,12 +94,12 @@
   ~ServerContext();
 
 #ifndef GRPC_CXX0X_NO_CHRONO
-  std::chrono::system_clock::time_point deadline() {
+  std::chrono::system_clock::time_point deadline() const {
     return Timespec2Timepoint(deadline_);
   }
 #endif  // !GRPC_CXX0X_NO_CHRONO
 
-  gpr_timespec raw_deadline() { return deadline_; }
+  gpr_timespec raw_deadline() const { return deadline_; }
 
   void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
   void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
@@ -122,7 +122,8 @@
   // was called.
   void TryCancel() const;
 
-  const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata() {
+  const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
+      const {
     return client_metadata_;
   }
 
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index 2a51671..86982bc 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -396,7 +396,7 @@
                                         size_t addr_len, unsigned port_index,
                                         grpc_tcp_listener **listener) {
   grpc_tcp_listener *sp = NULL;
-  int port;
+  int port = -1;
   int status;
   GUID guid = WSAID_ACCEPTEX;
   DWORD ioctl_num_bytes;
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
index 343dd48..ac2a37d 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
@@ -41,7 +41,7 @@
  */
 + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert
                    forHost:(nonnull NSString *)host
-                     error:(NSError **)errorPtr;
+                     error:(NSError * _Nullable * _Nullable)errorPtr;
 /**
  * Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate
  * Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be
@@ -51,6 +51,6 @@
             withPrivateKey:(nullable NSString *)pemPrivateKey
              withCertChain:(nullable NSString *)pemCertChain
                    forHost:(nonnull NSString *)host
-                     error:(NSError **)errorPtr;
+                     error:(NSError * _Nullable * _Nullable)errorPtr;
 
 @end
diff --git a/src/objective-c/ProtoRPC/ProtoMethod.h b/src/objective-c/ProtoRPC/ProtoMethod.h
index f9fdbb3..ae3a272 100644
--- a/src/objective-c/ProtoRPC/ProtoMethod.h
+++ b/src/objective-c/ProtoRPC/ProtoMethod.h
@@ -54,6 +54,9 @@
  * This subclass is empty now. Eventually we'll remove ProtoMethod class
  * to avoid potential naming conflict
  */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 @interface GRPCProtoMethod : ProtoMethod
+#pragma clang diagnostic pop
 
 @end
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h
index 5f91f6b..04fc1e4 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.h
+++ b/src/objective-c/ProtoRPC/ProtoRPC.h
@@ -56,6 +56,9 @@
  * This subclass is empty now. Eventually we'll remove ProtoRPC class
  * to avoid potential naming conflict
  */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 @interface GRPCProtoCall : ProtoRPC
+#pragma clang diagnostic pop
 
 @end
diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h
index 87d06e1..7faae1b 100644
--- a/src/objective-c/ProtoRPC/ProtoService.h
+++ b/src/objective-c/ProtoRPC/ProtoService.h
@@ -55,6 +55,9 @@
  * This subclass is empty now. Eventually we'll remove ProtoService class
  * to avoid potential naming conflict
  */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 @interface GRPCProtoService : ProtoService
+#pragma clang diagnostic pop
 
 @end
diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m
index 597c3cf..9740190 100644
--- a/src/objective-c/ProtoRPC/ProtoService.m
+++ b/src/objective-c/ProtoRPC/ProtoService.m
@@ -69,9 +69,9 @@
            requestsWriter:(GRXWriter *)requestsWriter
             responseClass:(Class)responseClass
        responsesWriteable:(id<GRXWriteable>)responsesWriteable {
-  ProtoMethod *methodName = [[ProtoMethod alloc] initWithPackage:_packageName
-                                                         service:_serviceName
-                                                          method:method];
+  GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName
+                                                                 service:_serviceName
+                                                                  method:method];
   return [[ProtoRPC alloc] initWithHost:_host
                                  method:methodName
                          requestsWriter:requestsWriter
diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
index 5addf26f..107e6de 100644
--- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
@@ -2,6 +2,10 @@
   s.name     = "RemoteTest"
   s.version  = "0.0.1"
   s.license  = "New BSD"
+  s.authors  = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
+  s.homepage = "http://www.grpc.io/"
+  s.summary = "RemoteTest example"
+  s.source = { :git => 'https://github.com/grpc/grpc.git' }
 
   s.ios.deployment_target = '7.1'
   s.osx.deployment_target = '10.9'
diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
index 611eb60..5c2a6d1 100644
--- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
+++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
@@ -7,16 +7,16 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C20055928615A6F8434E26B4 /* libPods-Sample.a */; };
 		6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; };
 		6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; };
 		6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; };
 		6369A2791A9322E20015FC5C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6369A2771A9322E20015FC5C /* Main.storyboard */; };
 		6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; };
-		FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = "<group>"; };
 		6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -26,8 +26,8 @@
 		6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
 		6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
-		AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
-		C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
+		C20055928615A6F8434E26B4 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -35,7 +35,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */,
+				426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -86,8 +86,8 @@
 		AB3331C9AE6488E61B2B094E /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */,
-				C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */,
+				E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */,
+				5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */,
 			);
 			name = Pods;
 			sourceTree = "<group>";
@@ -95,7 +95,7 @@
 		C4C2C5219053E079C9EFB930 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				2DC7B7C4C0410F43B9621631 /* libPods.a */,
+				C20055928615A6F8434E26B4 /* libPods-Sample.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -107,11 +107,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 6369A28D1A9322E20015FC5C /* Build configuration list for PBXNativeTarget "Sample" */;
 			buildPhases = (
-				41F7486D8F66994B0BFB84AF /* Check Pods Manifest.lock */,
+				41F7486D8F66994B0BFB84AF /* [CP] Check Pods Manifest.lock */,
 				6369A2661A9322E20015FC5C /* Sources */,
 				6369A2671A9322E20015FC5C /* Frameworks */,
 				6369A2681A9322E20015FC5C /* Resources */,
-				04554623324BE4A838846086 /* Copy Pods Resources */,
+				04554623324BE4A838846086 /* [CP] Copy Pods Resources */,
+				C7FAD018D05AB5F0B0FE81E2 /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -167,29 +168,29 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		04554623324BE4A838846086 /* Copy Pods Resources */ = {
+		04554623324BE4A838846086 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Copy Pods Resources";
+			name = "[CP] Copy Pods Resources";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		41F7486D8F66994B0BFB84AF /* Check Pods Manifest.lock */ = {
+		41F7486D8F66994B0BFB84AF /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Check Pods Manifest.lock";
+			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -197,6 +198,21 @@
 			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
 			showEnvVarsInLog = 0;
 		};
+		C7FAD018D05AB5F0B0FE81E2 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -304,7 +320,7 @@
 		};
 		6369A28E1A9322E20015FC5C /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */;
+			baseConfigurationReference = E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				INFOPLIST_FILE = Sample/Info.plist;
@@ -315,7 +331,7 @@
 		};
 		6369A28F1A9322E20015FC5C /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */;
+			baseConfigurationReference = 5A8C9F4B28733B249DE4AB6D /* Pods-Sample.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				INFOPLIST_FILE = Sample/Info.plist;
diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
index 2f57160..2a1b30f 100644
--- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
+++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
@@ -7,15 +7,14 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		253D3A297105CA46DA960A11 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC58ACA18DCCB1553531B885 /* libPods.a */; };
 		633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; };
 		633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; };
 		633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; };
 		633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; };
+		92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
 		633BFFC21B950B210007E424 /* SwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		633BFFC61B950B210007E424 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		633BFFC71B950B210007E424 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -23,8 +22,9 @@
 		633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
 		6367AD231B951655007FD3A4 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
-		C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
-		DC58ACA18DCCB1553531B885 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SwiftSample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.debug.xcconfig"; sourceTree = "<group>"; };
+		C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -32,7 +32,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				253D3A297105CA46DA960A11 /* libPods.a in Frameworks */,
+				92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -42,8 +42,8 @@
 		31F283C976AE97586C17CCD9 /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */,
-				C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */,
+				A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */,
+				C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */,
 			);
 			name = Pods;
 			sourceTree = "<group>";
@@ -90,7 +90,7 @@
 		9D63A7F6423989BA306810CA /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				DC58ACA18DCCB1553531B885 /* libPods.a */,
+				69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -102,12 +102,12 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */;
 			buildPhases = (
-				6BEEB33CA2705D7D2F2210E6 /* Check Pods Manifest.lock */,
+				6BEEB33CA2705D7D2F2210E6 /* [CP] Check Pods Manifest.lock */,
 				633BFFBE1B950B210007E424 /* Sources */,
 				633BFFBF1B950B210007E424 /* Frameworks */,
 				633BFFC01B950B210007E424 /* Resources */,
-				AC2F6F9AB1C090BB0BEE6E4D /* Copy Pods Resources */,
-				A1738A987353B0BF2C64F0F7 /* Embed Pods Frameworks */,
+				AC2F6F9AB1C090BB0BEE6E4D /* [CP] Copy Pods Resources */,
+				A1738A987353B0BF2C64F0F7 /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
@@ -164,14 +164,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		6BEEB33CA2705D7D2F2210E6 /* Check Pods Manifest.lock */ = {
+		6BEEB33CA2705D7D2F2210E6 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Check Pods Manifest.lock";
+			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -179,34 +179,34 @@
 			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
 			showEnvVarsInLog = 0;
 		};
-		A1738A987353B0BF2C64F0F7 /* Embed Pods Frameworks */ = {
+		A1738A987353B0BF2C64F0F7 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Embed Pods Frameworks";
+			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		AC2F6F9AB1C090BB0BEE6E4D /* Copy Pods Resources */ = {
+		AC2F6F9AB1C090BB0BEE6E4D /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Copy Pods Resources";
+			name = "[CP] Copy Pods Resources";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */
@@ -320,7 +320,7 @@
 		};
 		633BFFE21B950B210007E424 /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */;
+			baseConfigurationReference = A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				INFOPLIST_FILE = Info.plist;
@@ -333,7 +333,7 @@
 		};
 		633BFFE31B950B210007E424 /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */;
+			baseConfigurationReference = C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				INFOPLIST_FILE = Info.plist;
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 9a8d425..1167a71 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -48,9 +48,9 @@
 static NSString * const kService = @"TestService";
 static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
 
-static ProtoMethod *kInexistentMethod;
-static ProtoMethod *kEmptyCallMethod;
-static ProtoMethod *kUnaryCallMethod;
+static GRPCProtoMethod *kInexistentMethod;
+static GRPCProtoMethod *kEmptyCallMethod;
+static GRPCProtoMethod *kUnaryCallMethod;
 
 /** Observer class for testing that responseMetadata is KVO-compliant */
 @interface PassthroughObserver : NSObject
@@ -109,15 +109,15 @@
   [GRPCCall useInsecureConnectionsForHost:kHostAddress];
 
   // This method isn't implemented by the remote server.
-  kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage
-                                                   service:kService
-                                                    method:@"Inexistent"];
-  kEmptyCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
-                                                  service:kService
-                                                   method:@"EmptyCall"];
-  kUnaryCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
-                                                  service:kService
-                                                   method:@"UnaryCall"];
+  kInexistentMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
+                                                       service:kService
+                                                        method:@"Inexistent"];
+  kEmptyCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
+                                                      service:kService
+                                                       method:@"EmptyCall"];
+  kUnaryCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
+                                                      service:kService
+                                                       method:@"UnaryCall"];
 }
 
 - (void)testConnectionToRemoteServer {
@@ -303,9 +303,9 @@
 
   // Try to set parameters to nil for GRPCCall. This should cause an exception
   @try {
-    GRPCCall *call = [[GRPCCall alloc] initWithHost:nil
-                                               path:nil
-                                     requestsWriter:nil];
+    (void)[[GRPCCall alloc] initWithHost:nil
+                                    path:nil
+                          requestsWriter:nil];
     XCTFail(@"Did not receive an exception when parameters are nil");
   } @catch(NSException *theException) {
     NSLog(@"Received exception as expected: %@", theException.name);
@@ -316,9 +316,9 @@
   GRXWriter *requestsWriter = [GRXWriter emptyWriter];
   [requestsWriter finishWithError:nil];
   @try {
-    GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
-                                               path:kUnaryCallMethod.HTTPPath
-                                     requestsWriter:requestsWriter];
+    (void)[[GRPCCall alloc] initWithHost:kHostAddress
+                                    path:kUnaryCallMethod.HTTPPath
+                          requestsWriter:requestsWriter];
     XCTFail(@"Did not receive an exception when GRXWriter has incorrect state.");
   } @catch(NSException *theException) {
     NSLog(@"Received exception as expected: %@", theException.name);
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index 781c500..15ce120 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -58,7 +58,7 @@
                  requestedResponseSize:(NSNumber *)responseSize {
   RMTStreamingOutputCallRequest *request = [self message];
   RMTResponseParameters *parameters = [RMTResponseParameters message];
-  parameters.size = responseSize.integerValue;
+  parameters.size = (int)responseSize.integerValue;
   [request.responseParametersArray addObject:parameters];
   request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
   return request;
@@ -80,7 +80,9 @@
 
 #pragma mark Tests
 
+#ifdef GRPC_COMPILE_WITH_CRONET
 static cronet_engine *cronetEngine = NULL;
+#endif
 
 @implementation InteropTests {
   RMTTestService *_service;
@@ -186,7 +188,7 @@
   RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message];
   for (NSNumber *size in expectedSizes) {
     RMTResponseParameters *parameters = [RMTResponseParameters message];
-    parameters.size = [size integerValue];
+    parameters.size = (int)[size integerValue];
     [request.responseParametersArray addObject:parameters];
   }
 
@@ -282,9 +284,9 @@
   // A buffered pipe to which we never write any value acts as a writer that just hangs.
   GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
 
-  ProtoRPC *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
-                                                               handler:^(RMTStreamingInputCallResponse *response,
-                                                                         NSError *error) {
+  GRPCProtoCall *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
+                                                                    handler:^(RMTStreamingInputCallResponse *response,
+                                                                              NSError *error) {
     XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
     [expectation fulfill];
   }];
@@ -313,7 +315,7 @@
 
   [requestsBuffer writeValue:request];
 
-  __block ProtoRPC *call =
+  __block GRPCProtoCall *call =
       [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
                                          eventHandler:^(BOOL done,
                                                         RMTStreamingOutputCallResponse *response,
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index a7a88a3..6d5f94c 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -4,11 +4,11 @@
 install! 'cocoapods', :deterministic_uuids => false
 
 def shared_pods
-	pod 'Protobuf', :path => "../../../third_party/protobuf"
-	pod 'BoringSSL', :podspec => ".."
-	pod 'CronetFramework', :podspec => ".."
-	pod 'gRPC', :path => "../../.."
-	pod 'RemoteTest', :path => "RemoteTestClient"
+  pod 'Protobuf', :path => "../../../third_party/protobuf", :inhibit_warnings => true
+  pod 'BoringSSL', :podspec => "..", :inhibit_warnings => true
+  pod 'CronetFramework', :podspec => ".."
+  pod 'gRPC', :path => "../../.."
+  pod 'RemoteTest', :path => "RemoteTestClient"
 end
 
 target 'Tests' do
@@ -34,3 +34,19 @@
 target 'InteropTestsLocalCleartext' do
 	shared_pods
 end
+
+post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    target.build_configurations.each do |config|
+      config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES'
+    end
+    if target.name == 'gRPC'
+      target.build_configurations.each do |config|
+        # TODO(zyc) Remove this setting after the issue is resolved
+        # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
+        # function" warning
+        config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
+      end
+    end
+  end
+end
diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
index 89e0ea6..e895fe6 100644
--- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
@@ -893,6 +893,7 @@
 					"$(inherited)",
 				);
 				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
@@ -929,6 +930,7 @@
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
@@ -946,6 +948,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 060EF32D7EC0DF67ED617507 /* Pods-Tests.debug.xcconfig */;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
 			};
@@ -955,6 +958,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */;
 			buildSettings = {
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
 			};
diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json
index 8e50962..e384a2f 100644
--- a/src/python/grpcio/tests/tests.json
+++ b/src/python/grpcio/tests/tests.json
@@ -24,6 +24,7 @@
   "_implementations_test.ChannelCredentialsTest", 
   "_insecure_interop_test.InsecureInteropTest", 
   "_logging_pool_test.LoggingPoolTest", 
+  "_metadata_code_details_test.MetadataCodeDetailsTest",
   "_metadata_test.MetadataTest",
   "_not_found_test.NotFoundTest", 
   "_python_plugin_test.PythonPluginTest",
diff --git a/src/python/grpcio/tests/unit/_metadata_code_details_test.py b/src/python/grpcio/tests/unit/_metadata_code_details_test.py
new file mode 100644
index 0000000..dd74268
--- /dev/null
+++ b/src/python/grpcio/tests/unit/_metadata_code_details_test.py
@@ -0,0 +1,523 @@
+# 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.
+
+"""Tests application-provided metadata, status code, and details."""
+
+import threading
+import unittest
+
+import grpc
+from grpc.framework.foundation import logging_pool
+
+from tests.unit import test_common
+from tests.unit.framework.common import test_constants
+from tests.unit.framework.common import test_control
+
+_SERIALIZED_REQUEST = b'\x46\x47\x48'
+_SERIALIZED_RESPONSE = b'\x49\x50\x51'
+
+_REQUEST_SERIALIZER = lambda unused_request: _SERIALIZED_REQUEST
+_REQUEST_DESERIALIZER = lambda unused_serialized_request: object()
+_RESPONSE_SERIALIZER = lambda unused_response: _SERIALIZED_RESPONSE
+_RESPONSE_DESERIALIZER = lambda unused_serialized_resopnse: object()
+
+_SERVICE = b'test.TestService'
+_UNARY_UNARY = b'UnaryUnary'
+_UNARY_STREAM = b'UnaryStream'
+_STREAM_UNARY = b'StreamUnary'
+_STREAM_STREAM = b'StreamStream'
+
+_CLIENT_METADATA = (
+    (b'client-md-key', b'client-md-key'),
+    (b'client-md-key-bin', b'\x00\x01')
+)
+
+_SERVER_INITIAL_METADATA = (
+    (b'server-initial-md-key', b'server-initial-md-value'),
+    (b'server-initial-md-key-bin', b'\x00\x02')
+)
+
+_SERVER_TRAILING_METADATA = (
+    (b'server-trailing-md-key', b'server-trailing-md-value'),
+    (b'server-trailing-md-key-bin', b'\x00\x03')
+)
+
+_NON_OK_CODE = grpc.StatusCode.NOT_FOUND
+_DETAILS = b'Test details!'
+
+
+class _Servicer(object):
+
+  def __init__(self):
+    self._lock = threading.Lock()
+    self._code = None
+    self._details = None
+    self._exception = False
+    self._return_none = False
+    self._received_client_metadata = None
+
+  def unary_unary(self, request, context):
+    with self._lock:
+      self._received_client_metadata = context.invocation_metadata()
+      context.send_initial_metadata(_SERVER_INITIAL_METADATA)
+      context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+      if self._code is not None:
+        context.set_code(self._code)
+      if self._details is not None:
+        context.set_details(self._details)
+      if self._exception:
+        raise test_control.Defect()
+      else:
+        return None if self._return_none else object()
+
+  def unary_stream(self, request, context):
+    with self._lock:
+      self._received_client_metadata = context.invocation_metadata()
+      context.send_initial_metadata(_SERVER_INITIAL_METADATA)
+      context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+      if self._code is not None:
+        context.set_code(self._code)
+      if self._details is not None:
+        context.set_details(self._details)
+      for _ in range(test_constants.STREAM_LENGTH // 2):
+        yield _SERIALIZED_RESPONSE
+      if self._exception:
+        raise test_control.Defect()
+
+  def stream_unary(self, request_iterator, context):
+    with self._lock:
+      self._received_client_metadata = context.invocation_metadata()
+      context.send_initial_metadata(_SERVER_INITIAL_METADATA)
+      context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+      if self._code is not None:
+        context.set_code(self._code)
+      if self._details is not None:
+        context.set_details(self._details)
+      # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the
+      # request iterator.
+      for ignored_request in request_iterator:
+        pass
+      if self._exception:
+        raise test_control.Defect()
+      else:
+        return None if self._return_none else _SERIALIZED_RESPONSE
+
+  def stream_stream(self, request_iterator, context):
+    with self._lock:
+      self._received_client_metadata = context.invocation_metadata()
+      context.send_initial_metadata(_SERVER_INITIAL_METADATA)
+      context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+      if self._code is not None:
+        context.set_code(self._code)
+      if self._details is not None:
+        context.set_details(self._details)
+      # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the
+      # request iterator.
+      for ignored_request in request_iterator:
+        pass
+      for _ in range(test_constants.STREAM_LENGTH // 3):
+        yield object()
+      if self._exception:
+        raise test_control.Defect()
+
+  def set_code(self, code):
+    with self._lock:
+      self._code = code
+
+  def set_details(self, details):
+    with self._lock:
+      self._details = details
+
+  def set_exception(self):
+    with self._lock:
+      self._exception = True
+
+  def set_return_none(self):
+    with self._lock:
+      self._return_none = True
+
+  def received_client_metadata(self):
+    with self._lock:
+      return self._received_client_metadata
+
+
+def _generic_handler(servicer):
+  method_handlers = {
+      _UNARY_UNARY: grpc.unary_unary_rpc_method_handler(
+          servicer.unary_unary, request_deserializer=_REQUEST_DESERIALIZER,
+          response_serializer=_RESPONSE_SERIALIZER),
+      _UNARY_STREAM: grpc.unary_stream_rpc_method_handler(
+          servicer.unary_stream),
+      _STREAM_UNARY: grpc.stream_unary_rpc_method_handler(
+          servicer.stream_unary),
+      _STREAM_STREAM: grpc.stream_stream_rpc_method_handler(
+          servicer.stream_stream, request_deserializer=_REQUEST_DESERIALIZER,
+          response_serializer=_RESPONSE_SERIALIZER),
+  }
+  return grpc.method_handlers_generic_handler(_SERVICE, method_handlers)
+
+
+class MetadataCodeDetailsTest(unittest.TestCase):
+
+  def setUp(self):
+    self._servicer = _Servicer()
+    self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
+    self._server = grpc.server(
+        (_generic_handler(self._servicer),), self._server_pool)
+    port = self._server.add_insecure_port('[::]:0')
+    self._server.start()
+
+    channel = grpc.insecure_channel('localhost:{}'.format(port))
+    self._unary_unary = channel.unary_unary(
+        b'/'.join((b'', _SERVICE, _UNARY_UNARY,)),
+        request_serializer=_REQUEST_SERIALIZER,
+        response_deserializer=_RESPONSE_DESERIALIZER,)
+    self._unary_stream = channel.unary_stream(
+        b'/'.join((b'', _SERVICE, _UNARY_STREAM,)),)
+    self._stream_unary = channel.stream_unary(
+        b'/'.join((b'', _SERVICE, _STREAM_UNARY,)),)
+    self._stream_stream = channel.stream_stream(
+        b'/'.join((b'', _SERVICE, _STREAM_STREAM,)),
+        request_serializer=_REQUEST_SERIALIZER,
+        response_deserializer=_RESPONSE_DESERIALIZER,)
+
+
+  def testSuccessfulUnaryUnary(self):
+    self._servicer.set_details(_DETAILS)
+
+    unused_response, call = self._unary_unary.with_call(
+        object(), metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, call.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(grpc.StatusCode.OK, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testSuccessfulUnaryStream(self):
+    self._servicer.set_details(_DETAILS)
+
+    call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    for _ in call:
+      pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(grpc.StatusCode.OK, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testSuccessfulStreamUnary(self):
+    self._servicer.set_details(_DETAILS)
+
+    unused_response, call = self._stream_unary.with_call(
+        iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH),
+        metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, call.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(grpc.StatusCode.OK, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testSuccessfulStreamStream(self):
+    self._servicer.set_details(_DETAILS)
+
+    call = self._stream_stream(
+        iter([object()] * test_constants.STREAM_LENGTH),
+        metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    for _ in call:
+      pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(grpc.StatusCode.OK, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testCustomCodeUnaryUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA,
+            exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeUnaryStream(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+
+    call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    with self.assertRaises(grpc.RpcError):
+      for _ in call:
+        pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testCustomCodeStreamUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      self._stream_unary.with_call(
+          iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH),
+          metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+          _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+          _SERVER_INITIAL_METADATA,
+          exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+          _SERVER_TRAILING_METADATA,
+          exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeStreamStream(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+
+    call = self._stream_stream(
+        iter([object()] * test_constants.STREAM_LENGTH),
+        metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      for _ in call:
+        pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+          _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeExceptionUnaryUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_exception()
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+     self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA,
+            exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeExceptionUnaryStream(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_exception()
+
+    call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    with self.assertRaises(grpc.RpcError):
+      for _ in call:
+        pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testCustomCodeExceptionStreamUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_exception()
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      self._stream_unary.with_call(
+          iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH),
+          metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA,
+            exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeExceptionStreamStream(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_exception()
+
+    call = self._stream_stream(
+        iter([object()] * test_constants.STREAM_LENGTH),
+        metadata=_CLIENT_METADATA)
+    received_initial_metadata = call.initial_metadata()
+    with self.assertRaises(grpc.RpcError):
+      for _ in call:
+        pass
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA, received_initial_metadata))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA, call.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, call.code())
+    self.assertEqual(_DETAILS, call.details())
+
+  def testCustomCodeReturnNoneUnaryUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_return_none()
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA,
+            exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+  def testCustomCodeReturnNoneStreamUnary(self):
+    self._servicer.set_code(_NON_OK_CODE)
+    self._servicer.set_details(_DETAILS)
+    self._servicer.set_return_none()
+
+    with self.assertRaises(grpc.RpcError) as exception_context:
+      self._stream_unary.with_call(
+          iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH),
+          metadata=_CLIENT_METADATA)
+
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _CLIENT_METADATA, self._servicer.received_client_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_INITIAL_METADATA,
+            exception_context.exception.initial_metadata()))
+    self.assertTrue(
+        test_common.metadata_transmitted(
+            _SERVER_TRAILING_METADATA,
+            exception_context.exception.trailing_metadata()))
+    self.assertIs(_NON_OK_CODE, exception_context.exception.code())
+    self.assertEqual(_DETAILS, exception_context.exception.details())
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/tools/run_tests/build_artifact_python.bat b/tools/run_tests/build_artifact_python.bat
index fea0275..295347e 100644
--- a/tools/run_tests/build_artifact_python.bat
+++ b/tools/run_tests/build_artifact_python.bat
@@ -37,10 +37,11 @@
 
 mkdir src\python\grpcio\grpc\_cython\_windows
 
+@rem TODO(atash): maybe we could avoid the grpc_c.(32|64).python shim below if
+@rem this used the right python build?
 copy /Y vsprojects\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\grpc_c.32.python || goto :error
 copy /Y vsprojects\x64\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\grpc_c.64.python || goto :error
 
-
 set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;%PATH%
 
 pip install --upgrade six
@@ -50,12 +51,6 @@
 set GRPC_PYTHON_USE_CUSTOM_BDIST=0
 set GRPC_PYTHON_BUILD_WITH_CYTHON=1
 
-@rem TODO(atash): maybe we could avoid the grpc_c.(32|64).python shim above if
-@rem this used the right python build?
-python setup.py bdist_wheel
-
-@rem Build gRPC Python tools
-@rem
 @rem Because this is windows and *everything seems to hate Windows* we have to
 @rem set all of these flags ourselves because Python won't help us (see the
 @rem setup.py of the grpcio_tools project).
@@ -70,6 +65,18 @@
 python -c "from distutils.cygwinccompiler import get_msvcr; print(get_msvcr()[0])" > temp.txt
 set /p PYTHON_MSVCR=<temp.txt
 set GRPC_PYTHON_LDFLAGS=-static-libgcc -static-libstdc++ -mcrtdll=%PYTHON_MSVCR% -static -lpthread
+
+
+@rem Build gRPC
+if %2 == 32 (
+  python setup.py build_ext -c mingw32
+) else (
+  python setup.py build_ext -c mingw32 -DMS_WIN64
+)
+python setup.py bdist_wheel
+
+
+@rem Build gRPC Python tools
 python tools\distrib\python\make_grpcio_tools.py
 if %2 == 32 (
   python tools\distrib\python\grpcio_tools\setup.py build_ext -c mingw32