aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/python/grpcio_tests
diff options
context:
space:
mode:
authorGravatar Masood Malekghassemi <atash@google.com>2016-10-20 14:47:14 -0700
committerGravatar Masood Malekghassemi <atash@google.com>2016-10-28 14:53:10 -0700
commitd953959e2bafd645b6ed674861a310daba5f80ae (patch)
tree25675dc1c97dd60f231f4cfdd9c3c483246a8a90 /src/python/grpcio_tests
parent81cdf1e34e8501e3e0e50182dd6d13499b473868 (diff)
Enable split code generation
To support magical internal build processes, the pb2 files need to be split into pure-proto and gRPC parts. This performs that split and further fixes bad module names in the test harness that interfered with the intended test implementation. An unfortunate side effect, due to limitations of protoc and holdover behavior we must support in major version 1.x, is that trash files are generated in split generation. This shouldn't be a problem in normal protoc plugin use.
Diffstat (limited to 'src/python/grpcio_tests')
-rw-r--r--src/python/grpcio_tests/.gitignore1
-rw-r--r--src/python/grpcio_tests/setup.py10
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py304
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py30
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto39
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py30
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/messages.proto35
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py30
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/services.proto38
-rw-r--r--src/python/grpcio_tests/tests/tests.json90
10 files changed, 562 insertions, 45 deletions
diff --git a/src/python/grpcio_tests/.gitignore b/src/python/grpcio_tests/.gitignore
index fc620135dc..dcba283a8c 100644
--- a/src/python/grpcio_tests/.gitignore
+++ b/src/python/grpcio_tests/.gitignore
@@ -1,4 +1,5 @@
proto/
src/
*_pb2.py
+*_pb2_grpc.py
*.egg-info/
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 7384206602..01d5fa875b 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -80,8 +80,14 @@ PACKAGE_DATA = {
'credentials/server1.key',
'credentials/server1.pem',
],
- 'tests.protoc_plugin': [
- 'protoc_plugin_test.proto',
+ 'tests.protoc_plugin.protos.invocation_testing': [
+ 'same.proto',
+ ],
+ 'tests.protoc_plugin.protos.invocation_testing.split_messages': [
+ 'messages.proto',
+ ],
+ 'tests.protoc_plugin.protos.invocation_testing.split_services': [
+ 'services.proto',
],
'tests.unit': [
'credentials/ca.pem',
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
new file mode 100644
index 0000000000..089366a8c7
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
@@ -0,0 +1,304 @@
+# 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.
+
+import collections
+from concurrent import futures
+import contextlib
+import distutils.spawn
+import errno
+import importlib
+import os
+import os.path
+import pkgutil
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+import unittest
+
+import grpc
+from grpc.tools import protoc
+from tests.unit.framework.common import test_constants
+
+_MESSAGES_IMPORT = b'import "messages.proto";'
+
+@contextlib.contextmanager
+def _system_path(path):
+ old_system_path = sys.path[:]
+ sys.path = sys.path[0:1] + path + sys.path[1:]
+ yield
+ sys.path = old_system_path
+
+
+class DummySplitServicer(object):
+
+ def __init__(self, request_class, response_class):
+ self.request_class = request_class
+ self.response_class = response_class
+
+ def Call(self, request, context):
+ return self.response_class()
+
+
+class SeparateTestMixin(object):
+
+ def testImportAttributes(self):
+ with _system_path([self.python_out_directory]):
+ pb2 = importlib.import_module(self.pb2_import)
+ pb2.Request
+ pb2.Response
+ if self.should_find_services_in_pb2:
+ pb2.TestServiceServicer
+ else:
+ with self.assertRaises(AttributeError):
+ pb2.TestServiceServicer
+
+ with _system_path([self.grpc_python_out_directory]):
+ pb2_grpc = importlib.import_module(self.pb2_grpc_import)
+ pb2_grpc.TestServiceServicer
+ with self.assertRaises(AttributeError):
+ pb2_grpc.Request
+ with self.assertRaises(AttributeError):
+ pb2_grpc.Response
+
+ def testCall(self):
+ with _system_path([self.python_out_directory]):
+ pb2 = importlib.import_module(self.pb2_import)
+ with _system_path([self.grpc_python_out_directory]):
+ pb2_grpc = importlib.import_module(self.pb2_grpc_import)
+ server = grpc.server(
+ futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
+ pb2_grpc.add_TestServiceServicer_to_server(
+ DummySplitServicer(
+ pb2.Request, pb2.Response), server)
+ port = server.add_insecure_port('[::]:0')
+ server.start()
+ channel = grpc.insecure_channel('localhost:{}'.format(port))
+ stub = pb2_grpc.TestServiceStub(channel)
+ request = pb2.Request()
+ expected_response = pb2.Response()
+ response = stub.Call(request)
+ self.assertEqual(expected_response, response)
+
+
+class CommonTestMixin(object):
+
+ def testImportAttributes(self):
+ with _system_path([self.python_out_directory]):
+ pb2 = importlib.import_module(self.pb2_import)
+ pb2.Request
+ pb2.Response
+ if self.should_find_services_in_pb2:
+ pb2.TestServiceServicer
+ else:
+ with self.assertRaises(AttributeError):
+ pb2.TestServiceServicer
+
+ with _system_path([self.grpc_python_out_directory]):
+ pb2_grpc = importlib.import_module(self.pb2_grpc_import)
+ pb2_grpc.TestServiceServicer
+ with self.assertRaises(AttributeError):
+ pb2_grpc.Request
+ with self.assertRaises(AttributeError):
+ pb2_grpc.Response
+
+ def testCall(self):
+ with _system_path([self.python_out_directory]):
+ pb2 = importlib.import_module(self.pb2_import)
+ with _system_path([self.grpc_python_out_directory]):
+ pb2_grpc = importlib.import_module(self.pb2_grpc_import)
+ server = grpc.server(
+ futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
+ pb2_grpc.add_TestServiceServicer_to_server(
+ DummySplitServicer(
+ pb2.Request, pb2.Response), server)
+ port = server.add_insecure_port('[::]:0')
+ server.start()
+ channel = grpc.insecure_channel('localhost:{}'.format(port))
+ stub = pb2_grpc.TestServiceStub(channel)
+ request = pb2.Request()
+ expected_response = pb2.Response()
+ response = stub.Call(request)
+ self.assertEqual(expected_response, response)
+
+
+class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
+
+ def setUp(self):
+ same_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
+ self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.')
+ self.proto_directory = os.path.join(self.directory, 'proto_path')
+ self.python_out_directory = os.path.join(self.directory, 'python_out')
+ self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out')
+ os.makedirs(self.proto_directory)
+ os.makedirs(self.python_out_directory)
+ os.makedirs(self.grpc_python_out_directory)
+ same_proto_file = os.path.join(self.proto_directory, 'same_separate.proto')
+ open(same_proto_file, 'wb').write(same_proto_contents)
+ protoc_result = protoc.main([
+ '',
+ '--proto_path={}'.format(self.proto_directory),
+ '--python_out={}'.format(self.python_out_directory),
+ '--grpc_python_out={}'.format(self.grpc_python_out_directory),
+ same_proto_file,
+ ])
+ if protoc_result != 0:
+ raise Exception("unexpected protoc error")
+ open(os.path.join(self.grpc_python_out_directory, '__init__.py'), 'w').write('')
+ open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
+ self.pb2_import = 'same_separate_pb2'
+ self.pb2_grpc_import = 'same_separate_pb2_grpc'
+ self.should_find_services_in_pb2 = False
+
+ def tearDown(self):
+ shutil.rmtree(self.directory)
+
+
+class SameCommonTest(unittest.TestCase, CommonTestMixin):
+
+ def setUp(self):
+ same_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
+ self.directory = tempfile.mkdtemp(suffix='same_common', dir='.')
+ self.proto_directory = os.path.join(self.directory, 'proto_path')
+ self.python_out_directory = os.path.join(self.directory, 'python_out')
+ self.grpc_python_out_directory = self.python_out_directory
+ os.makedirs(self.proto_directory)
+ os.makedirs(self.python_out_directory)
+ same_proto_file = os.path.join(self.proto_directory, 'same_common.proto')
+ open(same_proto_file, 'wb').write(same_proto_contents)
+ protoc_result = protoc.main([
+ '',
+ '--proto_path={}'.format(self.proto_directory),
+ '--python_out={}'.format(self.python_out_directory),
+ '--grpc_python_out={}'.format(self.grpc_python_out_directory),
+ same_proto_file,
+ ])
+ if protoc_result != 0:
+ raise Exception("unexpected protoc error")
+ open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
+ self.pb2_import = 'same_common_pb2'
+ self.pb2_grpc_import = 'same_common_pb2_grpc'
+ self.should_find_services_in_pb2 = True
+
+ def tearDown(self):
+ shutil.rmtree(self.directory)
+
+
+class SplitCommonTest(unittest.TestCase, CommonTestMixin):
+
+ def setUp(self):
+ services_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing.split_services',
+ 'services.proto')
+ messages_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing.split_messages',
+ 'messages.proto')
+ self.directory = tempfile.mkdtemp(suffix='split_common', dir='.')
+ self.proto_directory = os.path.join(self.directory, 'proto_path')
+ self.python_out_directory = os.path.join(self.directory, 'python_out')
+ self.grpc_python_out_directory = self.python_out_directory
+ os.makedirs(self.proto_directory)
+ os.makedirs(self.python_out_directory)
+ services_proto_file = os.path.join(self.proto_directory,
+ 'split_common_services.proto')
+ messages_proto_file = os.path.join(self.proto_directory,
+ 'split_common_messages.proto')
+ open(services_proto_file, 'wb').write(services_proto_contents.replace(
+ _MESSAGES_IMPORT,
+ b'import "split_common_messages.proto";'
+ ))
+ open(messages_proto_file, 'wb').write(messages_proto_contents)
+ protoc_result = protoc.main([
+ '',
+ '--proto_path={}'.format(self.proto_directory),
+ '--python_out={}'.format(self.python_out_directory),
+ '--grpc_python_out={}'.format(self.python_out_directory),
+ services_proto_file,
+ messages_proto_file,
+ ])
+ if protoc_result != 0:
+ raise Exception("unexpected protoc error")
+ open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
+ self.pb2_import = 'split_common_messages_pb2'
+ self.pb2_grpc_import = 'split_common_services_pb2_grpc'
+ self.should_find_services_in_pb2 = False
+
+ def tearDown(self):
+ shutil.rmtree(self.directory)
+
+
+class SplitSeparateTest(unittest.TestCase, SeparateTestMixin):
+
+ def setUp(self):
+ services_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing.split_services',
+ 'services.proto')
+ messages_proto_contents = pkgutil.get_data(
+ 'tests.protoc_plugin.protos.invocation_testing.split_messages',
+ 'messages.proto')
+ self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.')
+ self.proto_directory = os.path.join(self.directory, 'proto_path')
+ self.python_out_directory = os.path.join(self.directory, 'python_out')
+ self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out')
+ os.makedirs(self.proto_directory)
+ os.makedirs(self.python_out_directory)
+ os.makedirs(self.grpc_python_out_directory)
+ services_proto_file = os.path.join(self.proto_directory,
+ 'split_separate_services.proto')
+ messages_proto_file = os.path.join(self.proto_directory,
+ 'split_separate_messages.proto')
+ open(services_proto_file, 'wb').write(services_proto_contents.replace(
+ _MESSAGES_IMPORT,
+ b'import "split_separate_messages.proto";'
+ ))
+ open(messages_proto_file, 'wb').write(messages_proto_contents)
+ protoc_result = protoc.main([
+ '',
+ '--proto_path={}'.format(self.proto_directory),
+ '--python_out={}'.format(self.python_out_directory),
+ '--grpc_python_out={}'.format(self.grpc_python_out_directory),
+ services_proto_file,
+ messages_proto_file,
+ ])
+ if protoc_result != 0:
+ raise Exception("unexpected protoc error")
+ open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
+ self.pb2_import = 'split_separate_messages_pb2'
+ self.pb2_grpc_import = 'split_separate_services_pb2_grpc'
+ self.should_find_services_in_pb2 = False
+
+ def tearDown(self):
+ shutil.rmtree(self.directory)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py
new file mode 100644
index 0000000000..2f88fa0412
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto
new file mode 100644
index 0000000000..269e2fd2c7
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto
@@ -0,0 +1,39 @@
+// 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.
+
+syntax = "proto3";
+
+package grpc_protoc_plugin.invocation_testing;
+
+message Request {}
+message Response {}
+
+service TestService {
+ rpc Call(Request) returns (Response);
+}
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py
new file mode 100644
index 0000000000..2f88fa0412
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/messages.proto b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/messages.proto
new file mode 100644
index 0000000000..de22dae049
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/messages.proto
@@ -0,0 +1,35 @@
+// 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.
+
+syntax = "proto3";
+
+package grpc_protoc_plugin.invocation_testing.split;
+
+message Request {}
+message Response {}
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py
new file mode 100644
index 0000000000..2f88fa0412
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py
@@ -0,0 +1,30 @@
+# 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.
+
+
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/services.proto b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/services.proto
new file mode 100644
index 0000000000..af999cd48d
--- /dev/null
+++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/services.proto
@@ -0,0 +1,38 @@
+// 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.
+
+syntax = "proto3";
+
+import "messages.proto";
+
+package grpc_protoc_plugin.invocation_testing.split;
+
+service TestService {
+ rpc Call(Request) returns (Response);
+}
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index 2e85f1f397..dd4a0257f5 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -1,45 +1,49 @@
[
- "_api_test.AllTest",
- "_api_test.ChannelConnectivityTest",
- "_api_test.ChannelTest",
- "_auth_test.AccessTokenCallCredentialsTest",
- "_auth_test.GoogleCallCredentialsTest",
- "_beta_features_test.BetaFeaturesTest",
- "_beta_features_test.ContextManagementAndLifecycleTest",
- "_cancel_many_calls_test.CancelManyCallsTest",
- "_channel_args_test.ChannelArgsTest",
- "_channel_connectivity_test.ChannelConnectivityTest",
- "_channel_ready_future_test.ChannelReadyFutureTest",
- "_channel_test.ChannelTest",
- "_compression_test.CompressionTest",
- "_connectivity_channel_test.ConnectivityStatesTest",
- "_credentials_test.CredentialsTest",
- "_empty_message_test.EmptyMessageTest",
- "_exit_test.ExitTest",
- "_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
- "_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
- "_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
- "_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
- "_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
- "_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
- "_health_servicer_test.HealthServicerTest",
- "_implementations_test.CallCredentialsTest",
- "_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",
- "_read_some_but_not_all_responses_test.ReadSomeButNotAllResponsesTest",
- "_reflection_servicer_test.ReflectionServicerTest",
- "_rpc_test.RPCTest",
- "_sanity_test.Sanity",
- "_secure_interop_test.SecureInteropTest",
- "_thread_cleanup_test.CleanupThreadTest",
- "_utilities_test.ChannelConnectivityTest",
- "beta_python_plugin_test.PythonPluginTest",
- "cygrpc_test.InsecureServerInsecureClient",
- "cygrpc_test.SecureServerSecureClient",
- "cygrpc_test.TypeSmokeTest"
+ "health_check._health_servicer_test.HealthServicerTest",
+ "interop._insecure_interop_test.InsecureInteropTest",
+ "interop._secure_interop_test.SecureInteropTest",
+ "protoc_plugin._python_plugin_test.PythonPluginTest",
+ "protoc_plugin._split_definitions_test.SameCommonTest",
+ "protoc_plugin._split_definitions_test.SameSeparateTest",
+ "protoc_plugin._split_definitions_test.SplitCommonTest",
+ "protoc_plugin._split_definitions_test.SplitSeparateTest",
+ "protoc_plugin.beta_python_plugin_test.PythonPluginTest",
+ "reflection._reflection_servicer_test.ReflectionServicerTest",
+ "unit._api_test.AllTest",
+ "unit._api_test.ChannelConnectivityTest",
+ "unit._api_test.ChannelTest",
+ "unit._auth_test.AccessTokenCallCredentialsTest",
+ "unit._auth_test.GoogleCallCredentialsTest",
+ "unit._channel_args_test.ChannelArgsTest",
+ "unit._channel_connectivity_test.ChannelConnectivityTest",
+ "unit._channel_ready_future_test.ChannelReadyFutureTest",
+ "unit._compression_test.CompressionTest",
+ "unit._credentials_test.CredentialsTest",
+ "unit._cython._cancel_many_calls_test.CancelManyCallsTest",
+ "unit._cython._channel_test.ChannelTest",
+ "unit._cython._read_some_but_not_all_responses_test.ReadSomeButNotAllResponsesTest",
+ "unit._cython.cygrpc_test.InsecureServerInsecureClient",
+ "unit._cython.cygrpc_test.SecureServerSecureClient",
+ "unit._cython.cygrpc_test.TypeSmokeTest",
+ "unit._empty_message_test.EmptyMessageTest",
+ "unit._exit_test.ExitTest",
+ "unit._metadata_code_details_test.MetadataCodeDetailsTest",
+ "unit._metadata_test.MetadataTest",
+ "unit._rpc_test.RPCTest",
+ "unit._sanity._sanity_test.Sanity",
+ "unit._thread_cleanup_test.CleanupThreadTest",
+ "unit.beta._beta_features_test.BetaFeaturesTest",
+ "unit.beta._beta_features_test.ContextManagementAndLifecycleTest",
+ "unit.beta._connectivity_channel_test.ConnectivityStatesTest",
+ "unit.beta._face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
+ "unit.beta._face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
+ "unit.beta._face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
+ "unit.beta._face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
+ "unit.beta._face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
+ "unit.beta._face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
+ "unit.beta._implementations_test.CallCredentialsTest",
+ "unit.beta._implementations_test.ChannelCredentialsTest",
+ "unit.beta._not_found_test.NotFoundTest",
+ "unit.beta._utilities_test.ChannelConnectivityTest",
+ "unit.framework.foundation._logging_pool_test.LoggingPoolTest"
]