api_models_test.py revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1#!/usr/bin/env python
2# Copyright 2013 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
6import json
7import unittest
8
9from api_models import APIModels
10from compiled_file_system import CompiledFileSystem
11from extensions_paths import API_PATHS, CHROME_API, CHROME_EXTENSIONS
12from features_bundle import FeaturesBundle
13from file_system import FileNotFoundError
14from mock_file_system import MockFileSystem
15from object_store_creator import ObjectStoreCreator
16from test_file_system import TestFileSystem
17from test_util import ReadFile
18
19
20_TEST_DATA = {
21  'api': {
22    'devtools': {
23      'inspected_window.json': ReadFile(
24          CHROME_API, 'devtools', 'inspected_window.json'),
25    },
26    '_api_features.json': json.dumps({
27      'alarms': {},
28      'app': {},
29      'app.runtime': {'noparent': True},
30      'app.runtime.foo': {},
31      'declarativeWebRequest': {},
32      'devtools.inspectedWindow': {},
33      'input': {},
34      'input.ime': {},
35      'storage': {},
36    }),
37    '_manifest_features.json': '{}',
38    '_permission_features.json': '{}',
39    'alarms.idl': ReadFile(CHROME_API, 'alarms.idl'),
40    'declarative_web_request.json': ReadFile(
41        CHROME_API, 'declarative_web_request.json'),
42    'input_ime.json': ReadFile(CHROME_API, 'input_ime.json'),
43    'page_action.json': ReadFile(CHROME_API, 'page_action.json'),
44  },
45  'docs': {
46    'templates': {
47      'json': {
48        'manifest.json': '{}',
49        'permissions.json': '{}',
50      }
51    }
52  },
53}
54
55
56class APIModelsTest(unittest.TestCase):
57  def setUp(self):
58    object_store_creator = ObjectStoreCreator.ForTest()
59    compiled_fs_factory = CompiledFileSystem.Factory(object_store_creator)
60    self._mock_file_system = MockFileSystem(
61        TestFileSystem(_TEST_DATA, relative_to=CHROME_EXTENSIONS))
62    features_bundle = FeaturesBundle(
63        self._mock_file_system, compiled_fs_factory, object_store_creator)
64    self._api_models = APIModels(
65        features_bundle, compiled_fs_factory, self._mock_file_system)
66
67  def testGetNames(self):
68    # Both 'app' and 'app.runtime' appear here because 'app.runtime' has
69    # noparent:true, but 'app.runtime.foo' etc doesn't so it's a sub-feature of
70    # 'app.runtime' not a separate API. 'devtools.inspectedWindow' is an API
71    # because there is no 'devtools'.
72    self.assertEqual(
73        ['alarms', 'app', 'app.runtime', 'declarativeWebRequest',
74         'devtools.inspectedWindow', 'input', 'storage'],
75        sorted(self._api_models.GetNames()))
76
77  def testGetModel(self):
78    def get_model_name(api_name):
79      return self._api_models.GetModel(api_name).Get().name
80    self.assertEqual('devtools.inspectedWindow',
81                     get_model_name('devtools.inspectedWindow'))
82    self.assertEqual('devtools.inspectedWindow',
83                     get_model_name('devtools/inspected_window.json'))
84    self.assertEqual('devtools.inspectedWindow',
85                     get_model_name(CHROME_API +
86                                    'devtools/inspected_window.json'))
87    self.assertEqual('alarms', get_model_name('alarms'))
88    self.assertEqual('alarms', get_model_name('alarms.idl'))
89    self.assertEqual('alarms', get_model_name(CHROME_API + 'alarms.idl'))
90    self.assertEqual('declarativeWebRequest',
91                     get_model_name('declarativeWebRequest'))
92    self.assertEqual('declarativeWebRequest',
93                     get_model_name('declarative_web_request.json'))
94    self.assertEqual('declarativeWebRequest',
95                     get_model_name(CHROME_API +
96                                    'declarative_web_request.json'))
97    self.assertEqual('input.ime', get_model_name('input.ime'))
98    self.assertEqual('input.ime', get_model_name('input_ime.json'))
99    self.assertEqual('input.ime',
100                     get_model_name(CHROME_API + 'input_ime.json'))
101    self.assertEqual('pageAction', get_model_name('pageAction'))
102    self.assertEqual('pageAction', get_model_name('page_action.json'))
103    self.assertEqual('pageAction', get_model_name(CHROME_API +
104                                                  'page_action.json'))
105
106  def testGetNonexistentModel(self):
107    self.assertRaises(FileNotFoundError,
108                      self._api_models.GetModel('notfound').Get)
109    self.assertRaises(FileNotFoundError,
110                      self._api_models.GetModel('notfound.json').Get)
111    self.assertRaises(FileNotFoundError,
112                      self._api_models.GetModel(CHROME_API +
113                                                'notfound.json').Get)
114    self.assertRaises(FileNotFoundError,
115                      self._api_models.GetModel(CHROME_API +
116                                                'alarms.json').Get)
117    self.assertRaises(FileNotFoundError,
118                      self._api_models.GetModel('storage').Get)
119    self.assertRaises(FileNotFoundError,
120                      self._api_models.GetModel(CHROME_API +
121                                                'storage.json').Get)
122    self.assertRaises(FileNotFoundError,
123                      self._api_models.GetModel(CHROME_API +
124                                                'storage.idl').Get)
125
126  def testSingleFile(self):
127    # 2 stats (1 for JSON and 1 for IDL) for each available API path.
128    # 1 read (for IDL file which existed).
129    future = self._api_models.GetModel('alarms')
130    self.assertTrue(*self._mock_file_system.CheckAndReset(
131        read_count=1, stat_count=len(API_PATHS)*2))
132
133    # 1 read-resolve (for the IDL file).
134    #
135    # The important part here and above is that it's only doing a single read;
136    # any more would break the contract that only a single file is accessed -
137    # see the SingleFile annotation in api_models._CreateAPIModel.
138    future.Get()
139    self.assertTrue(*self._mock_file_system.CheckAndReset(
140        read_resolve_count=1))
141
142    # 2 stats (1 for JSON and 1 for IDL) for each available API path.
143    # No reads (still cached).
144    future = self._api_models.GetModel('alarms')
145    self.assertTrue(*self._mock_file_system.CheckAndReset(
146        stat_count=len(API_PATHS)*2))
147    future.Get()
148    self.assertTrue(*self._mock_file_system.CheckAndReset())
149
150
151if __name__ == '__main__':
152  unittest.main()
153