availability_finder_test.py revision f2477e01787aa58f445919b809d89e252beef54f
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.
5import os
6import sys
7import unittest
8from collections import namedtuple
9
10import availability_finder
11from api_schema_graph import LookupResult
12from branch_utility import BranchUtility, ChannelInfo
13from compiled_file_system import CompiledFileSystem
14from fake_url_fetcher import FakeUrlFetcher
15from host_file_system_iterator import HostFileSystemIterator
16from mock_function import MockFunction
17from object_store_creator import ObjectStoreCreator
18from test_file_system import TestFileSystem
19from test_data.canned_data import (CANNED_API_FILE_SYSTEM_DATA, CANNED_BRANCHES)
20from test_data.object_level_availability.tabs import TABS_SCHEMA_BRANCHES
21from third_party.json_schema_compiler.memoize import memoize
22
23
24TABS_UNMODIFIED_VERSIONS = (16, 20, 23, 24)
25
26
27class _FakeHostFileSystemProvider(object):
28
29  def __init__(self, file_system_data):
30    self._file_system_data = file_system_data
31
32  def GetTrunk(self):
33    return self.GetBranch('trunk')
34
35  @memoize
36  def GetBranch(self, branch):
37    return TestFileSystem(self._file_system_data[str(branch)])
38
39
40class AvailabilityFinderTest(unittest.TestCase):
41
42  def setUp(self):
43    self._branch_utility = BranchUtility(
44        os.path.join('branch_utility', 'first.json'),
45        os.path.join('branch_utility', 'second.json'),
46        FakeUrlFetcher(os.path.join(sys.path[0], 'test_data')),
47        ObjectStoreCreator.ForTest())
48    api_fs_creator = _FakeHostFileSystemProvider(CANNED_API_FILE_SYSTEM_DATA)
49    self._node_fs_creator = _FakeHostFileSystemProvider(TABS_SCHEMA_BRANCHES)
50
51    def create_availability_finder(host_fs_creator):
52      test_object_store = ObjectStoreCreator.ForTest()
53      return availability_finder.AvailabilityFinder(
54          self._branch_utility,
55          CompiledFileSystem.Factory(test_object_store),
56          HostFileSystemIterator(host_fs_creator,
57                                 self._branch_utility),
58          host_fs_creator.GetTrunk(),
59          test_object_store)
60
61    self._avail_finder = create_availability_finder(api_fs_creator)
62    self._node_avail_finder = create_availability_finder(self._node_fs_creator)
63
64    # Imitate the actual SVN file system by incrementing the stats for paths
65    # where an API schema has changed.
66    last_stat = type('last_stat', (object,), {'val': 0})
67
68    def stat_paths(file_system, channel_info):
69      if channel_info.version not in TABS_UNMODIFIED_VERSIONS:
70        last_stat.val += 1
71      file_system.IncrementStat(by=last_stat.val)
72      # Continue looping. The iterator will stop after 'trunk' automatically.
73      return True
74
75    # Use the HostFileSystemIterator created above to change global stat values
76    # for the TestFileSystems that it creates.
77    self._node_avail_finder._file_system_iterator.Ascending(
78        self._node_avail_finder.GetApiAvailability('tabs'),
79        stat_paths)
80
81  def testGraphOptimization(self):
82    # Whenever an APISchemaGraph is created, _GetApiSchema() is called and its
83    # result is passed to the APISchemaGraph constructor.
84    # Use this function to determine how many APISchemaGraphs are created.
85    availability_finder._GetApiSchema = MockFunction(
86        availability_finder._GetApiSchema)
87
88    # The test data includes an extra branch where the API does not exist.
89    num_versions = len(TABS_SCHEMA_BRANCHES) - 1
90    # We expect an APISchemaGraph to be created only when an API schema file
91    # has different stat data from the previous version's schema file.
92    num_graphs_created = num_versions - len(TABS_UNMODIFIED_VERSIONS)
93
94    # Run the logic for object-level availability for an API.
95    self._node_avail_finder.GetApiNodeAvailability('tabs')
96
97    self.assertTrue(*availability_finder._GetApiSchema.CheckAndReset(
98        num_graphs_created))
99
100    # Let _GetApiSchema() be the original, unmodified function again.
101    availability_finder._GetApiSchema = availability_finder._GetApiSchema._fn
102
103  def testGetApiAvailability(self):
104    # Key: Using 'channel' (i.e. 'beta') to represent an availability listing
105    # for an API in a _features.json file, and using |channel| (i.e. |dev|) to
106    # represent the development channel, or phase of development, where an API's
107    # availability is being checked.
108
109    # Testing APIs with predetermined availability.
110    self.assertEqual(
111        ChannelInfo('trunk', 'trunk', 'trunk'),
112        self._avail_finder.GetApiAvailability('jsonTrunkAPI'))
113    self.assertEqual(
114        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
115        self._avail_finder.GetApiAvailability('jsonDevAPI'))
116    self.assertEqual(
117        ChannelInfo('beta', CANNED_BRANCHES[27], 27),
118        self._avail_finder.GetApiAvailability('jsonBetaAPI'))
119    self.assertEqual(
120        ChannelInfo('stable', CANNED_BRANCHES[20], 20),
121        self._avail_finder.GetApiAvailability('jsonStableAPI'))
122
123    # Testing a whitelisted API.
124    self.assertEquals(
125        ChannelInfo('beta', CANNED_BRANCHES[27], 27),
126        self._avail_finder.GetApiAvailability('declarativeWebRequest'))
127
128    # Testing APIs found only by checking file system existence.
129    self.assertEquals(
130        ChannelInfo('stable', CANNED_BRANCHES[23], 23),
131        self._avail_finder.GetApiAvailability('windows'))
132    self.assertEquals(
133        ChannelInfo('stable', CANNED_BRANCHES[18], 18),
134        self._avail_finder.GetApiAvailability('tabs'))
135    self.assertEquals(
136        ChannelInfo('stable', CANNED_BRANCHES[18], 18),
137        self._avail_finder.GetApiAvailability('input.ime'))
138
139    # Testing API channel existence for _api_features.json.
140    # Listed as 'dev' on |beta|, 'dev' on |dev|.
141    self.assertEquals(
142        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
143        self._avail_finder.GetApiAvailability('systemInfo.stuff'))
144    # Listed as 'stable' on |beta|.
145    self.assertEquals(
146        ChannelInfo('beta', CANNED_BRANCHES[27], 27),
147        self._avail_finder.GetApiAvailability('systemInfo.cpu'))
148
149    # Testing API channel existence for _manifest_features.json.
150    # Listed as 'trunk' on all channels.
151    self.assertEquals(
152        ChannelInfo('trunk', 'trunk', 'trunk'),
153        self._avail_finder.GetApiAvailability('sync'))
154    # No records of API until |trunk|.
155    self.assertEquals(
156        ChannelInfo('trunk', 'trunk', 'trunk'),
157        self._avail_finder.GetApiAvailability('history'))
158    # Listed as 'dev' on |dev|.
159    self.assertEquals(
160        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
161        self._avail_finder.GetApiAvailability('storage'))
162    # Stable in _manifest_features and into pre-18 versions.
163    self.assertEquals(
164        ChannelInfo('stable', CANNED_BRANCHES[8], 8),
165        self._avail_finder.GetApiAvailability('pageAction'))
166
167    # Testing API channel existence for _permission_features.json.
168    # Listed as 'beta' on |trunk|.
169    self.assertEquals(
170        ChannelInfo('trunk', 'trunk', 'trunk'),
171        self._avail_finder.GetApiAvailability('falseBetaAPI'))
172    # Listed as 'trunk' on |trunk|.
173    self.assertEquals(
174        ChannelInfo('trunk', 'trunk', 'trunk'),
175        self._avail_finder.GetApiAvailability('trunkAPI'))
176    # Listed as 'trunk' on all development channels.
177    self.assertEquals(
178        ChannelInfo('trunk', 'trunk', 'trunk'),
179        self._avail_finder.GetApiAvailability('declarativeContent'))
180    # Listed as 'dev' on all development channels.
181    self.assertEquals(
182        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
183        self._avail_finder.GetApiAvailability('bluetooth'))
184    # Listed as 'dev' on |dev|.
185    self.assertEquals(
186        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
187        self._avail_finder.GetApiAvailability('cookies'))
188    # Treated as 'stable' APIs.
189    self.assertEquals(
190        ChannelInfo('stable', CANNED_BRANCHES[24], 24),
191        self._avail_finder.GetApiAvailability('alarms'))
192    self.assertEquals(
193        ChannelInfo('stable', CANNED_BRANCHES[21], 21),
194        self._avail_finder.GetApiAvailability('bookmarks'))
195
196    # Testing older API existence using extension_api.json.
197    self.assertEquals(
198        ChannelInfo('stable', CANNED_BRANCHES[6], 6),
199        self._avail_finder.GetApiAvailability('menus'))
200    self.assertEquals(
201        ChannelInfo('stable', CANNED_BRANCHES[5], 5),
202        self._avail_finder.GetApiAvailability('idle'))
203
204    # Switches between _features.json files across branches.
205    # Listed as 'trunk' on all channels, in _api, _permission, or _manifest.
206    self.assertEquals(
207        ChannelInfo('trunk', 'trunk', 'trunk'),
208        self._avail_finder.GetApiAvailability('contextMenus'))
209    # Moves between _permission and _manifest as file system is traversed.
210    self.assertEquals(
211        ChannelInfo('stable', CANNED_BRANCHES[23], 23),
212        self._avail_finder.GetApiAvailability('systemInfo.display'))
213    self.assertEquals(
214        ChannelInfo('stable', CANNED_BRANCHES[17], 17),
215        self._avail_finder.GetApiAvailability('webRequest'))
216
217    # Mid-upgrade cases:
218    # Listed as 'dev' on |beta| and 'beta' on |dev|.
219    self.assertEquals(
220        ChannelInfo('dev', CANNED_BRANCHES[28], 28),
221        self._avail_finder.GetApiAvailability('notifications'))
222    # Listed as 'beta' on |stable|, 'dev' on |beta| ... until |stable| on trunk.
223    self.assertEquals(
224        ChannelInfo('trunk', 'trunk', 'trunk'),
225        self._avail_finder.GetApiAvailability('events'))
226
227  def testGetApiNodeAvailability(self):
228    availability_graph = self._node_avail_finder.GetApiNodeAvailability('tabs')
229
230    self.assertEquals(
231        LookupResult(True, self._branch_utility.GetChannelInfo('trunk')),
232        availability_graph.Lookup('tabs', 'properties',
233                                  'fakeTabsProperty3'))
234    self.assertEquals(
235        LookupResult(True, self._branch_utility.GetChannelInfo('dev')),
236        availability_graph.Lookup('tabs', 'events', 'onActivated',
237                                  'parameters', 'activeInfo', 'properties',
238                                  'windowId'))
239    self.assertEquals(
240        LookupResult(True, self._branch_utility.GetChannelInfo('dev')),
241        availability_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters',
242                                  'tab'))
243    self.assertEquals(
244        LookupResult(True, self._branch_utility.GetChannelInfo('beta')),
245        availability_graph.Lookup('tabs', 'events','onActivated'))
246    self.assertEquals(
247        LookupResult(True, self._branch_utility.GetChannelInfo('beta')),
248        availability_graph.Lookup('tabs', 'functions', 'get', 'parameters',
249                                  'tabId'))
250    self.assertEquals(
251        LookupResult(True, self._branch_utility.GetChannelInfo('stable')),
252        availability_graph.Lookup('tabs', 'types', 'InjectDetails',
253                                  'properties', 'code'))
254    self.assertEquals(
255        LookupResult(True, self._branch_utility.GetChannelInfo('stable')),
256        availability_graph.Lookup('tabs', 'types', 'InjectDetails',
257                                  'properties', 'file'))
258    self.assertEquals(
259        LookupResult(True, self._branch_utility.GetStableChannelInfo(25)),
260        availability_graph.Lookup('tabs', 'types', 'InjectDetails'))
261
262    # Nothing new in version 24 or 23.
263
264    self.assertEquals(
265        LookupResult(True, self._branch_utility.GetStableChannelInfo(22)),
266        availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
267                                  'windowId'))
268    self.assertEquals(
269        LookupResult(True, self._branch_utility.GetStableChannelInfo(21)),
270        availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
271                                  'selected'))
272
273    # Nothing new in version 20.
274
275    self.assertEquals(
276        LookupResult(True, self._branch_utility.GetStableChannelInfo(19)),
277        availability_graph.Lookup('tabs', 'functions', 'getCurrent'))
278    self.assertEquals(
279        LookupResult(True, self._branch_utility.GetStableChannelInfo(18)),
280        availability_graph.Lookup('tabs', 'types', 'Tab', 'properties',
281                                  'index'))
282    self.assertEquals(
283        LookupResult(True, self._branch_utility.GetStableChannelInfo(17)),
284        availability_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters',
285                                  'changeInfo'))
286
287    # Nothing new in version 16.
288
289    self.assertEquals(
290        LookupResult(True, self._branch_utility.GetStableChannelInfo(15)),
291        availability_graph.Lookup('tabs', 'properties',
292                                  'fakeTabsProperty2'))
293
294    # Everything else is available at the API's release, version 14 here.
295    self.assertEquals(
296        LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
297        availability_graph.Lookup('tabs', 'types', 'Tab'))
298    self.assertEquals(
299        LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
300        availability_graph.Lookup('tabs', 'types', 'Tab',
301                                  'properties', 'url'))
302    self.assertEquals(
303        LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
304        availability_graph.Lookup('tabs', 'properties',
305                                  'fakeTabsProperty1'))
306    self.assertEquals(
307        LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
308        availability_graph.Lookup('tabs', 'functions', 'get', 'parameters',
309                                  'callback'))
310    self.assertEquals(
311        LookupResult(True, self._branch_utility.GetStableChannelInfo(14)),
312        availability_graph.Lookup('tabs', 'events', 'onUpdated'))
313
314    # Test things that aren't available.
315    self.assertEqual(LookupResult(False, None),
316                     availability_graph.Lookup('tabs', 'types',
317                                               'UpdateInfo'))
318    self.assertEqual(LookupResult(False, None),
319                     availability_graph.Lookup('tabs', 'functions', 'get',
320                                               'parameters', 'callback',
321                                               'parameters', 'tab', 'id'))
322    self.assertEqual(LookupResult(False, None),
323                     availability_graph.Lookup('functions'))
324    self.assertEqual(LookupResult(False, None),
325                     availability_graph.Lookup('events', 'onActivated',
326                                               'parameters', 'activeInfo',
327                                               'tabId'))
328
329
330if __name__ == '__main__':
331  unittest.main()
332