From c07919281c521c57d34eba8bfbac910c9632beda Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Jun 2017 22:09:06 -0600 Subject: [PATCH] dtoc: Add tests Add some tests of dtoc's functionality to make it easier to expand and enhance the tool. Signed-off-by: Simon Glass --- tools/dtoc/dtoc.py | 31 +++- tools/dtoc/dtoc_test.dts | 12 ++ tools/dtoc/dtoc_test_aliases.dts | 18 ++ tools/dtoc/dtoc_test_empty.dts | 12 ++ tools/dtoc/dtoc_test_phandle.dts | 23 +++ tools/dtoc/dtoc_test_simple.dts | 48 ++++++ tools/dtoc/test_dtoc.py | 271 +++++++++++++++++++++++++++++++ 7 files changed, 411 insertions(+), 4 deletions(-) create mode 100644 tools/dtoc/dtoc_test.dts create mode 100644 tools/dtoc/dtoc_test_aliases.dts create mode 100644 tools/dtoc/dtoc_test_empty.dts create mode 100644 tools/dtoc/dtoc_test_phandle.dts create mode 100644 tools/dtoc/dtoc_test_simple.dts create mode 100644 tools/dtoc/test_dtoc.py diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py index 140a19e9d4..ce7bc054e5 100755 --- a/tools/dtoc/dtoc.py +++ b/tools/dtoc/dtoc.py @@ -29,6 +29,7 @@ see doc/driver-model/of-plat.txt from optparse import OptionParser import os import sys +import unittest # Bring in the patman libraries our_path = os.path.dirname(os.path.realpath(__file__)) @@ -36,9 +37,24 @@ sys.path.append(os.path.join(our_path, '../patman')) import dtb_platdata +def run_tests(): + """Run all the test we have for dtoc""" + import test_dtoc -if __name__ != "__main__": - pass + result = unittest.TestResult() + sys.argv = [sys.argv[0]] + for module in (test_dtoc.TestDtoc,): + suite = unittest.TestLoader().loadTestsFromTestCase(module) + suite.run(result) + + print result + for _, err in result.errors: + print err + for _, err in result.failures: + print err + +if __name__ != '__main__': + sys.exit(1) parser = OptionParser() parser.add_option('-d', '--dtb-file', action='store', @@ -47,7 +63,14 @@ parser.add_option('--include-disabled', action='store_true', help='Include disabled nodes') parser.add_option('-o', '--output', action='store', default='-', help='Select output filename') +parser.add_option('-t', '--test', action='store_true', dest='test', + default=False, help='run tests') (options, args) = parser.parse_args() -dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled, - options.output) +# Run our meagre tests +if options.test: + run_tests() + +else: + dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled, + options.output) diff --git a/tools/dtoc/dtoc_test.dts b/tools/dtoc/dtoc_test.dts new file mode 100644 index 0000000000..1e86655975 --- /dev/null +++ b/tools/dtoc/dtoc_test.dts @@ -0,0 +1,12 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { +}; diff --git a/tools/dtoc/dtoc_test_aliases.dts b/tools/dtoc/dtoc_test_aliases.dts new file mode 100644 index 0000000000..c727f185af --- /dev/null +++ b/tools/dtoc/dtoc_test_aliases.dts @@ -0,0 +1,18 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + spl-test { + u-boot,dm-pre-reloc; + compatible = "compat1", "compat2.1-fred", "compat3"; + intval = <1>; + }; + +}; diff --git a/tools/dtoc/dtoc_test_empty.dts b/tools/dtoc/dtoc_test_empty.dts new file mode 100644 index 0000000000..1e86655975 --- /dev/null +++ b/tools/dtoc/dtoc_test_empty.dts @@ -0,0 +1,12 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { +}; diff --git a/tools/dtoc/dtoc_test_phandle.dts b/tools/dtoc/dtoc_test_phandle.dts new file mode 100644 index 0000000000..e9828a695b --- /dev/null +++ b/tools/dtoc/dtoc_test_phandle.dts @@ -0,0 +1,23 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + phandle: phandle-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <1>; + }; + + phandle-source { + u-boot,dm-pre-reloc; + compatible = "source"; + clocks = <&phandle 1>; + }; +}; diff --git a/tools/dtoc/dtoc_test_simple.dts b/tools/dtoc/dtoc_test_simple.dts new file mode 100644 index 0000000000..c736686263 --- /dev/null +++ b/tools/dtoc/dtoc_test_simple.dts @@ -0,0 +1,48 @@ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /dts-v1/; + +/ { + spl-test { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + boolval; + intval = <1>; + intarray = <2 3 4>; + byteval = [05]; + bytearray = [06]; + longbytearray = [09 0a 0b 0c 0d 0e 0f 10 11]; + stringval = "message"; + stringarray = "multi-word", "message"; + }; + + spl-test2 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + intval = <3>; + intarray = <5>; + byteval = [08]; + bytearray = [01 23 34]; + longbytearray = [09 0a 0b 0c]; + stringval = "message2"; + stringarray = "another", "multi-word", "message"; + }; + + spl-test3 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + stringarray = "one"; + }; + + spl-test4 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test.2"; + }; + +}; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py new file mode 100644 index 0000000000..8b95c4124f --- /dev/null +++ b/tools/dtoc/test_dtoc.py @@ -0,0 +1,271 @@ +# +# Copyright (c) 2012 The Chromium OS Authors. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +"""Tests for the dtb_platdata module + +This includes unit tests for some functions and functional tests for +""" + +import collections +import os +import struct +import unittest + +import dtb_platdata +from dtb_platdata import conv_name_to_c +from dtb_platdata import get_compat_name +from dtb_platdata import get_value +from dtb_platdata import tab_to +import fdt +import fdt_util +import tools + +our_path = os.path.dirname(os.path.realpath(__file__)) + + +def get_dtb_file(dts_fname): + """Compile a .dts file to a .dtb + + Args: + dts_fname: Filename of .dts file in the current directory + + Returns: + Filename of compiled file in output directory + """ + return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname)) + + +class TestDtoc(unittest.TestCase): + """Tests for dtoc""" + @classmethod + def setUpClass(cls): + tools.PrepareOutputDir(None) + + @classmethod + def tearDownClass(cls): + tools._RemoveOutputDir() + + def test_name(self): + """Test conversion of device tree names to C identifiers""" + self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12')) + self.assertEqual('vendor_clock_frequency', + conv_name_to_c('vendor,clock-frequency')) + self.assertEqual('rockchip_rk3399_sdhci_5_1', + conv_name_to_c('rockchip,rk3399-sdhci-5.1')) + + def test_tab_to(self): + """Test operation of tab_to() function""" + self.assertEqual('fred ', tab_to(0, 'fred')) + self.assertEqual('fred\t', tab_to(1, 'fred')) + self.assertEqual('fred was here ', tab_to(1, 'fred was here')) + self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here')) + self.assertEqual('exactly8 ', tab_to(1, 'exactly8')) + self.assertEqual('exactly8\t', tab_to(2, 'exactly8')) + + def test_get_value(self): + """Test operation of get_value() function""" + self.assertEqual('0x45', + get_value(fdt.TYPE_INT, struct.pack('>I', 0x45))) + self.assertEqual('0x45', + get_value(fdt.TYPE_BYTE, struct.pack('I', 0x45))) + self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test')) + self.assertEqual('true', get_value(fdt.TYPE_BOOL, None)) + + def test_get_compat_name(self): + """Test operation of get_compat_name() function""" + Prop = collections.namedtuple('Prop', ['value']) + Node = collections.namedtuple('Node', ['props']) + + prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1']) + node = Node({'compatible': prop}) + self.assertEqual(('rockchip_rk3399_sdhci_5_1', ['arasan_sdhci_5_1']), + get_compat_name(node)) + + prop = Prop(['rockchip,rk3399-sdhci-5.1']) + node = Node({'compatible': prop}) + self.assertEqual(('rockchip_rk3399_sdhci_5_1', []), + get_compat_name(node)) + + prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third']) + node = Node({'compatible': prop}) + self.assertEqual(('rockchip_rk3399_sdhci_5_1', + ['arasan_sdhci_5_1', 'third']), + get_compat_name(node)) + + def test_empty_file(self): + """Test output from a device tree file with no nodes""" + dtb_file = get_dtb_file('dtoc_test_empty.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + lines = infile.read().splitlines() + self.assertEqual(['#include ', '#include '], lines) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + lines = infile.read().splitlines() + self.assertEqual(['#include ', '#include ', + '#include ', ''], lines) + + def test_simple(self): + """Test output from some simple nodes with various types of data""" + dtb_file = get_dtb_file('dtoc_test_simple.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_sandbox_spl_test { +\tbool\t\tboolval; +\tunsigned char\tbytearray[3]; +\tunsigned char\tbyteval; +\tfdt32_t\t\tintarray[4]; +\tfdt32_t\t\tintval; +\tunsigned char\tlongbytearray[9]; +\tconst char *\tstringarray[3]; +\tconst char *\tstringval; +}; +struct dtd_sandbox_spl_test_2 { +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +static struct dtd_sandbox_spl_test dtv_spl_test = { +\t.bytearray\t\t= {0x6, 0x0, 0x0}, +\t.byteval\t\t= 0x5, +\t.intval\t\t\t= 0x1, +\t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11}, +\t.stringval\t\t= "message", +\t.boolval\t\t= true, +\t.intarray\t\t= {0x2, 0x3, 0x4, 0x0}, +\t.stringarray\t\t= {"multi-word", "message", ""}, +}; +U_BOOT_DEVICE(spl_test) = { +\t.name\t\t= "sandbox_spl_test", +\t.platdata\t= &dtv_spl_test, +\t.platdata_size\t= sizeof(dtv_spl_test), +}; + +static struct dtd_sandbox_spl_test dtv_spl_test2 = { +\t.bytearray\t\t= {0x1, 0x23, 0x34}, +\t.byteval\t\t= 0x8, +\t.intval\t\t\t= 0x3, +\t.longbytearray\t\t= {0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, +\t.stringval\t\t= "message2", +\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, +\t.stringarray\t\t= {"another", "multi-word", "message"}, +}; +U_BOOT_DEVICE(spl_test2) = { +\t.name\t\t= "sandbox_spl_test", +\t.platdata\t= &dtv_spl_test2, +\t.platdata_size\t= sizeof(dtv_spl_test2), +}; + +static struct dtd_sandbox_spl_test dtv_spl_test3 = { +\t.stringarray\t\t= {"one", "", ""}, +}; +U_BOOT_DEVICE(spl_test3) = { +\t.name\t\t= "sandbox_spl_test", +\t.platdata\t= &dtv_spl_test3, +\t.platdata_size\t= sizeof(dtv_spl_test3), +}; + +static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { +}; +U_BOOT_DEVICE(spl_test4) = { +\t.name\t\t= "sandbox_spl_test_2", +\t.platdata\t= &dtv_spl_test4, +\t.platdata_size\t= sizeof(dtv_spl_test4), +}; + +''', data) + + def test_phandle(self): + """Test output from a node containing a phandle reference""" + dtb_file = get_dtb_file('dtoc_test_phandle.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_source { +\tstruct phandle_2_cell clocks[1]; +}; +struct dtd_target { +\tfdt32_t\t\tintval; +}; +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +static struct dtd_target dtv_phandle_target = { +\t.intval\t\t\t= 0x1, +}; +U_BOOT_DEVICE(phandle_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle_target, +\t.platdata_size\t= sizeof(dtv_phandle_target), +}; + +static struct dtd_source dtv_phandle_source = { +\t.clocks\t\t\t= {{&dtv_phandle_target, 1}}, +}; +U_BOOT_DEVICE(phandle_source) = { +\t.name\t\t= "source", +\t.platdata\t= &dtv_phandle_source, +\t.platdata_size\t= sizeof(dtv_phandle_source), +}; + +''', data) + + def test_aliases(self): + """Test output from a node with multiple compatible strings""" + dtb_file = get_dtb_file('dtoc_test_aliases.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +struct dtd_compat1 { +\tfdt32_t\t\tintval; +}; +#define dtd_compat2_1_fred dtd_compat1 +#define dtd_compat3 dtd_compat1 +''', data) + + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self.assertEqual('''#include +#include +#include + +static struct dtd_compat1 dtv_spl_test = { +\t.intval\t\t\t= 0x1, +}; +U_BOOT_DEVICE(spl_test) = { +\t.name\t\t= "compat1", +\t.platdata\t= &dtv_spl_test, +\t.platdata_size\t= sizeof(dtv_spl_test), +}; + +''', data) -- 2.39.2