Ejemplo n.º 1
0
 def _CheckChannelAvailabilityForNode(self,
                                      node_name,
                                      file_system,
                                      channel_info,
                                      earliest_channel_info):
   '''Searches through the _features files in a given |file_system| to
   determine whether or not an API node is available on the given channel,
   |channel_info|. |earliest_channel_info| is the earliest channel the node
   was introduced.
   '''
   features_bundle = self._CreateFeaturesBundle(file_system)
   available_channel = None
   # Only API nodes can have their availability overriden on a per-node basis,
   # so we only need to check _api_features.json.
   if channel_info.version >= _API_FEATURES_MIN_VERSION:
     available_channel = _GetChannelFromAPIFeatures(node_name, features_bundle)
   if (available_channel is None and
       channel_info.version >= earliest_channel_info.version):
     # Most API nodes inherit their availabiltity from their parent, so don't
     # explicitly appear in _api_features.json. For example, "tabs.create"
     # isn't listed; it inherits from "tabs". Assume these are available at
     # |channel_info|.
     available_channel = channel_info.channel
   newest = BranchUtility.NewestChannel((available_channel,
                                         channel_info.channel))
   return available_channel is not None and newest == channel_info.channel
def _GetChannelFromFeatures(api_name, json_fs, filename):
  '''Finds API channel information from the features |filename| within the the
  given |json_fs|. Returns None if channel information for the API cannot be
  located.
  '''
  feature = json_fs.GetFromFile('%s/%s' % (API, filename)).Get().get(api_name)
  if feature is None:
    return None
  if isinstance(feature, Mapping):
    # The channel information exists as a solitary dict.
    return feature.get('channel')
  # The channel information dict is nested within a list for whitelisting
  # purposes. Take the newest channel out of all of the entries.
  return BranchUtility.NewestChannel(entry.get('channel') for entry in feature)
Ejemplo n.º 3
0
def _GetChannelFromFeatures(api_name, file_system, path):
  '''Finds API channel information within _features.json files at the given
  |path| for the given |file_system|. Returns None if channel information for
  the API cannot be located.
  '''
  feature = file_system.GetFromFile(path).get(api_name)

  if feature is None:
    return None
  if isinstance(feature, collections.Mapping):
    # The channel information exists as a solitary dict.
    return feature.get('channel')
  # The channel information dict is nested within a list for whitelisting
  # purposes. Take the newest channel out of all of the entries.
  return BranchUtility.NewestChannel(entry.get('channel') for entry in feature)
Ejemplo n.º 4
0
  def GetApiAvailability(self, api_name):
    '''Determines the availability for an API by testing several scenarios.
    (i.e. Is the API experimental? Only available on certain development
    channels? If it's stable, when did it first become stable? etc.)
    '''
    availability = self._object_store.Get(api_name).Get()
    if availability is not None:
      return availability

    # Check for a predetermined availability for this API.
    api_info = self._json_cache.GetFromFile(_API_AVAILABILITIES).get(api_name)
    if api_info is not None:
      channel = api_info.get('channel')
      if channel == _STABLE:
        version = api_info.get('version')
      else:
        version = self._branch_utility.GetChannelInfo(channel).version
      # The file data for predetermined availabilities is already cached, so
      # skip caching this result.
      return AvailabilityInfo(channel, version)

    # Check for the API in the development channels.
    availability = None
    for channel_info in self._branch_utility.GetAllChannelInfo():
      available_channel = self._GetAvailableChannelForVersion(
          api_name,
          channel_info.version)
      # If the |available_channel| for the API is the same as, or older than,
      # the channel we're checking, then the API is available on this channel.
      if (available_channel is not None and
          BranchUtility.NewestChannel((available_channel, channel_info.channel))
              == channel_info.channel):
        availability = AvailabilityInfo(channel_info.channel,
                                        channel_info.version)
        break

    # The API should at least be available on trunk. It's a bug otherwise.
    assert availability, 'No availability found for %s' % api_name

    # If the API is in stable, find the chrome version in which it became
    # stable.
    if availability.channel == _STABLE:
      availability.version = self._FindEarliestStableAvailability(
          api_name,
          availability.version)

    self._object_store.Set(api_name, availability)
    return availability
Ejemplo n.º 5
0
 def _CheckChannelAvailability(self, api_name, file_system, channel_name):
     '''Searches through the _features files in a given |file_system|, falling
 back to checking the file system for API schema existence, to determine
 whether or not an API is available on the given channel, |channel_name|.
 '''
     json_fs = self._compiled_fs_factory.ForJson(file_system)
     schema_fs = self._compiled_fs_factory.ForApiSchema(file_system)
     available_channel = (
         _GetChannelFromApiFeatures(api_name, json_fs)
         or _GetChannelFromPermissionFeatures(api_name, json_fs)
         or _GetChannelFromManifestFeatures(api_name, json_fs))
     if available_channel is None and _HasApiSchema(api_name, schema_fs):
         # If an API is not represented in any of the _features files, but exists
         # in the filesystem, then assume it is available in this version.
         # The windows API is an example of this.
         available_channel = channel_name
     # If the channel we're checking is the same as or newer than the
     # |available_channel| then the API is available at this channel.
     return (available_channel is not None and BranchUtility.NewestChannel(
         (available_channel, channel_name)) == channel_name)
Ejemplo n.º 6
0
 def _CheckChannelAvailability(self, api_name, file_system, channel_info):
     '''Searches through the _features files in a given |file_system|, falling
 back to checking the file system for API schema existence, to determine
 whether or not an API is available on the given channel, |channel_info|.
 '''
     features_bundle = self._CreateFeaturesBundle(file_system)
     available_channel = (
         _GetChannelFromAPIFeatures(api_name, features_bundle)
         or _GetChannelFromPermissionFeatures(api_name, features_bundle)
         or _GetChannelFromManifestFeatures(api_name, features_bundle))
     if (available_channel is None and self._HasAPISchema(
             api_name, file_system, channel_info.version)):
         # If an API is not represented in any of the _features files, but exists
         # in the filesystem, then assume it is available in this version.
         # The chrome.windows API is an example of this.
         available_channel = channel_info.channel
     # If the channel we're checking is the same as or newer than the
     # |available_channel| then the API is available at this channel.
     newest = BranchUtility.NewestChannel(
         (available_channel, channel_info.channel))
     return available_channel is not None and newest == channel_info.channel
Ejemplo n.º 7
0
class BranchUtilityTest(unittest.TestCase):
    def setUp(self):
        self._branch_util = BranchUtility(
            os.path.join('branch_utility', 'first.json'),
            os.path.join('branch_utility', 'second.json'),
            FakeUrlFetcher(Server2Path('test_data')),
            ObjectStoreCreator.ForTest())

    def testSplitChannelNameFromPath(self):
        self.assertEquals(('stable', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'stable/extensions/stuff.html'))
        self.assertEquals(('dev', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'dev/extensions/stuff.html'))
        self.assertEquals(('beta', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'beta/extensions/stuff.html'))
        self.assertEquals(('master', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'master/extensions/stuff.html'))
        self.assertEquals((None, 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/stuff.html'))
        self.assertEquals(
            (None, 'apps/stuff.html'),
            self._branch_util.SplitChannelNameFromPath('apps/stuff.html'))
        self.assertEquals((None, 'extensions/dev/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/dev/stuff.html'))
        self.assertEquals(
            (None, 'stuff.html'),
            self._branch_util.SplitChannelNameFromPath('stuff.html'))

    def testNewestChannel(self):
        self.assertEquals(
            'master',
            self._branch_util.NewestChannel(
                ('master', 'dev', 'beta', 'stable')))
        self.assertEquals(
            'master',
            self._branch_util.NewestChannel(
                ('stable', 'beta', 'dev', 'master')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('stable', 'beta', 'dev')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('dev', 'beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('stable', 'beta')))
        self.assertEquals('stable',
                          self._branch_util.NewestChannel(('stable', )))
        self.assertEquals('beta', self._branch_util.NewestChannel(('beta', )))
        self.assertEquals('dev', self._branch_util.NewestChannel(('dev', )))
        self.assertEquals('master',
                          self._branch_util.NewestChannel(('master', )))

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testNewer(self):
        oldest_stable_info = ChannelInfo('stable', '963', 17)
        older_stable_info = ChannelInfo('stable', '1025', 18)
        old_stable_info = ChannelInfo('stable', '1084', 19)
        sort_of_old_stable_info = ChannelInfo('stable', '1500', 28)
        stable_info = ChannelInfo('stable', '1547', 29)
        beta_info = ChannelInfo('beta', '1599', 30)
        dev_info = ChannelInfo('dev', '1612', 31)
        master_info = ChannelInfo('master', 'master', 'master')

        self.assertEquals(older_stable_info,
                          self._branch_util.Newer(oldest_stable_info))
        self.assertEquals(old_stable_info,
                          self._branch_util.Newer(older_stable_info))
        self.assertEquals(stable_info,
                          self._branch_util.Newer(sort_of_old_stable_info))
        self.assertEquals(beta_info, self._branch_util.Newer(stable_info))
        self.assertEquals(dev_info, self._branch_util.Newer(beta_info))
        self.assertEquals(master_info, self._branch_util.Newer(dev_info))
        # Test the upper limit.
        self.assertEquals(None, self._branch_util.Newer(master_info))

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testOlder(self):
        master_info = ChannelInfo('master', 'master', 'master')
        dev_info = ChannelInfo('dev', '1612', 31)
        beta_info = ChannelInfo('beta', '1599', 30)
        stable_info = ChannelInfo('stable', '1547', 29)
        old_stable_info = ChannelInfo('stable', '1500', 28)
        older_stable_info = ChannelInfo('stable', '1453', 27)
        oldest_stable_info = ChannelInfo('stable', '396', 5)

        self.assertEquals(dev_info, self._branch_util.Older(master_info))
        self.assertEquals(beta_info, self._branch_util.Older(dev_info))
        self.assertEquals(stable_info, self._branch_util.Older(beta_info))
        self.assertEquals(old_stable_info,
                          self._branch_util.Older(stable_info))
        self.assertEquals(older_stable_info,
                          self._branch_util.Older(old_stable_info))
        # Test the lower limit.
        self.assertEquals(None, self._branch_util.Older(oldest_stable_info))

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testGetChannelInfo(self):
        master_info = ChannelInfo('master', 'master', 'master')
        self.assertEquals(master_info,
                          self._branch_util.GetChannelInfo('master'))

        dev_info = ChannelInfo('dev', '1612', 31)
        self.assertEquals(dev_info, self._branch_util.GetChannelInfo('dev'))

        beta_info = ChannelInfo('beta', '1599', 30)
        self.assertEquals(beta_info, self._branch_util.GetChannelInfo('beta'))

        stable_info = ChannelInfo('stable', '1547', 29)
        self.assertEquals(stable_info,
                          self._branch_util.GetChannelInfo('stable'))

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testGetLatestVersionNumber(self):
        self.assertEquals(37, self._branch_util.GetLatestVersionNumber())

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testGetBranchForVersion(self):
        self.assertEquals('1500', self._branch_util.GetBranchForVersion(28))
        self.assertEquals('1453', self._branch_util.GetBranchForVersion(27))
        self.assertEquals('1410', self._branch_util.GetBranchForVersion(26))
        self.assertEquals('1364', self._branch_util.GetBranchForVersion(25))
        self.assertEquals('1312', self._branch_util.GetBranchForVersion(24))
        self.assertEquals('1271', self._branch_util.GetBranchForVersion(23))
        self.assertEquals('1229', self._branch_util.GetBranchForVersion(22))
        self.assertEquals('1180', self._branch_util.GetBranchForVersion(21))
        self.assertEquals('1132', self._branch_util.GetBranchForVersion(20))
        self.assertEquals('1084', self._branch_util.GetBranchForVersion(19))
        self.assertEquals('1025', self._branch_util.GetBranchForVersion(18))
        self.assertEquals('963', self._branch_util.GetBranchForVersion(17))
        self.assertEquals('696', self._branch_util.GetBranchForVersion(11))
        self.assertEquals('396', self._branch_util.GetBranchForVersion(5))

    @unittest.skipIf(os.name == 'nt', "crbug.com/1114884")
    def testGetChannelForVersion(self):
        self.assertEquals('master',
                          self._branch_util.GetChannelForVersion('master'))
        self.assertEquals('dev', self._branch_util.GetChannelForVersion(31))
        self.assertEquals('beta', self._branch_util.GetChannelForVersion(30))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(26))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(22))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(18))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(14))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(32))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(42))
Ejemplo n.º 8
0
class BranchUtilityTest(unittest.TestCase):
    def setUp(self):
        self._branch_util = BranchUtility(
            os.path.join('branch_utility', 'first.json'),
            os.path.join('branch_utility', 'second.json'),
            FakeUrlFetcher(os.path.join(sys.path[0], 'test_data')),
            ObjectStoreCreator.ForTest())

    def testSplitChannelNameFromPath(self):
        self.assertEquals(('stable', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'stable/extensions/stuff.html'))
        self.assertEquals(('dev', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'dev/extensions/stuff.html'))
        self.assertEquals(('beta', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'beta/extensions/stuff.html'))
        self.assertEquals(('trunk', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'trunk/extensions/stuff.html'))
        self.assertEquals((None, 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/stuff.html'))
        self.assertEquals(
            (None, 'apps/stuff.html'),
            self._branch_util.SplitChannelNameFromPath('apps/stuff.html'))
        self.assertEquals((None, 'extensions/dev/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/dev/stuff.html'))
        self.assertEquals(
            (None, 'stuff.html'),
            self._branch_util.SplitChannelNameFromPath('stuff.html'))

    def testNewestChannel(self):
        self.assertEquals(
            'trunk',
            self._branch_util.NewestChannel(
                ('trunk', 'dev', 'beta', 'stable')))
        self.assertEquals(
            'trunk',
            self._branch_util.NewestChannel(
                ('stable', 'beta', 'dev', 'trunk')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('stable', 'beta', 'dev')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('dev', 'beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('stable', 'beta')))
        self.assertEquals('stable',
                          self._branch_util.NewestChannel(('stable', )))
        self.assertEquals('beta', self._branch_util.NewestChannel(('beta', )))
        self.assertEquals('dev', self._branch_util.NewestChannel(('dev', )))
        self.assertEquals('trunk', self._branch_util.NewestChannel(
            ('trunk', )))

    def testGetChannelInfo(self):
        self.assertEquals('trunk',
                          self._branch_util.GetChannelInfo('trunk').channel)
        self.assertEquals('trunk',
                          self._branch_util.GetChannelInfo('trunk').branch)
        self.assertEquals('trunk',
                          self._branch_util.GetChannelInfo('trunk').version)
        self.assertEquals('dev',
                          self._branch_util.GetChannelInfo('dev').channel)
        self.assertEquals(1500, self._branch_util.GetChannelInfo('dev').branch)
        self.assertEquals(28, self._branch_util.GetChannelInfo('dev').version)
        self.assertEquals('beta',
                          self._branch_util.GetChannelInfo('beta').channel)
        self.assertEquals(1453,
                          self._branch_util.GetChannelInfo('beta').branch)
        self.assertEquals(27, self._branch_util.GetChannelInfo('beta').version)
        self.assertEquals('stable',
                          self._branch_util.GetChannelInfo('stable').channel)
        self.assertEquals(1410,
                          self._branch_util.GetChannelInfo('stable').branch)
        self.assertEquals(26,
                          self._branch_util.GetChannelInfo('stable').version)

    def testGetLatestVersionNumber(self):
        self.assertEquals(28, self._branch_util.GetLatestVersionNumber())

    def testGetBranchForVersion(self):
        self.assertEquals(1453, self._branch_util.GetBranchForVersion(27))
        self.assertEquals(1410, self._branch_util.GetBranchForVersion(26))
        self.assertEquals(1364, self._branch_util.GetBranchForVersion(25))
        self.assertEquals(1312, self._branch_util.GetBranchForVersion(24))
        self.assertEquals(1271, self._branch_util.GetBranchForVersion(23))
        self.assertEquals(1229, self._branch_util.GetBranchForVersion(22))
        self.assertEquals(1180, self._branch_util.GetBranchForVersion(21))
        self.assertEquals(1132, self._branch_util.GetBranchForVersion(20))
        self.assertEquals(1084, self._branch_util.GetBranchForVersion(19))
        self.assertEquals(1025, self._branch_util.GetBranchForVersion(18))
        self.assertEquals(963, self._branch_util.GetBranchForVersion(17))
        self.assertEquals(696, self._branch_util.GetBranchForVersion(11))
        self.assertEquals(396, self._branch_util.GetBranchForVersion(5))

    def testGetChannelForVersion(self):
        self.assertEquals('trunk',
                          self._branch_util.GetChannelForVersion('trunk'))
        self.assertEquals('dev', self._branch_util.GetChannelForVersion(28))
        self.assertEquals('beta', self._branch_util.GetChannelForVersion(27))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(26))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(22))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(18))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(14))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(30))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(42))
Ejemplo n.º 9
0
def _ResolveFeature(feature_name, feature_values, extra_feature_values,
                    platform, features_type, features_map):
    '''Filters and combines the possible values for a feature into one dict.

  It uses |features_map| to resolve dependencies for each value and inherit
  unspecified platform and channel data. |feature_values| is then filtered
  by platform and all values with the most stable platform are merged into one
  dict. All values in |extra_feature_values| get merged into this dict.

  Returns |resolve_successful| and |feature|. |resolve_successful| is False
  if the feature's dependencies have not been merged yet themselves, meaning
  that this feature can not be reliably resolved yet. |feature| is the
  resulting feature dict, or None if the feature does not exist on the
  platform specified.
  '''
    feature = None
    most_stable_channel = None
    for value in feature_values:
        # If 'extension_types' or 'channel' is unspecified, these values should
        # be inherited from dependencies. If they are specified, these values
        # should override anything specified by dependencies.
        inherit_valid_platform = 'extension_types' not in value
        if inherit_valid_platform:
            valid_platform = None
        else:
            valid_platform = (value['extension_types'] == 'all'
                              or platform in value['extension_types'])
        inherit_channel = 'channel' not in value
        channel = value.get('channel')

        dependencies = value.get('dependencies', [])
        parent = GetParentName(feature_name, value,
                               features_map[features_type]['all_names'])
        if parent is not None:
            # The parent data needs to be resolved so the child can inherit it.
            if parent in features_map[features_type].get('unresolved', ()):
                return False, None
            value = _CopyParentFeatureValues(
                value, features_map[features_type]['resolved'].get(parent))
            # Add the parent as a dependency to ensure proper platform filtering.
            dependencies.append(features_type + ':' + parent)

        for dependency in dependencies:
            dep_type, dep_name = dependency.split(':')
            if (dep_type not in features_map
                    or dep_name in features_map[dep_type].get(
                        'unresolved', ())):
                # The dependency itself has not been merged yet or the features map
                # does not have the needed data. Fail to resolve.
                return False, None

            dep = features_map[dep_type]['resolved'].get(dep_name)
            if inherit_valid_platform and (valid_platform is None
                                           or valid_platform):
                # If dep is None, the dependency does not exist because it has been
                # filtered out by platform. This feature value does not explicitly
                # specify platform data, so filter this feature value out.
                # Only run this check if valid_platform is True or None so that it
                # can't be reset once it is False.
                valid_platform = dep is not None
            if inherit_channel and dep and 'channel' in dep:
                if channel is None or BranchUtility.NewestChannel(
                    (dep['channel'], channel)) != channel:
                    # Inherit the least stable channel from the dependencies.
                    channel = dep['channel']

        # Default to stable on all platforms.
        if valid_platform is None:
            valid_platform = True
        if valid_platform and channel is None:
            channel = 'stable'

        if valid_platform:
            # The feature value is valid. Merge it into the feature dict.
            if feature is None or BranchUtility.NewestChannel(
                (most_stable_channel, channel)) != channel:
                # If this is the first feature value to be merged, copy the dict.
                # If this feature value has a more stable channel than the most stable
                # channel so far, replace the old dict so that it only merges values
                # from the most stable channel.
                feature = copy(value)
                most_stable_channel = channel
            elif channel == most_stable_channel:
                feature.update(value)

    if feature is None:
        # Nothing was left after filtering the values, but all dependency resolves
        # were successful. This feature does not exist on |platform|.
        return True, None

    # Merge in any extra values.
    for value in extra_feature_values:
        feature.update(value)

    # Cleanup, fill in missing fields.
    if 'name' not in feature:
        feature['name'] = feature_name
    feature['channel'] = most_stable_channel
    return True, feature
Ejemplo n.º 10
0
class BranchUtilityTest(unittest.TestCase):
    def setUp(self):
        self._branch_util = BranchUtility(
            os.path.join('branch_utility', 'first.json'),
            os.path.join('branch_utility', 'second.json'),
            FakeUrlFetcher(os.path.join(sys.path[0], 'test_data')),
            ObjectStoreCreator.ForTest())

    def testSplitChannelNameFromPath(self):
        self.assertEquals(('stable', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'stable/extensions/stuff.html'))
        self.assertEquals(('dev', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'dev/extensions/stuff.html'))
        self.assertEquals(('beta', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'beta/extensions/stuff.html'))
        self.assertEquals(('trunk', 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'trunk/extensions/stuff.html'))
        self.assertEquals((None, 'extensions/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/stuff.html'))
        self.assertEquals(
            (None, 'apps/stuff.html'),
            self._branch_util.SplitChannelNameFromPath('apps/stuff.html'))
        self.assertEquals((None, 'extensions/dev/stuff.html'),
                          self._branch_util.SplitChannelNameFromPath(
                              'extensions/dev/stuff.html'))
        self.assertEquals(
            (None, 'stuff.html'),
            self._branch_util.SplitChannelNameFromPath('stuff.html'))

    def testNewestChannel(self):
        self.assertEquals(
            'trunk',
            self._branch_util.NewestChannel(
                ('trunk', 'dev', 'beta', 'stable')))
        self.assertEquals(
            'trunk',
            self._branch_util.NewestChannel(
                ('stable', 'beta', 'dev', 'trunk')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('stable', 'beta', 'dev')))
        self.assertEquals(
            'dev', self._branch_util.NewestChannel(('dev', 'beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('beta', 'stable')))
        self.assertEquals('beta',
                          self._branch_util.NewestChannel(('stable', 'beta')))
        self.assertEquals('stable',
                          self._branch_util.NewestChannel(('stable', )))
        self.assertEquals('beta', self._branch_util.NewestChannel(('beta', )))
        self.assertEquals('dev', self._branch_util.NewestChannel(('dev', )))
        self.assertEquals('trunk', self._branch_util.NewestChannel(
            ('trunk', )))

    def testNewer(self):
        oldest_stable_info = ChannelInfo('stable', '963', 17)
        older_stable_info = ChannelInfo('stable', '1025', 18)
        old_stable_info = ChannelInfo('stable', '1084', 19)
        sort_of_old_stable_info = ChannelInfo('stable', '1364', 25)
        stable_info = ChannelInfo('stable', '1410', 26)
        beta_info = ChannelInfo('beta', '1453', 27)
        dev_info = ChannelInfo('dev', '1500', 28)
        trunk_info = ChannelInfo('trunk', 'trunk', 'trunk')

        self.assertEquals(older_stable_info,
                          self._branch_util.Newer(oldest_stable_info))
        self.assertEquals(old_stable_info,
                          self._branch_util.Newer(older_stable_info))
        self.assertEquals(stable_info,
                          self._branch_util.Newer(sort_of_old_stable_info))
        self.assertEquals(beta_info, self._branch_util.Newer(stable_info))
        self.assertEquals(dev_info, self._branch_util.Newer(beta_info))
        self.assertEquals(trunk_info, self._branch_util.Newer(dev_info))
        # Test the upper limit.
        self.assertEquals(None, self._branch_util.Newer(trunk_info))

    def testOlder(self):
        trunk_info = ChannelInfo('trunk', 'trunk', 'trunk')
        dev_info = ChannelInfo('dev', '1500', 28)
        beta_info = ChannelInfo('beta', '1453', 27)
        stable_info = ChannelInfo('stable', '1410', 26)
        old_stable_info = ChannelInfo('stable', '1364', 25)
        older_stable_info = ChannelInfo('stable', '1312', 24)
        oldest_stable_info = ChannelInfo('stable', '396', 5)

        self.assertEquals(dev_info, self._branch_util.Older(trunk_info))
        self.assertEquals(beta_info, self._branch_util.Older(dev_info))
        self.assertEquals(stable_info, self._branch_util.Older(beta_info))
        self.assertEquals(old_stable_info,
                          self._branch_util.Older(stable_info))
        self.assertEquals(older_stable_info,
                          self._branch_util.Older(old_stable_info))
        # Test the lower limit.
        self.assertEquals(None, self._branch_util.Older(oldest_stable_info))

    def testGetChannelInfo(self):
        trunk_info = ChannelInfo('trunk', 'trunk', 'trunk')
        self.assertEquals(trunk_info,
                          self._branch_util.GetChannelInfo('trunk'))

        dev_info = ChannelInfo('dev', '1500', 28)
        self.assertEquals(dev_info, self._branch_util.GetChannelInfo('dev'))

        beta_info = ChannelInfo('beta', '1453', 27)
        self.assertEquals(beta_info, self._branch_util.GetChannelInfo('beta'))

        stable_info = ChannelInfo('stable', '1410', 26)
        self.assertEquals(stable_info,
                          self._branch_util.GetChannelInfo('stable'))

    def testGetLatestVersionNumber(self):
        self.assertEquals(28, self._branch_util.GetLatestVersionNumber())

    def testGetBranchForVersion(self):
        self.assertEquals('1500', self._branch_util.GetBranchForVersion(28))
        self.assertEquals('1453', self._branch_util.GetBranchForVersion(27))
        self.assertEquals('1410', self._branch_util.GetBranchForVersion(26))
        self.assertEquals('1364', self._branch_util.GetBranchForVersion(25))
        self.assertEquals('1312', self._branch_util.GetBranchForVersion(24))
        self.assertEquals('1271', self._branch_util.GetBranchForVersion(23))
        self.assertEquals('1229', self._branch_util.GetBranchForVersion(22))
        self.assertEquals('1180', self._branch_util.GetBranchForVersion(21))
        self.assertEquals('1132', self._branch_util.GetBranchForVersion(20))
        self.assertEquals('1084', self._branch_util.GetBranchForVersion(19))
        self.assertEquals('1025', self._branch_util.GetBranchForVersion(18))
        self.assertEquals('963', self._branch_util.GetBranchForVersion(17))
        self.assertEquals('696', self._branch_util.GetBranchForVersion(11))
        self.assertEquals('396', self._branch_util.GetBranchForVersion(5))

    def testGetChannelForVersion(self):
        self.assertEquals('trunk',
                          self._branch_util.GetChannelForVersion('trunk'))
        self.assertEquals('dev', self._branch_util.GetChannelForVersion(28))
        self.assertEquals('beta', self._branch_util.GetChannelForVersion(27))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(26))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(22))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(18))
        self.assertEquals('stable', self._branch_util.GetChannelForVersion(14))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(30))
        self.assertEquals(None, self._branch_util.GetChannelForVersion(42))