11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#!/usr/bin/env python
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# found in the LICENSE file.
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)import json
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)import unittest
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from api_models import APIModels
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from compiled_file_system import CompiledFileSystem
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)from extensions_paths import API, EXTENSIONS
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from features_bundle import FeaturesBundle
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from file_system import FileNotFoundError
140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)from mock_file_system import MockFileSystem
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from object_store_creator import ObjectStoreCreator
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from test_file_system import TestFileSystem
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)from test_util import ReadFile
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)_TEST_DATA = {
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  'api': {
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    'devtools': {
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      'inspected_window.json': ReadFile(
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          API, 'devtools', 'inspected_window.json'),
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    },
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    '_api_features.json': json.dumps({
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'alarms': {},
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      'app': {},
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      'app.runtime': {'noparent': True},
300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      'app.runtime.experimental': {},
310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      'app.runtime.experimental.foo': {},
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'declarativeWebRequest': {},
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'devtools.inspectedWindow': {},
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'experimental.accessibility': {},
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'storage': {},
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }),
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    '_manifest_features.json': '{}',
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    '_permission_features.json': '{}',
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    'alarms.idl': ReadFile(API, 'alarms.idl'),
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    'declarative_web_request.json': ReadFile(
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        API, 'declarative_web_request.json'),
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    'experimental_accessibility.json': ReadFile(
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        API, 'experimental_accessibility.json'),
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    'page_action.json': ReadFile(API, 'page_action.json'),
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  },
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  'docs': {
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    'templates': {
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      'json': {
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        'manifest.json': '{}',
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        'permissions.json': '{}',
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  },
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class APIModelsTest(unittest.TestCase):
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def setUp(self):
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    object_store_creator = ObjectStoreCreator.ForTest()
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    compiled_fs_factory = CompiledFileSystem.Factory(object_store_creator)
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self._mock_file_system = MockFileSystem(
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        TestFileSystem(_TEST_DATA, relative_to=EXTENSIONS))
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    features_bundle = FeaturesBundle(
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        self._mock_file_system, compiled_fs_factory, object_store_creator)
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self._api_models = APIModels(
660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        features_bundle, compiled_fs_factory, self._mock_file_system)
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def testGetNames(self):
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # Both 'app' and 'app.runtime' appear here because 'app.runtime' has
700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # noparent:true, but 'app.runtime.experimental' etc doesn't so it's a
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # sub-feature of 'app.runtime' not a separate API.
720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # 'devtools.inspectedWindow' is an API because there is no 'devtools'.
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual(
740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        ['alarms', 'app', 'app.runtime', 'declarativeWebRequest',
750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)         'devtools.inspectedWindow', 'experimental.accessibility', 'storage'],
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        sorted(self._api_models.GetNames()))
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def testGetModel(self):
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    def get_model_name(api_name):
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return self._api_models.GetModel(api_name).Get().name
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('devtools.inspectedWindow',
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('devtools.inspectedWindow'))
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('devtools.inspectedWindow',
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('devtools/inspected_window.json'))
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('devtools.inspectedWindow',
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     get_model_name('%s/devtools/inspected_window.json' % API))
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('alarms', get_model_name('alarms'))
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('alarms', get_model_name('alarms.idl'))
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.assertEqual('alarms', get_model_name('%s/alarms.idl' % API))
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('declarativeWebRequest',
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('declarativeWebRequest'))
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('declarativeWebRequest',
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('declarative_web_request.json'))
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('declarativeWebRequest',
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     get_model_name('%s/declarative_web_request.json' % API))
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('experimental.accessibility',
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('experimental.accessibility'))
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('experimental.accessibility',
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     get_model_name('experimental_accessibility.json'))
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('experimental.accessibility',
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     get_model_name('%s/experimental_accessibility.json' % API))
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('pageAction', get_model_name('pageAction'))
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertEqual('pageAction', get_model_name('page_action.json'))
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    self.assertEqual('pageAction', get_model_name('%s/page_action.json' % API))
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  def testGetNonexistentModel(self):
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                      self._api_models.GetModel('notfound').Get)
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                      self._api_models.GetModel('notfound.json').Get)
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      self._api_models.GetModel('%s/notfound.json' % API).Get)
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      self._api_models.GetModel('%s/alarms.json' % API).Get)
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                      self._api_models.GetModel('storage').Get)
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      self._api_models.GetModel('%s/storage.json' % API).Get)
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    self.assertRaises(FileNotFoundError,
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      self._api_models.GetModel('%s/storage.idl' % API).Get)
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  def testSingleFile(self):
1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # 2 stats (1 for JSON and 1 for IDL), 1 read (for IDL file which existed).
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    future = self._api_models.GetModel('alarms')
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    self.assertTrue(*self._mock_file_system.CheckAndReset(
1260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        read_count=1, stat_count=2))
1270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # 1 read-resolve (for the IDL file).
1290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    #
1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # The important part here and above is that it's only doing a single read;
1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # any more would break the contract that only a single file is accessed -
1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # see the SingleFile annotation in api_models._CreateAPIModel.
1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    future.Get()
1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    self.assertTrue(*self._mock_file_system.CheckAndReset(
1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        read_resolve_count=1))
1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    # 2 stats (1 for JSON and 1 for IDL), no reads (still cached).
1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    future = self._api_models.GetModel('alarms')
1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    self.assertTrue(*self._mock_file_system.CheckAndReset(stat_count=2))
1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    future.Get()
1410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    self.assertTrue(*self._mock_file_system.CheckAndReset())
1420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)if __name__ == '__main__':
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  unittest.main()
146