diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/dtoc/dtb_platdata.py | 148 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_driver_alias.dts | 20 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_invalid_driver.dts | 15 | ||||
-rw-r--r-- | tools/dtoc/dtoc_test_phandle_cd_gpios.dts | 42 | ||||
-rwxr-xr-x | tools/dtoc/test_dtoc.py | 287 | ||||
-rw-r--r-- | tools/patman/checkpatch.py | 24 | ||||
-rw-r--r-- | tools/patman/command.py | 7 | ||||
-rw-r--r-- | tools/patman/get_maintainer.py | 14 | ||||
-rw-r--r-- | tools/patman/gitutil.py | 10 | ||||
-rwxr-xr-x | tools/patman/main.py | 6 | ||||
-rw-r--r-- | tools/patman/series.py | 3 | ||||
-rw-r--r-- | tools/patman/settings.py | 7 | ||||
-rw-r--r-- | tools/patman/test_checkpatch.py (renamed from tools/patman/test.py) | 125 | ||||
-rw-r--r-- | tools/patman/test_util.py | 1 |
14 files changed, 587 insertions, 122 deletions
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index ecfe0624d1..c148c49625 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -13,6 +13,8 @@ static data. import collections import copy +import os +import re import sys from dtoc import fdt @@ -139,16 +141,61 @@ class DtbPlatdata(object): _valid_nodes: A list of Node object with compatible strings _include_disabled: true to include nodes marked status = "disabled" _outfile: The current output file (sys.stdout or a real file) + _warning_disabled: true to disable warnings about driver names not found _lines: Stashed list of output lines for outputting in the future + _aliases: Dict that hold aliases for compatible strings + key: First compatible string declared in a node + value: List of additional compatible strings declared in a node + _drivers: List of valid driver names found in drivers/ + _driver_aliases: Dict that holds aliases for driver names + key: Driver alias declared with + U_BOOT_DRIVER_ALIAS(driver_alias, driver_name) + value: Driver name declared with U_BOOT_DRIVER(driver_name) + _links: List of links to be included in dm_populate_phandle_data() """ - def __init__(self, dtb_fname, include_disabled): + def __init__(self, dtb_fname, include_disabled, warning_disabled): self._fdt = None self._dtb_fname = dtb_fname self._valid_nodes = None self._include_disabled = include_disabled self._outfile = None + self._warning_disabled = warning_disabled self._lines = [] self._aliases = {} + self._drivers = [] + self._driver_aliases = {} + self._links = [] + + def get_normalized_compat_name(self, node): + """Get a node's normalized compat name + + Returns a valid driver name by retrieving node's first compatible + string as a C identifier and performing a check against _drivers + and a lookup in driver_aliases printing a warning in case of failure. + + Args: + node: Node object to check + Return: + Tuple: + Driver name associated with the first compatible string + List of C identifiers for all the other compatible strings + (possibly empty) + In case of no match found, the return will be the same as + get_compat_name() + """ + compat_c, aliases_c = get_compat_name(node) + if compat_c not in self._drivers: + compat_c_old = compat_c + compat_c = self._driver_aliases.get(compat_c) + if not compat_c: + if not self._warning_disabled: + print('WARNING: the driver %s was not found in the driver list' + % (compat_c_old)) + compat_c = compat_c_old + else: + aliases_c = [compat_c_old] + aliases_c + + return compat_c, aliases_c def setup_output(self, fname): """Set up the output destination @@ -211,7 +258,7 @@ class DtbPlatdata(object): Return: Number of argument cells is this is a phandle, else None """ - if prop.name in ['clocks']: + if prop.name in ['clocks', 'cd-gpios']: if not isinstance(prop.value, list): prop.value = [prop.value] val = prop.value @@ -231,11 +278,14 @@ class DtbPlatdata(object): if not target: raise ValueError("Cannot parse '%s' in node '%s'" % (prop.name, node_name)) - prop_name = '#clock-cells' - cells = target.props.get(prop_name) + cells = None + for prop_name in ['#clock-cells', '#gpio-cells']: + cells = target.props.get(prop_name) + if cells: + break if not cells: - raise ValueError("Node '%s' has no '%s' property" % - (target.name, prop_name)) + raise ValueError("Node '%s' has no cells property" % + (target.name)) num_args = fdt_util.fdt32_to_cpu(cells.value) max_args = max(max_args, num_args) args.append(num_args) @@ -243,6 +293,54 @@ class DtbPlatdata(object): return PhandleInfo(max_args, args) return None + def scan_driver(self, fn): + """Scan a driver file to build a list of driver names and aliases + + This procedure will populate self._drivers and self._driver_aliases + + Args + fn: Driver filename to scan + """ + with open(fn, encoding='utf-8') as fd: + try: + buff = fd.read() + except UnicodeDecodeError: + # This seems to happen on older Python versions + print("Skipping file '%s' due to unicode error" % fn) + return + + # The following re will search for driver names declared as + # U_BOOT_DRIVER(driver_name) + drivers = re.findall('U_BOOT_DRIVER\((.*)\)', buff) + + for driver in drivers: + self._drivers.append(driver) + + # The following re will search for driver aliases declared as + # U_BOOT_DRIVER_ALIAS(alias, driver_name) + driver_aliases = re.findall('U_BOOT_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)', + buff) + + for alias in driver_aliases: # pragma: no cover + if len(alias) != 2: + continue + self._driver_aliases[alias[1]] = alias[0] + + def scan_drivers(self): + """Scan the driver folders to build a list of driver names and aliases + + This procedure will populate self._drivers and self._driver_aliases + + """ + basedir = sys.argv[0].replace('tools/dtoc/dtoc', '') + if basedir == '': + basedir = './' + for (dirpath, dirnames, filenames) in os.walk(basedir): + for fn in filenames: + if not fn.endswith('.c'): + continue + self.scan_driver(dirpath + '/' + fn) + def scan_dtb(self): """Scan the device tree to obtain a tree of nodes and properties @@ -353,7 +451,7 @@ class DtbPlatdata(object): """ structs = {} for node in self._valid_nodes: - node_name, _ = get_compat_name(node) + node_name, _ = self.get_normalized_compat_name(node) fields = {} # Get a list of all the valid properties in this node. @@ -377,14 +475,14 @@ class DtbPlatdata(object): upto = 0 for node in self._valid_nodes: - node_name, _ = get_compat_name(node) + node_name, _ = self.get_normalized_compat_name(node) struct = structs[node_name] for name, prop in node.props.items(): if name not in PROP_IGNORE_LIST and name[0] != '#': prop.Widen(struct[name]) upto += 1 - struct_name, aliases = get_compat_name(node) + struct_name, aliases = self.get_normalized_compat_name(node) for alias in aliases: self._aliases[alias] = struct_name @@ -461,9 +559,9 @@ class DtbPlatdata(object): Args: node: node to output """ - struct_name, _ = get_compat_name(node) + struct_name, _ = self.get_normalized_compat_name(node) var_name = conv_name_to_c(node.name) - self.buf('static const struct %s%s %s%s = {\n' % + self.buf('static struct %s%s %s%s = {\n' % (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) for pname in sorted(node.props): prop = node.props[pname] @@ -482,6 +580,7 @@ class DtbPlatdata(object): if info: # Process the list as pairs of (phandle, id) pos = 0 + item = 0 for args in info.args: phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) @@ -491,8 +590,16 @@ class DtbPlatdata(object): for i in range(args): arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i]))) pos += 1 + args - vals.append('\t{&%s%s, {%s}}' % (VAL_PREFIX, name, - ', '.join(arg_values))) + # node member is filled with NULL as the real value + # will be update at run-time during dm_init_and_scan() + # by dm_populate_phandle_data() + vals.append('\t{NULL, {%s}}' % (', '.join(arg_values))) + var_node = '%s%s.%s[%d].node' % \ + (VAL_PREFIX, var_name, member_name, item) + # Save the the link information to be use to define + # dm_populate_phandle_data() + self._links.append({'var_node': var_node, 'dev_name': name}) + item += 1 for val in vals: self.buf('\n\t\t%s,' % val) else: @@ -548,8 +655,18 @@ class DtbPlatdata(object): self.output_node(node) nodes_to_output.remove(node) + # Define dm_populate_phandle_data() which will add the linking between + # nodes using DM_GET_DEVICE + # dtv_dmc_at_xxx.clocks[0].node = DM_GET_DEVICE(clock_controller_at_xxx) + self.buf('void dm_populate_phandle_data(void) {\n') + for l in self._links: + self.buf('\t%s = DM_GET_DEVICE(%s);\n' % + (l['var_node'], l['dev_name'])) + self.buf('}\n') + + self.out(''.join(self.get_buf())) -def run_steps(args, dtb_file, include_disabled, output): +def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False): """Run all the steps of the dtoc tool Args: @@ -561,7 +678,8 @@ def run_steps(args, dtb_file, include_disabled, output): if not args: raise ValueError('Please specify a command: struct, platdata') - plat = DtbPlatdata(dtb_file, include_disabled) + plat = DtbPlatdata(dtb_file, include_disabled, warning_disabled) + plat.scan_drivers() plat.scan_dtb() plat.scan_tree() plat.scan_reg_sizes() diff --git a/tools/dtoc/dtoc_test_driver_alias.dts b/tools/dtoc/dtoc_test_driver_alias.dts new file mode 100644 index 0000000000..da7973b2e5 --- /dev/null +++ b/tools/dtoc/dtoc_test_driver_alias.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test device tree file for dtoc + * + * Copyright 2020 Collabora Ltd. + */ + +/dts-v1/; + +/ { + gpio_a: gpios@0 { + u-boot,dm-pre-reloc; + gpio-controller; + compatible = "sandbox_gpio_alias"; + #gpio-cells = <1>; + gpio-bank-name = "a"; + sandbox,gpio-count = <20>; + }; + +}; diff --git a/tools/dtoc/dtoc_test_invalid_driver.dts b/tools/dtoc/dtoc_test_invalid_driver.dts new file mode 100644 index 0000000000..914ac3e899 --- /dev/null +++ b/tools/dtoc/dtoc_test_invalid_driver.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test device tree file for dtoc + * + * Copyright 2017 Google, Inc + */ + +/dts-v1/; + +/ { + spl-test { + u-boot,dm-pre-reloc; + compatible = "invalid"; + }; +}; diff --git a/tools/dtoc/dtoc_test_phandle_cd_gpios.dts b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts new file mode 100644 index 0000000000..241743e73e --- /dev/null +++ b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test device tree file for dtoc + * + * Copyright 2020 Collabora Ltd. + */ + +/dts-v1/; + +/ { + phandle: phandle-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <0>; + #gpio-cells = <0>; + }; + + phandle_1: phandle2-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <1>; + #gpio-cells = <1>; + }; + phandle_2: phandle3-target { + u-boot,dm-pre-reloc; + compatible = "target"; + intval = <2>; + #gpio-cells = <2>; + }; + + phandle-source { + u-boot,dm-pre-reloc; + compatible = "source"; + cd-gpios = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>; + }; + + phandle-source2 { + u-boot,dm-pre-reloc; + compatible = "source"; + cd-gpios = <&phandle>; + }; +}; diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 8498e8303c..3c8e343b1f 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -12,6 +12,7 @@ tool. import collections import os import struct +import sys import unittest from dtoc import dtb_platdata @@ -47,6 +48,9 @@ C_HEADER = '''/* #include <dt-structs.h> ''' +C_EMPTY_POPULATE_PHANDLE_DATA = '''void dm_populate_phandle_data(void) { +} +''' def get_dtb_file(dts_fname, capture_stderr=False): @@ -101,6 +105,10 @@ class TestDtoc(unittest.TestCase): print('Failures written to /tmp/binman.{expected,actual}') self.assertEquals(expected, actual) + + def run_test(self, args, dtb_file, output): + dtb_platdata.run_steps(args, dtb_file, False, output, True) + def test_name(self): """Test conversion of device tree names to C identifiers""" self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12')) @@ -154,21 +162,22 @@ class TestDtoc(unittest.TestCase): """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) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: lines = infile.read().splitlines() self.assertEqual(HEADER.splitlines(), lines) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: lines = infile.read().splitlines() - self.assertEqual(C_HEADER.splitlines() + [''], lines) + self.assertEqual(C_HEADER.splitlines() + [''] + + C_EMPTY_POPULATE_PHANDLE_DATA.splitlines(), 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) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -193,11 +202,11 @@ struct dtd_sandbox_spl_test_2 { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_sandbox_spl_test dtv_spl_test = { +static struct dtd_sandbox_spl_test dtv_spl_test = { \t.boolval\t\t= true, \t.bytearray\t\t= {0x6, 0x0, 0x0}, \t.byteval\t\t= 0x5, @@ -215,7 +224,7 @@ U_BOOT_DEVICE(spl_test) = { \t.platdata_size\t= sizeof(dtv_spl_test), }; -static const struct dtd_sandbox_spl_test dtv_spl_test2 = { +static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.bytearray\t\t= {0x1, 0x23, 0x34}, \t.byteval\t\t= 0x8, \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, @@ -231,7 +240,7 @@ U_BOOT_DEVICE(spl_test2) = { \t.platdata_size\t= sizeof(dtv_spl_test2), }; -static const struct dtd_sandbox_spl_test dtv_spl_test3 = { +static struct dtd_sandbox_spl_test dtv_spl_test3 = { \t.stringarray\t\t= {"one", "", ""}, }; U_BOOT_DEVICE(spl_test3) = { @@ -240,7 +249,7 @@ U_BOOT_DEVICE(spl_test3) = { \t.platdata_size\t= sizeof(dtv_spl_test3), }; -static const struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { +static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = { }; U_BOOT_DEVICE(spl_test4) = { \t.name\t\t= "sandbox_spl_test_2", @@ -248,7 +257,7 @@ U_BOOT_DEVICE(spl_test4) = { \t.platdata_size\t= sizeof(dtv_spl_test4), }; -static const struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { +static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = { }; U_BOOT_DEVICE(i2c_at_0) = { \t.name\t\t= "sandbox_i2c_test", @@ -256,7 +265,7 @@ U_BOOT_DEVICE(i2c_at_0) = { \t.platdata_size\t= sizeof(dtv_i2c_at_0), }; -static const struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { +static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = { \t.low_power\t\t= true, \t.reg\t\t\t= {0x9, 0x0}, }; @@ -266,13 +275,78 @@ U_BOOT_DEVICE(pmic_at_9) = { \t.platdata_size\t= sizeof(dtv_pmic_at_9), }; +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) + + def test_driver_alias(self): + """Test output from a device tree file with a driver alias""" + dtb_file = get_dtb_file('dtoc_test_driver_alias.dts') + output = tools.GetOutputFilename('output') + self.run_test(['struct'], dtb_file, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(HEADER + ''' +struct dtd_sandbox_gpio { +\tconst char *\tgpio_bank_name; +\tbool\t\tgpio_controller; +\tfdt32_t\t\tsandbox_gpio_count; +}; +#define dtd_sandbox_gpio_alias dtd_sandbox_gpio +''', data) + + self.run_test(['platdata'], dtb_file, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(C_HEADER + ''' +static struct dtd_sandbox_gpio dtv_gpios_at_0 = { +\t.gpio_bank_name\t\t= "a", +\t.gpio_controller\t= true, +\t.sandbox_gpio_count\t= 0x14, +}; +U_BOOT_DEVICE(gpios_at_0) = { +\t.name\t\t= "sandbox_gpio", +\t.platdata\t= &dtv_gpios_at_0, +\t.platdata_size\t= sizeof(dtv_gpios_at_0), +}; + +void dm_populate_phandle_data(void) { +} +''', data) + + def test_invalid_driver(self): + """Test output from a device tree file with an invalid driver""" + dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts') + output = tools.GetOutputFilename('output') + with test_util.capture_sys_output() as (stdout, stderr): + dtb_platdata.run_steps(['struct'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(HEADER + ''' +struct dtd_invalid { +}; +''', data) + + with test_util.capture_sys_output() as (stdout, stderr): + dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + with open(output) as infile: + data = infile.read() + self._CheckStrings(C_HEADER + ''' +static struct dtd_invalid dtv_spl_test = { +}; +U_BOOT_DEVICE(spl_test) = { +\t.name\t\t= "invalid", +\t.platdata\t= &dtv_spl_test, +\t.platdata_size\t= sizeof(dtv_spl_test), +}; + +void dm_populate_phandle_data(void) { +} ''', 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) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -284,11 +358,11 @@ struct dtd_target { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_target dtv_phandle_target = { +static struct dtd_target dtv_phandle_target = { \t.intval\t\t\t= 0x0, }; U_BOOT_DEVICE(phandle_target) = { @@ -297,7 +371,7 @@ U_BOOT_DEVICE(phandle_target) = { \t.platdata_size\t= sizeof(dtv_phandle_target), }; -static const struct dtd_target dtv_phandle2_target = { +static struct dtd_target dtv_phandle2_target = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(phandle2_target) = { @@ -306,7 +380,7 @@ U_BOOT_DEVICE(phandle2_target) = { \t.platdata_size\t= sizeof(dtv_phandle2_target), }; -static const struct dtd_target dtv_phandle3_target = { +static struct dtd_target dtv_phandle3_target = { \t.intval\t\t\t= 0x2, }; U_BOOT_DEVICE(phandle3_target) = { @@ -315,12 +389,12 @@ U_BOOT_DEVICE(phandle3_target) = { \t.platdata_size\t= sizeof(dtv_phandle3_target), }; -static const struct dtd_source dtv_phandle_source = { +static struct dtd_source dtv_phandle_source = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}}, -\t\t\t{&dtv_phandle2_target, {11}}, -\t\t\t{&dtv_phandle3_target, {12, 13}}, -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}}, +\t\t\t{NULL, {11}}, +\t\t\t{NULL, {12, 13}}, +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source) = { \t.name\t\t= "source", @@ -328,9 +402,9 @@ U_BOOT_DEVICE(phandle_source) = { \t.platdata_size\t= sizeof(dtv_phandle_source), }; -static const struct dtd_source dtv_phandle_source2 = { +static struct dtd_source dtv_phandle_source2 = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source2) = { \t.name\t\t= "source", @@ -338,13 +412,20 @@ U_BOOT_DEVICE(phandle_source2) = { \t.platdata_size\t= sizeof(dtv_phandle_source2), }; +void dm_populate_phandle_data(void) { +\tdtv_phandle_source.clocks[0].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source.clocks[1].node = DM_GET_DEVICE(phandle2_target); +\tdtv_phandle_source.clocks[2].node = DM_GET_DEVICE(phandle3_target); +\tdtv_phandle_source.clocks[3].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target); +} ''', data) def test_phandle_single(self): """Test output from a node containing a phandle reference""" dtb_file = get_dtb_file('dtoc_test_phandle_single.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -360,11 +441,11 @@ struct dtd_target { """Test that phandle targets are generated before their references""" dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_target dtv_phandle_target = { +static struct dtd_target dtv_phandle_target = { }; U_BOOT_DEVICE(phandle_target) = { \t.name\t\t= "target", @@ -372,9 +453,72 @@ U_BOOT_DEVICE(phandle_target) = { \t.platdata_size\t= sizeof(dtv_phandle_target), }; -static const struct dtd_source dtv_phandle_source2 = { +static struct dtd_source dtv_phandle_source2 = { \t.clocks\t\t\t= { -\t\t\t{&dtv_phandle_target, {}},}, +\t\t\t{NULL, {}},}, +}; +U_BOOT_DEVICE(phandle_source2) = { +\t.name\t\t= "source", +\t.platdata\t= &dtv_phandle_source2, +\t.platdata_size\t= sizeof(dtv_phandle_source2), +}; + +void dm_populate_phandle_data(void) { +\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target); +} +''', data) + + def test_phandle_cd_gpio(self): + """Test that phandle targets are generated when unsing cd-gpios""" + dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts') + output = tools.GetOutputFilename('output') + dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True) + with open(output) as infile: + data = infile.read() + self._CheckStrings(C_HEADER + ''' +static struct dtd_target dtv_phandle_target = { +\t.intval\t\t\t= 0x0, +}; +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_target dtv_phandle2_target = { +\t.intval\t\t\t= 0x1, +}; +U_BOOT_DEVICE(phandle2_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle2_target, +\t.platdata_size\t= sizeof(dtv_phandle2_target), +}; + +static struct dtd_target dtv_phandle3_target = { +\t.intval\t\t\t= 0x2, +}; +U_BOOT_DEVICE(phandle3_target) = { +\t.name\t\t= "target", +\t.platdata\t= &dtv_phandle3_target, +\t.platdata_size\t= sizeof(dtv_phandle3_target), +}; + +static struct dtd_source dtv_phandle_source = { +\t.cd_gpios\t\t= { +\t\t\t{NULL, {}}, +\t\t\t{NULL, {11}}, +\t\t\t{NULL, {12, 13}}, +\t\t\t{NULL, {}},}, +}; +U_BOOT_DEVICE(phandle_source) = { +\t.name\t\t= "source", +\t.platdata\t= &dtv_phandle_source, +\t.platdata_size\t= sizeof(dtv_phandle_source), +}; + +static struct dtd_source dtv_phandle_source2 = { +\t.cd_gpios\t\t= { +\t\t\t{NULL, {}},}, }; U_BOOT_DEVICE(phandle_source2) = { \t.name\t\t= "source", @@ -382,6 +526,13 @@ U_BOOT_DEVICE(phandle_source2) = { \t.platdata_size\t= sizeof(dtv_phandle_source2), }; +void dm_populate_phandle_data(void) { +\tdtv_phandle_source.cd_gpios[0].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source.cd_gpios[1].node = DM_GET_DEVICE(phandle2_target); +\tdtv_phandle_source.cd_gpios[2].node = DM_GET_DEVICE(phandle3_target); +\tdtv_phandle_source.cd_gpios[3].node = DM_GET_DEVICE(phandle_target); +\tdtv_phandle_source2.cd_gpios[0].node = DM_GET_DEVICE(phandle_target); +} ''', data) def test_phandle_bad(self): @@ -390,7 +541,7 @@ U_BOOT_DEVICE(phandle_source2) = { capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) self.assertIn("Cannot parse 'clocks' in node 'phandle-source'", str(e.exception)) @@ -400,15 +551,15 @@ U_BOOT_DEVICE(phandle_source2) = { capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps(['struct'], dtb_file, False, output) - self.assertIn("Node 'phandle-target' has no '#clock-cells' property", + self.run_test(['struct'], dtb_file, output) + self.assertIn("Node 'phandle-target' has no cells property", str(e.exception)) 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) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -419,11 +570,11 @@ struct dtd_compat1 { #define dtd_compat3 dtd_compat1 ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_compat1 dtv_spl_test = { +static struct dtd_compat1 dtv_spl_test = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(spl_test) = { @@ -432,13 +583,13 @@ U_BOOT_DEVICE(spl_test) = { \t.platdata_size\t= sizeof(dtv_spl_test), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses64(self): """Test output from a node with a 'reg' property with na=2, ns=2""" dtb_file = get_dtb_file('dtoc_test_addr64.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -453,11 +604,11 @@ struct dtd_test3 { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DEVICE(test1) = { @@ -466,7 +617,7 @@ U_BOOT_DEVICE(test1) = { \t.platdata_size\t= sizeof(dtv_test1), }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654}, }; U_BOOT_DEVICE(test2) = { @@ -475,7 +626,7 @@ U_BOOT_DEVICE(test2) = { \t.platdata_size\t= sizeof(dtv_test2), }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { @@ -484,13 +635,13 @@ U_BOOT_DEVICE(test3) = { \t.platdata_size\t= sizeof(dtv_test3), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses32(self): """Test output from a node with a 'reg' property with na=1, ns=1""" dtb_file = get_dtb_file('dtoc_test_addr32.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -502,11 +653,11 @@ struct dtd_test2 { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x5678}, }; U_BOOT_DEVICE(test1) = { @@ -515,7 +666,7 @@ U_BOOT_DEVICE(test1) = { \t.platdata_size\t= sizeof(dtv_test1), }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3}, }; U_BOOT_DEVICE(test2) = { @@ -524,13 +675,13 @@ U_BOOT_DEVICE(test2) = { \t.platdata_size\t= sizeof(dtv_test2), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses64_32(self): """Test output from a node with a 'reg' property with na=2, ns=1""" dtb_file = get_dtb_file('dtoc_test_addr64_32.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -545,11 +696,11 @@ struct dtd_test3 { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x123400000000, 0x5678}, }; U_BOOT_DEVICE(test1) = { @@ -558,7 +709,7 @@ U_BOOT_DEVICE(test1) = { \t.platdata_size\t= sizeof(dtv_test1), }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x1234567890123456, 0x98765432}, }; U_BOOT_DEVICE(test2) = { @@ -567,7 +718,7 @@ U_BOOT_DEVICE(test2) = { \t.platdata_size\t= sizeof(dtv_test2), }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { @@ -576,13 +727,13 @@ U_BOOT_DEVICE(test3) = { \t.platdata_size\t= sizeof(dtv_test3), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_addresses32_64(self): """Test output from a node with a 'reg' property with na=1, ns=2""" dtb_file = get_dtb_file('dtoc_test_addr32_64.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -597,11 +748,11 @@ struct dtd_test3 { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_test1 dtv_test1 = { +static struct dtd_test1 dtv_test1 = { \t.reg\t\t\t= {0x1234, 0x567800000000}, }; U_BOOT_DEVICE(test1) = { @@ -610,7 +761,7 @@ U_BOOT_DEVICE(test1) = { \t.platdata_size\t= sizeof(dtv_test1), }; -static const struct dtd_test2 dtv_test2 = { +static struct dtd_test2 dtv_test2 = { \t.reg\t\t\t= {0x12345678, 0x9876543210987654}, }; U_BOOT_DEVICE(test2) = { @@ -619,7 +770,7 @@ U_BOOT_DEVICE(test2) = { \t.platdata_size\t= sizeof(dtv_test2), }; -static const struct dtd_test3 dtv_test3 = { +static struct dtd_test3 dtv_test3 = { \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3}, }; U_BOOT_DEVICE(test3) = { @@ -628,7 +779,7 @@ U_BOOT_DEVICE(test3) = { \t.platdata_size\t= sizeof(dtv_test3), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def test_bad_reg(self): """Test that a reg property with an invalid type generates an error""" @@ -636,7 +787,7 @@ U_BOOT_DEVICE(test3) = { dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) self.assertIn("Node 'spl-test' reg property is not an int", str(e.exception)) @@ -646,7 +797,7 @@ U_BOOT_DEVICE(test3) = { dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)", str(e.exception)) @@ -654,7 +805,7 @@ U_BOOT_DEVICE(test3) = { """Test that a subequent node can add a new property to a struct""" dtb_file = get_dtb_file('dtoc_test_add_prop.dts') output = tools.GetOutputFilename('output') - dtb_platdata.run_steps(['struct'], dtb_file, False, output) + self.run_test(['struct'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(HEADER + ''' @@ -664,11 +815,11 @@ struct dtd_sandbox_spl_test { }; ''', data) - dtb_platdata.run_steps(['platdata'], dtb_file, False, output) + self.run_test(['platdata'], dtb_file, output) with open(output) as infile: data = infile.read() self._CheckStrings(C_HEADER + ''' -static const struct dtd_sandbox_spl_test dtv_spl_test = { +static struct dtd_sandbox_spl_test dtv_spl_test = { \t.intval\t\t\t= 0x1, }; U_BOOT_DEVICE(spl_test) = { @@ -677,7 +828,7 @@ U_BOOT_DEVICE(spl_test) = { \t.platdata_size\t= sizeof(dtv_spl_test), }; -static const struct dtd_sandbox_spl_test dtv_spl_test2 = { +static struct dtd_sandbox_spl_test dtv_spl_test2 = { \t.intarray\t\t= 0x5, }; U_BOOT_DEVICE(spl_test2) = { @@ -686,18 +837,18 @@ U_BOOT_DEVICE(spl_test2) = { \t.platdata_size\t= sizeof(dtv_spl_test2), }; -''', data) +''' + C_EMPTY_POPULATE_PHANDLE_DATA, data) def testStdout(self): """Test output to stdout""" dtb_file = get_dtb_file('dtoc_test_simple.dts') with test_util.capture_sys_output() as (stdout, stderr): - dtb_platdata.run_steps(['struct'], dtb_file, False, '-') + self.run_test(['struct'], dtb_file, '-') def testNoCommand(self): """Test running dtoc without a command""" with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps([], '', False, '') + self.run_test([], '', '') self.assertIn("Please specify a command: struct, platdata", str(e.exception)) @@ -706,6 +857,6 @@ U_BOOT_DEVICE(spl_test2) = { dtb_file = get_dtb_file('dtoc_test_simple.dts') output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: - dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output) + self.run_test(['invalid-cmd'], dtb_file, output) self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)", str(e.exception)) diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py index 98c63af1dd..07c3e2739a 100644 --- a/tools/patman/checkpatch.py +++ b/tools/patman/checkpatch.py @@ -38,7 +38,7 @@ def FindCheckPatch(): sys.exit('Cannot find checkpatch.pl - please put it in your ' + '~/bin directory or use --no-check') -def CheckPatch(fname, verbose=False): +def CheckPatch(fname, verbose=False, show_types=False): """Run checkpatch.pl on a file. Returns: @@ -64,8 +64,10 @@ def CheckPatch(fname, verbose=False): result.problems = [] chk = FindCheckPatch() item = {} - result.stdout = command.Output(chk, '--no-tree', fname, - raise_on_error=False) + args = [chk, '--no-tree'] + if show_types: + args.append('--show-types') + result.stdout = command.Output(*args, fname, raise_on_error=False) #pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE) #stdout, stderr = pipe.communicate() @@ -81,9 +83,10 @@ def CheckPatch(fname, verbose=False): ' checks, (\d+)') re_ok = re.compile('.*has no obvious style problems') re_bad = re.compile('.*has style problems, please review') - re_error = re.compile('ERROR: (.*)') - re_warning = re.compile(emacs_prefix + 'WARNING:(?:[A-Z_]+:)? (.*)') - re_check = re.compile('CHECK: (.*)') + type_name = '([A-Z_]+:)?' + re_error = re.compile('ERROR:%s (.*)' % type_name) + re_warning = re.compile(emacs_prefix + 'WARNING:%s (.*)' % type_name) + re_check = re.compile('CHECK:%s (.*)' % type_name) re_file = re.compile('#\d+: FILE: ([^:]*):(\d+):') re_note = re.compile('NOTE: (.*)') indent = ' ' * 6 @@ -129,13 +132,16 @@ def CheckPatch(fname, verbose=False): check_match = re_check.match(line) subject_match = line.startswith('Subject:') if err_match: - item['msg'] = err_match.group(1) + item['cptype'] = err_match.group(1) + item['msg'] = err_match.group(2) item['type'] = 'error' elif warn_match: - item['msg'] = warn_match.group(1) + item['cptype'] = warn_match.group(1) + item['msg'] = warn_match.group(2) item['type'] = 'warning' elif check_match: - item['msg'] = check_match.group(1) + item['cptype'] = check_match.group(1) + item['msg'] = check_match.group(2) item['type'] = 'check' elif file_match: item['file'] = file_match.group(1) diff --git a/tools/patman/command.py b/tools/patman/command.py index e67ac159e5..bf8ea6c8c3 100644 --- a/tools/patman/command.py +++ b/tools/patman/command.py @@ -5,7 +5,6 @@ import os from patman import cros_subprocess -from patman import tools """Shell command ease-ups for Python.""" @@ -35,9 +34,9 @@ class CommandResult: def ToOutput(self, binary): if not binary: - self.stdout = tools.ToString(self.stdout) - self.stderr = tools.ToString(self.stderr) - self.combined = tools.ToString(self.combined) + self.stdout = self.stdout.decode('utf-8') + self.stderr = self.stderr.decode('utf-8') + self.combined = self.combined.decode('utf-8') return self diff --git a/tools/patman/get_maintainer.py b/tools/patman/get_maintainer.py index 473f0feebf..af4ba15bcd 100644 --- a/tools/patman/get_maintainer.py +++ b/tools/patman/get_maintainer.py @@ -5,17 +5,16 @@ import os from patman import command -from patman import gitutil -def FindGetMaintainer(): +def FindGetMaintainer(try_list): """Look for the get_maintainer.pl script. + Args: + try_list: List of directories to try for the get_maintainer.pl script + Returns: If the script is found we'll return a path to it; else None. """ - try_list = [ - os.path.join(gitutil.GetTopLevel(), 'scripts'), - ] # Look in the list for path in try_list: fname = os.path.join(path, 'get_maintainer.pl') @@ -24,7 +23,7 @@ def FindGetMaintainer(): return None -def GetMaintainer(fname, verbose=False): +def GetMaintainer(dir_list, fname, verbose=False): """Run get_maintainer.pl on a file if we find it. We look for get_maintainer.pl in the 'scripts' directory at the top of @@ -32,12 +31,13 @@ def GetMaintainer(fname, verbose=False): then we fail silently. Args: + dir_list: List of directories to try for the get_maintainer.pl script fname: Path to the patch file to run get_maintainer.pl on. Returns: A list of email addresses to CC to. """ - get_maintainer = FindGetMaintainer() + get_maintainer = FindGetMaintainer(dir_list) if not get_maintainer: if verbose: print("WARNING: Couldn't find get_maintainer.pl") diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index 72fc95d558..5189840eab 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -7,9 +7,7 @@ import os import subprocess import sys -from patman import checkpatch from patman import command -from patman import series from patman import settings from patman import terminal from patman import tools @@ -369,9 +367,9 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname, >>> alias['boys'] = ['fred', ' john'] >>> alias['all'] = ['fred ', 'john', ' mary '] >>> alias[os.getenv('USER')] = ['this-is-me@me.com'] - >>> series = series.Series() - >>> series.to = ['fred'] - >>> series.cc = ['mary'] + >>> series = {} + >>> series['to'] = ['fred'] + >>> series['cc'] = ['mary'] >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \ False, alias) 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ @@ -380,7 +378,7 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname, alias) 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ "m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1' - >>> series.cc = ['all'] + >>> series['cc'] = ['all'] >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, True, 'cc-fname', \ True, alias) 'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \ diff --git a/tools/patman/main.py b/tools/patman/main.py index 0974c84059..28a9a26087 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -25,7 +25,7 @@ from patman import patchstream from patman import project from patman import settings from patman import terminal -from patman import test +from patman import test_checkpatch parser = OptionParser() @@ -80,7 +80,7 @@ specified by tags you place in the commits. Use -n to do a dry run first.""" # Parse options twice: first to get the project and second to handle # defaults properly (which depends on project). (options, args) = parser.parse_args() -settings.Setup(parser, options.project, '') +settings.Setup(gitutil, parser, options.project, '') (options, args) = parser.parse_args() if __name__ != "__main__": @@ -93,7 +93,7 @@ elif options.test: sys.argv = [sys.argv[0]] result = unittest.TestResult() - for module in (test.TestPatch, func_test.TestFunctional): + for module in (test_checkpatch.TestPatch, func_test.TestFunctional): suite = unittest.TestLoader().loadTestsFromTestCase(module) suite.run(result) diff --git a/tools/patman/series.py b/tools/patman/series.py index ca7ca556dc..b7eef37d03 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -263,7 +263,8 @@ class Series(dict): if type(add_maintainers) == type(cc): cc += add_maintainers elif add_maintainers: - cc += get_maintainer.GetMaintainer(commit.patch) + dir_list = [os.path.join(gitutil.GetTopLevel(), 'scripts')] + cc += get_maintainer.GetMaintainer(dir_list, commit.patch) for x in set(cc) & set(settings.bounces): print(col.Color(col.YELLOW, 'Skipping "%s"' % x)) cc = set(cc) - set(settings.bounces) diff --git a/tools/patman/settings.py b/tools/patman/settings.py index ca74fc611f..635561ac05 100644 --- a/tools/patman/settings.py +++ b/tools/patman/settings.py @@ -11,7 +11,6 @@ import os import re from patman import command -from patman import gitutil from patman import tools """Default settings per-project. @@ -185,7 +184,7 @@ def ReadGitAliases(fname): fd.close() -def CreatePatmanConfigFile(config_fname): +def CreatePatmanConfigFile(gitutil, config_fname): """Creates a config file under $(HOME)/.patman if it can't find one. Args: @@ -301,7 +300,7 @@ def GetItems(config, section): except: raise -def Setup(parser, project_name, config_fname=''): +def Setup(gitutil, parser, project_name, config_fname=''): """Set up the settings module by reading config files. Args: @@ -318,7 +317,7 @@ def Setup(parser, project_name, config_fname=''): if not os.path.exists(config_fname): print("No config file found ~/.patman\nCreating one...\n") - CreatePatmanConfigFile(config_fname) + CreatePatmanConfigFile(gitutil, config_fname) config.read(config_fname) diff --git a/tools/patman/test.py b/tools/patman/test_checkpatch.py index e7f709e34c..c9580adb54 100644 --- a/tools/patman/test.py +++ b/tools/patman/test_checkpatch.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # SPDX-License-Identifier: GPL-2.0+ # +# Tests for U-Boot-specific checkpatch.pl features +# # Copyright (c) 2011 The Chromium OS Authors. # @@ -15,11 +17,76 @@ from patman import series from patman import commit -class TestPatch(unittest.TestCase): - """Test this program +class Line: + def __init__(self, fname, text): + self.fname = fname + self.text = text + + +class PatchMaker: + def __init__(self): + self.lines = [] + + def add_line(self, fname, text): + self.lines.append(Line(fname, text)) + + def get_patch_text(self): + base = '''From 125b77450f4c66b8fd9654319520bbe795c9ef31 Mon Sep 17 00:00:00 2001 +From: Simon Glass <sjg@chromium.org> +Date: Sun, 14 Jun 2020 09:45:14 -0600 +Subject: [PATCH] Test commit + +This is a test commit. + +Signed-off-by: Simon Glass <sjg@chromium.org> +--- + +''' + lines = base.splitlines() + + # Create the diffstat + change = 0 + insert = 0 + for line in self.lines: + lines.append(' %s | 1 +' % line.fname) + change += 1 + insert += 1 + lines.append(' %d files changed, %d insertions(+)' % (change, insert)) + lines.append('') + + # Create the patch info for each file + for line in self.lines: + lines.append('diff --git a/%s b/%s' % (line.fname, line.fname)) + lines.append('index 7837d459f18..5ba7840f68e 100644') + lines.append('--- a/%s' % line.fname) + lines.append('+++ b/%s' % line.fname) + lines += ('''@@ -121,6 +121,7 @@ enum uclass_id { + UCLASS_W1, /* Dallas 1-Wire bus */ + UCLASS_W1_EEPROM, /* one-wire EEPROMs */ + UCLASS_WDT, /* Watchdog Timer driver */ ++%s + + UCLASS_COUNT, + UCLASS_INVALID = -1, +''' % line.text).splitlines() + lines.append('---') + lines.append('2.17.1') - TODO: Write tests for the rest of the functionality - """ + return '\n'.join(lines) + + def get_patch(self): + inhandle, inname = tempfile.mkstemp() + infd = os.fdopen(inhandle, 'w') + infd.write(self.get_patch_text()) + infd.close() + return inname + + def run_checkpatch(self): + return checkpatch.CheckPatch(self.get_patch(), show_types=True) + + +class TestPatch(unittest.TestCase): + """Test the u_boot_line() function in checkpatch.pl""" def testBasic(self): """Test basic filter operation""" @@ -281,6 +348,56 @@ index 0000000..2234c87 self.assertEqual(result.lines, 62) os.remove(inf) + def checkSingleMessage(self, pm, msg, pmtype = 'warning'): + """Helper function to run checkpatch and check the result + + Args: + pm: PatchMaker object to use + msg" Expected message (e.g. 'LIVETREE') + pmtype: Type of problem ('error', 'warning') + """ + result = pm.run_checkpatch() + if pmtype == 'warning': + self.assertEqual(result.warnings, 1) + elif pmtype == 'error': + self.assertEqual(result.errors, 1) + if len(result.problems) != 1: + print(result.problems) + self.assertEqual(len(result.problems), 1) + self.assertIn(msg, result.problems[0]['cptype']) + + def testUclass(self): + """Test for possible new uclass""" + pm = PatchMaker() + pm.add_line('include/dm/uclass-id.h', 'UCLASS_WIBBLE,') + self.checkSingleMessage(pm, 'NEW_UCLASS') + + def testLivetree(self): + """Test for Use the livetree API""" + pm = PatchMaker() + pm.add_line('common/main.c', 'fdtdec_do_something()') + self.checkSingleMessage(pm, 'LIVETREE') + + def testNewCommand(self): + """Test for Use the livetree API""" + pm = PatchMaker() + pm.add_line('common/main.c', 'do_wibble(struct cmd_tbl *cmd_tbl)') + self.checkSingleMessage(pm, 'CMD_TEST') + + def testNewCommand(self): + """Test for Use the livetree API""" + pm = PatchMaker() + pm.add_line('common/main.c', '#ifdef CONFIG_YELLOW') + pm.add_line('common/init.h', '#ifdef CONFIG_YELLOW') + pm.add_line('fred.dtsi', '#ifdef CONFIG_YELLOW') + self.checkSingleMessage(pm, "PREFER_IF") + + def testCommandUseDefconfig(self): + """Test for Use the livetree API""" + pm = PatchMaker() + pm.add_line('common/main.c', '#undef CONFIG_CMD_WHICH') + self.checkSingleMessage(pm, 'DEFINE_CONFIG_CMD', 'error') + if __name__ == "__main__": unittest.main() diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py index 4d28d9fc92..aac58fb72f 100644 --- a/tools/patman/test_util.py +++ b/tools/patman/test_util.py @@ -11,7 +11,6 @@ import sys import unittest from patman import command -from patman import test_util from io import StringIO |