| #!/usr/bin/python |
| |
| # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This contains tests for bundle_firmware using the unittest framework. |
| |
| It supports creating a few images so far, but the testing is very basic. |
| """ |
| |
| import collections |
| import os |
| import shutil |
| import unittest |
| import tempfile |
| |
| from bundle_firmware import Bundle |
| import bundle_firmware |
| import cros_output |
| from tools import Tools |
| |
| |
| def GetFlagName(index): |
| """Returns the flag name for the given index value (0...n-1).""" |
| return bundle_firmware.gbb_flag_properties.keys()[index] |
| |
| def GetFlagValue(index): |
| """Returns the flag value for the given index value (0...n-1).""" |
| return bundle_firmware.gbb_flag_properties.values()[index] |
| |
| |
| class TestBundleFirmware(unittest.TestCase): |
| """Unit test class for bundle_firmware.py.""" |
| |
| def setUp(self): |
| """Set up filenames for running the test. |
| |
| A fake U-Boot binary is created ready for use in tests. |
| """ |
| self._file_upto = 0 # How many files we have created |
| self.tmpdir = tempfile.mkdtemp() |
| self.output = cros_output.Output() |
| self.tools = Tools(self.output) |
| self.tools.PrepareOutputDir(None) |
| self.bundle = Bundle(self.tools, self.output) |
| self.uboot_fname = self.MakeRandomFile(500 * 1024) |
| self.bct_fname = os.path.abspath('bin/board.bct') |
| self.bundle.SetDirs('##/usr/share/vboot/devkeys') |
| self.bundle.SetOptions(False, None) |
| |
| def tearDown(self): |
| """Clean up after completion of tests.""" |
| del self.bundle |
| |
| # Delete the temporary directory created by the tools object. |
| self.tools.FinalizeOutputDir() |
| del self.tools |
| del self.output |
| shutil.rmtree(self.tmpdir) |
| |
| def TmpName(self, file_num): |
| """Returns a suitable filename for the given temporary file number. |
| |
| Args: |
| file_num: The temporary file number (0 is the first). |
| |
| Returns: |
| The filenme of the file_num'th file. |
| """ |
| return os.path.join(self.tmpdir, '%02d.bin' % file_num) |
| |
| def MakeRandomFile(self, size): |
| """Make a file of the given size, and fill it with pseudo-random data. |
| |
| The file will be created in the 'bin' directory. |
| |
| Uses the contents of lorem.txt from here: |
| http://desktoppub.about.com/library/weekly/lorem.txt |
| |
| Based on an algorithm here: |
| |
| http://jessenoller.com/2008/05/30/making-re-creatable- |
| random-data-files-really-fast-in-python/ |
| |
| Args: |
| size: Size of file to create, in bytes. |
| |
| Returns: |
| Absolute path to the created file. |
| """ |
| fname = os.path.abspath(self.TmpName(self._file_upto)) |
| self._file_upto += 1 |
| with open(fname, 'wb') as fd: |
| seed = '1092384956781341341234656953214543219' |
| words = open('lorem.txt', 'r').read().split() |
| |
| def _GetData(): |
| """Continuously yield the next 1024 bytes of data.""" |
| a = collections.deque(words) |
| b = collections.deque(seed) |
| while True: |
| yield ' '.join(list(a)[0:1024]) |
| a.rotate(int(b[0])) |
| b.rotate(1) |
| |
| get_data = _GetData() |
| upto = 0 |
| while upto < size: |
| data = get_data.next() |
| todo = min(size - upto, len(data)) |
| fd.write(data[:todo]) |
| upto += todo |
| |
| return fname |
| |
| # pylint: disable=W0212,C6409 |
| def test_NoBoard(self): |
| """With no board selected, it should fail.""" |
| self.assertRaises(ValueError, self.bundle.SelectFdt, 'tegra-map.dts', True) |
| |
| def assertRaisesContains(self, exception, match, func, *args): |
| try: |
| func(*args) |
| except Exception as e: |
| if not match in str(e): |
| self.fail('Unexpected exception thrown: %s' % str(e)) |
| else: |
| self.fail('IOError not thrown') |
| |
| def test_Defaults(self): |
| """Test that default handling works correctly.""" |
| uboot_fname = self.MakeRandomFile(600 * 1024) |
| self.bundle.SetFiles('robin_hood', bct=self.bct_fname, uboot=uboot_fname) |
| |
| # If we don't ask for defaults, we should not get them. This first one |
| # raises because it tries to operate on the string None |
| self.assertRaises(ValueError, self.bundle.SelectFdt, None, False) |
| |
| # This one raises because the file 'fred' does not exist. |
| self.assertRaises(IOError, self.bundle.SelectFdt, 'fred', False) |
| |
| # Same with this one, but we check the filename. |
| self.assertRaisesContains(IOError, |
| '/build/robin_hood/firmware/dtb/fred.dtb', self.bundle.SelectFdt, |
| 'fred', True) |
| |
| def test_TooLarge(self): |
| """Test for failure when U-Boot exceeds the size available for it.""" |
| uboot_fname = self.MakeRandomFile(900 * 1024) |
| self.bundle.SetFiles('robin_hood', bct=self.bct_fname, uboot=uboot_fname) |
| self.bundle.CheckOptions() |
| self.bundle.SelectFdt('dts/tegra-map.dts', True) |
| image = os.path.join(self.tmpdir, 'image.bin') |
| self.assertRaises(ValueError, self.bundle.Start, 'hwid', image, False) |
| |
| def test_Normal(self): |
| """Test that we get output for a simple case.""" |
| uboot_fname = self.MakeRandomFile(600 * 1024) |
| self.bundle.SetFiles('robin_hood', bct=self.bct_fname, uboot=uboot_fname) |
| self.bundle.CheckOptions() |
| self.bundle.SelectFdt('dts/tegra-map.dts', True) |
| image = os.path.join(self.tmpdir, 'image.bin') |
| out_fname = self.bundle.Start('hwid', image, False) |
| |
| # We expect the size to be 2MB. |
| # TODO(sjg@chromium.org): Read this from the fdt file instead. |
| self.assertEquals(os.stat(image).st_size, 2 * 1024 * 1024) |
| |
| def test_Flags(self): |
| bundle = self.bundle |
| self.assertEquals(0, bundle.DecodeGBBFlagsFromOptions(0, None)) |
| |
| # Make sure each flag works. |
| all = [] |
| all_value = 0 |
| for flag, value in bundle_firmware.gbb_flag_properties.iteritems(): |
| self.assertEquals(value, bundle.DecodeGBBFlagsFromOptions(0, flag)) |
| all.append(flag) |
| all_value |= value |
| |
| # Nop. |
| self.assertEquals(23, bundle.DecodeGBBFlagsFromOptions(23, '')) |
| self.assertEquals(23, bundle.DecodeGBBFlagsFromOptions(23, None)) |
| |
| # Starting from 0, try turning on all flags. |
| self.assertEquals(all_value, |
| bundle.DecodeGBBFlagsFromOptions(0, ','.join(all))) |
| |
| # Starting from the value for all flags on, try turning off all flags. |
| all_off = ['-%s' % item for item in bundle_firmware.gbb_flag_properties] |
| self.assertEquals(0, bundle.DecodeGBBFlagsFromOptions(all_value, |
| ','.join(all_off))) |
| |
| # Make sure + and - work. Start with a random flag. |
| start_value = GetFlagValue(2) | GetFlagValue(3) |
| expr = '+%s,+%s,-%s' % (GetFlagName(1), GetFlagName(4), GetFlagName(3)) |
| expect_value = start_value | GetFlagValue(1) | GetFlagValue(4) |
| expect_value &= ~ GetFlagValue(3) |
| self.assertEquals(expect_value, |
| bundle.DecodeGBBFlagsFromOptions(start_value, expr)) |
| |
| # Try hex value |
| self.assertEquals(0x69, bundle.DecodeGBBFlagsFromOptions(4, '69')) |
| self.assertEquals(0xc, bundle.DecodeGBBFlagsFromOptions(4, 'c')) |
| self.assertEquals(0xc, bundle.DecodeGBBFlagsFromOptions(4, '00c')) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |