2 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright (c) 2012 The Chromium OS Authors.
6 """Tests for the dtb_platdata module
8 This includes unit tests for some functions and functional tests for the dtoc
19 from dtoc import dtb_platdata
20 from dtb_platdata import conv_name_to_c
21 from dtb_platdata import get_compat_name
22 from dtb_platdata import get_value
23 from dtb_platdata import tab_to
25 from dtoc import fdt_util
26 from patman import test_util
27 from patman import tools
29 our_path = os.path.dirname(os.path.realpath(__file__))
35 * This file was generated by dtoc from a .dtb (device tree binary) file.
39 #include <linux/libfdt.h>'''
44 * This file was generated by dtoc from a .dtb (device tree binary) file.
47 /* Allow use of U_BOOT_DEVICE() in this file */
52 #include <dt-structs.h>
55 C_EMPTY_POPULATE_PHANDLE_DATA = '''void dm_populate_phandle_data(void) {
60 def get_dtb_file(dts_fname, capture_stderr=False):
61 """Compile a .dts file to a .dtb
64 dts_fname: Filename of .dts file in the current directory
65 capture_stderr: True to capture and discard stderr output
68 Filename of compiled file in output directory
70 return fdt_util.EnsureCompiled(os.path.join(our_path, dts_fname),
71 capture_stderr=capture_stderr)
74 class TestDtoc(unittest.TestCase):
78 tools.PrepareOutputDir(None)
82 def tearDownClass(cls):
83 tools._RemoveOutputDir()
85 def _WritePythonString(self, fname, data):
86 """Write a string with tabs expanded as done in this Python file
89 fname: Filename to write to
90 data: Raw string to convert
92 data = data.replace('\t', '\\t')
93 with open(fname, 'w') as fd:
96 def _CheckStrings(self, expected, actual):
97 """Check that a string matches its expected value
99 If the strings do not match, they are written to the /tmp directory in
100 the same Python format as is used here in the test. This allows for
101 easy comparison and update of the tests.
104 expected: Expected string
105 actual: Actual string
107 if expected != actual:
108 self._WritePythonString('/tmp/binman.expected', expected)
109 self._WritePythonString('/tmp/binman.actual', actual)
110 print('Failures written to /tmp/binman.{expected,actual}')
111 self.assertEquals(expected, actual)
114 def run_test(self, args, dtb_file, output):
115 dtb_platdata.run_steps(args, dtb_file, False, output, True)
118 """Test conversion of device tree names to C identifiers"""
119 self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12'))
120 self.assertEqual('vendor_clock_frequency',
121 conv_name_to_c('vendor,clock-frequency'))
122 self.assertEqual('rockchip_rk3399_sdhci_5_1',
123 conv_name_to_c('rockchip,rk3399-sdhci-5.1'))
125 def test_tab_to(self):
126 """Test operation of tab_to() function"""
127 self.assertEqual('fred ', tab_to(0, 'fred'))
128 self.assertEqual('fred\t', tab_to(1, 'fred'))
129 self.assertEqual('fred was here ', tab_to(1, 'fred was here'))
130 self.assertEqual('fred was here\t\t', tab_to(3, 'fred was here'))
131 self.assertEqual('exactly8 ', tab_to(1, 'exactly8'))
132 self.assertEqual('exactly8\t', tab_to(2, 'exactly8'))
134 def test_get_value(self):
135 """Test operation of get_value() function"""
136 self.assertEqual('0x45',
137 get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
138 self.assertEqual('0x45',
139 get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
140 self.assertEqual('0x0',
141 get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
142 self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
143 self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
145 def test_get_compat_name(self):
146 """Test operation of get_compat_name() function"""
147 Prop = collections.namedtuple('Prop', ['value'])
148 Node = collections.namedtuple('Node', ['props'])
150 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1'])
151 node = Node({'compatible': prop})
152 self.assertEqual((['rockchip_rk3399_sdhci_5_1', 'arasan_sdhci_5_1']),
153 get_compat_name(node))
155 prop = Prop(['rockchip,rk3399-sdhci-5.1'])
156 node = Node({'compatible': prop})
157 self.assertEqual((['rockchip_rk3399_sdhci_5_1']),
158 get_compat_name(node))
160 prop = Prop(['rockchip,rk3399-sdhci-5.1', 'arasan,sdhci-5.1', 'third'])
161 node = Node({'compatible': prop})
162 self.assertEqual((['rockchip_rk3399_sdhci_5_1',
163 'arasan_sdhci_5_1', 'third']),
164 get_compat_name(node))
166 def test_empty_file(self):
167 """Test output from a device tree file with no nodes"""
168 dtb_file = get_dtb_file('dtoc_test_empty.dts')
169 output = tools.GetOutputFilename('output')
170 self.run_test(['struct'], dtb_file, output)
171 with open(output) as infile:
172 lines = infile.read().splitlines()
173 self.assertEqual(HEADER.splitlines(), lines)
175 self.run_test(['platdata'], dtb_file, output)
176 with open(output) as infile:
177 lines = infile.read().splitlines()
178 self.assertEqual(C_HEADER.splitlines() + [''] +
179 C_EMPTY_POPULATE_PHANDLE_DATA.splitlines(), lines)
181 def test_simple(self):
182 """Test output from some simple nodes with various types of data"""
183 dtb_file = get_dtb_file('dtoc_test_simple.dts')
184 output = tools.GetOutputFilename('output')
185 self.run_test(['struct'], dtb_file, output)
186 with open(output) as infile:
188 self._CheckStrings(HEADER + '''
189 struct dtd_sandbox_i2c_test {
191 struct dtd_sandbox_pmic_test {
195 struct dtd_sandbox_spl_test {
196 \tconst char * acpi_name;
198 \tunsigned char\tbytearray[3];
199 \tunsigned char\tbyteval;
200 \tfdt32_t\t\tintarray[4];
202 \tunsigned char\tlongbytearray[9];
203 \tunsigned char\tnotstring[5];
204 \tconst char *\tstringarray[3];
205 \tconst char *\tstringval;
207 struct dtd_sandbox_spl_test_2 {
211 self.run_test(['platdata'], dtb_file, output)
212 with open(output) as infile:
214 self._CheckStrings(C_HEADER + '''
215 /* Node /i2c@0 index 0 */
216 static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
218 U_BOOT_DEVICE(i2c_at_0) = {
219 \t.name\t\t= "sandbox_i2c_test",
220 \t.platdata\t= &dtv_i2c_at_0,
221 \t.platdata_size\t= sizeof(dtv_i2c_at_0),
225 /* Node /i2c@0/pmic@9 index 1 */
226 static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
227 \t.low_power\t\t= true,
228 \t.reg\t\t\t= {0x9, 0x0},
230 U_BOOT_DEVICE(pmic_at_9) = {
231 \t.name\t\t= "sandbox_pmic_test",
232 \t.platdata\t= &dtv_pmic_at_9,
233 \t.platdata_size\t= sizeof(dtv_pmic_at_9),
237 /* Node /spl-test index 2 */
238 static struct dtd_sandbox_spl_test dtv_spl_test = {
239 \t.boolval\t\t= true,
240 \t.bytearray\t\t= {0x6, 0x0, 0x0},
242 \t.intarray\t\t= {0x2, 0x3, 0x4, 0x0},
243 \t.intval\t\t\t= 0x1,
244 \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
246 \t.notstring\t\t= {0x20, 0x21, 0x22, 0x10, 0x0},
247 \t.stringarray\t\t= {"multi-word", "message", ""},
248 \t.stringval\t\t= "message",
250 U_BOOT_DEVICE(spl_test) = {
251 \t.name\t\t= "sandbox_spl_test",
252 \t.platdata\t= &dtv_spl_test,
253 \t.platdata_size\t= sizeof(dtv_spl_test),
257 /* Node /spl-test2 index 3 */
258 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
259 \t.acpi_name\t\t= "\\\\_SB.GPO0",
260 \t.bytearray\t\t= {0x1, 0x23, 0x34},
262 \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
263 \t.intval\t\t\t= 0x3,
264 \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0x0, 0x0, 0x0, 0x0,
266 \t.stringarray\t\t= {"another", "multi-word", "message"},
267 \t.stringval\t\t= "message2",
269 U_BOOT_DEVICE(spl_test2) = {
270 \t.name\t\t= "sandbox_spl_test",
271 \t.platdata\t= &dtv_spl_test2,
272 \t.platdata_size\t= sizeof(dtv_spl_test2),
276 /* Node /spl-test3 index 4 */
277 static struct dtd_sandbox_spl_test dtv_spl_test3 = {
278 \t.longbytearray\t\t= {0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
280 \t.stringarray\t\t= {"one", "", ""},
282 U_BOOT_DEVICE(spl_test3) = {
283 \t.name\t\t= "sandbox_spl_test",
284 \t.platdata\t= &dtv_spl_test3,
285 \t.platdata_size\t= sizeof(dtv_spl_test3),
289 /* Node /spl-test4 index 5 */
290 static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
292 U_BOOT_DEVICE(spl_test4) = {
293 \t.name\t\t= "sandbox_spl_test_2",
294 \t.platdata\t= &dtv_spl_test4,
295 \t.platdata_size\t= sizeof(dtv_spl_test4),
299 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
301 def test_driver_alias(self):
302 """Test output from a device tree file with a driver alias"""
303 dtb_file = get_dtb_file('dtoc_test_driver_alias.dts')
304 output = tools.GetOutputFilename('output')
305 self.run_test(['struct'], dtb_file, output)
306 with open(output) as infile:
308 self._CheckStrings(HEADER + '''
309 struct dtd_sandbox_gpio {
310 \tconst char *\tgpio_bank_name;
311 \tbool\t\tgpio_controller;
312 \tfdt32_t\t\tsandbox_gpio_count;
316 self.run_test(['platdata'], dtb_file, output)
317 with open(output) as infile:
319 self._CheckStrings(C_HEADER + '''
320 /* Node /gpios@0 index 0 */
321 static struct dtd_sandbox_gpio dtv_gpios_at_0 = {
322 \t.gpio_bank_name\t\t= "a",
323 \t.gpio_controller\t= true,
324 \t.sandbox_gpio_count\t= 0x14,
326 U_BOOT_DEVICE(gpios_at_0) = {
327 \t.name\t\t= "sandbox_gpio",
328 \t.platdata\t= &dtv_gpios_at_0,
329 \t.platdata_size\t= sizeof(dtv_gpios_at_0),
333 void dm_populate_phandle_data(void) {
337 def test_invalid_driver(self):
338 """Test output from a device tree file with an invalid driver"""
339 dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts')
340 output = tools.GetOutputFilename('output')
341 with test_util.capture_sys_output() as (stdout, stderr):
342 dtb_platdata.run_steps(['struct'], dtb_file, False, output)
343 with open(output) as infile:
345 self._CheckStrings(HEADER + '''
350 with test_util.capture_sys_output() as (stdout, stderr):
351 dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
352 with open(output) as infile:
354 self._CheckStrings(C_HEADER + '''
355 /* Node /spl-test index 0 */
356 static struct dtd_invalid dtv_spl_test = {
358 U_BOOT_DEVICE(spl_test) = {
359 \t.name\t\t= "invalid",
360 \t.platdata\t= &dtv_spl_test,
361 \t.platdata_size\t= sizeof(dtv_spl_test),
365 void dm_populate_phandle_data(void) {
369 def test_phandle(self):
370 """Test output from a node containing a phandle reference"""
371 dtb_file = get_dtb_file('dtoc_test_phandle.dts')
372 output = tools.GetOutputFilename('output')
373 self.run_test(['struct'], dtb_file, output)
374 with open(output) as infile:
376 self._CheckStrings(HEADER + '''
378 \tstruct phandle_2_arg clocks[4];
385 self.run_test(['platdata'], dtb_file, output)
386 with open(output) as infile:
388 self._CheckStrings(C_HEADER + '''
389 /* Node /phandle2-target index 0 */
390 static struct dtd_target dtv_phandle2_target = {
391 \t.intval\t\t\t= 0x1,
393 U_BOOT_DEVICE(phandle2_target) = {
394 \t.name\t\t= "target",
395 \t.platdata\t= &dtv_phandle2_target,
396 \t.platdata_size\t= sizeof(dtv_phandle2_target),
400 /* Node /phandle3-target index 1 */
401 static struct dtd_target dtv_phandle3_target = {
402 \t.intval\t\t\t= 0x2,
404 U_BOOT_DEVICE(phandle3_target) = {
405 \t.name\t\t= "target",
406 \t.platdata\t= &dtv_phandle3_target,
407 \t.platdata_size\t= sizeof(dtv_phandle3_target),
411 /* Node /phandle-target index 4 */
412 static struct dtd_target dtv_phandle_target = {
413 \t.intval\t\t\t= 0x0,
415 U_BOOT_DEVICE(phandle_target) = {
416 \t.name\t\t= "target",
417 \t.platdata\t= &dtv_phandle_target,
418 \t.platdata_size\t= sizeof(dtv_phandle_target),
422 /* Node /phandle-source index 2 */
423 static struct dtd_source dtv_phandle_source = {
430 U_BOOT_DEVICE(phandle_source) = {
431 \t.name\t\t= "source",
432 \t.platdata\t= &dtv_phandle_source,
433 \t.platdata_size\t= sizeof(dtv_phandle_source),
437 /* Node /phandle-source2 index 3 */
438 static struct dtd_source dtv_phandle_source2 = {
442 U_BOOT_DEVICE(phandle_source2) = {
443 \t.name\t\t= "source",
444 \t.platdata\t= &dtv_phandle_source2,
445 \t.platdata_size\t= sizeof(dtv_phandle_source2),
449 void dm_populate_phandle_data(void) {
453 def test_phandle_single(self):
454 """Test output from a node containing a phandle reference"""
455 dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
456 output = tools.GetOutputFilename('output')
457 self.run_test(['struct'], dtb_file, output)
458 with open(output) as infile:
460 self._CheckStrings(HEADER + '''
462 \tstruct phandle_0_arg clocks[1];
469 def test_phandle_reorder(self):
470 """Test that phandle targets are generated before their references"""
471 dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
472 output = tools.GetOutputFilename('output')
473 self.run_test(['platdata'], dtb_file, output)
474 with open(output) as infile:
476 self._CheckStrings(C_HEADER + '''
477 /* Node /phandle-target index 1 */
478 static struct dtd_target dtv_phandle_target = {
480 U_BOOT_DEVICE(phandle_target) = {
481 \t.name\t\t= "target",
482 \t.platdata\t= &dtv_phandle_target,
483 \t.platdata_size\t= sizeof(dtv_phandle_target),
487 /* Node /phandle-source2 index 0 */
488 static struct dtd_source dtv_phandle_source2 = {
492 U_BOOT_DEVICE(phandle_source2) = {
493 \t.name\t\t= "source",
494 \t.platdata\t= &dtv_phandle_source2,
495 \t.platdata_size\t= sizeof(dtv_phandle_source2),
499 void dm_populate_phandle_data(void) {
503 def test_phandle_cd_gpio(self):
504 """Test that phandle targets are generated when unsing cd-gpios"""
505 dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts')
506 output = tools.GetOutputFilename('output')
507 dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
508 with open(output) as infile:
510 self._CheckStrings(C_HEADER + '''
511 /* Node /phandle2-target index 0 */
512 static struct dtd_target dtv_phandle2_target = {
513 \t.intval\t\t\t= 0x1,
515 U_BOOT_DEVICE(phandle2_target) = {
516 \t.name\t\t= "target",
517 \t.platdata\t= &dtv_phandle2_target,
518 \t.platdata_size\t= sizeof(dtv_phandle2_target),
522 /* Node /phandle3-target index 1 */
523 static struct dtd_target dtv_phandle3_target = {
524 \t.intval\t\t\t= 0x2,
526 U_BOOT_DEVICE(phandle3_target) = {
527 \t.name\t\t= "target",
528 \t.platdata\t= &dtv_phandle3_target,
529 \t.platdata_size\t= sizeof(dtv_phandle3_target),
533 /* Node /phandle-target index 4 */
534 static struct dtd_target dtv_phandle_target = {
535 \t.intval\t\t\t= 0x0,
537 U_BOOT_DEVICE(phandle_target) = {
538 \t.name\t\t= "target",
539 \t.platdata\t= &dtv_phandle_target,
540 \t.platdata_size\t= sizeof(dtv_phandle_target),
544 /* Node /phandle-source index 2 */
545 static struct dtd_source dtv_phandle_source = {
552 U_BOOT_DEVICE(phandle_source) = {
553 \t.name\t\t= "source",
554 \t.platdata\t= &dtv_phandle_source,
555 \t.platdata_size\t= sizeof(dtv_phandle_source),
559 /* Node /phandle-source2 index 3 */
560 static struct dtd_source dtv_phandle_source2 = {
564 U_BOOT_DEVICE(phandle_source2) = {
565 \t.name\t\t= "source",
566 \t.platdata\t= &dtv_phandle_source2,
567 \t.platdata_size\t= sizeof(dtv_phandle_source2),
571 void dm_populate_phandle_data(void) {
575 def test_phandle_bad(self):
576 """Test a node containing an invalid phandle fails"""
577 dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts',
579 output = tools.GetOutputFilename('output')
580 with self.assertRaises(ValueError) as e:
581 self.run_test(['struct'], dtb_file, output)
582 self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
585 def test_phandle_bad2(self):
586 """Test a phandle target missing its #*-cells property"""
587 dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts',
589 output = tools.GetOutputFilename('output')
590 with self.assertRaises(ValueError) as e:
591 self.run_test(['struct'], dtb_file, output)
592 self.assertIn("Node 'phandle-target' has no cells property",
595 def test_addresses64(self):
596 """Test output from a node with a 'reg' property with na=2, ns=2"""
597 dtb_file = get_dtb_file('dtoc_test_addr64.dts')
598 output = tools.GetOutputFilename('output')
599 self.run_test(['struct'], dtb_file, output)
600 with open(output) as infile:
602 self._CheckStrings(HEADER + '''
614 self.run_test(['platdata'], dtb_file, output)
615 with open(output) as infile:
617 self._CheckStrings(C_HEADER + '''
618 /* Node /test1 index 0 */
619 static struct dtd_test1 dtv_test1 = {
620 \t.reg\t\t\t= {0x1234, 0x5678},
622 U_BOOT_DEVICE(test1) = {
623 \t.name\t\t= "test1",
624 \t.platdata\t= &dtv_test1,
625 \t.platdata_size\t= sizeof(dtv_test1),
629 /* Node /test2 index 1 */
630 static struct dtd_test2 dtv_test2 = {
631 \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
633 U_BOOT_DEVICE(test2) = {
634 \t.name\t\t= "test2",
635 \t.platdata\t= &dtv_test2,
636 \t.platdata_size\t= sizeof(dtv_test2),
640 /* Node /test3 index 2 */
641 static struct dtd_test3 dtv_test3 = {
642 \t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
644 U_BOOT_DEVICE(test3) = {
645 \t.name\t\t= "test3",
646 \t.platdata\t= &dtv_test3,
647 \t.platdata_size\t= sizeof(dtv_test3),
651 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
653 def test_addresses32(self):
654 """Test output from a node with a 'reg' property with na=1, ns=1"""
655 dtb_file = get_dtb_file('dtoc_test_addr32.dts')
656 output = tools.GetOutputFilename('output')
657 self.run_test(['struct'], dtb_file, output)
658 with open(output) as infile:
660 self._CheckStrings(HEADER + '''
669 self.run_test(['platdata'], dtb_file, output)
670 with open(output) as infile:
672 self._CheckStrings(C_HEADER + '''
673 /* Node /test1 index 0 */
674 static struct dtd_test1 dtv_test1 = {
675 \t.reg\t\t\t= {0x1234, 0x5678},
677 U_BOOT_DEVICE(test1) = {
678 \t.name\t\t= "test1",
679 \t.platdata\t= &dtv_test1,
680 \t.platdata_size\t= sizeof(dtv_test1),
684 /* Node /test2 index 1 */
685 static struct dtd_test2 dtv_test2 = {
686 \t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
688 U_BOOT_DEVICE(test2) = {
689 \t.name\t\t= "test2",
690 \t.platdata\t= &dtv_test2,
691 \t.platdata_size\t= sizeof(dtv_test2),
695 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
697 def test_addresses64_32(self):
698 """Test output from a node with a 'reg' property with na=2, ns=1"""
699 dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
700 output = tools.GetOutputFilename('output')
701 self.run_test(['struct'], dtb_file, output)
702 with open(output) as infile:
704 self._CheckStrings(HEADER + '''
716 self.run_test(['platdata'], dtb_file, output)
717 with open(output) as infile:
719 self._CheckStrings(C_HEADER + '''
720 /* Node /test1 index 0 */
721 static struct dtd_test1 dtv_test1 = {
722 \t.reg\t\t\t= {0x123400000000, 0x5678},
724 U_BOOT_DEVICE(test1) = {
725 \t.name\t\t= "test1",
726 \t.platdata\t= &dtv_test1,
727 \t.platdata_size\t= sizeof(dtv_test1),
731 /* Node /test2 index 1 */
732 static struct dtd_test2 dtv_test2 = {
733 \t.reg\t\t\t= {0x1234567890123456, 0x98765432},
735 U_BOOT_DEVICE(test2) = {
736 \t.name\t\t= "test2",
737 \t.platdata\t= &dtv_test2,
738 \t.platdata_size\t= sizeof(dtv_test2),
742 /* Node /test3 index 2 */
743 static struct dtd_test3 dtv_test3 = {
744 \t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
746 U_BOOT_DEVICE(test3) = {
747 \t.name\t\t= "test3",
748 \t.platdata\t= &dtv_test3,
749 \t.platdata_size\t= sizeof(dtv_test3),
753 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
755 def test_addresses32_64(self):
756 """Test output from a node with a 'reg' property with na=1, ns=2"""
757 dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
758 output = tools.GetOutputFilename('output')
759 self.run_test(['struct'], dtb_file, output)
760 with open(output) as infile:
762 self._CheckStrings(HEADER + '''
774 self.run_test(['platdata'], dtb_file, output)
775 with open(output) as infile:
777 self._CheckStrings(C_HEADER + '''
778 /* Node /test1 index 0 */
779 static struct dtd_test1 dtv_test1 = {
780 \t.reg\t\t\t= {0x1234, 0x567800000000},
782 U_BOOT_DEVICE(test1) = {
783 \t.name\t\t= "test1",
784 \t.platdata\t= &dtv_test1,
785 \t.platdata_size\t= sizeof(dtv_test1),
789 /* Node /test2 index 1 */
790 static struct dtd_test2 dtv_test2 = {
791 \t.reg\t\t\t= {0x12345678, 0x9876543210987654},
793 U_BOOT_DEVICE(test2) = {
794 \t.name\t\t= "test2",
795 \t.platdata\t= &dtv_test2,
796 \t.platdata_size\t= sizeof(dtv_test2),
800 /* Node /test3 index 2 */
801 static struct dtd_test3 dtv_test3 = {
802 \t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
804 U_BOOT_DEVICE(test3) = {
805 \t.name\t\t= "test3",
806 \t.platdata\t= &dtv_test3,
807 \t.platdata_size\t= sizeof(dtv_test3),
811 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
813 def test_bad_reg(self):
814 """Test that a reg property with an invalid type generates an error"""
815 # Capture stderr since dtc will emit warnings for this file
816 dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
817 output = tools.GetOutputFilename('output')
818 with self.assertRaises(ValueError) as e:
819 self.run_test(['struct'], dtb_file, output)
820 self.assertIn("Node 'spl-test' reg property is not an int",
823 def test_bad_reg2(self):
824 """Test that a reg property with an invalid cell count is detected"""
825 # Capture stderr since dtc will emit warnings for this file
826 dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
827 output = tools.GetOutputFilename('output')
828 with self.assertRaises(ValueError) as e:
829 self.run_test(['struct'], dtb_file, output)
830 self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
833 def test_add_prop(self):
834 """Test that a subequent node can add a new property to a struct"""
835 dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
836 output = tools.GetOutputFilename('output')
837 self.run_test(['struct'], dtb_file, output)
838 with open(output) as infile:
840 self._CheckStrings(HEADER + '''
841 struct dtd_sandbox_spl_test {
842 \tfdt32_t\t\tintarray;
847 self.run_test(['platdata'], dtb_file, output)
848 with open(output) as infile:
850 self._CheckStrings(C_HEADER + '''
851 /* Node /spl-test index 0 */
852 static struct dtd_sandbox_spl_test dtv_spl_test = {
853 \t.intval\t\t\t= 0x1,
855 U_BOOT_DEVICE(spl_test) = {
856 \t.name\t\t= "sandbox_spl_test",
857 \t.platdata\t= &dtv_spl_test,
858 \t.platdata_size\t= sizeof(dtv_spl_test),
862 /* Node /spl-test2 index 1 */
863 static struct dtd_sandbox_spl_test dtv_spl_test2 = {
864 \t.intarray\t\t= 0x5,
866 U_BOOT_DEVICE(spl_test2) = {
867 \t.name\t\t= "sandbox_spl_test",
868 \t.platdata\t= &dtv_spl_test2,
869 \t.platdata_size\t= sizeof(dtv_spl_test2),
873 ''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
875 def testStdout(self):
876 """Test output to stdout"""
877 dtb_file = get_dtb_file('dtoc_test_simple.dts')
878 with test_util.capture_sys_output() as (stdout, stderr):
879 self.run_test(['struct'], dtb_file, '-')
881 def testNoCommand(self):
882 """Test running dtoc without a command"""
883 with self.assertRaises(ValueError) as e:
884 self.run_test([], '', '')
885 self.assertIn("Please specify a command: struct, platdata",
888 def testBadCommand(self):
889 """Test running dtoc with an invalid command"""
890 dtb_file = get_dtb_file('dtoc_test_simple.dts')
891 output = tools.GetOutputFilename('output')
892 with self.assertRaises(ValueError) as e:
893 self.run_test(['invalid-cmd'], dtb_file, output)
894 self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
897 def testScanDrivers(self):
898 """Test running dtoc with additional drivers to scan"""
899 dtb_file = get_dtb_file('dtoc_test_simple.dts')
900 output = tools.GetOutputFilename('output')
901 with test_util.capture_sys_output() as (stdout, stderr):
902 dtb_platdata.run_steps(['struct'], dtb_file, False, output, True,
903 [None, '', 'tools/dtoc/dtoc_test_scan_drivers.cxx'])
905 def testUnicodeError(self):
906 """Test running dtoc with an invalid unicode file
908 To be able to perform this test without adding a weird text file which
909 would produce issues when using checkpatch.pl or patman, generate the
910 file at runtime and then process it.
912 dtb_file = get_dtb_file('dtoc_test_simple.dts')
913 output = tools.GetOutputFilename('output')
914 driver_fn = '/tmp/' + next(tempfile._get_candidate_names())
915 with open(driver_fn, 'wb+') as df:
918 with test_util.capture_sys_output() as (stdout, stderr):
919 dtb_platdata.run_steps(['struct'], dtb_file, False, output, True,