Home | History | Annotate | Download | only in json_schema_compiler
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import idl_schema
      7 import unittest
      8 
      9 from json_parse import OrderedDict
     10 
     11 def getFunction(schema, name):
     12   for item in schema['functions']:
     13     if item['name'] == name:
     14       return item
     15   raise KeyError('Missing function %s' % name)
     16 
     17 
     18 def getParams(schema, name):
     19   function = getFunction(schema, name)
     20   return function['parameters']
     21 
     22 
     23 def getReturns(schema, name):
     24   function = getFunction(schema, name)
     25   return function['returns']
     26 
     27 
     28 def getType(schema, id):
     29   for item in schema['types']:
     30     if item['id'] == id:
     31       return item
     32 
     33 
     34 class IdlSchemaTest(unittest.TestCase):
     35   def setUp(self):
     36     loaded = idl_schema.Load('test/idl_basics.idl')
     37     self.assertEquals(1, len(loaded))
     38     self.assertEquals('idl_basics', loaded[0]['namespace'])
     39     self.idl_basics = loaded[0]
     40     self.maxDiff = None
     41 
     42   def testSimpleCallbacks(self):
     43     schema = self.idl_basics
     44     expected = [{'type': 'function', 'name': 'cb', 'parameters':[]}]
     45     self.assertEquals(expected, getParams(schema, 'function4'))
     46 
     47     expected = [{'type': 'function', 'name': 'cb',
     48                  'parameters':[{'name': 'x', 'type': 'integer'}]}]
     49     self.assertEquals(expected, getParams(schema, 'function5'))
     50 
     51     expected = [{'type': 'function', 'name': 'cb',
     52                  'parameters':[{'name': 'arg', '$ref': 'MyType1'}]}]
     53     self.assertEquals(expected, getParams(schema, 'function6'))
     54 
     55   def testCallbackWithArrayArgument(self):
     56     schema = self.idl_basics
     57     expected = [{'type': 'function', 'name': 'cb',
     58                  'parameters':[{'name': 'arg', 'type': 'array',
     59                                 'items':{'$ref': 'MyType2'}}]}]
     60     self.assertEquals(expected, getParams(schema, 'function12'))
     61 
     62 
     63   def testArrayOfCallbacks(self):
     64     schema = idl_schema.Load('test/idl_function_types.idl')[0]
     65     expected = [{'type': 'array', 'name': 'callbacks',
     66                  'items':{'type': 'function', 'name': 'MyCallback',
     67                           'parameters':[{'type': 'integer', 'name': 'x'}]}}]
     68     self.assertEquals(expected, getParams(schema, 'whatever'))
     69 
     70   def testLegalValues(self):
     71     self.assertEquals({
     72         'x': {'name': 'x', 'type': 'integer', 'enum': [1,2],
     73               'description': 'This comment tests "double-quotes".'},
     74         'y': {'name': 'y', 'type': 'string'},
     75         'z': {'name': 'z', 'type': 'string'},
     76         'a': {'name': 'a', 'type': 'string'},
     77         'b': {'name': 'b', 'type': 'string'},
     78         'c': {'name': 'c', 'type': 'string'}},
     79       getType(self.idl_basics, 'MyType1')['properties'])
     80 
     81   def testMemberOrdering(self):
     82     self.assertEquals(
     83         ['x', 'y', 'z', 'a', 'b', 'c'],
     84         getType(self.idl_basics, 'MyType1')['properties'].keys())
     85 
     86   def testEnum(self):
     87     schema = self.idl_basics
     88     expected = {'enum': [{'name': 'name1', 'description': 'comment1'},
     89                          {'name': 'name2'}],
     90                 'description': 'Enum description',
     91                 'type': 'string', 'id': 'EnumType'}
     92     self.assertEquals(expected, getType(schema, expected['id']))
     93 
     94     expected = [{'name': 'type', '$ref': 'EnumType'},
     95                 {'type': 'function', 'name': 'cb',
     96                   'parameters':[{'name': 'type', '$ref': 'EnumType'}]}]
     97     self.assertEquals(expected, getParams(schema, 'function13'))
     98 
     99     expected = [{'items': {'$ref': 'EnumType'}, 'name': 'types',
    100                  'type': 'array'}]
    101     self.assertEquals(expected, getParams(schema, 'function14'))
    102 
    103   def testScopedArguments(self):
    104     schema = self.idl_basics
    105     expected = [{'name': 'value', '$ref': 'idl_other_namespace.SomeType'}]
    106     self.assertEquals(expected, getParams(schema, 'function20'))
    107 
    108     expected = [{'items': {'$ref': 'idl_other_namespace.SomeType'},
    109                  'name': 'values',
    110                  'type': 'array'}]
    111     self.assertEquals(expected, getParams(schema, 'function21'))
    112 
    113     expected = [{'name': 'value',
    114                  '$ref': 'idl_other_namespace.sub_namespace.AnotherType'}]
    115     self.assertEquals(expected, getParams(schema, 'function22'))
    116 
    117     expected = [{'items': {'$ref': 'idl_other_namespace.sub_namespace.'
    118                                    'AnotherType'},
    119                  'name': 'values',
    120                  'type': 'array'}]
    121     self.assertEquals(expected, getParams(schema, 'function23'))
    122 
    123   def testNoCompile(self):
    124     schema = self.idl_basics
    125     func = getFunction(schema, 'function15')
    126     self.assertTrue(func is not None)
    127     self.assertTrue(func['nocompile'])
    128 
    129   def testNoDocOnEnum(self):
    130     schema = self.idl_basics
    131     enum_with_nodoc = getType(schema, 'EnumTypeWithNoDoc')
    132     self.assertTrue(enum_with_nodoc is not None)
    133     self.assertTrue(enum_with_nodoc['nodoc'])
    134 
    135   def testInternalNamespace(self):
    136     idl_basics  = self.idl_basics
    137     self.assertEquals('idl_basics', idl_basics['namespace'])
    138     self.assertTrue(idl_basics['internal'])
    139     self.assertFalse(idl_basics['nodoc'])
    140 
    141   def testReturnTypes(self):
    142     schema = self.idl_basics
    143     self.assertEquals({'name': 'function24', 'type': 'integer'},
    144                       getReturns(schema, 'function24'))
    145     self.assertEquals({'name': 'function25', '$ref': 'MyType1',
    146                        'optional': True},
    147                       getReturns(schema, 'function25'))
    148     self.assertEquals({'name': 'function26', 'type': 'array',
    149                        'items': {'$ref': 'MyType1'}},
    150                       getReturns(schema, 'function26'))
    151     self.assertEquals({'name': 'function27', '$ref': 'EnumType',
    152                        'optional': True},
    153                       getReturns(schema, 'function27'))
    154     self.assertEquals({'name': 'function28', 'type': 'array',
    155                        'items': {'$ref': 'EnumType'}},
    156                       getReturns(schema, 'function28'))
    157     self.assertEquals({'name': 'function29', '$ref':
    158                        'idl_other_namespace.SomeType',
    159                        'optional': True},
    160                       getReturns(schema, 'function29'))
    161     self.assertEquals({'name': 'function30', 'type': 'array',
    162                        'items': {'$ref': 'idl_other_namespace.SomeType'}},
    163                       getReturns(schema, 'function30'))
    164 
    165   def testChromeOSPlatformsNamespace(self):
    166     schema = idl_schema.Load('test/idl_namespace_chromeos.idl')[0]
    167     self.assertEquals('idl_namespace_chromeos', schema['namespace'])
    168     expected = ['chromeos']
    169     self.assertEquals(expected, schema['platforms'])
    170 
    171   def testAllPlatformsNamespace(self):
    172     schema = idl_schema.Load('test/idl_namespace_all_platforms.idl')[0]
    173     self.assertEquals('idl_namespace_all_platforms', schema['namespace'])
    174     expected = ['chromeos', 'chromeos_touch', 'linux', 'mac', 'win']
    175     self.assertEquals(expected, schema['platforms'])
    176 
    177   def testNonSpecificPlatformsNamespace(self):
    178     schema = idl_schema.Load('test/idl_namespace_non_specific_platforms.idl')[0]
    179     self.assertEquals('idl_namespace_non_specific_platforms',
    180                       schema['namespace'])
    181     expected = None
    182     self.assertEquals(expected, schema['platforms'])
    183 
    184   def testSpecificImplementNamespace(self):
    185     schema = idl_schema.Load('test/idl_namespace_specific_implement.idl')[0]
    186     self.assertEquals('idl_namespace_specific_implement',
    187                       schema['namespace'])
    188     expected = 'idl_namespace_specific_implement.idl'
    189     self.assertEquals(expected, schema['compiler_options']['implemented_in'])
    190 
    191   def testSpecificImplementOnChromeOSNamespace(self):
    192     schema = idl_schema.Load(
    193         'test/idl_namespace_specific_implement_chromeos.idl')[0]
    194     self.assertEquals('idl_namespace_specific_implement_chromeos',
    195                       schema['namespace'])
    196     expected_implemented_path = 'idl_namespace_specific_implement_chromeos.idl'
    197     expected_platform = ['chromeos']
    198     self.assertEquals(expected_implemented_path,
    199                       schema['compiler_options']['implemented_in'])
    200     self.assertEquals(expected_platform, schema['platforms'])
    201 
    202   def testCallbackComment(self):
    203     schema = self.idl_basics
    204     self.assertEquals('A comment on a callback.',
    205                       getParams(schema, 'function16')[0]['description'])
    206     self.assertEquals(
    207         'A parameter.',
    208         getParams(schema, 'function16')[0]['parameters'][0]['description'])
    209     self.assertEquals(
    210         'Just a parameter comment, with no comment on the callback.',
    211         getParams(schema, 'function17')[0]['parameters'][0]['description'])
    212     self.assertEquals(
    213         'Override callback comment.',
    214         getParams(schema, 'function18')[0]['description'])
    215 
    216   def testFunctionComment(self):
    217     schema = self.idl_basics
    218     func = getFunction(schema, 'function3')
    219     self.assertEquals(('This comment should appear in the documentation, '
    220                        'despite occupying multiple lines.'),
    221                       func['description'])
    222     self.assertEquals(
    223         [{'description': ('So should this comment about the argument. '
    224                           '<em>HTML</em> is fine too.'),
    225           'name': 'arg',
    226           '$ref': 'MyType1'}],
    227         func['parameters'])
    228     func = getFunction(schema, 'function4')
    229     self.assertEquals(('This tests if "double-quotes" are escaped correctly.'
    230                        '<br/><br/> It also tests a comment with two newlines.'),
    231                       func['description'])
    232 
    233   def testReservedWords(self):
    234     schema = idl_schema.Load('test/idl_reserved_words.idl')[0]
    235 
    236     foo_type = getType(schema, 'Foo')
    237     self.assertEquals([{'name': 'float'}, {'name': 'DOMString'}],
    238                       foo_type['enum'])
    239 
    240     enum_type = getType(schema, 'enum')
    241     self.assertEquals([{'name': 'callback'}, {'name': 'namespace'}],
    242                       enum_type['enum'])
    243 
    244     dictionary = getType(schema, 'dictionary')
    245     self.assertEquals('integer', dictionary['properties']['long']['type'])
    246 
    247     mytype = getType(schema, 'MyType')
    248     self.assertEquals('string', mytype['properties']['interface']['type'])
    249 
    250     params = getParams(schema, 'static')
    251     self.assertEquals('Foo', params[0]['$ref'])
    252     self.assertEquals('enum', params[1]['$ref'])
    253 
    254   def testObjectTypes(self):
    255     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    256 
    257     foo_type = getType(schema, 'FooType')
    258     self.assertEquals('object', foo_type['type'])
    259     self.assertEquals('integer', foo_type['properties']['x']['type'])
    260     self.assertEquals('object', foo_type['properties']['y']['type'])
    261     self.assertEquals(
    262         'any',
    263         foo_type['properties']['y']['additionalProperties']['type'])
    264     self.assertEquals('object', foo_type['properties']['z']['type'])
    265     self.assertEquals(
    266         'any',
    267         foo_type['properties']['z']['additionalProperties']['type'])
    268     self.assertEquals('Window', foo_type['properties']['z']['isInstanceOf'])
    269 
    270     bar_type = getType(schema, 'BarType')
    271     self.assertEquals('object', bar_type['type'])
    272     self.assertEquals('any', bar_type['properties']['x']['type'])
    273 
    274   def testObjectTypesInFunctions(self):
    275     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    276 
    277     params = getParams(schema, 'objectFunction1')
    278     self.assertEquals('object', params[0]['type'])
    279     self.assertEquals('any', params[0]['additionalProperties']['type'])
    280     self.assertEquals('ImageData', params[0]['isInstanceOf'])
    281 
    282     params = getParams(schema, 'objectFunction2')
    283     self.assertEquals('any', params[0]['type'])
    284 
    285   def testObjectTypesWithOptionalFields(self):
    286     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    287 
    288     baz_type = getType(schema, 'BazType')
    289     self.assertEquals(True, baz_type['properties']['x']['optional'])
    290     self.assertEquals('integer', baz_type['properties']['x']['type'])
    291     self.assertEquals(True, baz_type['properties']['foo']['optional'])
    292     self.assertEquals('FooType', baz_type['properties']['foo']['$ref'])
    293 
    294   def testObjectTypesWithUnions(self):
    295     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    296 
    297     union_type = getType(schema, 'UnionType')
    298     expected = {
    299                  'type': 'object',
    300                  'id': 'UnionType',
    301                  'properties': {
    302                    'x': {
    303                      'name': 'x',
    304                      'optional': True,
    305                      'choices': [
    306                        {'type': 'integer'},
    307                        {'$ref': 'FooType'},
    308                      ]
    309                    },
    310                    'y': {
    311                      'name': 'y',
    312                      'choices': [
    313                        {'type': 'string'},
    314                        {'type': 'object',
    315                         'additionalProperties': {'type': 'any'}}
    316                      ]
    317                    },
    318                    'z': {
    319                      'name': 'z',
    320                      'choices': [
    321                        {'type': 'object', 'isInstanceOf': 'ImageData',
    322                         'additionalProperties': {'type': 'any'}},
    323                        {'type': 'integer'}
    324                      ]
    325                    }
    326                  },
    327                }
    328 
    329     self.assertEquals(expected, union_type)
    330 
    331   def testUnionsWithModifiers(self):
    332     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    333 
    334     union_type = getType(schema, 'ModifiedUnionType')
    335     expected = {
    336                  'type': 'object',
    337                  'id': 'ModifiedUnionType',
    338                  'properties': {
    339                    'x': {
    340                      'name': 'x',
    341                      'nodoc': True,
    342                      'choices': [
    343                        {'type': 'integer'},
    344                        {'type': 'string'}
    345                      ]
    346                    }
    347                  }
    348                }
    349 
    350     self.assertEquals(expected, union_type)
    351 
    352   def testUnionsWithFunctions(self):
    353     schema = idl_schema.Load('test/idl_function_types.idl')[0]
    354 
    355     union_params = getParams(schema, 'union_params')
    356     expected = [{
    357                  'name': 'x',
    358                  'choices': [
    359                    {'type': 'integer'},
    360                    {'type': 'string'}
    361                  ]
    362                }]
    363 
    364     self.assertEquals(expected, union_params)
    365 
    366   def testUnionsWithCallbacks(self):
    367     schema = idl_schema.Load('test/idl_function_types.idl')[0]
    368 
    369     blah_params = getParams(schema, 'blah')
    370     expected = [{
    371                  'type': 'function', 'name': 'callback', 'parameters': [{
    372                    'name': 'x',
    373                    'choices': [
    374                      {'type': 'integer'},
    375                      {'type': 'string'}
    376                    ]}
    377                  ]
    378                }]
    379     self.assertEquals(expected, blah_params)
    380 
    381     badabish_params = getParams(schema, 'badabish')
    382     expected = [{
    383                  'type': 'function', 'name': 'callback', 'parameters': [{
    384                    'name': 'x', 'optional': True, 'choices': [
    385                      {'type': 'integer'},
    386                      {'type': 'string'}
    387                    ]
    388                  }]
    389                }]
    390 
    391     self.assertEquals(expected, badabish_params)
    392 
    393 
    394 if __name__ == '__main__':
    395   unittest.main()
    396