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