blob: e83a88063f7e8084d7e8fcb17a17bafb8309baaa [file] [log] [blame]
Mark Slee57cc25e2007-02-28 21:43:54 +00001#!/usr/bin/env python
Nobuaki Sukegawa64b8f6c2015-10-10 02:12:48 +09002# -*- coding: utf-8 -*-
David Reissea2cba82009-03-30 21:35:00 +00003#
4# Licensed to the Apache Software Foundation (ASF) under one
5# or more contributor license agreements. See the NOTICE file
6# distributed with this work for additional information
7# regarding copyright ownership. The ASF licenses this file
8# to you under the Apache License, Version 2.0 (the
9# "License"); you may not use this file except in compliance
10# with the License. You may obtain a copy of the License at
11#
12# http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing,
15# software distributed under the License is distributed on an
16# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17# KIND, either express or implied. See the License for the
18# specific language governing permissions and limitations
19# under the License.
20#
21
Jens Geyerd629ea02015-09-23 21:16:50 +020022import glob
23import os
24import sys
Mark Slee57cc25e2007-02-28 21:43:54 +000025import time
Jens Geyerd629ea02015-09-23 21:16:50 +020026import unittest
Mark Slee5299a952007-10-05 00:13:24 +000027from optparse import OptionParser
Mark Slee57cc25e2007-02-28 21:43:54 +000028
Nobuaki Sukegawaa185d7e2015-11-06 21:24:24 +090029SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
30ROOT_DIR = os.path.dirname(os.path.dirname(SCRIPT_DIR))
31DEFAULT_LIBDIR_GLOB = os.path.join(ROOT_DIR, 'lib', 'py', 'build', 'lib.*')
Roger Meierf4eec7a2011-09-11 18:16:21 +000032
Jens Geyerd629ea02015-09-23 21:16:50 +020033
Mark Slee5299a952007-10-05 00:13:24 +000034class AbstractTest(unittest.TestCase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090035 def setUp(self):
36 if options.http_path:
37 self.transport = THttpClient.THttpClient(options.host, port=options.port, path=options.http_path)
38 else:
39 if options.ssl:
40 from thrift.transport import TSSLSocket
41 socket = TSSLSocket.TSSLSocket(options.host, options.port, validate=False)
42 else:
43 socket = TSocket.TSocket(options.host, options.port)
44 # frame or buffer depending upon args
45 self.transport = TTransport.TBufferedTransport(socket)
46 if options.trans == 'framed':
47 self.transport = TTransport.TFramedTransport(socket)
48 elif options.trans == 'buffered':
49 self.transport = TTransport.TBufferedTransport(socket)
50 elif options.trans == '':
51 raise AssertionError('Unknown --transport option: %s' % options.trans)
52 if options.zlib:
53 self.transport = TZlibTransport.TZlibTransport(self.transport, 9)
54 self.transport.open()
55 protocol = self.get_protocol(self.transport)
56 self.client = ThriftTest.Client(protocol)
David Reiss0c90f6f2008-02-06 22:18:40 +000057
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090058 def tearDown(self):
59 self.transport.close()
Mark Sleefc89d392006-09-04 00:04:39 +000060
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090061 def testVoid(self):
62 print('testVoid')
63 self.client.testVoid()
David Reiss0c90f6f2008-02-06 22:18:40 +000064
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090065 def testString(self):
66 print('testString')
67 self.assertEqual(self.client.testString('Python' * 20), 'Python' * 20)
68 self.assertEqual(self.client.testString(''), '')
69 s1 = u'\b\t\n/\\\\\r{}:パイソン"'
70 s2 = u"""Afrikaans, Alemannisch, Aragonés, العربية, مصرى,
Nobuaki Sukegawa64b8f6c2015-10-10 02:12:48 +090071 Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška,
72 Беларуская, Беларуская (тарашкевіца), Български, Bamanankan,
73 বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн,
74 Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg,
75 Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English,
76 Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt,
77 Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego,
78 Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski,
79 Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia,
80 Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa,
81 ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар,
82 Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino,
83 Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa
84 Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa
85 Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪
86 Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad,
87 Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو,
88 Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română,
89 Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple
90 English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk,
91 Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog,
92 Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük,
93 Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文,
94 Bân-lâm-gú, 粵語"""
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090095 if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
96 s1 = s1.encode('utf8')
97 s2 = s2.encode('utf8')
98 self.assertEqual(self.client.testString(s1), s1)
99 self.assertEqual(self.client.testString(s2), s2)
Mark Sleec9676562006-09-05 17:34:52 +0000100
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900101 def testBool(self):
102 print('testBool')
103 self.assertEqual(self.client.testBool(True), True)
104 self.assertEqual(self.client.testBool(False), False)
Nobuaki Sukegawaa649e742015-09-21 13:53:25 +0900105
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900106 def testByte(self):
107 print('testByte')
108 self.assertEqual(self.client.testByte(63), 63)
109 self.assertEqual(self.client.testByte(-127), -127)
Mark Sleec98d0502006-09-06 02:42:25 +0000110
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900111 def testI32(self):
112 print('testI32')
113 self.assertEqual(self.client.testI32(-1), -1)
114 self.assertEqual(self.client.testI32(0), 0)
Mark Sleec9676562006-09-05 17:34:52 +0000115
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900116 def testI64(self):
117 print('testI64')
118 self.assertEqual(self.client.testI64(1), 1)
119 self.assertEqual(self.client.testI64(-34359738368), -34359738368)
Mark Sleec98d0502006-09-06 02:42:25 +0000120
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900121 def testDouble(self):
122 print('testDouble')
123 self.assertEqual(self.client.testDouble(-5.235098235), -5.235098235)
124 self.assertEqual(self.client.testDouble(0), 0)
125 self.assertEqual(self.client.testDouble(-1), -1)
126 self.assertEqual(self.client.testDouble(-0.000341012439638598279), -0.000341012439638598279)
Mark Sleec9676562006-09-05 17:34:52 +0000127
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900128 def testBinary(self):
129 print('testBinary')
130 val = bytearray([i for i in range(0, 256)])
131 self.assertEqual(bytearray(self.client.testBinary(bytes(val))), val)
Jens Geyerd629ea02015-09-23 21:16:50 +0200132
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900133 def testStruct(self):
134 print('testStruct')
135 x = Xtruct()
136 x.string_thing = "Zero"
137 x.byte_thing = 1
138 x.i32_thing = -3
139 x.i64_thing = -5
140 y = self.client.testStruct(x)
141 self.assertEqual(y, x)
Mark Sleefc89d392006-09-04 00:04:39 +0000142
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900143 def testNest(self):
144 print('testNest')
145 inner = Xtruct(string_thing="Zero", byte_thing=1, i32_thing=-3, i64_thing=-5)
146 x = Xtruct2(struct_thing=inner, byte_thing=0, i32_thing=0)
147 y = self.client.testNest(x)
148 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000149
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900150 def testMap(self):
151 print('testMap')
152 x = {0: 1, 1: 2, 2: 3, 3: 4, -1: -2}
153 y = self.client.testMap(x)
154 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000155
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900156 def testSet(self):
157 print('testSet')
158 x = set([8, 1, 42])
159 y = self.client.testSet(x)
160 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000161
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900162 def testList(self):
163 print('testList')
164 x = [1, 4, 9, -42]
165 y = self.client.testList(x)
166 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000167
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900168 def testEnum(self):
169 print('testEnum')
170 x = Numberz.FIVE
171 y = self.client.testEnum(x)
172 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000173
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900174 def testTypedef(self):
175 print('testTypedef')
176 x = 0xffffffffffffff # 7 bytes of 0xff
177 y = self.client.testTypedef(x)
178 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000179
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900180 def testMapMap(self):
181 print('testMapMap')
182 x = {
183 -4: {-4: -4, -3: -3, -2: -2, -1: -1},
184 4: {4: 4, 3: 3, 2: 2, 1: 1},
185 }
186 y = self.client.testMapMap(42)
187 self.assertEqual(y, x)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000188
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900189 def testMulti(self):
190 print('testMulti')
191 xpected = Xtruct(string_thing='Hello2', byte_thing=74, i32_thing=0xff00ff, i64_thing=0xffffffffd0d0)
192 y = self.client.testMulti(xpected.byte_thing,
193 xpected.i32_thing,
194 xpected.i64_thing,
195 {0: 'abc'},
196 Numberz.FIVE,
197 0xf0f0f0)
198 self.assertEqual(y, xpected)
Mark Sleec9676562006-09-05 17:34:52 +0000199
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900200 def testException(self):
201 print('testException')
202 self.client.testException('Safe')
203 try:
204 self.client.testException('Xception')
205 self.fail("should have gotten exception")
206 except Xception as x:
207 self.assertEqual(x.errorCode, 1001)
208 self.assertEqual(x.message, 'Xception')
209 # TODO ensure same behavior for repr within generated python variants
210 # ensure exception's repr method works
211 # x_repr = repr(x)
212 # self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')')
Mark Sleec9676562006-09-05 17:34:52 +0000213
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900214 try:
215 self.client.testException('TException')
216 self.fail("should have gotten exception")
217 except TException as x:
218 pass
David Reissbcaa2ad2008-06-10 22:55:26 +0000219
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900220 # Should not throw
221 self.client.testException('success')
Nobuaki Sukegawa01ede042015-09-29 02:16:53 +0900222
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900223 def testMultiException(self):
224 print('testMultiException')
225 try:
226 self.client.testMultiException('Xception', 'ignore')
227 except Xception as ex:
228 self.assertEqual(ex.errorCode, 1001)
229 self.assertEqual(ex.message, 'This is an Xception')
Nobuaki Sukegawa01ede042015-09-29 02:16:53 +0900230
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900231 try:
232 self.client.testMultiException('Xception2', 'ignore')
233 except Xception2 as ex:
234 self.assertEqual(ex.errorCode, 2002)
235 self.assertEqual(ex.struct_thing.string_thing, 'This is an Xception2')
Nobuaki Sukegawa01ede042015-09-29 02:16:53 +0900236
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900237 y = self.client.testMultiException('success', 'foobar')
238 self.assertEqual(y.string_thing, 'foobar')
Nobuaki Sukegawa01ede042015-09-29 02:16:53 +0900239
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900240 def testOneway(self):
241 print('testOneway')
242 start = time.time()
243 self.client.testOneway(1) # type is int, not float
244 end = time.time()
245 self.assertTrue(end - start < 3,
246 "oneway sleep took %f sec" % (end - start))
Roger Meier76150722014-05-31 22:22:07 +0200247
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900248 def testOnewayThenNormal(self):
249 print('testOnewayThenNormal')
250 self.client.testOneway(1) # type is int, not float
251 self.assertEqual(self.client.testString('Python'), 'Python')
David Reissdb893b62008-02-18 02:11:48 +0000252
Roger Meier879cab22014-05-03 17:51:21 +0200253
Mark Slee5299a952007-10-05 00:13:24 +0000254class NormalBinaryTest(AbstractTest):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900255 def get_protocol(self, transport):
256 return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)
Mark Sleefc89d392006-09-04 00:04:39 +0000257
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900258
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000259class CompactTest(AbstractTest):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900260 def get_protocol(self, transport):
261 return TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000262
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900263
Roger Meier85fb6de2012-11-02 00:05:42 +0000264class JSONTest(AbstractTest):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900265 def get_protocol(self, transport):
266 return TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
Roger Meier85fb6de2012-11-02 00:05:42 +0000267
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900268
Mark Slee5299a952007-10-05 00:13:24 +0000269class AcceleratedBinaryTest(AbstractTest):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900270 def get_protocol(self, transport):
271 return TBinaryProtocol.TBinaryProtocolAcceleratedFactory().getProtocol(transport)
Mark Sleea3302652006-10-25 19:03:32 +0000272
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900273
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900274class AcceleratedCompactTest(AbstractTest):
275 def get_protocol(self, transport):
276 return TCompactProtocol.TCompactProtocolAcceleratedFactory().getProtocol(transport)
277
278
David Reiss9ff3b9d2008-02-15 01:10:23 +0000279def suite():
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900280 suite = unittest.TestSuite()
281 loader = unittest.TestLoader()
282 if options.proto == 'binary': # look for --proto on cmdline
283 suite.addTest(loader.loadTestsFromTestCase(NormalBinaryTest))
284 elif options.proto == 'accel':
285 suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest))
286 elif options.proto == 'compact':
287 suite.addTest(loader.loadTestsFromTestCase(CompactTest))
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900288 elif options.proto == 'accelc':
289 suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900290 elif options.proto == 'json':
291 suite.addTest(loader.loadTestsFromTestCase(JSONTest))
292 else:
293 raise AssertionError('Unknown protocol given with --protocol: %s' % options.proto)
294 return suite
Mark Slee5299a952007-10-05 00:13:24 +0000295
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900296
David Reiss74421272008-11-07 23:09:31 +0000297class OwnArgsTestProgram(unittest.TestProgram):
298 def parseArgs(self, argv):
299 if args:
300 self.testNames = args
301 else:
Nobuaki Sukegawaa185d7e2015-11-06 21:24:24 +0900302 self.testNames = ([self.defaultTest])
David Reiss74421272008-11-07 23:09:31 +0000303 self.createTests()
304
David Reiss9ff3b9d2008-02-15 01:10:23 +0000305if __name__ == "__main__":
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900306 parser = OptionParser()
307 parser.add_option('--libpydir', type='string', dest='libpydir',
308 help='include this directory in sys.path for locating library code')
309 parser.add_option('--genpydir', type='string', dest='genpydir',
310 help='include this directory in sys.path for locating generated code')
311 parser.add_option("--port", type="int", dest="port",
312 help="connect to server at port")
313 parser.add_option("--host", type="string", dest="host",
314 help="connect to server")
315 parser.add_option("--zlib", action="store_true", dest="zlib",
316 help="use zlib wrapper for compressed transport")
317 parser.add_option("--ssl", action="store_true", dest="ssl",
318 help="use SSL for encrypted transport")
319 parser.add_option("--http", dest="http_path",
320 help="Use the HTTP transport with the specified path")
321 parser.add_option('-v', '--verbose', action="store_const",
322 dest="verbose", const=2,
323 help="verbose output")
324 parser.add_option('-q', '--quiet', action="store_const",
325 dest="verbose", const=0,
326 help="minimal output")
327 parser.add_option('--protocol', dest="proto", type="string",
328 help="protocol to use, one of: accel, binary, compact, json")
329 parser.add_option('--transport', dest="trans", type="string",
330 help="transport to use, one of: buffered, framed")
331 parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary')
332 options, args = parser.parse_args()
Nobuaki Sukegawaa185d7e2015-11-06 21:24:24 +0900333
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900334 if options.genpydir:
335 sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir))
336 if options.libpydir:
337 sys.path.insert(0, glob.glob(options.libpydir)[0])
338 else:
339 sys.path.insert(0, glob.glob(DEFAULT_LIBDIR_GLOB)[0])
Nobuaki Sukegawaa185d7e2015-11-06 21:24:24 +0900340
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900341 from ThriftTest import ThriftTest
342 from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2
343 from thrift.Thrift import TException
344 from thrift.transport import TTransport
345 from thrift.transport import TSocket
346 from thrift.transport import THttpClient
347 from thrift.transport import TZlibTransport
348 from thrift.protocol import TBinaryProtocol
349 from thrift.protocol import TCompactProtocol
350 from thrift.protocol import TJSONProtocol
Nobuaki Sukegawaa185d7e2015-11-06 21:24:24 +0900351
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900352 OwnArgsTestProgram(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=1))