1#!/usr/bin/env python 2 3# 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 22import datetime 23import glob 24import os 25import sys 26import time 27import unittest 28 29basepath = os.path.abspath(os.path.dirname(__file__)) 30sys.path.insert(0, basepath + '/gen-py.tornado') 31sys.path.insert(0, glob.glob(os.path.join(basepath, '../../lib/py/build/lib*'))[0]) 32 33try: 34 __import__('tornado') 35except ImportError: 36 print("module `tornado` not found, skipping test") 37 sys.exit(0) 38 39from tornado import gen 40from tornado.testing import AsyncTestCase, get_unused_port, gen_test 41 42from thrift import TTornado 43from thrift.Thrift import TApplicationException 44from thrift.protocol import TBinaryProtocol 45 46from ThriftTest import ThriftTest 47from ThriftTest.ttypes import Xception, Xtruct 48 49 50class TestHandler(object): 51 def __init__(self, test_instance): 52 self.test_instance = test_instance 53 54 def testVoid(self): 55 pass 56 57 def testString(self, s): 58 if s == 'unexpected_error': 59 raise Exception(s) 60 return s 61 62 def testByte(self, b): 63 return b 64 65 def testI16(self, i16): 66 return i16 67 68 def testI32(self, i32): 69 return i32 70 71 def testI64(self, i64): 72 return i64 73 74 def testDouble(self, dub): 75 return dub 76 77 def testBinary(self, thing): 78 return thing 79 80 def testStruct(self, thing): 81 return thing 82 83 def testException(self, s): 84 if s == 'Xception': 85 raise Xception(1001, s) 86 elif s == 'throw_undeclared': 87 raise ValueError('testing undeclared exception') 88 89 def testOneway(self, seconds): 90 start = time.time() 91 92 def fire_oneway(): 93 end = time.time() 94 self.test_instance.stop((start, end, seconds)) 95 96 self.test_instance.io_loop.add_timeout( 97 datetime.timedelta(seconds=seconds), 98 fire_oneway) 99 raise Exception('testing exception in oneway method') 100 101 def testNest(self, thing): 102 return thing 103 104 @gen.coroutine 105 def testMap(self, thing): 106 yield gen.moment 107 raise gen.Return(thing) 108 109 def testSet(self, thing): 110 return thing 111 112 def testList(self, thing): 113 return thing 114 115 def testEnum(self, thing): 116 return thing 117 118 def testTypedef(self, thing): 119 return thing 120 121 122class ThriftTestCase(AsyncTestCase): 123 def setUp(self): 124 super(ThriftTestCase, self).setUp() 125 126 self.port = get_unused_port() 127 128 # server 129 self.handler = TestHandler(self) 130 self.processor = ThriftTest.Processor(self.handler) 131 self.pfactory = TBinaryProtocol.TBinaryProtocolFactory() 132 133 self.server = TTornado.TTornadoServer(self.processor, self.pfactory, io_loop=self.io_loop) 134 self.server.bind(self.port) 135 self.server.start(1) 136 137 # client 138 transport = TTornado.TTornadoStreamTransport('localhost', self.port, io_loop=self.io_loop) 139 pfactory = TBinaryProtocol.TBinaryProtocolFactory() 140 self.io_loop.run_sync(transport.open) 141 self.client = ThriftTest.Client(transport, pfactory) 142 143 @gen_test 144 def test_void(self): 145 v = yield self.client.testVoid() 146 self.assertEqual(v, None) 147 148 @gen_test 149 def test_string(self): 150 v = yield self.client.testString('Python') 151 self.assertEqual(v, 'Python') 152 153 @gen_test 154 def test_byte(self): 155 v = yield self.client.testByte(63) 156 self.assertEqual(v, 63) 157 158 @gen_test 159 def test_i32(self): 160 v = yield self.client.testI32(-1) 161 self.assertEqual(v, -1) 162 163 v = yield self.client.testI32(0) 164 self.assertEqual(v, 0) 165 166 @gen_test 167 def test_i64(self): 168 v = yield self.client.testI64(-34359738368) 169 self.assertEqual(v, -34359738368) 170 171 @gen_test 172 def test_double(self): 173 v = yield self.client.testDouble(-5.235098235) 174 self.assertEqual(v, -5.235098235) 175 176 @gen_test 177 def test_struct(self): 178 x = Xtruct() 179 x.string_thing = "Zero" 180 x.byte_thing = 1 181 x.i32_thing = -3 182 x.i64_thing = -5 183 y = yield self.client.testStruct(x) 184 185 self.assertEqual(y.string_thing, "Zero") 186 self.assertEqual(y.byte_thing, 1) 187 self.assertEqual(y.i32_thing, -3) 188 self.assertEqual(y.i64_thing, -5) 189 190 @gen_test 191 def test_oneway(self): 192 self.client.testOneway(1) 193 v = yield self.client.testI32(-1) 194 self.assertEqual(v, -1) 195 196 @gen_test 197 def test_map(self): 198 """ 199 TestHandler.testMap is a coroutine, this test checks if gen.Return() from a coroutine works. 200 """ 201 expected = {1: 1} 202 res = yield self.client.testMap(expected) 203 self.assertEqual(res, expected) 204 205 @gen_test 206 def test_exception(self): 207 try: 208 yield self.client.testException('Xception') 209 except Xception as ex: 210 self.assertEqual(ex.errorCode, 1001) 211 self.assertEqual(ex.message, 'Xception') 212 else: 213 self.fail("should have gotten exception") 214 try: 215 yield self.client.testException('throw_undeclared') 216 except TApplicationException: 217 pass 218 else: 219 self.fail("should have gotten exception") 220 221 yield self.client.testException('Safe') 222 223 224def suite(): 225 suite = unittest.TestSuite() 226 loader = unittest.TestLoader() 227 suite.addTest(loader.loadTestsFromTestCase(ThriftTestCase)) 228 return suite 229 230 231if __name__ == '__main__': 232 unittest.TestProgram(defaultTest='suite', 233 testRunner=unittest.TextTestRunner(verbosity=1)) 234