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(
    230         '<p>This tests if "double-quotes" are escaped correctly.</p>'
    231         '<p>It also tests a comment with two newlines.</p>',
    232         func['description'])
    233 
    234   def testReservedWords(self):
    235     schema = idl_schema.Load('test/idl_reserved_words.idl')[0]
    236 
    237     foo_type = getType(schema, 'Foo')
    238     self.assertEquals([{'name': 'float'}, {'name': 'DOMString'}],
    239                       foo_type['enum'])
    240 
    241     enum_type = getType(schema, 'enum')
    242     self.assertEquals([{'name': 'callback'}, {'name': 'namespace'}],
    243                       enum_type['enum'])
    244 
    245     dictionary = getType(schema, 'dictionary')
    246     self.assertEquals('integer', dictionary['properties']['long']['type'])
    247 
    248     mytype = getType(schema, 'MyType')
    249     self.assertEquals('string', mytype['properties']['interface']['type'])
    250 
    251     params = getParams(schema, 'static')
    252     self.assertEquals('Foo', params[0]['$ref'])
    253     self.assertEquals('enum', params[1]['$ref'])
    254 
    255   def testObjectTypes(self):
    256     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    257 
    258     foo_type = getType(schema, 'FooType')
    259     self.assertEquals('object', foo_type['type'])
    260     self.assertEquals('integer', foo_type['properties']['x']['type'])
    261     self.assertEquals('object', foo_type['properties']['y']['type'])
    262     self.assertEquals(
    263         'any',
    264         foo_type['properties']['y']['additionalProperties']['type'])
    265     self.assertEquals('object', foo_type['properties']['z']['type'])
    266     self.assertEquals(
    267         'any',
    268         foo_type['properties']['z']['additionalProperties']['type'])
    269     self.assertEquals('Window', foo_type['properties']['z']['isInstanceOf'])
    270 
    271     bar_type = getType(schema, 'BarType')
    272     self.assertEquals('object', bar_type['type'])
    273     self.assertEquals('any', bar_type['properties']['x']['type'])
    274 
    275   def testObjectTypesInFunctions(self):
    276     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    277 
    278     params = getParams(schema, 'objectFunction1')
    279     self.assertEquals('object', params[0]['type'])
    280     self.assertEquals('any', params[0]['additionalProperties']['type'])
    281     self.assertEquals('ImageData', params[0]['isInstanceOf'])
    282 
    283     params = getParams(schema, 'objectFunction2')
    284     self.assertEquals('any', params[0]['type'])
    285 
    286   def testObjectTypesWithOptionalFields(self):
    287     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    288 
    289     baz_type = getType(schema, 'BazType')
    290     self.assertEquals(True, baz_type['properties']['x']['optional'])
    291     self.assertEquals('integer', baz_type['properties']['x']['type'])
    292     self.assertEquals(True, baz_type['properties']['foo']['optional'])
    293     self.assertEquals('FooType', baz_type['properties']['foo']['$ref'])
    294 
    295   def testObjectTypesWithUnions(self):
    296     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    297 
    298     union_type = getType(schema, 'UnionType')
    299     expected = {
    300                  'type': 'object',
    301                  'id': 'UnionType',
    302                  'properties': {
    303                    'x': {
    304                      'name': 'x',
    305                      'optional': True,
    306                      'choices': [
    307                        {'type': 'integer'},
    308                        {'$ref': 'FooType'},
    309                      ]
    310                    },
    311                    'y': {
    312                      'name': 'y',
    313                      'choices': [
    314                        {'type': 'string'},
    315                        {'type': 'object',
    316                         'additionalProperties': {'type': 'any'}}
    317                      ]
    318                    },
    319                    'z': {
    320                      'name': 'z',
    321                      'choices': [
    322                        {'type': 'object', 'isInstanceOf': 'ImageData',
    323                         'additionalProperties': {'type': 'any'}},
    324                        {'type': 'integer'}
    325                      ]
    326                    }
    327                  },
    328                }
    329 
    330     self.assertEquals(expected, union_type)
    331 
    332   def testUnionsWithModifiers(self):
    333     schema = idl_schema.Load('test/idl_object_types.idl')[0]
    334 
    335     union_type = getType(schema, 'ModifiedUnionType')
    336     expected = {
    337                  'type': 'object',
    338                  'id': 'ModifiedUnionType',
    339                  'properties': {
    340                    'x': {
    341                      'name': 'x',
    342                      'nodoc': True,
    343                      'choices': [
    344                        {'type': 'integer'},
    345                        {'type': 'string'}
    346                      ]
    347                    }
    348                  }
    349                }
    350 
    351     self.assertEquals(expected, union_type)
    352 
    353   def testUnionsWithFunctions(self):
    354     schema = idl_schema.Load('test/idl_function_types.idl')[0]
    355 
    356     union_params = getParams(schema, 'union_params')
    357     expected = [{
    358                  'name': 'x',
    359                  'choices': [
    360                    {'type': 'integer'},
    361                    {'type': 'string'}
    362                  ]
    363                }]
    364 
    365     self.assertEquals(expected, union_params)
    366 
    367   def testUnionsWithCallbacks(self):
    368     schema = idl_schema.Load('test/idl_function_types.idl')[0]
    369 
    370     blah_params = getParams(schema, 'blah')
    371     expected = [{
    372                  'type': 'function', 'name': 'callback', 'parameters': [{
    373                    'name': 'x',
    374                    'choices': [
    375                      {'type': 'integer'},
    376                      {'type': 'string'}
    377                    ]}
    378                  ]
    379                }]
    380     self.assertEquals(expected, blah_params)
    381 
    382     badabish_params = getParams(schema, 'badabish')
    383     expected = [{
    384                  'type': 'function', 'name': 'callback', 'parameters': [{
    385                    'name': 'x', 'optional': True, 'choices': [
    386                      {'type': 'integer'},
    387                      {'type': 'string'}
    388                    ]
    389                  }]
    390                }]
    391 
    392     self.assertEquals(expected, badabish_params)
    393 
    394 
    395 if __name__ == '__main__':
    396   unittest.main()
    397