|  | #!/usr/bin/env python | 
|  |  | 
|  | # | 
|  | # Licensed to the Apache Software Foundation (ASF) under one | 
|  | # or more contributor license agreements. See the NOTICE file | 
|  | # distributed with this work for additional information | 
|  | # regarding copyright ownership. The ASF licenses this file | 
|  | # to you under the Apache License, Version 2.0 (the | 
|  | # "License"); you may not use this file except in compliance | 
|  | # with the License. You may obtain a copy of the License at | 
|  | # | 
|  | #   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | # Unless required by applicable law or agreed to in writing, | 
|  | # software distributed under the License is distributed on an | 
|  | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | # KIND, either express or implied. See the License for the | 
|  | # specific language governing permissions and limitations | 
|  | # under the License. | 
|  | # | 
|  |  | 
|  | r""" | 
|  | PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py | 
|  | """ | 
|  |  | 
|  | # TODO(dreiss): Test error cases.  Check for memory leaks. | 
|  |  | 
|  | from __future__ import print_function | 
|  |  | 
|  | import math | 
|  | import os | 
|  | import sys | 
|  | import timeit | 
|  |  | 
|  | from copy import deepcopy | 
|  | from pprint import pprint | 
|  |  | 
|  | from thrift.transport import TTransport | 
|  | from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated | 
|  | from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated | 
|  |  | 
|  | from DebugProtoTest import Srv | 
|  | from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper | 
|  |  | 
|  |  | 
|  | class TDevNullTransport(TTransport.TTransportBase): | 
|  | def __init__(self): | 
|  | pass | 
|  |  | 
|  | def isOpen(self): | 
|  | return True | 
|  |  | 
|  |  | 
|  | ooe1 = OneOfEach() | 
|  | ooe1.im_true = True | 
|  | ooe1.im_false = False | 
|  | ooe1.a_bite = 0xd6 | 
|  | ooe1.integer16 = 27000 | 
|  | ooe1.integer32 = 1 << 24 | 
|  | ooe1.integer64 = 6000 * 1000 * 1000 | 
|  | ooe1.double_precision = math.pi | 
|  | ooe1.some_characters = "Debug THIS!" | 
|  | ooe1.zomg_unicode = u"\xd7\n\a\t" | 
|  |  | 
|  | ooe2 = OneOfEach() | 
|  | ooe2.integer16 = 16 | 
|  | ooe2.integer32 = 32 | 
|  | ooe2.integer64 = 64 | 
|  | ooe2.double_precision = (math.sqrt(5) + 1) / 2 | 
|  | ooe2.some_characters = ":R (me going \"rrrr\")" | 
|  | ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\ | 
|  | u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\ | 
|  | u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\ | 
|  | u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\ | 
|  | u"\xc7\x83\xe2\x80\xbc" | 
|  |  | 
|  | if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): | 
|  | ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8') | 
|  | ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8') | 
|  |  | 
|  | hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}}) | 
|  | hm.big.append(ooe1) | 
|  | hm.big.append(ooe2) | 
|  | hm.big[0].a_bite = 0x22 | 
|  | hm.big[1].a_bite = 0x22 | 
|  |  | 
|  | hm.contain.add(("and a one", "and a two")) | 
|  | hm.contain.add(("then a one, two", "three!", "FOUR!")) | 
|  | if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): | 
|  | hm.contain.add((u"\xd7\n\a\t".encode('utf8'),)) | 
|  | else: | 
|  | hm.contain.add((u"\xd7\n\a\t",)) | 
|  | hm.contain.add(()) | 
|  |  | 
|  | hm.bonks["nothing"] = [] | 
|  | hm.bonks["something"] = [ | 
|  | Bonk(**{"type": 1, "message": "Wait."}), | 
|  | Bonk(**{"type": 2, "message": "What?"}), | 
|  | ] | 
|  | hm.bonks["poe"] = [ | 
|  | Bonk(**{"type": 3, "message": "quoth"}), | 
|  | Bonk(**{"type": 4, "message": "the raven"}), | 
|  | Bonk(**{"type": 5, "message": "nevermore"}), | 
|  | ] | 
|  |  | 
|  | rs = RandomStuff() | 
|  | rs.a = 1 | 
|  | rs.b = 2 | 
|  | rs.c = 3 | 
|  | rs.myintlist = list(range(20)) | 
|  | rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})} | 
|  | rs.bigint = 124523452435 | 
|  | rs.triple = 3.14 | 
|  |  | 
|  | # make sure this splits two buffers in a buffered protocol | 
|  | rshuge = RandomStuff() | 
|  | rshuge.myintlist = list(range(10000)) | 
|  |  | 
|  | my_zero = Srv.Janky_result(**{"success": 5}) | 
|  |  | 
|  |  | 
|  | class Test(object): | 
|  | def __init__(self, fast, slow): | 
|  | self._fast = fast | 
|  | self._slow = slow | 
|  |  | 
|  | def _check_write(self, o): | 
|  | trans_fast = TTransport.TMemoryBuffer() | 
|  | trans_slow = TTransport.TMemoryBuffer() | 
|  | prot_fast = self._fast(trans_fast, fallback=False) | 
|  | prot_slow = self._slow(trans_slow) | 
|  |  | 
|  | o.write(prot_fast) | 
|  | o.write(prot_slow) | 
|  | ORIG = trans_slow.getvalue() | 
|  | MINE = trans_fast.getvalue() | 
|  | if ORIG != MINE: | 
|  | print("actual  : %s\nexpected: %s" % (repr(MINE), repr(ORIG))) | 
|  | raise Exception('write value mismatch') | 
|  |  | 
|  | def _check_read(self, o): | 
|  | prot = self._slow(TTransport.TMemoryBuffer()) | 
|  | o.write(prot) | 
|  |  | 
|  | slow_version_binary = prot.trans.getvalue() | 
|  |  | 
|  | prot = self._fast( | 
|  | TTransport.TMemoryBuffer(slow_version_binary), fallback=False) | 
|  | c = o.__class__() | 
|  | c.read(prot) | 
|  | if c != o: | 
|  | print("actual  : ") | 
|  | pprint(repr(c)) | 
|  | print("expected: ") | 
|  | pprint(repr(o)) | 
|  | raise Exception('read value mismatch') | 
|  |  | 
|  | prot = self._fast( | 
|  | TTransport.TBufferedTransport( | 
|  | TTransport.TMemoryBuffer(slow_version_binary)), fallback=False) | 
|  | c = o.__class__() | 
|  | c.read(prot) | 
|  | if c != o: | 
|  | print("actual  : ") | 
|  | pprint(repr(c)) | 
|  | print("expected: ") | 
|  | pprint(repr(o)) | 
|  | raise Exception('read value mismatch') | 
|  |  | 
|  | def do_test(self): | 
|  | self._check_write(HolyMoley()) | 
|  | self._check_read(HolyMoley()) | 
|  |  | 
|  | self._check_write(hm) | 
|  | no_set = deepcopy(hm) | 
|  | no_set.contain = set() | 
|  | self._check_read(no_set) | 
|  | self._check_read(hm) | 
|  |  | 
|  | self._check_write(rs) | 
|  | self._check_read(rs) | 
|  |  | 
|  | self._check_write(rshuge) | 
|  | self._check_read(rshuge) | 
|  |  | 
|  | self._check_write(my_zero) | 
|  | self._check_read(my_zero) | 
|  |  | 
|  | self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2})) | 
|  |  | 
|  | # One case where the serialized form changes, but only superficially. | 
|  | o = Backwards(**{"first_tag2": 4, "second_tag1": 2}) | 
|  | trans_fast = TTransport.TMemoryBuffer() | 
|  | trans_slow = TTransport.TMemoryBuffer() | 
|  | prot_fast = self._fast(trans_fast, fallback=False) | 
|  | prot_slow = self._slow(trans_slow) | 
|  |  | 
|  | o.write(prot_fast) | 
|  | o.write(prot_slow) | 
|  | ORIG = trans_slow.getvalue() | 
|  | MINE = trans_fast.getvalue() | 
|  | assert id(ORIG) != id(MINE) | 
|  |  | 
|  | prot = self._fast(TTransport.TMemoryBuffer(), fallback=False) | 
|  | o.write(prot) | 
|  | prot = self._slow( | 
|  | TTransport.TMemoryBuffer(prot.trans.getvalue())) | 
|  | c = o.__class__() | 
|  | c.read(prot) | 
|  | if c != o: | 
|  | print("copy: ") | 
|  | pprint(repr(c)) | 
|  | print("orig: ") | 
|  | pprint(repr(o)) | 
|  |  | 
|  |  | 
|  | def do_test(fast, slow): | 
|  | Test(fast, slow).do_test() | 
|  |  | 
|  |  | 
|  | def do_benchmark(protocol, iters=5000, skip_slow=False): | 
|  | setup = """ | 
|  | from __main__ import hm, rs, TDevNullTransport | 
|  | from thrift.protocol.{0} import {0}{1} | 
|  | trans = TDevNullTransport() | 
|  | prot = {0}{1}(trans{2}) | 
|  | """ | 
|  |  | 
|  | setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False') | 
|  | if not skip_slow: | 
|  | setup_slow = setup.format(protocol, '', '') | 
|  |  | 
|  | print("Starting Benchmarks") | 
|  |  | 
|  | if not skip_slow: | 
|  | print("HolyMoley Standard = %f" % | 
|  | timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters)) | 
|  |  | 
|  | print("HolyMoley Acceler. = %f" % | 
|  | timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters)) | 
|  |  | 
|  | if not skip_slow: | 
|  | print("FastStruct Standard = %f" % | 
|  | timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters)) | 
|  |  | 
|  | print("FastStruct Acceler. = %f" % | 
|  | timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters)) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | print('Testing TBinaryAccelerated') | 
|  | do_test(TBinaryProtocolAccelerated, TBinaryProtocol) | 
|  | do_benchmark('TBinaryProtocol') | 
|  | print('Testing TCompactAccelerated') | 
|  | do_test(TCompactProtocolAccelerated, TCompactProtocol) | 
|  | do_benchmark('TCompactProtocol') |