blob: db938e65459c77a5cbc1a21889e575f7cbde4670 [file] [log] [blame]
Masood Malekghassemid9539592016-10-20 14:47:14 -07001# Copyright 2016, Google Inc.
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8# * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14# * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30import collections
31from concurrent import futures
32import contextlib
33import distutils.spawn
34import errno
35import importlib
36import os
37import os.path
38import pkgutil
39import shutil
40import subprocess
41import sys
42import tempfile
43import threading
44import unittest
45
46import grpc
Masood Malekghassemifb261bf2016-12-12 13:19:31 -080047from grpc_tools import protoc
Masood Malekghassemid9539592016-10-20 14:47:14 -070048from tests.unit.framework.common import test_constants
49
50_MESSAGES_IMPORT = b'import "messages.proto";'
Ken Paysondbf571e2017-02-09 14:10:03 -080051_SPLIT_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing.split;'
52_COMMON_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing;'
Masood Malekghassemid9539592016-10-20 14:47:14 -070053
Masood Malekghassemicc793702017-01-13 19:20:10 -080054
Masood Malekghassemid9539592016-10-20 14:47:14 -070055@contextlib.contextmanager
56def _system_path(path):
Masood Malekghassemicc793702017-01-13 19:20:10 -080057 old_system_path = sys.path[:]
58 sys.path = sys.path[0:1] + path + sys.path[1:]
59 yield
60 sys.path = old_system_path
Masood Malekghassemid9539592016-10-20 14:47:14 -070061
62
63class DummySplitServicer(object):
64
Masood Malekghassemicc793702017-01-13 19:20:10 -080065 def __init__(self, request_class, response_class):
66 self.request_class = request_class
67 self.response_class = response_class
Masood Malekghassemid9539592016-10-20 14:47:14 -070068
Masood Malekghassemicc793702017-01-13 19:20:10 -080069 def Call(self, request, context):
70 return self.response_class()
Masood Malekghassemid9539592016-10-20 14:47:14 -070071
72
73class SeparateTestMixin(object):
74
Masood Malekghassemicc793702017-01-13 19:20:10 -080075 def testImportAttributes(self):
76 with _system_path([self.python_out_directory]):
77 pb2 = importlib.import_module(self.pb2_import)
78 pb2.Request
79 pb2.Response
80 if self.should_find_services_in_pb2:
81 pb2.TestServiceServicer
82 else:
83 with self.assertRaises(AttributeError):
84 pb2.TestServiceServicer
Masood Malekghassemid9539592016-10-20 14:47:14 -070085
Masood Malekghassemicc793702017-01-13 19:20:10 -080086 with _system_path([self.grpc_python_out_directory]):
87 pb2_grpc = importlib.import_module(self.pb2_grpc_import)
88 pb2_grpc.TestServiceServicer
89 with self.assertRaises(AttributeError):
90 pb2_grpc.Request
91 with self.assertRaises(AttributeError):
92 pb2_grpc.Response
Masood Malekghassemid9539592016-10-20 14:47:14 -070093
Masood Malekghassemicc793702017-01-13 19:20:10 -080094 def testCall(self):
95 with _system_path([self.python_out_directory]):
96 pb2 = importlib.import_module(self.pb2_import)
97 with _system_path([self.grpc_python_out_directory]):
98 pb2_grpc = importlib.import_module(self.pb2_grpc_import)
99 server = grpc.server(
100 futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
101 pb2_grpc.add_TestServiceServicer_to_server(
102 DummySplitServicer(pb2.Request, pb2.Response), server)
103 port = server.add_insecure_port('[::]:0')
104 server.start()
105 channel = grpc.insecure_channel('localhost:{}'.format(port))
106 stub = pb2_grpc.TestServiceStub(channel)
107 request = pb2.Request()
108 expected_response = pb2.Response()
109 response = stub.Call(request)
110 self.assertEqual(expected_response, response)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700111
112
113class CommonTestMixin(object):
114
Masood Malekghassemicc793702017-01-13 19:20:10 -0800115 def testImportAttributes(self):
116 with _system_path([self.python_out_directory]):
117 pb2 = importlib.import_module(self.pb2_import)
118 pb2.Request
119 pb2.Response
120 if self.should_find_services_in_pb2:
121 pb2.TestServiceServicer
122 else:
123 with self.assertRaises(AttributeError):
124 pb2.TestServiceServicer
Masood Malekghassemid9539592016-10-20 14:47:14 -0700125
Masood Malekghassemicc793702017-01-13 19:20:10 -0800126 with _system_path([self.grpc_python_out_directory]):
127 pb2_grpc = importlib.import_module(self.pb2_grpc_import)
128 pb2_grpc.TestServiceServicer
129 with self.assertRaises(AttributeError):
130 pb2_grpc.Request
131 with self.assertRaises(AttributeError):
132 pb2_grpc.Response
Masood Malekghassemid9539592016-10-20 14:47:14 -0700133
Masood Malekghassemicc793702017-01-13 19:20:10 -0800134 def testCall(self):
135 with _system_path([self.python_out_directory]):
136 pb2 = importlib.import_module(self.pb2_import)
137 with _system_path([self.grpc_python_out_directory]):
138 pb2_grpc = importlib.import_module(self.pb2_grpc_import)
139 server = grpc.server(
140 futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
141 pb2_grpc.add_TestServiceServicer_to_server(
142 DummySplitServicer(pb2.Request, pb2.Response), server)
143 port = server.add_insecure_port('[::]:0')
144 server.start()
145 channel = grpc.insecure_channel('localhost:{}'.format(port))
146 stub = pb2_grpc.TestServiceStub(channel)
147 request = pb2.Request()
148 expected_response = pb2.Response()
149 response = stub.Call(request)
150 self.assertEqual(expected_response, response)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700151
152
153class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
154
Masood Malekghassemicc793702017-01-13 19:20:10 -0800155 def setUp(self):
156 same_proto_contents = pkgutil.get_data(
157 'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
158 self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.')
159 self.proto_directory = os.path.join(self.directory, 'proto_path')
160 self.python_out_directory = os.path.join(self.directory, 'python_out')
161 self.grpc_python_out_directory = os.path.join(self.directory,
162 'grpc_python_out')
163 os.makedirs(self.proto_directory)
164 os.makedirs(self.python_out_directory)
165 os.makedirs(self.grpc_python_out_directory)
166 same_proto_file = os.path.join(self.proto_directory,
167 'same_separate.proto')
Ken Paysondbf571e2017-02-09 14:10:03 -0800168 open(same_proto_file, 'wb').write(
169 same_proto_contents.replace(
170 _COMMON_NAMESPACE,
171 b'package grpc_protoc_plugin.invocation_testing.same_separate;'))
Masood Malekghassemicc793702017-01-13 19:20:10 -0800172 protoc_result = protoc.main([
173 '',
174 '--proto_path={}'.format(self.proto_directory),
175 '--python_out={}'.format(self.python_out_directory),
176 '--grpc_python_out=grpc_2_0:{}'.format(
177 self.grpc_python_out_directory),
178 same_proto_file,
179 ])
180 if protoc_result != 0:
181 raise Exception("unexpected protoc error")
182 open(os.path.join(self.grpc_python_out_directory, '__init__.py'),
183 'w').write('')
184 open(os.path.join(self.python_out_directory, '__init__.py'),
185 'w').write('')
186 self.pb2_import = 'same_separate_pb2'
187 self.pb2_grpc_import = 'same_separate_pb2_grpc'
188 self.should_find_services_in_pb2 = False
Masood Malekghassemid9539592016-10-20 14:47:14 -0700189
Masood Malekghassemicc793702017-01-13 19:20:10 -0800190 def tearDown(self):
191 shutil.rmtree(self.directory)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700192
193
194class SameCommonTest(unittest.TestCase, CommonTestMixin):
195
Masood Malekghassemicc793702017-01-13 19:20:10 -0800196 def setUp(self):
197 same_proto_contents = pkgutil.get_data(
198 'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
199 self.directory = tempfile.mkdtemp(suffix='same_common', dir='.')
200 self.proto_directory = os.path.join(self.directory, 'proto_path')
201 self.python_out_directory = os.path.join(self.directory, 'python_out')
202 self.grpc_python_out_directory = self.python_out_directory
203 os.makedirs(self.proto_directory)
204 os.makedirs(self.python_out_directory)
205 same_proto_file = os.path.join(self.proto_directory,
206 'same_common.proto')
Ken Paysondbf571e2017-02-09 14:10:03 -0800207 open(same_proto_file, 'wb').write(
208 same_proto_contents.replace(
209 _COMMON_NAMESPACE,
210 b'package grpc_protoc_plugin.invocation_testing.same_common;'))
211
Masood Malekghassemicc793702017-01-13 19:20:10 -0800212 protoc_result = protoc.main([
213 '',
214 '--proto_path={}'.format(self.proto_directory),
215 '--python_out={}'.format(self.python_out_directory),
216 '--grpc_python_out={}'.format(self.grpc_python_out_directory),
217 same_proto_file,
218 ])
219 if protoc_result != 0:
220 raise Exception("unexpected protoc error")
221 open(os.path.join(self.python_out_directory, '__init__.py'),
222 'w').write('')
223 self.pb2_import = 'same_common_pb2'
224 self.pb2_grpc_import = 'same_common_pb2_grpc'
225 self.should_find_services_in_pb2 = True
Masood Malekghassemid9539592016-10-20 14:47:14 -0700226
Masood Malekghassemicc793702017-01-13 19:20:10 -0800227 def tearDown(self):
228 shutil.rmtree(self.directory)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700229
230
231class SplitCommonTest(unittest.TestCase, CommonTestMixin):
232
Masood Malekghassemicc793702017-01-13 19:20:10 -0800233 def setUp(self):
234 services_proto_contents = pkgutil.get_data(
235 'tests.protoc_plugin.protos.invocation_testing.split_services',
236 'services.proto')
237 messages_proto_contents = pkgutil.get_data(
238 'tests.protoc_plugin.protos.invocation_testing.split_messages',
239 'messages.proto')
240 self.directory = tempfile.mkdtemp(suffix='split_common', dir='.')
241 self.proto_directory = os.path.join(self.directory, 'proto_path')
242 self.python_out_directory = os.path.join(self.directory, 'python_out')
243 self.grpc_python_out_directory = self.python_out_directory
244 os.makedirs(self.proto_directory)
245 os.makedirs(self.python_out_directory)
246 services_proto_file = os.path.join(self.proto_directory,
247 'split_common_services.proto')
248 messages_proto_file = os.path.join(self.proto_directory,
249 'split_common_messages.proto')
250 open(services_proto_file, 'wb').write(
251 services_proto_contents.replace(
Ken Paysondbf571e2017-02-09 14:10:03 -0800252 _MESSAGES_IMPORT, b'import "split_common_messages.proto";')
253 .replace(
254 _SPLIT_NAMESPACE,
255 b'package grpc_protoc_plugin.invocation_testing.split_common;'))
256 open(messages_proto_file, 'wb').write(
257 messages_proto_contents.replace(
258 _SPLIT_NAMESPACE,
259 b'package grpc_protoc_plugin.invocation_testing.split_common;'))
Masood Malekghassemicc793702017-01-13 19:20:10 -0800260 protoc_result = protoc.main([
261 '',
262 '--proto_path={}'.format(self.proto_directory),
263 '--python_out={}'.format(self.python_out_directory),
264 '--grpc_python_out={}'.format(self.grpc_python_out_directory),
265 services_proto_file,
266 messages_proto_file,
267 ])
268 if protoc_result != 0:
269 raise Exception("unexpected protoc error")
270 open(os.path.join(self.python_out_directory, '__init__.py'),
271 'w').write('')
272 self.pb2_import = 'split_common_messages_pb2'
273 self.pb2_grpc_import = 'split_common_services_pb2_grpc'
274 self.should_find_services_in_pb2 = False
Masood Malekghassemid9539592016-10-20 14:47:14 -0700275
Masood Malekghassemicc793702017-01-13 19:20:10 -0800276 def tearDown(self):
277 shutil.rmtree(self.directory)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700278
279
280class SplitSeparateTest(unittest.TestCase, SeparateTestMixin):
281
Masood Malekghassemicc793702017-01-13 19:20:10 -0800282 def setUp(self):
283 services_proto_contents = pkgutil.get_data(
284 'tests.protoc_plugin.protos.invocation_testing.split_services',
285 'services.proto')
286 messages_proto_contents = pkgutil.get_data(
287 'tests.protoc_plugin.protos.invocation_testing.split_messages',
288 'messages.proto')
289 self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.')
290 self.proto_directory = os.path.join(self.directory, 'proto_path')
291 self.python_out_directory = os.path.join(self.directory, 'python_out')
292 self.grpc_python_out_directory = os.path.join(self.directory,
293 'grpc_python_out')
294 os.makedirs(self.proto_directory)
295 os.makedirs(self.python_out_directory)
296 os.makedirs(self.grpc_python_out_directory)
297 services_proto_file = os.path.join(self.proto_directory,
298 'split_separate_services.proto')
299 messages_proto_file = os.path.join(self.proto_directory,
300 'split_separate_messages.proto')
301 open(services_proto_file, 'wb').write(
302 services_proto_contents.replace(
Ken Paysondbf571e2017-02-09 14:10:03 -0800303 _MESSAGES_IMPORT, b'import "split_separate_messages.proto";')
304 .replace(
305 _SPLIT_NAMESPACE,
306 b'package grpc_protoc_plugin.invocation_testing.split_separate;'
307 ))
308 open(messages_proto_file, 'wb').write(
309 messages_proto_contents.replace(
310 _SPLIT_NAMESPACE,
311 b'package grpc_protoc_plugin.invocation_testing.split_separate;'
312 ))
Masood Malekghassemicc793702017-01-13 19:20:10 -0800313 protoc_result = protoc.main([
314 '',
315 '--proto_path={}'.format(self.proto_directory),
316 '--python_out={}'.format(self.python_out_directory),
317 '--grpc_python_out=grpc_2_0:{}'.format(
318 self.grpc_python_out_directory),
319 services_proto_file,
320 messages_proto_file,
321 ])
322 if protoc_result != 0:
323 raise Exception("unexpected protoc error")
324 open(os.path.join(self.python_out_directory, '__init__.py'),
325 'w').write('')
326 self.pb2_import = 'split_separate_messages_pb2'
327 self.pb2_grpc_import = 'split_separate_services_pb2_grpc'
328 self.should_find_services_in_pb2 = False
Masood Malekghassemid9539592016-10-20 14:47:14 -0700329
Masood Malekghassemicc793702017-01-13 19:20:10 -0800330 def tearDown(self):
331 shutil.rmtree(self.directory)
Masood Malekghassemid9539592016-10-20 14:47:14 -0700332
333
334if __name__ == '__main__':
Masood Malekghassemicc793702017-01-13 19:20:10 -0800335 unittest.main(verbosity=2)