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