interop: implement special_status_message interop test (#2241)

fixes #2240
diff --git a/interop/client/client.go b/interop/client/client.go
index 42ee7da..69bba92 100644
--- a/interop/client/client.go
+++ b/interop/client/client.go
@@ -64,6 +64,7 @@
         cancel_after_begin: cancellation after metadata has been sent but before payloads are sent;
         cancel_after_first_response: cancellation after receiving 1st message from the server;
         status_code_and_message: status code propagated back to client;
+        special_status_message: Unicode and whitespace is correctly processed in status message;
         custom_metadata: server will echo custom metadata;
         unimplemented_method: client attempts to call unimplemented method;
         unimplemented_service: client attempts to call unimplemented service.`)
@@ -193,6 +194,9 @@
 	case "status_code_and_message":
 		interop.DoStatusCodeAndMessage(tc)
 		grpclog.Infoln("StatusCodeAndMessage done")
+	case "special_status_message":
+		interop.DoSpecialStatusMessage(tc)
+		grpclog.Infoln("SpecialStatusMessage done")
 	case "custom_metadata":
 		interop.DoCustomMetadata(tc)
 		grpclog.Infoln("CustomMetadata done")
diff --git a/interop/test_utils.go b/interop/test_utils.go
index cbc7756..ee1ae70 100644
--- a/interop/test_utils.go
+++ b/interop/test_utils.go
@@ -563,6 +563,27 @@
 	}
 }
 
+// DoSpecialStatusMessage verifies Unicode and whitespace is correctly processed
+// in status message.
+func DoSpecialStatusMessage(tc testpb.TestServiceClient, args ...grpc.CallOption) {
+	const (
+		code int32  = 2
+		msg  string = "\t\ntest with whitespace\r\nand Unicode BMP ☺ and non-BMP 😈\t\n"
+	)
+	expectedErr := status.Error(codes.Code(code), msg)
+	req := &testpb.SimpleRequest{
+		ResponseStatus: &testpb.EchoStatus{
+			Code:    code,
+			Message: msg,
+		},
+	}
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	defer cancel()
+	if _, err := tc.UnaryCall(ctx, req, args...); err == nil || err.Error() != expectedErr.Error() {
+		grpclog.Fatalf("%v.UnaryCall(_, %v) = _, %v, want _, %v", tc, req, err, expectedErr)
+	}
+}
+
 // DoUnimplementedService attempts to call a method from an unimplemented service.
 func DoUnimplementedService(tc testpb.UnimplementedServiceClient) {
 	_, err := tc.UnimplementedCall(context.Background(), &testpb.Empty{})