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