availability_finder_test.py revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 8 9import api_schema_graph 10from availability_finder import AvailabilityFinder, AvailabilityInfo 11from branch_utility import BranchUtility, ChannelInfo 12from compiled_file_system import CompiledFileSystem 13from fake_host_file_system_provider import FakeHostFileSystemProvider 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 platform_util import GetPlatforms 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 test_util import Server2Path 22 23 24TABS_UNMODIFIED_VERSIONS = (16, 20, 23, 24) 25 26class AvailabilityFinderTest(unittest.TestCase): 27 28 def _create_availability_finder(self, 29 host_fs_creator, 30 host_fs_iterator, 31 platform): 32 test_object_store = ObjectStoreCreator.ForTest() 33 return AvailabilityFinder( 34 self._branch_utility, 35 CompiledFileSystem.Factory(test_object_store), 36 host_fs_iterator, 37 host_fs_creator.GetTrunk(), 38 test_object_store, 39 platform) 40 41 def setUp(self): 42 self._branch_utility = BranchUtility( 43 os.path.join('branch_utility', 'first.json'), 44 os.path.join('branch_utility', 'second.json'), 45 FakeUrlFetcher(Server2Path('test_data')), 46 ObjectStoreCreator.ForTest()) 47 self._api_fs_creator = FakeHostFileSystemProvider( 48 CANNED_API_FILE_SYSTEM_DATA) 49 self._node_fs_creator = FakeHostFileSystemProvider(TABS_SCHEMA_BRANCHES) 50 self._api_fs_iterator = HostFileSystemIterator(self._api_fs_creator, 51 self._branch_utility) 52 self._node_fs_iterator = HostFileSystemIterator(self._node_fs_creator, 53 self._branch_utility) 54 55 # Imitate the actual SVN file system by incrementing the stats for paths 56 # where an API schema has changed. 57 last_stat = type('last_stat', (object,), {'val': 0}) 58 59 def stat_paths(file_system, channel_info): 60 if channel_info.version not in TABS_UNMODIFIED_VERSIONS: 61 last_stat.val += 1 62 # HACK: |file_system| is a MockFileSystem backed by a TestFileSystem. 63 # Increment the TestFileSystem stat count. 64 file_system._file_system.IncrementStat(by=last_stat.val) 65 # Continue looping. The iterator will stop after 'trunk' automatically. 66 return True 67 68 # Use the HostFileSystemIterator created above to change global stat values 69 # for the TestFileSystems that it creates. 70 self._node_fs_iterator.Ascending( 71 # The earliest version represented with the tabs' test data is 13. 72 self._branch_utility.GetStableChannelInfo(13), 73 stat_paths) 74 75 def testGraphOptimization(self): 76 for platform in GetPlatforms(): 77 # Keep track of how many times the APISchemaGraph constructor is called. 78 original_constructor = api_schema_graph.APISchemaGraph 79 mock_constructor = MockFunction(original_constructor) 80 api_schema_graph.APISchemaGraph = mock_constructor 81 82 node_avail_finder = self._create_availability_finder( 83 self._node_fs_creator, self._node_fs_iterator, platform) 84 try: 85 # The test data includes an extra branch where the API does not exist. 86 num_versions = len(TABS_SCHEMA_BRANCHES) - 1 87 # We expect an APISchemaGraph to be created only when an API schema file 88 # has different stat data from the previous version's schema file. 89 num_graphs_created = num_versions - len(TABS_UNMODIFIED_VERSIONS) 90 91 # Run the logic for object-level availability for an API. 92 node_avail_finder.GetAPINodeAvailability('tabs') 93 94 self.assertTrue(*api_schema_graph.APISchemaGraph.CheckAndReset( 95 num_graphs_created)) 96 finally: 97 # Ensure that the APISchemaGraph constructor is reset to be the original 98 # constructor. 99 api_schema_graph.APISchemaGraph = original_constructor 100 101 def testGetAPIAvailability(self): 102 # Key: Using 'channel' (i.e. 'beta') to represent an availability listing 103 # for an API in a _features.json file, and using |channel| (i.e. |dev|) to 104 # represent the development channel, or phase of development, where an API's 105 # availability is being checked. 106 107 def assertGet(ch_info, api, only_on=None, scheduled=None): 108 for platform in GetPlatforms(): 109 get_availability = self._create_availability_finder( 110 self._api_fs_creator, 111 self._api_fs_iterator, 112 platform if only_on is None else only_on).GetAPIAvailability 113 self.assertEqual(AvailabilityInfo(ch_info, scheduled=scheduled), 114 get_availability(api)) 115 116 # Testing APIs with predetermined availability. 117 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'jsonTrunkAPI') 118 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'jsonDevAPI') 119 assertGet(ChannelInfo('beta', CANNED_BRANCHES[30], 30), 'jsonBetaAPI') 120 assertGet(ChannelInfo('stable', CANNED_BRANCHES[20], 20), 'jsonStableAPI') 121 122 # Testing a whitelisted API. 123 assertGet(ChannelInfo('beta', CANNED_BRANCHES[30], 30), 124 'declarativeWebRequest') 125 126 # Testing APIs found only by checking file system existence. 127 assertGet(ChannelInfo('stable', CANNED_BRANCHES[23], 23), 'windows') 128 assertGet(ChannelInfo('stable', CANNED_BRANCHES[18], 18), 'tabs') 129 assertGet(ChannelInfo('stable', CANNED_BRANCHES[18], 18), 'input.ime') 130 131 # Testing API channel existence for _api_features.json. 132 # Listed as 'dev' on |beta|, 'dev' on |dev|. 133 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'systemInfo.stuff') 134 # Listed as 'stable' on |beta|. 135 assertGet(ChannelInfo('beta', CANNED_BRANCHES[30], 30), 136 'systemInfo.cpu', 137 scheduled=31) 138 139 # Testing API channel existence for _manifest_features.json. 140 # Listed as 'trunk' on all channels. 141 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'sync') 142 # No records of API until |trunk|. 143 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'history') 144 # Listed as 'dev' on |dev|. 145 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'storage') 146 # Stable in _manifest_features and into pre-18 versions. 147 assertGet(ChannelInfo('stable', CANNED_BRANCHES[8], 8), 'pageAction') 148 149 # Testing API channel existence for _permission_features.json. 150 # Listed as 'beta' on |trunk|. 151 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'falseBetaAPI') 152 # Listed as 'trunk' on |trunk|. 153 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'trunkAPI') 154 # Listed as 'trunk' on all development channels. 155 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'declarativeContent') 156 # Listed as 'dev' on all development channels. 157 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'bluetooth') 158 # Listed as 'dev' on |dev|. 159 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'cookies') 160 # Treated as 'stable' APIs. 161 assertGet(ChannelInfo('stable', CANNED_BRANCHES[24], 24), 'alarms') 162 assertGet(ChannelInfo('stable', CANNED_BRANCHES[21], 21), 'bookmarks') 163 164 # Testing older API existence using extension_api.json. 165 assertGet(ChannelInfo('stable', CANNED_BRANCHES[6], 6), 'menus') 166 assertGet(ChannelInfo('stable', CANNED_BRANCHES[5], 5), 'idle') 167 168 # Switches between _features.json files across branches. 169 # Listed as 'trunk' on all channels, in _api, _permission, or _manifest. 170 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'contextMenus') 171 # Moves between _permission and _manifest as file system is traversed. 172 assertGet(ChannelInfo('stable', CANNED_BRANCHES[23], 23), 173 'systemInfo.display') 174 assertGet(ChannelInfo('stable', CANNED_BRANCHES[17], 17), 'webRequest') 175 176 # Mid-upgrade cases: 177 # Listed as 'dev' on |beta| and 'beta' on |dev|. 178 assertGet(ChannelInfo('dev', CANNED_BRANCHES[31], 31), 'notifications') 179 # Listed as 'beta' on |stable|, 'dev' on |beta|...until |stable| on trunk. 180 assertGet(ChannelInfo('trunk', 'trunk', 'trunk'), 'events') 181 182 # Check for differing availability across apps|extensions 183 assertGet(ChannelInfo('stable', CANNED_BRANCHES[26], 26), 184 'appsFirst', 185 only_on='extensions') 186 assertGet(ChannelInfo('stable', CANNED_BRANCHES[25], 25), 187 'appsFirst', 188 only_on='apps') 189 190 def testGetAPINodeAvailability(self): 191 def assertEquals(found, channel_info, actual, scheduled=None): 192 lookup_result = api_schema_graph.LookupResult 193 if channel_info is None: 194 self.assertEquals(lookup_result(found, None), actual) 195 else: 196 self.assertEquals(lookup_result(found, AvailabilityInfo(channel_info, 197 scheduled=scheduled)), actual) 198 199 for platform in GetPlatforms(): 200 # Allow the LookupResult constructions below to take just one line. 201 avail_finder = self._create_availability_finder( 202 self._node_fs_creator, 203 self._node_fs_iterator, 204 platform) 205 tabs_graph = avail_finder.GetAPINodeAvailability('tabs') 206 fake_tabs_graph = avail_finder.GetAPINodeAvailability('fakeTabs') 207 208 assertEquals(True, self._branch_utility.GetChannelInfo('trunk'), 209 tabs_graph.Lookup('tabs', 'properties', 'fakeTabsProperty3')) 210 assertEquals(True, self._branch_utility.GetChannelInfo('dev'), 211 tabs_graph.Lookup('tabs', 'events', 'onActivated', 'parameters', 212 'activeInfo', 'properties', 'windowId'), scheduled=31) 213 assertEquals(True, self._branch_utility.GetChannelInfo('dev'), 214 tabs_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters', 'tab'), 215 scheduled=31) 216 assertEquals(True, self._branch_utility.GetChannelInfo('beta'), 217 tabs_graph.Lookup('tabs', 'events', 'onActivated'), scheduled=30) 218 assertEquals(True, self._branch_utility.GetChannelInfo('beta'), 219 tabs_graph.Lookup('tabs', 'functions', 'get', 'parameters', 'tabId'), 220 scheduled=30) 221 assertEquals(True, self._branch_utility.GetChannelInfo('stable'), 222 tabs_graph.Lookup('tabs', 'types', 'InjectDetails', 'properties', 223 'code')) 224 assertEquals(True, self._branch_utility.GetChannelInfo('stable'), 225 tabs_graph.Lookup('tabs', 'types', 'InjectDetails', 'properties', 226 'file')) 227 assertEquals(True, self._branch_utility.GetStableChannelInfo(25), 228 tabs_graph.Lookup('tabs', 'types', 'InjectDetails')) 229 230 # Test inlined type. 231 assertEquals(True, self._branch_utility.GetChannelInfo('trunk'), 232 tabs_graph.Lookup('tabs', 'types', 'InlinedType')) 233 234 # Test implicitly inlined type. 235 assertEquals(True, self._branch_utility.GetStableChannelInfo(25), 236 fake_tabs_graph.Lookup('fakeTabs', 'types', 237 'WasImplicitlyInlinedType')) 238 239 # Test a node that was restricted to dev channel when it was introduced. 240 assertEquals(True, self._branch_utility.GetChannelInfo('beta'), 241 tabs_graph.Lookup('tabs', 'functions', 'restrictedFunc'), 242 scheduled=30) 243 244 # Test an explicitly scheduled node. 245 assertEquals(True, self._branch_utility.GetChannelInfo('dev'), 246 tabs_graph.Lookup('tabs', 'functions', 'scheduledFunc'), 247 scheduled=31) 248 249 # Nothing new in version 24 or 23. 250 251 assertEquals(True, self._branch_utility.GetStableChannelInfo(22), 252 tabs_graph.Lookup('tabs', 'types', 'Tab', 'properties', 'windowId')) 253 assertEquals(True, self._branch_utility.GetStableChannelInfo(21), 254 tabs_graph.Lookup('tabs', 'types', 'Tab', 'properties', 'selected')) 255 256 # Nothing new in version 20. 257 258 assertEquals(True, self._branch_utility.GetStableChannelInfo(19), 259 tabs_graph.Lookup('tabs', 'functions', 'getCurrent')) 260 assertEquals(True, self._branch_utility.GetStableChannelInfo(18), 261 tabs_graph.Lookup('tabs', 'types', 'Tab', 'properties', 'index')) 262 assertEquals(True, self._branch_utility.GetStableChannelInfo(17), 263 tabs_graph.Lookup('tabs', 'events', 'onUpdated', 'parameters', 264 'changeInfo')) 265 266 # Nothing new in version 16. 267 268 assertEquals(True, self._branch_utility.GetStableChannelInfo(15), 269 tabs_graph.Lookup('tabs', 'properties', 'fakeTabsProperty2')) 270 271 # Everything else is available at the API's release, version 14 here. 272 assertEquals(True, self._branch_utility.GetStableChannelInfo(14), 273 tabs_graph.Lookup('tabs', 'types', 'Tab')) 274 assertEquals(True, self._branch_utility.GetStableChannelInfo(14), 275 tabs_graph.Lookup('tabs', 'types', 'Tab', 'properties', 'url')) 276 assertEquals(True, self._branch_utility.GetStableChannelInfo(14), 277 tabs_graph.Lookup('tabs', 'properties', 'fakeTabsProperty1')) 278 assertEquals(True, self._branch_utility.GetStableChannelInfo(14), 279 tabs_graph.Lookup('tabs', 'functions', 'get', 'parameters', 280 'callback')) 281 assertEquals(True, self._branch_utility.GetStableChannelInfo(14), 282 tabs_graph.Lookup('tabs', 'events', 'onUpdated')) 283 284 # Test things that aren't available. 285 assertEquals(False, None, tabs_graph.Lookup('tabs', 'types', 286 'UpdateInfo')) 287 assertEquals(False, None, tabs_graph.Lookup('tabs', 'functions', 'get', 288 'parameters', 'callback', 'parameters', 'tab', 'id')) 289 assertEquals(False, None, tabs_graph.Lookup('functions')) 290 assertEquals(False, None, tabs_graph.Lookup('events', 'onActivated', 291 'parameters', 'activeInfo', 'tabId')) 292 293 294if __name__ == '__main__': 295 unittest.main() 296