15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom cpp_namespace_environment import CppNamespaceEnvironment 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from cpp_type_generator import CppTypeGenerator 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from json_schema import CachedLoad 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import model 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import unittest 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from collections import defaultdict 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _FakeSchemaLoader(object): 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, model): 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._model = model 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def ResolveType(self, type_name, default): 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parts = type_name.rsplit('.', 1) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if len(parts) == 1: 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return default if type_name in default.types else None 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self._model.namespaces[parts[0]] 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CppTypeGeneratorTest(unittest.TestCase): 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def setUp(self): 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.models = defaultdict(model.Model) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.forbidden_json = CachedLoad('test/forbidden.json') 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.forbidden = self.models['forbidden'].AddNamespace( 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.forbidden_json[0], 'path/to/forbidden.json') 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.permissions_json = CachedLoad('test/permissions.json') 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions = self.models['permissions'].AddNamespace( 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions_json[0], 'path/to/permissions.json') 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.windows_json = CachedLoad('test/windows.json') 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.windows = self.models['windows'].AddNamespace(self.windows_json[0], 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'path/to/window.json') 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.tabs_json = CachedLoad('test/tabs.json') 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.tabs = self.models['tabs'].AddNamespace(self.tabs_json[0], 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'path/to/tabs.json') 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.browser_action_json = CachedLoad('test/browser_action.json') 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.browser_action = self.models['browser_action'].AddNamespace( 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.browser_action_json[0], 'path/to/browser_action.json') 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.font_settings_json = CachedLoad('test/font_settings.json') 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.font_settings = self.models['font_settings'].AddNamespace( 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.font_settings_json[0], 'path/to/font_settings.json') 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.dependency_tester_json = CachedLoad('test/dependency_tester.json') 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.dependency_tester = self.models['dependency_tester'].AddNamespace( 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.dependency_tester_json[0], 'path/to/dependency_tester.json') 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.content_settings_json = CachedLoad('test/content_settings.json') 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.content_settings = self.models['content_settings'].AddNamespace( 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.content_settings_json[0], 'path/to/content_settings.json') 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def testGenerateIncludesAndForwardDeclarations(self): 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = model.Model() 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.windows_json[0], 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/windows.json', 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment('%(namespace)s')) 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.tabs_json[0], 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/tabs.json', 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment('%(namespace)s')) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(m, _FakeSchemaLoader(m)) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('', manager.GenerateIncludes().Render()) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('#include "path/to/tabs.h"', 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GenerateIncludes(include_soft=True).Render()) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.assertEquals( 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'namespace tabs {\n' 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'struct Tab;\n' 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '} // namespace tabs', 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager.GenerateForwardDeclarations().Render()) 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m = model.Model() 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.windows_json[0], 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/windows.json', 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment( 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'foo::bar::%(namespace)s')) 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.tabs_json[0], 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/tabs.json', 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment( 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'foo::bar::%(namespace)s')) 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager = CppTypeGenerator(m, _FakeSchemaLoader(m)) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.assertEquals( 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'namespace foo {\n' 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'namespace bar {\n' 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'namespace tabs {\n' 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'struct Tab;\n' 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '} // namespace tabs\n' 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '} // namespace bar\n' 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '} // namespace foo', 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci manager.GenerateForwardDeclarations().Render()) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('permissions'), 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(m)) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('', manager.GenerateIncludes().Render()) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('', manager.GenerateIncludes().Render()) 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.assertEquals('', manager.GenerateForwardDeclarations().Render()) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('content_settings'), 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(m)) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('', manager.GenerateIncludes().Render()) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def testGenerateIncludesAndForwardDeclarationsDependencies(self): 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = model.Model() 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Insert 'font_settings' before 'browser_action' in order to test that 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # CppTypeGenerator sorts them properly. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m.AddNamespace(self.font_settings_json[0], 'path/to/font_settings.json') 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m.AddNamespace(self.browser_action_json[0], 'path/to/browser_action.json') 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependency_tester = m.AddNamespace(self.dependency_tester_json[0], 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'path/to/dependency_tester.json') 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(m, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(m), 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default_namespace=dependency_tester) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals('#include "path/to/browser_action.h"\n' 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) '#include "path/to/font_settings.h"', 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager.GenerateIncludes().Render()) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.assertEquals('', manager.GenerateForwardDeclarations().Render()) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetCppTypeSimple(self): 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None)) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'int', 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.tabs.types['Tab'].properties['id'].type_)) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'std::string', 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.tabs.types['Tab'].properties['status'].type_)) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'bool', 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.tabs.types['Tab'].properties['selected'].type_)) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def testStringAsType(self): 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('font_settings'), 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(None)) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'std::string', 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.font_settings.types['FakeStringType'])) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def testArrayAsType(self): 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('browser_action'), 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(None)) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'std::vector<int>', 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.browser_action.types['ColorArray'])) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetCppTypeArray(self): 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('windows'), 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(None)) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'std::vector<linked_ptr<Window> >', 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.windows.functions['getAll'].callback.params[0].type_)) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('permissions'), 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(None)) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals( 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'std::vector<std::string>', 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions.types['Permissions'].properties['origins'].type_)) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetCppTypeLocalRef(self): 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None)) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Tab', 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType(self.tabs.functions['get'].callback.params[0].type_)) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetCppTypeIncludedRef(self): 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m = model.Model() 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.windows_json[0], 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/windows.json', 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment('%(namespace)s')) 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci m.AddNamespace(self.tabs_json[0], 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'path/to/tabs.json', 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment=CppNamespaceEnvironment('%(namespace)s')) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(m, _FakeSchemaLoader(m)) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals( 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'std::vector<linked_ptr<tabs::Tab> >', 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.windows.types['Window'].properties['tabs'].type_)) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetCppTypeWithPadForGeneric(self): 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager = CppTypeGenerator(self.models.get('permissions'), 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _FakeSchemaLoader(None)) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('std::vector<std::string>', 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions.types['Permissions'].properties['origins'].type_, 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_in_container=False)) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals('linked_ptr<std::vector<std::string> >', 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions.types['Permissions'].properties['origins'].type_, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_in_container=True)) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.assertEquals('bool', 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) manager.GetCppType( 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.permissions.functions['contains'].callback.params[0].type_, 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_in_container=True)) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__': 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unittest.main() 194