_split_definitions_test.py
Go to the documentation of this file.
1 # Copyright 2016 gRPC authors.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import abc
16 import contextlib
17 import importlib
18 import os
19 from os import path
20 import pkgutil
21 import platform
22 import shutil
23 import sys
24 import tempfile
25 import unittest
26 
27 import grpc
28 from grpc_tools import protoc
29 import six
30 
31 from tests.unit import test_common
32 
33 _MESSAGES_IMPORT = b'import "messages.proto";'
34 _SPLIT_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing.split;'
35 _COMMON_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing;'
36 
37 _RELATIVE_PROTO_PATH = 'relative_proto_path'
38 _RELATIVE_PYTHON_OUT = 'relative_python_out'
39 
40 
41 @contextlib.contextmanager
42 def _system_path(path_insertion):
43  old_system_path = sys.path[:]
44  sys.path = sys.path[0:1] + path_insertion + sys.path[1:]
45  yield
46  sys.path = old_system_path
47 
48 
49 # NOTE(nathaniel): https://twitter.com/exoplaneteer/status/677259364256747520
50 # Life lesson "just always default to idempotence" reinforced.
51 def _create_directory_tree(root, path_components_sequence):
52  created = set()
53  for path_components in path_components_sequence:
54  thus_far = ''
55  for path_component in path_components:
56  relative_path = path.join(thus_far, path_component)
57  if relative_path not in created:
58  os.makedirs(path.join(root, relative_path))
59  created.add(relative_path)
60  thus_far = path.join(thus_far, path_component)
61 
62 
63 def _massage_proto_content(proto_content, test_name_bytes,
64  messages_proto_relative_file_name_bytes):
65  package_substitution = (b'package grpc_protoc_plugin.invocation_testing.' +
66  test_name_bytes + b';')
67  common_namespace_substituted = proto_content.replace(
68  _COMMON_NAMESPACE, package_substitution)
69  split_namespace_substituted = common_namespace_substituted.replace(
70  _SPLIT_NAMESPACE, package_substitution)
71  message_import_replaced = split_namespace_substituted.replace(
72  _MESSAGES_IMPORT,
73  b'import "' + messages_proto_relative_file_name_bytes + b'";')
74  return message_import_replaced
75 
76 
77 def _packagify(directory):
78  for subdirectory, _, _ in os.walk(directory):
79  init_file_name = path.join(subdirectory, '__init__.py')
80  with open(init_file_name, 'wb') as init_file:
81  init_file.write(b'')
82 
83 
84 class _Servicer(object):
85 
86  def __init__(self, response_class):
87  self._response_class = response_class
88 
89  def Call(self, request, context):
90  return self._response_class()
91 
92 
93 def _protoc(proto_path, python_out, grpc_python_out_flag, grpc_python_out,
94  absolute_proto_file_names):
95  args = [
96  '',
97  '--proto_path={}'.format(proto_path),
98  ]
99  if python_out is not None:
100  args.append('--python_out={}'.format(python_out))
101  if grpc_python_out is not None:
102  args.append('--grpc_python_out={}:{}'.format(grpc_python_out_flag,
103  grpc_python_out))
104  args.extend(absolute_proto_file_names)
105  return protoc.main(args)
106 
107 
108 class _Mid2016ProtocStyle(object):
109 
110  def name(self):
111  return 'Mid2016ProtocStyle'
112 
114  return True
115 
116  def protoc(self, proto_path, python_out, absolute_proto_file_names):
117  return (_protoc(proto_path, python_out, 'grpc_1_0', python_out,
118  absolute_proto_file_names),)
119 
120 
122 
123  def name(self):
124  return 'SingleProtocExecutionProtocStyle'
125 
127  return False
128 
129  def protoc(self, proto_path, python_out, absolute_proto_file_names):
130  return (_protoc(proto_path, python_out, 'grpc_2_0', python_out,
131  absolute_proto_file_names),)
132 
133 
135 
136  def name(self):
137  return 'ProtoBeforeGrpcProtocStyle'
138 
140  return False
141 
142  def protoc(self, proto_path, python_out, absolute_proto_file_names):
143  pb2_protoc_exit_code = _protoc(proto_path, python_out, None, None,
144  absolute_proto_file_names)
145  pb2_grpc_protoc_exit_code = _protoc(proto_path, None, 'grpc_2_0',
146  python_out,
147  absolute_proto_file_names)
148  return pb2_protoc_exit_code, pb2_grpc_protoc_exit_code
149 
150 
152 
153  def name(self):
154  return 'GrpcBeforeProtoProtocStyle'
155 
157  return False
158 
159  def protoc(self, proto_path, python_out, absolute_proto_file_names):
160  pb2_grpc_protoc_exit_code = _protoc(proto_path, None, 'grpc_2_0',
161  python_out,
162  absolute_proto_file_names)
163  pb2_protoc_exit_code = _protoc(proto_path, python_out, None, None,
164  absolute_proto_file_names)
165  return pb2_grpc_protoc_exit_code, pb2_protoc_exit_code
166 
167 
168 _PROTOC_STYLES = (
173 )
174 
175 
176 @unittest.skipIf(platform.python_implementation() == 'PyPy',
177  'Skip test if run with PyPy!')
178 class _Test(six.with_metaclass(abc.ABCMeta, unittest.TestCase)):
179 
180  def setUp(self):
181  self._directory = tempfile.mkdtemp(suffix=self.NAME, dir='.')
182  self._proto_path = path.join(self._directory, _RELATIVE_PROTO_PATH)
183  self._python_out = path.join(self._directory, _RELATIVE_PYTHON_OUT)
184 
185  os.makedirs(self._proto_path)
186  os.makedirs(self._python_out)
187 
188  proto_directories_and_names = {
189  (
190  self.MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES,
191  self.MESSAGES_PROTO_FILE_NAME,
192  ),
193  (
194  self.SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES,
195  self.SERVICES_PROTO_FILE_NAME,
196  ),
197  }
198  messages_proto_relative_file_name_forward_slashes = '/'.join(
199  self.MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES +
200  (self.MESSAGES_PROTO_FILE_NAME,))
202  self._proto_path,
203  (relative_proto_directory_names for relative_proto_directory_names,
204  _ in proto_directories_and_names))
206  for relative_directory_names, file_name in proto_directories_and_names:
207  absolute_proto_file_name = path.join(
208  self._proto_path, *relative_directory_names + (file_name,))
209  raw_proto_content = pkgutil.get_data(
210  'tests.protoc_plugin.protos.invocation_testing',
211  path.join(*relative_directory_names + (file_name,)))
212  massaged_proto_content = _massage_proto_content(
213  raw_proto_content, self.NAME.encode(),
214  messages_proto_relative_file_name_forward_slashes.encode())
215  with open(absolute_proto_file_name, 'wb') as proto_file:
216  proto_file.write(massaged_proto_content)
217  self._absolute_proto_file_names.add(absolute_proto_file_name)
218 
219  def tearDown(self):
220  shutil.rmtree(self._directory)
221 
222  def _protoc(self):
223  protoc_exit_codes = self.PROTOC_STYLE.protoc(
225  for protoc_exit_code in protoc_exit_codes:
226  self.assertEqual(0, protoc_exit_code)
227 
228  _packagify(self._python_out)
229 
230  generated_modules = {}
231  expected_generated_full_module_names = {
232  self.EXPECTED_MESSAGES_PB2,
233  self.EXPECTED_SERVICES_PB2,
234  self.EXPECTED_SERVICES_PB2_GRPC,
235  }
236  with _system_path([self._python_out]):
237  for full_module_name in expected_generated_full_module_names:
238  module = importlib.import_module(full_module_name)
239  generated_modules[full_module_name] = module
240 
241  self._messages_pb2 = generated_modules[self.EXPECTED_MESSAGES_PB2]
242  self._services_pb2 = generated_modules[self.EXPECTED_SERVICES_PB2]
243  self._services_pb2_grpc = generated_modules[
244  self.EXPECTED_SERVICES_PB2_GRPC]
245 
246  def _services_modules(self):
247  if self.PROTOC_STYLE.grpc_in_pb2_expected():
248  return self._services_pb2, self._services_pb2_grpc
249  else:
250  return (self._services_pb2_grpc,)
251 
253  self._protoc()
254 
255  self._messages_pb2.Request
256  self._messages_pb2.Response
257  self._services_pb2.DESCRIPTOR.services_by_name['TestService']
258  for services_module in self._services_modules():
259  services_module.TestServiceStub
260  services_module.TestServiceServicer
261  services_module.add_TestServiceServicer_to_server
262 
263  def test_call(self):
264  self._protoc()
265 
266  for services_module in self._services_modules():
267  server = test_common.test_server()
268  services_module.add_TestServiceServicer_to_server(
269  _Servicer(self._messages_pb2.Response), server)
270  port = server.add_insecure_port('[::]:0')
271  server.start()
272  channel = grpc.insecure_channel('localhost:{}'.format(port))
273  stub = services_module.TestServiceStub(channel)
274  response = stub.Call(self._messages_pb2.Request())
275  self.assertEqual(self._messages_pb2.Response(), response)
276  server.stop(None)
277 
278 
279 def _create_test_case_class(split_proto, protoc_style):
280  attributes = {}
281 
282  name = '{}{}'.format('SplitProto' if split_proto else 'SameProto',
283  protoc_style.name())
284  attributes['NAME'] = name
285 
286  if split_proto:
287  attributes['MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES'] = (
288  'split_messages',
289  'sub',
290  )
291  attributes['MESSAGES_PROTO_FILE_NAME'] = 'messages.proto'
292  attributes['SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES'] = (
293  'split_services',)
294  attributes['SERVICES_PROTO_FILE_NAME'] = 'services.proto'
295  attributes['EXPECTED_MESSAGES_PB2'] = 'split_messages.sub.messages_pb2'
296  attributes['EXPECTED_SERVICES_PB2'] = 'split_services.services_pb2'
297  attributes['EXPECTED_SERVICES_PB2_GRPC'] = (
298  'split_services.services_pb2_grpc')
299  else:
300  attributes['MESSAGES_PROTO_RELATIVE_DIRECTORY_NAMES'] = ()
301  attributes['MESSAGES_PROTO_FILE_NAME'] = 'same.proto'
302  attributes['SERVICES_PROTO_RELATIVE_DIRECTORY_NAMES'] = ()
303  attributes['SERVICES_PROTO_FILE_NAME'] = 'same.proto'
304  attributes['EXPECTED_MESSAGES_PB2'] = 'same_pb2'
305  attributes['EXPECTED_SERVICES_PB2'] = 'same_pb2'
306  attributes['EXPECTED_SERVICES_PB2_GRPC'] = 'same_pb2_grpc'
307 
308  attributes['PROTOC_STYLE'] = protoc_style
309 
310  attributes['__module__'] = _Test.__module__
311 
312  return type('{}Test'.format(name), (_Test,), attributes)
313 
314 
316  for split_proto in (
317  False,
318  True,
319  ):
320  for protoc_style in _PROTOC_STYLES:
321  yield _create_test_case_class(split_proto, protoc_style)
322 
323 
324 def load_tests(loader, tests, pattern):
325  tests = tuple(
326  loader.loadTestsFromTestCase(test_case_class)
327  for test_case_class in _create_test_case_classes())
328  return unittest.TestSuite(tests=tests)
329 
330 
331 if __name__ == '__main__':
332  unittest.main(verbosity=2)
tests.protoc_plugin._split_definitions_test._create_directory_tree
def _create_directory_tree(root, path_components_sequence)
Definition: _split_definitions_test.py:51
grpc.insecure_channel
def insecure_channel(target, options=None, compression=None)
Definition: src/python/grpcio/grpc/__init__.py:1962
tests.protoc_plugin._split_definitions_test._ProtoBeforeGrpcProtocStyle.name
def name(self)
Definition: _split_definitions_test.py:136
http2_test_server.format
format
Definition: http2_test_server.py:118
tests.protoc_plugin._split_definitions_test._Test._directory
_directory
Definition: _split_definitions_test.py:181
tests.protoc_plugin._split_definitions_test._packagify
def _packagify(directory)
Definition: _split_definitions_test.py:77
tests.protoc_plugin._split_definitions_test._Test
Definition: _split_definitions_test.py:178
tests.protoc_plugin._split_definitions_test._GrpcBeforeProtoProtocStyle
Definition: _split_definitions_test.py:151
tests.protoc_plugin._split_definitions_test._SingleProtocExecutionProtocStyle
Definition: _split_definitions_test.py:121
tests.protoc_plugin._split_definitions_test._Servicer.__init__
def __init__(self, response_class)
Definition: _split_definitions_test.py:86
tests.protoc_plugin._split_definitions_test._GrpcBeforeProtoProtocStyle.name
def name(self)
Definition: _split_definitions_test.py:153
tests.protoc_plugin._split_definitions_test._Test._messages_pb2
_messages_pb2
Definition: _split_definitions_test.py:241
tests.protoc_plugin._split_definitions_test._Test._absolute_proto_file_names
_absolute_proto_file_names
Definition: _split_definitions_test.py:205
tests.protoc_plugin._split_definitions_test._Test._services_pb2_grpc
_services_pb2_grpc
Definition: _split_definitions_test.py:243
grpc._common.encode
def encode(s)
Definition: grpc/_common.py:68
tests.protoc_plugin._split_definitions_test._SingleProtocExecutionProtocStyle.name
def name(self)
Definition: _split_definitions_test.py:123
tests.protoc_plugin._split_definitions_test._SingleProtocExecutionProtocStyle.protoc
def protoc(self, proto_path, python_out, absolute_proto_file_names)
Definition: _split_definitions_test.py:129
tests.protoc_plugin._split_definitions_test._Test.test_call
def test_call(self)
Definition: _split_definitions_test.py:263
tests.protoc_plugin._split_definitions_test._Test._python_out
_python_out
Definition: _split_definitions_test.py:183
google::protobuf::compiler
Definition: bloaty/third_party/protobuf/benchmarks/util/protoc-gen-gogoproto.cc:19
tests.protoc_plugin._split_definitions_test._Test._services_pb2
_services_pb2
Definition: _split_definitions_test.py:242
tests.protoc_plugin._split_definitions_test._Test.setUp
def setUp(self)
Definition: _split_definitions_test.py:180
tests.protoc_plugin._split_definitions_test._create_test_case_classes
def _create_test_case_classes()
Definition: _split_definitions_test.py:315
tests.protoc_plugin._split_definitions_test._Test._proto_path
_proto_path
Definition: _split_definitions_test.py:182
tests.protoc_plugin._split_definitions_test._create_test_case_class
def _create_test_case_class(split_proto, protoc_style)
Definition: _split_definitions_test.py:279
tests.protoc_plugin._split_definitions_test._Test.tearDown
def tearDown(self)
Definition: _split_definitions_test.py:219
tests.protoc_plugin._split_definitions_test._Test._services_modules
def _services_modules(self)
Definition: _split_definitions_test.py:246
tests.protoc_plugin._split_definitions_test._SingleProtocExecutionProtocStyle.grpc_in_pb2_expected
def grpc_in_pb2_expected(self)
Definition: _split_definitions_test.py:126
tests.protoc_plugin._split_definitions_test.load_tests
def load_tests(loader, tests, pattern)
Definition: _split_definitions_test.py:324
tests.protoc_plugin._split_definitions_test._GrpcBeforeProtoProtocStyle.grpc_in_pb2_expected
def grpc_in_pb2_expected(self)
Definition: _split_definitions_test.py:156
tests.protoc_plugin._split_definitions_test._Mid2016ProtocStyle
Definition: _split_definitions_test.py:108
tests.protoc_plugin._split_definitions_test._Test.test_imported_attributes
def test_imported_attributes(self)
Definition: _split_definitions_test.py:252
tests.protoc_plugin._split_definitions_test._Servicer.Call
def Call(self, request, context)
Definition: _split_definitions_test.py:89
tests.protoc_plugin._split_definitions_test._ProtoBeforeGrpcProtocStyle.grpc_in_pb2_expected
def grpc_in_pb2_expected(self)
Definition: _split_definitions_test.py:139
tests.protoc_plugin._split_definitions_test._system_path
def _system_path(path_insertion)
Definition: _split_definitions_test.py:42
tests.protoc_plugin._split_definitions_test._ProtoBeforeGrpcProtocStyle
Definition: _split_definitions_test.py:134
add
static void add(const char *beg, const char *end, char ***ss, size_t *ns)
Definition: debug/trace.cc:96
tests.unit
Definition: src/python/grpcio_tests/tests/unit/__init__.py:1
tests.protoc_plugin._split_definitions_test._Mid2016ProtocStyle.name
def name(self)
Definition: _split_definitions_test.py:110
tests.protoc_plugin._split_definitions_test._Test._protoc
def _protoc(self)
Definition: _split_definitions_test.py:222
tests.protoc_plugin._split_definitions_test._massage_proto_content
def _massage_proto_content(proto_content, test_name_bytes, messages_proto_relative_file_name_bytes)
Definition: _split_definitions_test.py:63
tests.protoc_plugin._split_definitions_test._Mid2016ProtocStyle.protoc
def protoc(self, proto_path, python_out, absolute_proto_file_names)
Definition: _split_definitions_test.py:116
tests.protoc_plugin._split_definitions_test._GrpcBeforeProtoProtocStyle.protoc
def protoc(self, proto_path, python_out, absolute_proto_file_names)
Definition: _split_definitions_test.py:159
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
tests.protoc_plugin._split_definitions_test._protoc
def _protoc(proto_path, python_out, grpc_python_out_flag, grpc_python_out, absolute_proto_file_names)
Definition: _split_definitions_test.py:93
open
#define open
Definition: test-fs.c:46
demo_pb2.Request
Request
Definition: demo_pb2.py:108
tests.protoc_plugin._split_definitions_test._ProtoBeforeGrpcProtocStyle.protoc
def protoc(self, proto_path, python_out, absolute_proto_file_names)
Definition: _split_definitions_test.py:142
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
demo_pb2.Response
Response
Definition: demo_pb2.py:115
tests.protoc_plugin._split_definitions_test._Servicer._response_class
_response_class
Definition: _split_definitions_test.py:87
tests.protoc_plugin._split_definitions_test._Servicer
Definition: _split_definitions_test.py:84
tests.protoc_plugin._split_definitions_test._Mid2016ProtocStyle.grpc_in_pb2_expected
def grpc_in_pb2_expected(self)
Definition: _split_definitions_test.py:113


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:27