idl_schema_test.py 19 KB

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