blob: e7478e4214e93b68145d28f904b67c6218dbf4d6 [file] [log] [blame]
Mark Slee57cc25e2007-02-28 21:43:54 +00001#!/usr/bin/env python
Mark Sleec9676562006-09-05 17:34:52 +00002
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#
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000021from __future__ import division
Jens Geyerd629ea02015-09-23 21:16:50 +020022import glob
23import logging
24import os
25import sys
26import time
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000027from optparse import OptionParser
Mark Sleec9676562006-09-05 17:34:52 +000028
Jens Geyerd629ea02015-09-23 21:16:50 +020029# Print TServer log to stdout so that the test-runner can redirect it to log files
Randy Abernethy983bf7d2015-10-09 12:28:57 -070030logging.basicConfig(level=logging.DEBUG)
Jens Geyerd629ea02015-09-23 21:16:50 +020031
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000032parser = OptionParser()
Roger Meierf4eec7a2011-09-11 18:16:21 +000033parser.add_option('--genpydir', type='string', dest='genpydir',
34 default='gen-py',
35 help='include this local directory in sys.path for locating generated code')
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000036parser.add_option("--port", type="int", dest="port",
37 help="port number for server to listen on")
Bryan Duxbury16066592011-03-22 18:06:04 +000038parser.add_option("--zlib", action="store_true", dest="zlib",
39 help="use zlib wrapper for compressed transport")
40parser.add_option("--ssl", action="store_true", dest="ssl",
41 help="use SSL for encrypted transport")
Roger Meier76150722014-05-31 22:22:07 +020042parser.add_option('-v', '--verbose', action="store_const",
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000043 dest="verbose", const=2,
44 help="verbose output")
Roger Meier76150722014-05-31 22:22:07 +020045parser.add_option('-q', '--quiet', action="store_const",
Bryan Duxbury16066592011-03-22 18:06:04 +000046 dest="verbose", const=0,
47 help="minimal output")
Roger Meier76150722014-05-31 22:22:07 +020048parser.add_option('--protocol', dest="proto", type="string",
Roger Meier85fb6de2012-11-02 00:05:42 +000049 help="protocol to use, one of: accel, binary, compact, json")
Roger Meier76150722014-05-31 22:22:07 +020050parser.add_option('--transport', dest="trans", type="string",
51 help="transport to use, one of: buffered, framed")
Bryan Duxbury16066592011-03-22 18:06:04 +000052parser.set_defaults(port=9090, verbose=1, proto='binary')
Bryan Duxbury59d4efd2011-03-21 17:38:22 +000053options, args = parser.parse_args()
54
Jens Geyerd629ea02015-09-23 21:16:50 +020055script_dir = os.path.realpath(os.path.dirname(__file__)) # <-- absolute dir the script is in
56lib_dir = os.path.join(os.path.dirname(os.path.dirname(script_dir)), 'lib', 'py', 'build', 'lib.*')
57
cdwijayarathna0d4072b2014-08-09 21:32:21 +053058sys.path.insert(0, os.path.join(script_dir, options.genpydir))
Jens Geyerd629ea02015-09-23 21:16:50 +020059sys.path.insert(0, glob.glob(lib_dir)[0])
Roger Meierf4eec7a2011-09-11 18:16:21 +000060
jfarrelldbf2bb52014-07-09 23:37:12 -040061from ThriftTest import ThriftTest
Roger Meierf4eec7a2011-09-11 18:16:21 +000062from ThriftTest.ttypes import *
Roger Meier1f554e12013-01-05 20:38:35 +010063from thrift.Thrift import TException
Roger Meierf4eec7a2011-09-11 18:16:21 +000064from thrift.transport import TTransport
65from thrift.transport import TSocket
66from thrift.transport import TZlibTransport
67from thrift.protocol import TBinaryProtocol
68from thrift.protocol import TCompactProtocol
Roger Meier85fb6de2012-11-02 00:05:42 +000069from thrift.protocol import TJSONProtocol
Roger Meierf4eec7a2011-09-11 18:16:21 +000070from thrift.server import TServer, TNonblockingServer, THttpServer
71
Jens Geyerd629ea02015-09-23 21:16:50 +020072PROT_FACTORIES = {
73 'binary': TBinaryProtocol.TBinaryProtocolFactory,
Roger Meierf4eec7a2011-09-11 18:16:21 +000074 'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory,
Roger Meier85fb6de2012-11-02 00:05:42 +000075 'compact': TCompactProtocol.TCompactProtocolFactory,
Jens Geyerd629ea02015-09-23 21:16:50 +020076 'json': TJSONProtocol.TJSONProtocolFactory,
77}
Roger Meierf4eec7a2011-09-11 18:16:21 +000078
Mark Sleec9676562006-09-05 17:34:52 +000079
Jens Geyerd629ea02015-09-23 21:16:50 +020080class TestHandler(object):
Mark Sleec9676562006-09-05 17:34:52 +000081 def testVoid(self):
Bryan Duxbury16066592011-03-22 18:06:04 +000082 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -070083 logging.info('testVoid()')
Mark Sleec9676562006-09-05 17:34:52 +000084
85 def testString(self, str):
Bryan Duxbury16066592011-03-22 18:06:04 +000086 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -070087 logging.info('testString(%s)' % str)
Mark Sleec9676562006-09-05 17:34:52 +000088 return str
89
Nobuaki Sukegawaa649e742015-09-21 13:53:25 +090090 def testBool(self, boolean):
91 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -070092 logging.info('testBool(%s)' % str(boolean).lower())
Nobuaki Sukegawaa649e742015-09-21 13:53:25 +090093 return boolean
94
Mark Sleec9676562006-09-05 17:34:52 +000095 def testByte(self, byte):
Bryan Duxbury16066592011-03-22 18:06:04 +000096 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -070097 logging.info('testByte(%d)' % byte)
Mark Sleec9676562006-09-05 17:34:52 +000098 return byte
99
Mark Sleec98d0502006-09-06 02:42:25 +0000100 def testI16(self, i16):
Bryan Duxbury16066592011-03-22 18:06:04 +0000101 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700102 logging.info('testI16(%d)' % i16)
Mark Sleec98d0502006-09-06 02:42:25 +0000103 return i16
104
105 def testI32(self, i32):
Bryan Duxbury16066592011-03-22 18:06:04 +0000106 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700107 logging.info('testI32(%d)' % i32)
Mark Sleec98d0502006-09-06 02:42:25 +0000108 return i32
109
110 def testI64(self, i64):
Bryan Duxbury16066592011-03-22 18:06:04 +0000111 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700112 logging.info('testI64(%d)' % i64)
Mark Sleec98d0502006-09-06 02:42:25 +0000113 return i64
114
115 def testDouble(self, dub):
Bryan Duxbury16066592011-03-22 18:06:04 +0000116 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700117 logging.info('testDouble(%f)' % dub)
Mark Sleec98d0502006-09-06 02:42:25 +0000118 return dub
119
Jens Geyer8bcfdd92014-12-14 03:14:26 +0100120 def testBinary(self, thing):
121 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700122 logging.info('testBinary()') # TODO: hex output
Jens Geyerd629ea02015-09-23 21:16:50 +0200123 return thing
124
Mark Sleec98d0502006-09-06 02:42:25 +0000125 def testStruct(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000126 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700127 logging.info('testStruct({%s, %s, %s, %s})' % (thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing))
Mark Sleec98d0502006-09-06 02:42:25 +0000128 return thing
129
Roger Meier1f554e12013-01-05 20:38:35 +0100130 def testException(self, arg):
Jens Geyerd629ea02015-09-23 21:16:50 +0200131 # if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700132 logging.info('testException(%s)' % arg)
Roger Meier1f554e12013-01-05 20:38:35 +0100133 if arg == 'Xception':
134 raise Xception(errorCode=1001, message=arg)
135 elif arg == 'TException':
136 raise TException(message='This is a TException')
137
138 def testMultiException(self, arg0, arg1):
Bryan Duxbury16066592011-03-22 18:06:04 +0000139 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700140 logging.info('testMultiException(%s, %s)' % (arg0, arg1))
Roger Meier1f554e12013-01-05 20:38:35 +0100141 if arg0 == 'Xception':
142 raise Xception(errorCode=1001, message='This is an Xception')
143 elif arg0 == 'Xception2':
144 raise Xception2(
145 errorCode=2002,
146 struct_thing=Xtruct(string_thing='This is an Xception2'))
147 return Xtruct(string_thing=arg1)
Mark Sleec9676562006-09-05 17:34:52 +0000148
David Reiss6ce401d2009-03-24 20:01:58 +0000149 def testOneway(self, seconds):
Bryan Duxbury16066592011-03-22 18:06:04 +0000150 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700151 logging.info('testOneway(%d) => sleeping...' % seconds)
Jens Geyerd629ea02015-09-23 21:16:50 +0200152 time.sleep(seconds / 3) # be quick
Bryan Duxbury16066592011-03-22 18:06:04 +0000153 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700154 logging.info('done sleeping')
David Reissdb893b62008-02-18 02:11:48 +0000155
David Reiss74421272008-11-07 23:09:31 +0000156 def testNest(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000157 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700158 logging.info('testNest(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000159 return thing
160
161 def testMap(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000162 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700163 logging.info('testMap(%s)' % thing)
Jens Geyerd629ea02015-09-23 21:16:50 +0200164 return thing
165
166 def testStringMap(self, thing):
167 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700168 logging.info('testStringMap(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000169 return thing
170
171 def testSet(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000172 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700173 logging.info('testSet(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000174 return thing
175
176 def testList(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000177 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700178 logging.info('testList(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000179 return thing
180
181 def testEnum(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000182 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700183 logging.info('testEnum(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000184 return thing
185
186 def testTypedef(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000187 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700188 logging.info('testTypedef(%s)' % thing)
David Reiss74421272008-11-07 23:09:31 +0000189 return thing
190
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000191 def testMapMap(self, thing):
Bryan Duxbury16066592011-03-22 18:06:04 +0000192 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700193 logging.info('testMapMap(%s)' % thing)
Jens Geyerd629ea02015-09-23 21:16:50 +0200194 return {
195 -4: {
196 -4: -4,
197 -3: -3,
198 -2: -2,
199 -1: -1,
200 },
201 4: {
202 4: 4,
203 3: 3,
204 2: 2,
205 1: 1,
206 },
207 }
Roger Meier1f554e12013-01-05 20:38:35 +0100208
209 def testInsanity(self, argument):
210 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700211 logging.info('testInsanity(%s)' % argument)
Jens Geyerd629ea02015-09-23 21:16:50 +0200212 return {
213 1: {
214 2: argument,
215 3: argument,
216 },
217 2: {6: Insanity()},
218 }
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000219
220 def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5):
Bryan Duxbury16066592011-03-22 18:06:04 +0000221 if options.verbose > 1:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700222 logging.info('testMulti(%s)' % [arg0, arg1, arg2, arg3, arg4, arg5])
Roger Meier1f554e12013-01-05 20:38:35 +0100223 return Xtruct(string_thing='Hello2',
224 byte_thing=arg0, i32_thing=arg1, i64_thing=arg2)
225
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000226
Roger Meier76150722014-05-31 22:22:07 +0200227# set up the protocol factory form the --protocol option
Bryan Duxbury16066592011-03-22 18:06:04 +0000228pfactory_cls = PROT_FACTORIES.get(options.proto, None)
229if pfactory_cls is None:
Roger Meier76150722014-05-31 22:22:07 +0200230 raise AssertionError('Unknown --protocol option: %s' % options.proto)
Bryan Duxbury16066592011-03-22 18:06:04 +0000231pfactory = pfactory_cls()
232
233# get the server type (TSimpleServer, TNonblockingServer, etc...)
234if len(args) > 1:
235 raise AssertionError('Only one server type may be specified, not multiple types.')
236server_type = args[0]
237
238# Set up the handler and processor objects
jfarrelldbf2bb52014-07-09 23:37:12 -0400239handler = TestHandler()
240processor = ThriftTest.Processor(handler)
David Reissbcaa2ad2008-06-10 22:55:26 +0000241
Bryan Duxbury16066592011-03-22 18:06:04 +0000242# Handle THttpServer as a special case
243if server_type == 'THttpServer':
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700244 server = THttpServer.THttpServer(processor, ('', options.port), pfactory)
Bryan Duxbury16066592011-03-22 18:06:04 +0000245 server.serve()
246 sys.exit(0)
247
248# set up server transport and transport factory
Roger Meier76150722014-05-31 22:22:07 +0200249
Jens Geyerd629ea02015-09-23 21:16:50 +0200250abs_key_path = os.path.join(os.path.dirname(script_dir), 'keys', 'server.pem')
Roger Meier76150722014-05-31 22:22:07 +0200251
Bryan Duxbury16066592011-03-22 18:06:04 +0000252host = None
253if options.ssl:
254 from thrift.transport import TSSLSocket
Roger Meier76150722014-05-31 22:22:07 +0200255 transport = TSSLSocket.TSSLServerSocket(host, options.port, certfile=abs_key_path)
David Reiss74421272008-11-07 23:09:31 +0000256else:
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000257 transport = TSocket.TServerSocket(host, options.port)
Bryan Duxbury16066592011-03-22 18:06:04 +0000258tfactory = TTransport.TBufferedTransportFactory()
Roger Meier76150722014-05-31 22:22:07 +0200259if options.trans == 'buffered':
260 tfactory = TTransport.TBufferedTransportFactory()
261elif options.trans == 'framed':
262 tfactory = TTransport.TFramedTransportFactory()
263elif options.trans == '':
264 raise AssertionError('Unknown --transport option: %s' % options.trans)
265else:
266 tfactory = TTransport.TBufferedTransportFactory()
Bryan Duxbury16066592011-03-22 18:06:04 +0000267# if --zlib, then wrap server transport, and use a different transport factory
268if options.zlib:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700269 transport = TZlibTransport.TZlibTransport(transport) # wrap with zlib
Bryan Duxbury16066592011-03-22 18:06:04 +0000270 tfactory = TZlibTransport.TZlibTransportFactory()
271
272# do server-specific setup here:
273if server_type == "TNonblockingServer":
274 server = TNonblockingServer.TNonblockingServer(processor, transport, inputProtocolFactory=pfactory)
275elif server_type == "TProcessPoolServer":
276 import signal
277 from thrift.server import TProcessPoolServer
278 server = TProcessPoolServer.TProcessPoolServer(processor, transport, tfactory, pfactory)
279 server.setNumWorkers(5)
Jens Geyerd629ea02015-09-23 21:16:50 +0200280
Bryan Duxbury16066592011-03-22 18:06:04 +0000281 def set_alarm():
282 def clean_shutdown(signum, frame):
283 for worker in server.workers:
284 if options.verbose > 0:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700285 logging.info('Terminating worker: %s' % worker)
Bryan Duxbury16066592011-03-22 18:06:04 +0000286 worker.terminate()
287 if options.verbose > 0:
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700288 logging.info('Requesting server to stop()')
Roger Meierf4eec7a2011-09-11 18:16:21 +0000289 try:
290 server.stop()
291 except:
292 pass
Bryan Duxbury16066592011-03-22 18:06:04 +0000293 signal.signal(signal.SIGALRM, clean_shutdown)
Jens Geyerf7d327a2015-07-25 15:44:20 +0200294 signal.alarm(4)
Bryan Duxbury16066592011-03-22 18:06:04 +0000295 set_alarm()
296else:
297 # look up server class dynamically to instantiate server
298 ServerClass = getattr(TServer, server_type)
299 server = ServerClass(processor, transport, tfactory, pfactory)
300# enter server main loop
Mark Slee794993d2006-09-20 01:56:10 +0000301server.serve()