#!/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.
#

import sys
import glob
from optparse import OptionParser
parser = OptionParser()
parser.add_option('--genpydir', type='string', dest='genpydir', default='gen-py')
options, args = parser.parse_args()
del sys.argv[1:] # clean up hack so unittest doesn't complain
sys.path.insert(0, options.genpydir)
sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0])

from ThriftTest.ttypes import *
from thrift.protocol import TJSONProtocol
from thrift.transport import TTransport

import json
import unittest


class SimpleJSONProtocolTest(unittest.TestCase):
  protocol_factory = TJSONProtocol.TSimpleJSONProtocolFactory()

  def _assertDictEqual(self, a ,b, msg=None):
    if hasattr(self, 'assertDictEqual'):
      # assertDictEqual only in Python 2.7. Depends on your machine.
      self.assertDictEqual(a, b, msg)
      return

    # Substitute implementation not as good as unittest library's
    self.assertEquals(len(a), len(b), msg)
    for k, v in a.iteritems():
      self.assertTrue(k in b, msg)
      self.assertEquals(b.get(k), v, msg)

  def _serialize(self, obj):
    trans = TTransport.TMemoryBuffer()
    prot = self.protocol_factory.getProtocol(trans)
    obj.write(prot)
    return trans.getvalue()

  def _deserialize(self, objtype, data):
    prot = self.protocol_factory.getProtocol(TTransport.TMemoryBuffer(data))
    ret = objtype()
    ret.read(prot)
    return ret

  def testWriteOnly(self):
    self.assertRaises(NotImplementedError,
                      self._deserialize, VersioningTestV1, b'{}')

  def testSimpleMessage(self):
      v1obj = VersioningTestV1(
          begin_in_both=12345,
          old_string='aaa',
          end_in_both=54321)
      expected = dict(begin_in_both=v1obj.begin_in_both,
                      old_string=v1obj.old_string,
                      end_in_both=v1obj.end_in_both)
      actual = json.loads(self._serialize(v1obj).decode('ascii'))

      self._assertDictEqual(expected, actual)

  def testComplicated(self):
      v2obj = VersioningTestV2(
          begin_in_both=12345,
          newint=1,
          newbyte=2,
          newshort=3,
          newlong=4,
          newdouble=5.0,
          newstruct=Bonk(message="Hello!", type=123),
          newlist=[7,8,9],
          newset=set([42,1,8]),
          newmap={1:2,2:3},
          newstring="Hola!",
          end_in_both=54321)
      expected = dict(begin_in_both=v2obj.begin_in_both,
                      newint=v2obj.newint,
                      newbyte=v2obj.newbyte,
                      newshort=v2obj.newshort,
                      newlong=v2obj.newlong,
                      newdouble=v2obj.newdouble,
                      newstruct=dict(message=v2obj.newstruct.message,
                                     type=v2obj.newstruct.type),
                      newlist=v2obj.newlist,
                      newset=list(v2obj.newset),
                      newmap=v2obj.newmap,
                      newstring=v2obj.newstring,
                      end_in_both=v2obj.end_in_both)

      # Need to load/dump because map keys get escaped.
      expected = json.loads(json.dumps(expected))
      actual = json.loads(self._serialize(v2obj).decode('ascii'))
      self._assertDictEqual(expected, actual)


if __name__ == '__main__':
  unittest.main()

