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