cpp_type_generator_test.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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. from cpp_namespace_environment import CppNamespaceEnvironment
  6. from cpp_type_generator import CppTypeGenerator
  7. from json_schema import CachedLoad
  8. import idl_schema
  9. import model
  10. import unittest
  11. from collections import defaultdict
  12. class _FakeSchemaLoader(object):
  13. def __init__(self, model):
  14. self._model = model
  15. def ResolveType(self, type_name, default):
  16. parts = type_name.rsplit('.', 1)
  17. if len(parts) == 1:
  18. return default if type_name in default.types else None
  19. return self._model.namespaces[parts[0]]
  20. class CppTypeGeneratorTest(unittest.TestCase):
  21. def setUp(self):
  22. self.models = defaultdict(model.Model)
  23. forbidden_json = CachedLoad('test/forbidden.json')
  24. self.models['forbidden'].AddNamespace(
  25. forbidden_json[0], 'path/to/forbidden.json')
  26. permissions_json = CachedLoad('test/permissions.json')
  27. self.permissions = self.models['permissions'].AddNamespace(
  28. permissions_json[0], 'path/to/permissions.json')
  29. self.windows_json = CachedLoad('test/windows.json')
  30. self.windows = self.models['windows'].AddNamespace(self.windows_json[0],
  31. 'path/to/window.json')
  32. self.tabs_json = CachedLoad('test/tabs.json')
  33. self.tabs = self.models['tabs'].AddNamespace(self.tabs_json[0],
  34. 'path/to/tabs.json')
  35. self.browser_action_json = CachedLoad('test/browser_action.json')
  36. self.browser_action = self.models['browser_action'].AddNamespace(
  37. self.browser_action_json[0], 'path/to/browser_action.json')
  38. self.font_settings_json = CachedLoad('test/font_settings.json')
  39. self.font_settings = self.models['font_settings'].AddNamespace(
  40. self.font_settings_json[0], 'path/to/font_settings.json')
  41. self.dependency_tester_json = CachedLoad('test/dependency_tester.json')
  42. self.models['dependency_tester'].AddNamespace(
  43. self.dependency_tester_json[0], 'path/to/dependency_tester.json')
  44. content_settings_json = CachedLoad('test/content_settings.json')
  45. self.models['content_settings'].AddNamespace(
  46. content_settings_json[0], 'path/to/content_settings.json')
  47. objects_movable_idl = idl_schema.Load('test/objects_movable.idl')
  48. self.objects_movable = self.models['objects_movable'].AddNamespace(
  49. objects_movable_idl[0], 'path/to/objects_movable.idl',
  50. include_compiler_options=True)
  51. self.simple_api_json = CachedLoad('test/simple_api.json')
  52. self.models['simple_api'].AddNamespace(
  53. self.simple_api_json[0], 'path/to/simple_api.json')
  54. self.crossref_enums_json = CachedLoad('test/crossref_enums.json')
  55. self.models['crossref_enums'].AddNamespace(
  56. self.crossref_enums_json[0], 'path/to/crossref_enums.json')
  57. self.crossref_enums_array_json = CachedLoad(
  58. 'test/crossref_enums_array.json')
  59. self.models['crossref_enums_array'].AddNamespace(
  60. self.crossref_enums_array_json[0],
  61. 'path/to/crossref_enums_array.json')
  62. def testGenerateIncludesAndForwardDeclarations(self):
  63. m = model.Model()
  64. m.AddNamespace(self.windows_json[0],
  65. 'path/to/windows.json',
  66. environment=CppNamespaceEnvironment('%(namespace)s'))
  67. m.AddNamespace(self.tabs_json[0],
  68. 'path/to/tabs.json',
  69. environment=CppNamespaceEnvironment('%(namespace)s'))
  70. manager = CppTypeGenerator(m, _FakeSchemaLoader(m))
  71. self.assertEqual('', manager.GenerateIncludes().Render())
  72. self.assertEqual('#include "path/to/tabs.h"',
  73. manager.GenerateIncludes(include_soft=True).Render())
  74. self.assertEqual(
  75. 'namespace tabs {\n'
  76. 'struct Tab;\n'
  77. '} // namespace tabs',
  78. manager.GenerateForwardDeclarations().Render())
  79. m = model.Model()
  80. m.AddNamespace(self.windows_json[0],
  81. 'path/to/windows.json',
  82. environment=CppNamespaceEnvironment(
  83. 'foo::bar::%(namespace)s'))
  84. m.AddNamespace(self.tabs_json[0],
  85. 'path/to/tabs.json',
  86. environment=CppNamespaceEnvironment(
  87. 'foo::bar::%(namespace)s'))
  88. manager = CppTypeGenerator(m, _FakeSchemaLoader(m))
  89. self.assertEqual(
  90. 'namespace foo {\n'
  91. 'namespace bar {\n'
  92. 'namespace tabs {\n'
  93. 'struct Tab;\n'
  94. '} // namespace tabs\n'
  95. '} // namespace bar\n'
  96. '} // namespace foo',
  97. manager.GenerateForwardDeclarations().Render())
  98. manager = CppTypeGenerator(self.models.get('permissions'),
  99. _FakeSchemaLoader(m))
  100. self.assertEqual('', manager.GenerateIncludes().Render())
  101. self.assertEqual('', manager.GenerateIncludes().Render())
  102. self.assertEqual('', manager.GenerateForwardDeclarations().Render())
  103. manager = CppTypeGenerator(self.models.get('content_settings'),
  104. _FakeSchemaLoader(m))
  105. self.assertEqual('', manager.GenerateIncludes().Render())
  106. def testGenerateIncludesAndForwardDeclarationsDependencies(self):
  107. m = model.Model()
  108. # Insert 'font_settings' before 'browser_action' in order to test that
  109. # CppTypeGenerator sorts them properly.
  110. m.AddNamespace(self.font_settings_json[0], 'path/to/font_settings.json')
  111. m.AddNamespace(self.browser_action_json[0], 'path/to/browser_action.json')
  112. dependency_tester = m.AddNamespace(self.dependency_tester_json[0],
  113. 'path/to/dependency_tester.json')
  114. manager = CppTypeGenerator(m,
  115. _FakeSchemaLoader(m),
  116. default_namespace=dependency_tester)
  117. self.assertEqual('#include "path/to/browser_action.h"\n'
  118. '#include "path/to/font_settings.h"',
  119. manager.GenerateIncludes().Render())
  120. self.assertEqual('', manager.GenerateForwardDeclarations().Render())
  121. def testGetCppTypeSimple(self):
  122. manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
  123. self.assertEqual(
  124. 'int',
  125. manager.GetCppType(self.tabs.types['Tab'].properties['id'].type_))
  126. self.assertEqual(
  127. 'std::string',
  128. manager.GetCppType(self.tabs.types['Tab'].properties['status'].type_))
  129. self.assertEqual(
  130. 'bool',
  131. manager.GetCppType(self.tabs.types['Tab'].properties['selected'].type_))
  132. def testStringAsType(self):
  133. manager = CppTypeGenerator(self.models.get('font_settings'),
  134. _FakeSchemaLoader(None))
  135. self.assertEqual(
  136. 'std::string',
  137. manager.GetCppType(self.font_settings.types['FakeStringType']))
  138. def testArrayAsType(self):
  139. manager = CppTypeGenerator(self.models.get('browser_action'),
  140. _FakeSchemaLoader(None))
  141. self.assertEqual(
  142. 'std::vector<int>',
  143. manager.GetCppType(self.browser_action.types['ColorArray']))
  144. def testGetCppTypeArray(self):
  145. manager = CppTypeGenerator(self.models.get('windows'),
  146. _FakeSchemaLoader(None))
  147. self.assertEqual(
  148. 'std::vector<Window>',
  149. manager.GetCppType(
  150. self.windows.functions['getAll'].returns_async.params[0].type_))
  151. manager = CppTypeGenerator(self.models.get('permissions'),
  152. _FakeSchemaLoader(None))
  153. self.assertEqual(
  154. 'std::vector<std::string>',
  155. manager.GetCppType(
  156. self.permissions.types['Permissions'].properties['origins'].type_))
  157. manager = CppTypeGenerator(self.models.get('objects_movable'),
  158. _FakeSchemaLoader(None))
  159. self.assertEqual(
  160. 'std::vector<MovablePod>',
  161. manager.GetCppType(
  162. self.objects_movable.types['MovableParent'].
  163. properties['pods'].type_))
  164. def testGetCppTypeLocalRef(self):
  165. manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
  166. self.assertEqual(
  167. 'Tab',
  168. manager.GetCppType(
  169. self.tabs.functions['get'].returns_async.params[0].type_))
  170. def testGetCppTypeIncludedRef(self):
  171. m = model.Model()
  172. m.AddNamespace(self.windows_json[0],
  173. 'path/to/windows.json',
  174. environment=CppNamespaceEnvironment('%(namespace)s'))
  175. m.AddNamespace(self.tabs_json[0],
  176. 'path/to/tabs.json',
  177. environment=CppNamespaceEnvironment('%(namespace)s'))
  178. manager = CppTypeGenerator(m, _FakeSchemaLoader(m))
  179. self.assertEqual(
  180. 'std::vector<tabs::Tab>',
  181. manager.GetCppType(
  182. self.windows.types['Window'].properties['tabs'].type_))
  183. def testGetCppTypeWithPadForGeneric(self):
  184. manager = CppTypeGenerator(self.models.get('permissions'),
  185. _FakeSchemaLoader(None))
  186. self.assertEqual('std::vector<std::string>',
  187. manager.GetCppType(
  188. self.permissions.types['Permissions'].properties['origins'].type_,
  189. is_in_container=False))
  190. self.assertEqual('std::vector<std::string>',
  191. manager.GetCppType(
  192. self.permissions.types['Permissions'].properties['origins'].type_,
  193. is_in_container=True))
  194. self.assertEqual(
  195. 'bool',
  196. manager.GetCppType(self.permissions.functions['contains'].returns_async.
  197. params[0].type_, is_in_container=True))
  198. def testHardIncludesForEnums(self):
  199. """Tests that enums generate hard includes. Note that it's important to use
  200. use a separate file (cross_enums) here to isolate the test case so that
  201. other types don't cause the hard-dependency.
  202. """
  203. m = model.Model()
  204. m.AddNamespace(self.crossref_enums_json[0],
  205. 'path/to/crossref_enums.json',
  206. environment=CppNamespaceEnvironment('%(namespace)s'))
  207. m.AddNamespace(self.simple_api_json[0],
  208. 'path/to/simple_api.json',
  209. environment=CppNamespaceEnvironment('%(namespace)s'))
  210. manager = CppTypeGenerator(self.models.get('crossref_enums'),
  211. _FakeSchemaLoader(m))
  212. self.assertEqual('#include "path/to/simple_api.h"',
  213. manager.GenerateIncludes().Render())
  214. def testHardIncludesForEnumArrays(self):
  215. """Tests that enums in arrays generate hard includes. Note that it's
  216. important to use a separate file (cross_enums_array) here to isolate the
  217. test case so that other types don't cause the hard-dependency.
  218. """
  219. m = model.Model()
  220. m.AddNamespace(self.crossref_enums_array_json[0],
  221. 'path/to/crossref_enums_array.json',
  222. environment=CppNamespaceEnvironment('%(namespace)s'))
  223. m.AddNamespace(self.simple_api_json[0],
  224. 'path/to/simple_api.json',
  225. environment=CppNamespaceEnvironment('%(namespace)s'))
  226. manager = CppTypeGenerator(self.models.get('crossref_enums_array'),
  227. _FakeSchemaLoader(m))
  228. self.assertEqual('#include "path/to/simple_api.h"',
  229. manager.GenerateIncludes().Render())
  230. if __name__ == '__main__':
  231. unittest.main()