1 # -*- coding: utf-8 -*-
2 # SPDX-License-Identifier: GPL-2.0+
4 # Tests for U-Boot-specific checkpatch.pl features
6 # Copyright (c) 2011 The Chromium OS Authors.
13 from patman import checkpatch
14 from patman import gitutil
15 from patman import patchstream
16 from patman import series
17 from patman import commit
21 def __init__(self, fname, text):
30 def add_line(self, fname, text):
31 self.lines.append(Line(fname, text))
33 def get_patch_text(self):
34 base = '''From 125b77450f4c66b8fd9654319520bbe795c9ef31 Mon Sep 17 00:00:00 2001
36 Date: Sun, 14 Jun 2020 09:45:14 -0600
37 Subject: [PATCH] Test commit
39 This is a test commit.
45 lines = base.splitlines()
50 for line in self.lines:
51 lines.append(' %s | 1 +' % line.fname)
54 lines.append(' %d files changed, %d insertions(+)' % (change, insert))
57 # Create the patch info for each file
58 for line in self.lines:
59 lines.append('diff --git a/%s b/%s' % (line.fname, line.fname))
60 lines.append('index 7837d459f18..5ba7840f68e 100644')
61 lines.append('--- a/%s' % line.fname)
62 lines.append('+++ b/%s' % line.fname)
63 lines += ('''@@ -121,6 +121,7 @@ enum uclass_id {
64 UCLASS_W1, /* Dallas 1-Wire bus */
65 UCLASS_W1_EEPROM, /* one-wire EEPROMs */
66 UCLASS_WDT, /* Watchdog Timer driver */
71 ''' % line.text).splitlines()
73 lines.append('2.17.1')
75 return '\n'.join(lines)
78 inhandle, inname = tempfile.mkstemp()
79 infd = os.fdopen(inhandle, 'w')
80 infd.write(self.get_patch_text())
84 def run_checkpatch(self):
85 return checkpatch.CheckPatch(self.get_patch(), show_types=True)
88 class TestPatch(unittest.TestCase):
89 """Test the u_boot_line() function in checkpatch.pl"""
92 """Test basic filter operation"""
95 From 656c9a8c31fa65859d924cd21da920d6ba537fad Mon Sep 17 00:00:00 2001
97 Date: Thu, 28 Apr 2011 09:58:51 -0700
98 Subject: [PATCH (resend) 3/7] Tegra2: Add more clock support
100 This adds functions to enable/disable clocks and reset to on-chip peripherals.
102 cmd/pci.c:152:11: warning: format ‘%llx’ expects argument of type
103 ‘long long unsigned int’, but argument 3 has type
104 ‘u64 {aka long unsigned int}’ [-Wformat=]
106 BUG=chromium-os:13875
107 TEST=build U-Boot for Seaboard, boot
109 Change-Id: I80fe1d0c0b7dd10aa58ce5bb1d9290b6664d5413
111 Review URL: http://codereview.chromium.org/6900006
115 arch/arm/cpu/armv7/tegra2/Makefile | 2 +-
116 arch/arm/cpu/armv7/tegra2/ap20.c | 57 ++----
117 arch/arm/cpu/armv7/tegra2/clock.c | 163 +++++++++++++++++
119 expected='''Message-Id: <19991231235959.0.I80fe1d0c0b7dd10aa58ce5bb1d9290b6664d5413@changeid>
122 From 656c9a8c31fa65859d924cd21da920d6ba537fad Mon Sep 17 00:00:00 2001
124 Date: Thu, 28 Apr 2011 09:58:51 -0700
125 Subject: [PATCH (resend) 3/7] Tegra2: Add more clock support
127 This adds functions to enable/disable clocks and reset to on-chip peripherals.
129 cmd/pci.c:152:11: warning: format ‘%llx’ expects argument of type
130 ‘long long unsigned int’, but argument 3 has type
131 ‘u64 {aka long unsigned int}’ [-Wformat=]
136 arch/arm/cpu/armv7/tegra2/Makefile | 2 +-
137 arch/arm/cpu/armv7/tegra2/ap20.c | 57 ++----
138 arch/arm/cpu/armv7/tegra2/clock.c | 163 +++++++++++++++++
141 inhandle, inname = tempfile.mkstemp()
142 infd = os.fdopen(inhandle, 'w', encoding='utf-8')
146 exphandle, expname = tempfile.mkstemp()
147 expfd = os.fdopen(exphandle, 'w', encoding='utf-8')
148 expfd.write(expected)
151 # Normally by the time we call fix_patch we've already collected
152 # metadata. Here, we haven't, but at least fake up something.
153 # Set the "count" to -1 which tells fix_patch to use a bogus/fixed
154 # time for generating the Message-Id.
155 com = commit.Commit('')
156 com.change_id = 'I80fe1d0c0b7dd10aa58ce5bb1d9290b6664d5413'
159 patchstream.fix_patch(None, inname, series.Series(), com)
161 rc = os.system('diff -u %s %s' % (inname, expname))
162 self.assertEqual(rc, 0)
167 def GetData(self, data_type):
168 data='''From 4924887af52713cabea78420eff03badea8f0035 Mon Sep 17 00:00:00 2001
170 Date: Thu, 7 Apr 2011 10:14:41 -0700
171 Subject: [PATCH 1/4] Add microsecond boot time measurement
173 This defines the basics of a new boot time measurement feature. This allows
174 logging of very accurate time measurements as the boot proceeds, by using
175 an available microsecond counter.
181 common/bootstage.c | 50 ++++++++++++++++++++++++++++++++++++
182 include/bootstage.h | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++
183 include/common.h | 8 ++++++
184 5 files changed, 141 insertions(+), 0 deletions(-)
185 create mode 100644 common/bootstage.c
186 create mode 100644 include/bootstage.h
188 diff --git a/README b/README
189 index 6f3748d..f9e4e65 100644
192 @@ -2026,6 +2026,17 @@ The following options need to be configured:
193 example, some LED's) on your board. At the moment,
194 the following checkpoints are implemented:
196 +- Time boot progress
199 + Define this option to enable microsecond boot stage timing
200 + on supported platforms. For this to work your platform
201 + needs to define a function timer_get_us() which returns the
202 + number of microseconds since reset. This would normally
203 + be done in your SOC or board timer.c file.
205 + You can add calls to bootstage_mark() to set time markers.
207 - Standalone program support:
208 CONFIG_STANDALONE_LOAD_ADDR
210 diff --git a/MAINTAINERS b/MAINTAINERS
211 index b167b028ec..beb7dc634f 100644
214 @@ -474,3 +474,8 @@ S: Maintained
215 T: git git://git.denx.de/u-boot.git
222 +F: common/bootstage.c
223 diff --git a/common/bootstage.c b/common/bootstage.c
225 index 0000000..2234c87
227 +++ b/common/bootstage.c
231 + * Copyright (c) 2011, Google Inc. All rights reserved.
236 + * This module records the progress of boot and arbitrary commands, and
237 + * permits accurate timestamping of each. The records can optionally be
238 + * passed to kernel in the ATAGs
243 +struct bootstage_record {
248 +static struct bootstage_record record[BOOTSTAGE_COUNT];
250 +u32 bootstage_mark(enum bootstage_id id, const char *name)
252 + struct bootstage_record *rec = &record[id];
254 + /* Only record the first event for each */
256 + rec->time_us = (u32)timer_get_us();
260 + %ssomething_else) {
261 + rec->time_us = (u32)timer_get_us();
264 +%sreturn rec->time_us;
270 license = '// SPDX-License-Identifier: GPL-2.0+'
273 if data_type == 'good':
275 elif data_type == 'no-signoff':
277 elif data_type == 'no-license':
279 elif data_type == 'spaces':
281 elif data_type == 'indent':
284 print('not implemented')
285 return data % (signoff, license, tab, indent, tab)
287 def SetupData(self, data_type):
288 inhandle, inname = tempfile.mkstemp()
289 infd = os.fdopen(inhandle, 'w')
290 data = self.GetData(data_type)
296 """Test checkpatch operation"""
297 inf = self.SetupData('good')
298 result = checkpatch.CheckPatch(inf)
299 self.assertEqual(result.ok, True)
300 self.assertEqual(result.problems, [])
301 self.assertEqual(result.errors, 0)
302 self.assertEqual(result.warnings, 0)
303 self.assertEqual(result.checks, 0)
304 self.assertEqual(result.lines, 62)
307 def testNoSignoff(self):
308 inf = self.SetupData('no-signoff')
309 result = checkpatch.CheckPatch(inf)
310 self.assertEqual(result.ok, False)
311 self.assertEqual(len(result.problems), 1)
312 self.assertEqual(result.errors, 1)
313 self.assertEqual(result.warnings, 0)
314 self.assertEqual(result.checks, 0)
315 self.assertEqual(result.lines, 62)
318 def testNoLicense(self):
319 inf = self.SetupData('no-license')
320 result = checkpatch.CheckPatch(inf)
321 self.assertEqual(result.ok, False)
322 self.assertEqual(len(result.problems), 1)
323 self.assertEqual(result.errors, 0)
324 self.assertEqual(result.warnings, 1)
325 self.assertEqual(result.checks, 0)
326 self.assertEqual(result.lines, 62)
329 def testSpaces(self):
330 inf = self.SetupData('spaces')
331 result = checkpatch.CheckPatch(inf)
332 self.assertEqual(result.ok, False)
333 self.assertEqual(len(result.problems), 3)
334 self.assertEqual(result.errors, 0)
335 self.assertEqual(result.warnings, 3)
336 self.assertEqual(result.checks, 0)
337 self.assertEqual(result.lines, 62)
340 def testIndent(self):
341 inf = self.SetupData('indent')
342 result = checkpatch.CheckPatch(inf)
343 self.assertEqual(result.ok, False)
344 self.assertEqual(len(result.problems), 1)
345 self.assertEqual(result.errors, 0)
346 self.assertEqual(result.warnings, 0)
347 self.assertEqual(result.checks, 1)
348 self.assertEqual(result.lines, 62)
351 def checkSingleMessage(self, pm, msg, pmtype = 'warning'):
352 """Helper function to run checkpatch and check the result
355 pm: PatchMaker object to use
356 msg: Expected message (e.g. 'LIVETREE')
357 pmtype: Type of problem ('error', 'warning')
359 result = pm.run_checkpatch()
360 if pmtype == 'warning':
361 self.assertEqual(result.warnings, 1)
362 elif pmtype == 'error':
363 self.assertEqual(result.errors, 1)
364 if len(result.problems) != 1:
365 print(result.problems)
366 self.assertEqual(len(result.problems), 1)
367 self.assertIn(msg, result.problems[0]['cptype'])
369 def testUclass(self):
370 """Test for possible new uclass"""
372 pm.add_line('include/dm/uclass-id.h', 'UCLASS_WIBBLE,')
373 self.checkSingleMessage(pm, 'NEW_UCLASS')
375 def testLivetree(self):
376 """Test for using the livetree API"""
378 pm.add_line('common/main.c', 'fdtdec_do_something()')
379 self.checkSingleMessage(pm, 'LIVETREE')
381 def testNewCommand(self):
382 """Test for adding a new command"""
384 pm.add_line('common/main.c', 'do_wibble(struct cmd_tbl *cmd_tbl)')
385 self.checkSingleMessage(pm, 'CMD_TEST')
387 def testPreferIf(self):
388 """Test for using #ifdef"""
390 pm.add_line('common/main.c', '#ifdef CONFIG_YELLOW')
391 pm.add_line('common/init.h', '#ifdef CONFIG_YELLOW')
392 pm.add_line('fred.dtsi', '#ifdef CONFIG_YELLOW')
393 self.checkSingleMessage(pm, "PREFER_IF")
395 def testCommandUseDefconfig(self):
396 """Test for enabling/disabling commands using preprocesor"""
398 pm.add_line('common/main.c', '#undef CONFIG_CMD_WHICH')
399 self.checkSingleMessage(pm, 'DEFINE_CONFIG_CMD', 'error')
401 def testBarredIncludeInHdr(self):
402 """Test for using a barred include in a header file"""
404 #pm.add_line('include/myfile.h', '#include <common.h>')
405 pm.add_line('include/myfile.h', '#include <dm.h>')
406 self.checkSingleMessage(pm, 'BARRED_INCLUDE_IN_HDR', 'error')
408 def testConfigIsEnabledConfig(self):
409 """Test for accidental CONFIG_IS_ENABLED(CONFIG_*) calls"""
411 pm.add_line('common/main.c', 'if (CONFIG_IS_ENABLED(CONFIG_CLK))')
412 self.checkSingleMessage(pm, 'CONFIG_IS_ENABLED_CONFIG', 'error')
414 def check_struct(self, auto, suffix, warning):
415 """Check one of the warnings for struct naming
418 auto: Auto variable name, e.g. 'per_child_auto'
419 suffix: Suffix to expect on member, e.g. '_priv'
420 warning: Warning name, e.g. 'PRIV_AUTO'
423 pm.add_line('common/main.c', '.%s = sizeof(struct(fred)),' % auto)
424 pm.add_line('common/main.c', '.%s = sizeof(struct(mary%s)),' %
426 self.checkSingleMessage(
427 pm, warning, "struct 'fred' should have a %s suffix" % suffix)
429 def testDmDriverAuto(self):
430 """Check for the correct suffix on 'struct driver' auto members"""
431 self.check_struct('priv_auto', '_priv', 'PRIV_AUTO')
432 self.check_struct('plat_auto', '_plat', 'PLAT_AUTO')
433 self.check_struct('per_child_auto', '_priv', 'CHILD_PRIV_AUTO')
434 self.check_struct('per_child_plat_auto', '_plat', 'CHILD_PLAT_AUTO')
436 def testDmUclassAuto(self):
437 """Check for the correct suffix on 'struct uclass' auto members"""
438 # Some of these are omitted since they match those from struct driver
439 self.check_struct('per_device_auto', '_priv', 'DEVICE_PRIV_AUTO')
440 self.check_struct('per_device_plat_auto', '_plat', 'DEVICE_PLAT_AUTO')
442 def check_strl(self, func):
443 """Check one of the checks for strn(cpy|cat)"""
445 pm.add_line('common/main.c', "strn%s(foo, bar, sizeof(foo));" % func)
446 self.checkSingleMessage(pm, "STRL",
447 "strl%s is preferred over strn%s because it always produces a nul-terminated string\n"
451 """Check for uses of strn(cat|cpy)"""
452 self.check_strl("cat");
453 self.check_strl("cpy");
455 if __name__ == "__main__":