Home | History | Annotate | Download | only in stable_images
      1 # Copyright 2016 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """
      6 Unit tests for functions in `assign_stable_images`.
      7 """
      8 
      9 
     10 import mock
     11 import unittest
     12 
     13 import common
     14 from autotest_lib.site_utils.stable_images import assign_stable_images
     15 from autotest_lib.site_utils.stable_images import build_data
     16 
     17 
     18 _DEFAULT_BOARD = assign_stable_images._DEFAULT_BOARD
     19 
     20 
     21 class GetFirmwareUpgradesTests(unittest.TestCase):
     22     """Tests for _get_firmware_upgrades."""
     23 
     24     @mock.patch.object(build_data, 'get_firmware_versions')
     25     def test_get_firmware_upgrades(self, mock_get_firmware_versions):
     26         """Test _get_firmware_upgrades."""
     27         mock_get_firmware_versions.side_effect = [
     28             {'auron_paine': 'fw_version'},
     29             {'blue': 'fw_version',
     30              'robo360': 'fw_version',
     31              'porbeagle': 'fw_version'}
     32         ]
     33         cros_versions = {
     34             'coral': 'R64-10176.65.0',
     35             'auron_paine': 'R64-10176.65.0'
     36         }
     37         boards = ['auron_paine', 'coral']
     38 
     39         firmware_upgrades = assign_stable_images._get_firmware_upgrades(
     40             cros_versions)
     41         expected_firmware_upgrades = {
     42             'auron_paine': 'fw_version',
     43             'blue': 'fw_version',
     44             'robo360': 'fw_version',
     45             'porbeagle': 'fw_version'
     46         }
     47         self.assertEqual(firmware_upgrades, expected_firmware_upgrades)
     48 
     49 
     50 class GetUpgradeTests(unittest.TestCase):
     51     """Tests for the `_get_upgrade_versions()` function."""
     52 
     53     # _VERSIONS - a list of sample version strings such as may be used
     54     #   for Chrome OS, sorted from oldest to newest.  These are used to
     55     #   construct test data in multiple test cases, below.
     56     _VERSIONS = ['R1-1.0.0', 'R1-1.1.0', 'R2-4.0.0']
     57 
     58     def test_board_conversions(self):
     59         """
     60         Test proper mapping of names from the AFE to Omaha.
     61 
     62         Board names in Omaha don't have '_' characters; when an AFE
     63         board contains '_' characters, they must be converted to '-'.
     64 
     65         Assert that for various forms of name in the AFE mapping, the
     66         converted name is the one looked up in the Omaha mapping.
     67         """
     68         board_equivalents = [
     69             ('a-b', 'a-b'), ('c_d', 'c-d'),
     70             ('e_f-g', 'e-f-g'), ('hi', 'hi')]
     71         afe_versions = {
     72             _DEFAULT_BOARD: self._VERSIONS[0]
     73         }
     74         omaha_versions = {}
     75         expected = {}
     76         boards = set()
     77         for afe_board, omaha_board in board_equivalents:
     78             boards.add(afe_board)
     79             afe_versions[afe_board] = self._VERSIONS[1]
     80             omaha_versions[omaha_board] = self._VERSIONS[2]
     81             expected[afe_board] = self._VERSIONS[2]
     82         upgrades, _ = assign_stable_images._get_upgrade_versions(
     83                 afe_versions, omaha_versions, boards)
     84         self.assertEqual(upgrades, expected)
     85 
     86     def test_afe_default(self):
     87         """
     88         Test that the AFE default board mapping is honored.
     89 
     90         If a board isn't present in the AFE dictionary, the mapping
     91         for `_DEFAULT_BOARD` should be used.
     92 
     93         Primary assertions:
     94           * When a board is present in the AFE mapping, its version
     95             mapping is used.
     96           * When a board is not present in the AFE mapping, the default
     97             version mapping is used.
     98 
     99         Secondarily, assert that when a mapping is absent from Omaha,
    100         the AFE mapping is left unchanged.
    101         """
    102         afe_versions = {
    103             _DEFAULT_BOARD: self._VERSIONS[0],
    104             'a': self._VERSIONS[1]
    105         }
    106         boards = set(['a', 'b'])
    107         expected = {
    108             'a': self._VERSIONS[1],
    109             'b': self._VERSIONS[0]
    110         }
    111         upgrades, _ = assign_stable_images._get_upgrade_versions(
    112                 afe_versions, {}, boards)
    113         self.assertEqual(upgrades, expected)
    114 
    115     def test_omaha_upgrade(self):
    116         """
    117         Test that upgrades from Omaha are detected.
    118 
    119         Primary assertion:
    120           * If a board is found in Omaha, and the version in Omaha is
    121             newer than the AFE version, the Omaha version is the one
    122             used.
    123 
    124         Secondarily, asserts that version comparisons between various
    125         specific version strings are all correct.
    126         """
    127         boards = set(['a'])
    128         for i in range(0, len(self._VERSIONS) - 1):
    129             afe_versions = {_DEFAULT_BOARD: self._VERSIONS[i]}
    130             for j in range(i+1, len(self._VERSIONS)):
    131                 omaha_versions = {b: self._VERSIONS[j] for b in boards}
    132                 upgrades, _ = assign_stable_images._get_upgrade_versions(
    133                         afe_versions, omaha_versions, boards)
    134                 self.assertEqual(upgrades, omaha_versions)
    135 
    136     def test_no_upgrade(self):
    137         """
    138         Test that if Omaha is behind the AFE, it is ignored.
    139 
    140         Primary assertion:
    141           * If a board is found in Omaha, and the version in Omaha is
    142             older than the AFE version, the AFE version is the one used.
    143 
    144         Secondarily, asserts that version comparisons between various
    145         specific version strings are all correct.
    146         """
    147         boards = set(['a'])
    148         for i in range(1, len(self._VERSIONS)):
    149             afe_versions = {_DEFAULT_BOARD: self._VERSIONS[i]}
    150             expected = {b: self._VERSIONS[i] for b in boards}
    151             for j in range(0, i):
    152                 omaha_versions = {b: self._VERSIONS[j] for b in boards}
    153                 upgrades, _ = assign_stable_images._get_upgrade_versions(
    154                         afe_versions, omaha_versions, boards)
    155                 self.assertEqual(upgrades, expected)
    156 
    157     def test_ignore_unused_boards(self):
    158         """
    159         Test that unlisted boards are ignored.
    160 
    161         Assert that boards present in the AFE or Omaha mappings aren't
    162         included in the return mappings when they aren't in the passed
    163         in set of boards.
    164         """
    165         unused_boards = set(['a', 'b'])
    166         used_boards = set(['c', 'd'])
    167         afe_versions = {b: self._VERSIONS[0] for b in unused_boards}
    168         afe_versions[_DEFAULT_BOARD] = self._VERSIONS[1]
    169         expected = {b: self._VERSIONS[1] for b in used_boards}
    170         omaha_versions = expected.copy()
    171         omaha_versions.update(
    172                 {b: self._VERSIONS[0] for b in unused_boards})
    173         upgrades, _ = assign_stable_images._get_upgrade_versions(
    174                 afe_versions, omaha_versions, used_boards)
    175         self.assertEqual(upgrades, expected)
    176 
    177     def test_default_unchanged(self):
    178         """
    179         Test correct handling when the default build is unchanged.
    180 
    181         Assert that if in Omaha, one board in a set of three upgrades
    182         from the AFE default, that the returned default board mapping is
    183         the original default in the AFE.
    184         """
    185         boards = set(['a', 'b', 'c'])
    186         afe_versions = {_DEFAULT_BOARD: self._VERSIONS[0]}
    187         omaha_versions = {b: self._VERSIONS[0] for b in boards}
    188         omaha_versions['c'] = self._VERSIONS[1]
    189         _, new_default = assign_stable_images._get_upgrade_versions(
    190                 afe_versions, omaha_versions, boards)
    191         self.assertEqual(new_default, self._VERSIONS[0])
    192 
    193     def test_default_upgrade(self):
    194         """
    195         Test correct handling when the default build must change.
    196 
    197         Assert that if in Omaha, two boards in a set of three upgrade
    198         from the AFE default, that the returned default board mapping is
    199         the new build in Omaha.
    200         """
    201         boards = set(['a', 'b', 'c'])
    202         afe_versions = {_DEFAULT_BOARD: self._VERSIONS[0]}
    203         omaha_versions = {b: self._VERSIONS[1] for b in boards}
    204         omaha_versions['c'] = self._VERSIONS[0]
    205         _, new_default = assign_stable_images._get_upgrade_versions(
    206                 afe_versions, omaha_versions, boards)
    207         self.assertEqual(new_default, self._VERSIONS[1])
    208 
    209 
    210 # Sample version string values to be used when testing
    211 # `_apply_upgrades()`.
    212 #
    213 # _OLD_DEFAULT - Test value representing the default version mapping
    214 #   in the `old_versions` dictionary in a call to `_apply_upgrades()`.
    215 # _NEW_DEFAULT - Test value representing the default version mapping
    216 #   in the `new_versions` dictionary when a version update is being
    217 #   tested.
    218 # _OLD_VERSION - Test value representing an arbitrary version for a
    219 #   board that is mapped in the `old_versions` dictionary in a call to
    220 #   `_apply_upgrades()`.
    221 # _NEW_VERSION - Test value representing an arbitrary version for a
    222 #   board that is mapped in the `new_versions` dictionary in a call to
    223 #   `_apply_upgrades()`.
    224 #
    225 _OLD_DEFAULT = 'old-default-version'
    226 _NEW_DEFAULT = 'new-default-version'
    227 _OLD_VERSION = 'old-board-version'
    228 _NEW_VERSION = 'new-board-version'
    229 
    230 
    231 class _StubAFE(object):
    232     """Stubbed out version of `server.frontend.AFE`."""
    233 
    234     CROS_IMAGE_TYPE = 'cros-image-type'
    235     FIRMWARE_IMAGE_TYPE = 'firmware-image-type'
    236 
    237     def get_stable_version_map(self, image_type):
    238         return image_type
    239 
    240 
    241 class _TestUpdater(assign_stable_images._VersionUpdater):
    242     """
    243     Subclass of `_VersionUpdater` for testing.
    244 
    245     This class extends `_VersionUpdater` to provide support for testing
    246     various assertions about the behavior of the base class and its
    247     interactions with `_apply_cros_upgrades()` and
    248     `_apply_firmware_upgrades()`.
    249 
    250     The class tests assertions along the following lines:
    251       * When applied to the original mappings, the calls to
    252         `_do_set_mapping()` and `_do_delete_mapping()` create the
    253         expected final mapping state.
    254       * Calls to report state changes are made with the expected
    255         values.
    256       * There's a one-to-one match between reported and actually
    257         executed changes.
    258 
    259     """
    260 
    261     def __init__(self, testcase):
    262         super(_TestUpdater, self).__init__(_StubAFE(), dry_run=True)
    263         self._testcase = testcase
    264         self._default_changed = None
    265         self._reported_mappings = None
    266         self._updated_mappings = None
    267         self._reported_deletions = None
    268         self._actual_deletions = None
    269         self._original_mappings = None
    270         self._mappings = None
    271         self._expected_mappings = None
    272         self._unchanged_boards = None
    273 
    274     def pretest_init(self, initial_versions, expected_versions):
    275         """
    276         Initialize for testing.
    277 
    278         @param initial_versions   Mappings to be used as the starting
    279                                   point for testing.
    280         @param expected_versions  The expected final value of the
    281                                   mappings after the test.
    282         """
    283         self._default_changed = False
    284         self._reported_mappings = {}
    285         self._updated_mappings = {}
    286         self._reported_deletions = set()
    287         self._actual_deletions = set()
    288         self._original_mappings = initial_versions.copy()
    289         self._mappings = initial_versions.copy()
    290         self._expected_mappings = expected_versions
    291         self._unchanged_boards = set()
    292 
    293     def check_results(self, change_default):
    294         """
    295         Assert that observed changes match expectations.
    296 
    297         Asserts the following:
    298           * The `report_default_changed()` method was called (or not)
    299             based on whether `change_default` is true (or not).
    300           * The changes reported via `_report_board_changed()` match
    301             the changes actually applied.
    302           * The final mappings after applying requested changes match
    303             the actually expected mappings.
    304 
    305         @param old_versions   Parameter to be passed to
    306                               `_apply_cros_upgrades()`.
    307         @param new_versions   Parameter to be passed to
    308                               `_apply_cros_upgrades()`.
    309         @param change_default   Whether the test should include a change
    310                                 to the default version mapping.
    311         """
    312         self._testcase.assertEqual(change_default,
    313                                    self._default_changed)
    314         self._testcase.assertEqual(self._reported_mappings,
    315                                    self._updated_mappings)
    316         self._testcase.assertEqual(self._reported_deletions,
    317                                    self._actual_deletions)
    318         self._testcase.assertEqual(self._mappings,
    319                                    self._expected_mappings)
    320 
    321     def report_default_changed(self, old_default, new_default):
    322         """
    323         Override of our parent class' method for test purposes.
    324 
    325         Saves a record of the report for testing the final result in
    326         `apply_upgrades()`, above.
    327 
    328         Assert the following:
    329           * The old and new default values match the values that
    330             were passed in the original call's arguments.
    331           * This function is not being called for a second time.
    332 
    333         @param old_default  The original default version.
    334         @param new_default  The new default version to be applied.
    335         """
    336         self._testcase.assertNotEqual(old_default, new_default)
    337         self._testcase.assertEqual(old_default,
    338                                    self._original_mappings[_DEFAULT_BOARD])
    339         self._testcase.assertEqual(new_default,
    340                                    self._expected_mappings[_DEFAULT_BOARD])
    341         self._testcase.assertFalse(self._default_changed)
    342         self._default_changed = True
    343         self._reported_mappings[_DEFAULT_BOARD] = new_default
    344 
    345     def _report_board_changed(self, board, old_version, new_version):
    346         """
    347         Override of our parent class' method for test purposes.
    348 
    349         Saves a record of the report for testing the final result in
    350         `apply_upgrades()`, above.
    351 
    352         Assert the following:
    353           * The change being reported actually reports two different
    354             versions.
    355           * If the board isn't mapped to the default version, then the
    356             reported old version is the actually mapped old version.
    357           * If the board isn't changing to the default version, then the
    358             reported new version is the expected new version.
    359           * This is not a second report for this board.
    360 
    361         The implementation implicitly requires that the specified board
    362         have a valid mapping.
    363 
    364         @param board        The board with the changing version.
    365         @param old_version  The original version mapped to the board.
    366         @param new_version  The new version to be applied to the board.
    367         """
    368         self._testcase.assertNotEqual(old_version, new_version)
    369         if board in self._original_mappings:
    370             self._testcase.assertEqual(old_version,
    371                                        self._original_mappings[board])
    372         if board in self._expected_mappings:
    373             self._testcase.assertEqual(new_version,
    374                                        self._expected_mappings[board])
    375             self._testcase.assertNotIn(board, self._reported_mappings)
    376             self._reported_mappings[board] = new_version
    377         else:
    378             self._testcase.assertNotIn(board, self._reported_deletions)
    379             self._reported_deletions.add(board)
    380 
    381     def report_board_unchanged(self, board, old_version):
    382         """
    383         Override of our parent class' method for test purposes.
    384 
    385         Assert the following:
    386           * The version being reported as unchanged is actually mapped.
    387           * The reported old version matches the expected value.
    388           * This is not a second report for this board.
    389 
    390         @param board        The board that is not changing.
    391         @param old_version  The board's version mapping.
    392         """
    393         self._testcase.assertIn(board, self._original_mappings)
    394         self._testcase.assertEqual(old_version,
    395                                    self._original_mappings[board])
    396         self._testcase.assertNotIn(board, self._unchanged_boards)
    397         self._unchanged_boards.add(board)
    398 
    399     def _do_set_mapping(self, board, new_version):
    400         """
    401         Override of our parent class' method for test purposes.
    402 
    403         Saves a record of the change for testing the final result in
    404         `apply_upgrades()`, above.
    405 
    406         Assert the following:
    407           * This is not a second change for this board.
    408           * If we're changing the default mapping, then every board
    409             that will be changing to a non-default mapping has been
    410             updated.
    411 
    412         @param board        The board with the changing version.
    413         @param new_version  The new version to be applied to the board.
    414         """
    415         self._mappings[board] = new_version
    416         self._testcase.assertNotIn(board, self._updated_mappings)
    417         self._updated_mappings[board] = new_version
    418         if board == _DEFAULT_BOARD:
    419             for board in self._expected_mappings:
    420                 self._testcase.assertIn(board, self._mappings)
    421 
    422     def _do_delete_mapping(self, board):
    423         """
    424         Override of our parent class' method for test purposes.
    425 
    426         Saves a record of the change for testing the final result in
    427         `apply_upgrades()`, above.
    428 
    429         Assert that the board has a mapping prior to deletion.
    430 
    431         @param board        The board with the version to be deleted.
    432         """
    433         self._testcase.assertNotEqual(board, _DEFAULT_BOARD)
    434         self._testcase.assertIn(board, self._mappings)
    435         del self._mappings[board]
    436         self._actual_deletions.add(board)
    437 
    438 
    439 class ApplyCrOSUpgradesTests(unittest.TestCase):
    440     """Tests for the `_apply_cros_upgrades()` function."""
    441 
    442     def _apply_upgrades(self, old_versions, new_versions, change_default):
    443         """
    444         Test a single call to `_apply_cros_upgrades()`.
    445 
    446         All assertions are handled by an instance of `_TestUpdater`.
    447 
    448         @param old_versions   Parameter to be passed to
    449                               `_apply_cros_upgrades()`.
    450         @param new_versions   Parameter to be passed to
    451                               `_apply_cros_upgrades()`.
    452         @param change_default   Whether the test should include a change
    453                                 to the default version mapping.
    454         """
    455         old_versions[_DEFAULT_BOARD] = _OLD_DEFAULT
    456         if change_default:
    457             new_default = _NEW_DEFAULT
    458         else:
    459             new_default = _OLD_DEFAULT
    460         expected_versions = {
    461             b: v for b, v in new_versions.items() if v != new_default
    462         }
    463         expected_versions[_DEFAULT_BOARD] = new_default
    464         updater = _TestUpdater(self)
    465         updater.pretest_init(old_versions, expected_versions)
    466         assign_stable_images._apply_cros_upgrades(
    467             updater, old_versions, new_versions, new_default)
    468         updater.check_results(change_default)
    469 
    470     def test_no_changes(self):
    471         """
    472         Test an empty upgrade that does nothing.
    473 
    474         Test the boundary case of an upgrade where there are no boards,
    475         and the default does not change.
    476         """
    477         self._apply_upgrades({}, {}, False)
    478 
    479     def test_change_default(self):
    480         """
    481         Test an empty upgrade that merely changes the default.
    482 
    483         Test the boundary case of an upgrade where there are no boards,
    484         but the default is upgraded.
    485         """
    486         self._apply_upgrades({}, {}, True)
    487 
    488     def test_board_default_no_changes(self):
    489         """
    490         Test that a board at default stays with an unchanged default.
    491 
    492         Test the case of a board that is mapped to the default, where
    493         neither the board nor the default change.
    494         """
    495         self._apply_upgrades({}, {'board': _OLD_DEFAULT}, False)
    496 
    497     def test_board_left_behind(self):
    498         """
    499         Test a board left at the old default after a default upgrade.
    500 
    501         Test the case of a board that stays mapped to the old default as
    502         the default board is upgraded.
    503         """
    504         self._apply_upgrades({}, {'board': _OLD_DEFAULT}, True)
    505 
    506     def test_board_upgrade_from_default(self):
    507         """
    508         Test upgrading a board from a default that doesn't change.
    509 
    510         Test the case of upgrading a board from default to non-default,
    511         where the default doesn't change.
    512         """
    513         self._apply_upgrades({}, {'board': _NEW_VERSION}, False)
    514 
    515     def test_board_and_default_diverge(self):
    516         """
    517         Test upgrading a board that diverges from the default.
    518 
    519         Test the case of upgrading a board and default together from the
    520         same to different versions.
    521         """
    522         self._apply_upgrades({}, {'board': _NEW_VERSION}, True)
    523 
    524     def test_board_tracks_default(self):
    525         """
    526         Test upgrading a board to track a default upgrade.
    527 
    528         Test the case of upgrading a board and the default together.
    529         """
    530         self._apply_upgrades({}, {'board': _NEW_DEFAULT}, True)
    531 
    532     def test_board_non_default_no_changes(self):
    533         """
    534         Test an upgrade with no changes to a board or the default.
    535 
    536         Test the case of an upgrade with a board in it, where neither
    537         the board nor the default change.
    538         """
    539         self._apply_upgrades({'board': _NEW_VERSION},
    540                              {'board': _NEW_VERSION},
    541                              False)
    542 
    543     def test_board_upgrade_and_keep_default(self):
    544         """
    545         Test a board upgrade with an unchanged default.
    546 
    547         Test the case of upgrading a board while the default stays the
    548         same.
    549         """
    550         self._apply_upgrades({'board': _OLD_VERSION},
    551                              {'board': _NEW_VERSION},
    552                              False)
    553 
    554     def test_board_upgrade_and_change_default(self):
    555         """
    556         Test upgrading a board and the default separately.
    557 
    558         Test the case of upgrading both a board and the default, each
    559         from and to different versions.
    560         """
    561         self._apply_upgrades({'board': _OLD_VERSION},
    562                              {'board': _NEW_VERSION},
    563                              True)
    564 
    565     def test_board_leads_default(self):
    566         """
    567         Test a board that upgrades ahead of the new default.
    568 
    569         Test the case of upgrading both a board and the default, where
    570         the board's old version is the new default version.
    571         """
    572         self._apply_upgrades({'board': _NEW_DEFAULT},
    573                              {'board': _NEW_VERSION},
    574                              True)
    575 
    576     def test_board_lags_to_old_default(self):
    577         """
    578         Test a board that upgrades behind the old default.
    579 
    580         Test the case of upgrading both a board and the default, where
    581         the board's new version is the old default version.
    582         """
    583         self._apply_upgrades({'board': _OLD_VERSION},
    584                              {'board': _OLD_DEFAULT},
    585                              True)
    586 
    587     def test_board_joins_old_default(self):
    588         """
    589         Test upgrading a board to a default that doesn't change.
    590 
    591         Test the case of upgrading board to the default, where the
    592         default mapping stays unchanged.
    593         """
    594         self._apply_upgrades({'board': _OLD_VERSION},
    595                              {'board': _OLD_DEFAULT},
    596                              False)
    597 
    598     def test_board_joins_new_default(self):
    599         """
    600         Test upgrading a board to match the new default.
    601 
    602         Test the case of upgrading board and the default to the same
    603         version.
    604         """
    605         self._apply_upgrades({'board': _OLD_VERSION},
    606                              {'board': _NEW_DEFAULT},
    607                              True)
    608 
    609     def test_board_becomes_default(self):
    610         """
    611         Test a board that becomes default after a default upgrade.
    612 
    613         Test the case of upgrading the default to a version already
    614         mapped for an existing board.
    615         """
    616         self._apply_upgrades({'board': _NEW_DEFAULT},
    617                              {'board': _NEW_DEFAULT},
    618                              True)
    619 
    620 
    621 class ApplyFirmwareUpgradesTests(unittest.TestCase):
    622     """Tests for the `_apply_firmware_upgrades()` function."""
    623 
    624     def _apply_upgrades(self, old_versions, new_versions):
    625         """
    626         Test a single call to `_apply_firmware_upgrades()`.
    627 
    628         All assertions are handled by an instance of `_TestUpdater`.
    629 
    630         @param old_versions   Parameter to be passed to
    631                               `_apply_firmware_upgrades()`.
    632         @param new_versions   Parameter to be passed to
    633                               `_apply_firmware_upgrades()`.
    634         """
    635         updater = _TestUpdater(self)
    636         updater.pretest_init(old_versions, new_versions)
    637         assign_stable_images._apply_firmware_upgrades(
    638             updater, old_versions, new_versions)
    639         updater.check_results(False)
    640 
    641     def test_no_changes(self):
    642         """
    643         Test an empty upgrade that does nothing.
    644 
    645         Test the boundary case of an upgrade where there are no boards.
    646         """
    647         self._apply_upgrades({}, {})
    648 
    649     def test_board_added(self):
    650         """
    651         Test an upgrade that adds a new board.
    652 
    653         Test the case of an upgrade where a board that was previously
    654         unmapped is added.
    655         """
    656         self._apply_upgrades({}, {'board': _NEW_VERSION})
    657 
    658     def test_board_unchanged(self):
    659         """
    660         Test an upgrade with no changes to a board.
    661 
    662         Test the case of an upgrade with a board that stays the same.
    663         """
    664         self._apply_upgrades({'board': _NEW_VERSION},
    665                              {'board': _NEW_VERSION})
    666 
    667     def test_board_upgrade_and_change_default(self):
    668         """
    669         Test upgrading a board.
    670 
    671         Test the case of upgrading a board to a new version.
    672         """
    673         self._apply_upgrades({'board': _OLD_VERSION},
    674                              {'board': _NEW_VERSION})
    675 
    676 
    677 if __name__ == '__main__':
    678     unittest.main()
    679