diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index dfb90fadc20146476257498b44351fe6b709d2fc..066877e0c6d245789383619652a9e1756ab6a652 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -316,7 +316,6 @@ void InteropClient::DoHalfDuplex() {
   unsigned int i = 0;
   StreamingOutputCallResponse response;
   while (stream->Read(&response)) {
-    GPR_ASSERT(response.payload().has_body());
     GPR_ASSERT(response.payload().body() ==
                grpc::string(response_stream_sizes[i], '\0'));
     ++i;
@@ -346,7 +345,6 @@ void InteropClient::DoPingPong() {
     payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
     GPR_ASSERT(stream->Write(request));
     GPR_ASSERT(stream->Read(&response));
-    GPR_ASSERT(response.payload().has_body());
     GPR_ASSERT(response.payload().body() ==
                grpc::string(response_stream_sizes[i], '\0'));
   }
@@ -393,7 +391,6 @@ void InteropClient::DoCancelAfterFirstResponse() {
   StreamingOutputCallResponse response;
   GPR_ASSERT(stream->Write(request));
   GPR_ASSERT(stream->Read(&response));
-  GPR_ASSERT(response.payload().has_body());
   GPR_ASSERT(response.payload().body() == grpc::string(31415, '\0'));
   gpr_log(GPR_INFO, "Trying to cancel...");
   context.TryCancel();
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 05a10de51e4196a270e1ad7ed80be9d9d9fe8e8c..4e809ed902b92ccafabeef8111813b835363deaf 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -99,7 +99,7 @@ class TestServiceImpl : public TestService::Service {
 
   Status UnaryCall(ServerContext* context, const SimpleRequest* request,
                    SimpleResponse* response) {
-    if (request->has_response_size() && request->response_size() > 0) {
+    if (request->response_size() > 0) {
       if (!SetPayload(request->response_type(), request->response_size(),
                       response->mutable_payload())) {
         return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
@@ -140,7 +140,7 @@ class TestServiceImpl : public TestService::Service {
     StreamingInputCallRequest request;
     int aggregated_payload_size = 0;
     while (reader->Read(&request)) {
-      if (request.has_payload() && request.payload().has_body()) {
+      if (request.has_payload()) {
         aggregated_payload_size += request.payload().body().size();
       }
     }
diff --git a/test/cpp/util/echo.proto b/test/cpp/util/echo.proto
index 58ec680ecd00df32254a4afe63a392a5d8d5d6e6..6bb09316b457fbc0e70520899e6523f378b75310 100644
--- a/test/cpp/util/echo.proto
+++ b/test/cpp/util/echo.proto
@@ -28,7 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+syntax = "proto3";
 
 import "test/cpp/util/messages.proto";
 
diff --git a/test/cpp/util/echo_duplicate.proto b/test/cpp/util/echo_duplicate.proto
index e54c016d2f3c3d0a69c8a1bde1f56dfc4a957e53..9c1d67825a4a307eee747f309970c85987971397 100644
--- a/test/cpp/util/echo_duplicate.proto
+++ b/test/cpp/util/echo_duplicate.proto
@@ -30,7 +30,7 @@
 
 // This is a partial copy of echo.proto with a different package name.
 
-syntax = "proto2";
+syntax = "proto3";
 
 import "test/cpp/util/messages.proto";
 
diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto
index 24e199b809757b7f85c955eab6158219e67cda12..359d1db74fa4310a9ae58aa5de7d18a6452d8cc6 100644
--- a/test/cpp/util/messages.proto
+++ b/test/cpp/util/messages.proto
@@ -28,32 +28,32 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+syntax = "proto3";
 
 package grpc.cpp.test.util;
 
 message RequestParams {
-  optional bool echo_deadline = 1;
-  optional int32 client_cancel_after_us = 2;
-  optional int32 server_cancel_after_us = 3;
-  optional bool echo_metadata = 4;
-  optional bool check_auth_context = 5;
-  optional int32 response_message_length = 6;
-  optional bool echo_peer = 7;
+  bool echo_deadline = 1;
+  int32 client_cancel_after_us = 2;
+  int32 server_cancel_after_us = 3;
+  bool echo_metadata = 4;
+  bool check_auth_context = 5;
+  int32 response_message_length = 6;
+  bool echo_peer = 7;
 }
 
 message EchoRequest {
-  optional string message = 1;
-  optional RequestParams param = 2;
+  string message = 1;
+  RequestParams param = 2;
 }
 
 message ResponseParams {
-  optional int64 request_deadline = 1;
-  optional string host = 2;
-  optional string peer = 3;
+  int64 request_deadline = 1;
+  string host = 2;
+  string peer = 3;
 }
 
 message EchoResponse {
-  optional string message = 1;
-  optional ResponseParams param = 2;
+  string message = 1;
+  ResponseParams param = 2;
 }
diff --git a/test/proto/empty.proto b/test/proto/empty.proto
index 4295a0a960c0a07a7cf1df88438d3a8715a1b48b..6d0eb937d674ca3ee9aaf9c2ed8313250cd76647 100644
--- a/test/proto/empty.proto
+++ b/test/proto/empty.proto
@@ -28,7 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-syntax = "proto2";
+syntax = "proto3";
 
 package grpc.testing;
 
diff --git a/test/proto/messages.proto b/test/proto/messages.proto
index 89e55443b542d0a04a083cdafa2392a07ec6a2e4..193b6c4171288c6968d29625f22d61229ceba3aa 100644
--- a/test/proto/messages.proto
+++ b/test/proto/messages.proto
@@ -30,7 +30,7 @@
 
 // Message definitions to be used by integration test service definitions.
 
-syntax = "proto2";
+syntax = "proto3";
 
 package grpc.testing;
 
@@ -57,59 +57,59 @@ enum CompressionType {
 // A block of data, to simply increase gRPC message size.
 message Payload {
   // The type of data in body.
-  optional PayloadType type = 1;
+  PayloadType type = 1;
   // Primary contents of payload.
-  optional bytes body = 2;
+  bytes body = 2;
 }
 
 // A protobuf representation for grpc status. This is used by test
 // clients to specify a status that the server should attempt to return.
-message EchoStatus { 
-  optional int32 code = 1;
-  optional string message = 2;
+message EchoStatus {
+  int32 code = 1;
+  string message = 2;
 }
 
 // Unary request.
 message SimpleRequest {
   // Desired payload type in the response from the server.
   // If response_type is RANDOM, server randomly chooses one from other formats.
-  optional PayloadType response_type = 1;
+  PayloadType response_type = 1;
 
   // Desired payload size in the response from the server.
   // If response_type is COMPRESSABLE, this denotes the size before compression.
-  optional int32 response_size = 2;
+  int32 response_size = 2;
 
   // Optional input payload sent along with the request.
-  optional Payload payload = 3;
+  Payload payload = 3;
 
   // Whether SimpleResponse should include username.
-  optional bool fill_username = 4;
+  bool fill_username = 4;
 
   // Whether SimpleResponse should include OAuth scope.
-  optional bool fill_oauth_scope = 5;
+  bool fill_oauth_scope = 5;
 
   // Compression algorithm to be used by the server for the response (stream)
-  optional CompressionType response_compression = 6;
+  CompressionType response_compression = 6;
 
   // Whether server should return a given status
-  optional EchoStatus response_status = 7;
+  EchoStatus response_status = 7;
 }
 
 // Unary response, as configured by the request.
 message SimpleResponse {
   // Payload to increase message size.
-  optional Payload payload = 1;
+  Payload payload = 1;
   // The user the request came from, for verifying authentication was
   // successful when the client expected it.
-  optional string username = 2;
+  string username = 2;
   // OAuth scope.
-  optional string oauth_scope = 3;
+  string oauth_scope = 3;
 }
 
 // Client-streaming request.
 message StreamingInputCallRequest {
   // Optional input payload sent along with the request.
-  optional Payload payload = 1;
+  Payload payload = 1;
 
   // Not expecting any payload from the response.
 }
@@ -117,18 +117,18 @@ message StreamingInputCallRequest {
 // Client-streaming response.
 message StreamingInputCallResponse {
   // Aggregated size of payloads received from the client.
-  optional int32 aggregated_payload_size = 1;
+  int32 aggregated_payload_size = 1;
 }
 
 // Configuration for a particular response.
 message ResponseParameters {
   // Desired payload sizes in responses from the server.
   // If response_type is COMPRESSABLE, this denotes the size before compression.
-  optional int32 size = 1;
+  int32 size = 1;
 
   // Desired interval between consecutive responses in the response stream in
   // microseconds.
-  optional int32 interval_us = 2;
+  int32 interval_us = 2;
 }
 
 // Server-streaming request.
@@ -137,31 +137,31 @@ message StreamingOutputCallRequest {
   // If response_type is RANDOM, the payload from each response in the stream
   // might be of different types. This is to simulate a mixed type of payload
   // stream.
-  optional PayloadType response_type = 1;
+  PayloadType response_type = 1;
 
   // Configuration for each expected response message.
   repeated ResponseParameters response_parameters = 2;
 
   // Optional input payload sent along with the request.
-  optional Payload payload = 3;
+  Payload payload = 3;
 
   // Compression algorithm to be used by the server for the response (stream)
-  optional CompressionType response_compression = 6;
+  CompressionType response_compression = 6;
 
   // Whether server should return a given status
-  optional EchoStatus response_status = 7;
+  EchoStatus response_status = 7;
 }
 
 // Server-streaming response, as configured by the request and parameters.
 message StreamingOutputCallResponse {
   // Payload to increase response size.
-  optional Payload payload = 1;
+  Payload payload = 1;
 }
 
 // For reconnect interop test only.
 // Server tells client whether its reconnects are following the spec and the
 // reconnect backoffs it saw.
 message ReconnectInfo {
-  optional bool passed = 1;
+  bool passed = 1;
   repeated int32 backoff_ms = 2;
 }
diff --git a/test/proto/test.proto b/test/proto/test.proto
index 368522dc4c925d67390b1efdd2c52216aa5bf8d2..92aff23929c8bbc05981e43c4436c9fc9afb1b62 100644
--- a/test/proto/test.proto
+++ b/test/proto/test.proto
@@ -31,7 +31,7 @@
 // An integration test service that covers all the method signature permutations
 // of unary/streaming requests/responses.
 
-syntax = "proto2";
+syntax = "proto3";
 
 import "test/proto/empty.proto";
 import "test/proto/messages.proto";