1#!/usr/bin/python 2# SPDX-License-Identifier: GPL-2.0+ 3# Copyright (c) 2018 Google, Inc 4# Written by Simon Glass <sjg@chromium.org> 5# 6 7from optparse import OptionParser 8import glob 9import os 10import sys 11import unittest 12 13# Bring in the patman libraries 14our_path = os.path.dirname(os.path.realpath(__file__)) 15for dirname in ['../patman', '..']: 16 sys.path.insert(0, os.path.join(our_path, dirname)) 17 18import command 19import fdt 20from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL 21from fdt_util import fdt32_to_cpu 22import libfdt 23import test_util 24import tools 25 26class TestFdt(unittest.TestCase): 27 """Tests for the Fdt module 28 29 This includes unit tests for some functions and functional tests for the fdt 30 module. 31 """ 32 @classmethod 33 def setUpClass(cls): 34 tools.PrepareOutputDir(None) 35 36 @classmethod 37 def tearDownClass(cls): 38 tools._FinaliseForTest() 39 40 def setUp(self): 41 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') 42 43 def testFdt(self): 44 """Test that we can open an Fdt""" 45 self.dtb.Scan() 46 root = self.dtb.GetRoot() 47 self.assertTrue(isinstance(root, fdt.Node)) 48 49 def testGetNode(self): 50 """Test the GetNode() method""" 51 node = self.dtb.GetNode('/spl-test') 52 self.assertTrue(isinstance(node, fdt.Node)) 53 node = self.dtb.GetNode('/i2c@0/pmic@9') 54 self.assertTrue(isinstance(node, fdt.Node)) 55 self.assertEqual('pmic@9', node.name) 56 57 def testFlush(self): 58 """Check that we can flush the device tree out to its file""" 59 fname = self.dtb._fname 60 with open(fname) as fd: 61 data = fd.read() 62 os.remove(fname) 63 with self.assertRaises(IOError): 64 open(fname) 65 self.dtb.Flush() 66 with open(fname) as fd: 67 data = fd.read() 68 69 def testPack(self): 70 """Test that packing a device tree works""" 71 self.dtb.Pack() 72 73 def testGetFdt(self): 74 """Tetst that we can access the raw device-tree data""" 75 self.assertTrue(isinstance(self.dtb.GetContents(), bytearray)) 76 77 def testGetProps(self): 78 """Tests obtaining a list of properties""" 79 node = self.dtb.GetNode('/spl-test') 80 props = self.dtb.GetProps(node) 81 self.assertEqual(['boolval', 'bytearray', 'byteval', 'compatible', 82 'intarray', 'intval', 'longbytearray', 83 'stringarray', 'stringval', 'u-boot,dm-pre-reloc'], 84 sorted(props.keys())) 85 86 def testCheckError(self): 87 """Tests the ChecKError() function""" 88 with self.assertRaises(ValueError) as e: 89 self.dtb.CheckErr(-libfdt.NOTFOUND, 'hello') 90 self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception)) 91 92 93class TestNode(unittest.TestCase): 94 """Test operation of the Node class""" 95 96 @classmethod 97 def setUpClass(cls): 98 tools.PrepareOutputDir(None) 99 100 @classmethod 101 def tearDownClass(cls): 102 tools._FinaliseForTest() 103 104 def setUp(self): 105 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') 106 self.node = self.dtb.GetNode('/spl-test') 107 108 def testOffset(self): 109 """Tests that we can obtain the offset of a node""" 110 self.assertTrue(self.node.Offset() > 0) 111 112 def testDelete(self): 113 """Tests that we can delete a property""" 114 node2 = self.dtb.GetNode('/spl-test2') 115 offset1 = node2.Offset() 116 self.node.DeleteProp('intval') 117 offset2 = node2.Offset() 118 self.assertTrue(offset2 < offset1) 119 self.node.DeleteProp('intarray') 120 offset3 = node2.Offset() 121 self.assertTrue(offset3 < offset2) 122 123 def testFindNode(self): 124 """Tests that we can find a node using the _FindNode() functoin""" 125 node = self.dtb.GetRoot()._FindNode('i2c@0') 126 self.assertEqual('i2c@0', node.name) 127 subnode = node._FindNode('pmic@9') 128 self.assertEqual('pmic@9', subnode.name) 129 130 131class TestProp(unittest.TestCase): 132 """Test operation of the Prop class""" 133 134 @classmethod 135 def setUpClass(cls): 136 tools.PrepareOutputDir(None) 137 138 @classmethod 139 def tearDownClass(cls): 140 tools._FinaliseForTest() 141 142 def setUp(self): 143 self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') 144 self.node = self.dtb.GetNode('/spl-test') 145 self.fdt = self.dtb.GetFdtObj() 146 147 def testGetEmpty(self): 148 """Tests the GetEmpty() function for the various supported types""" 149 self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL)) 150 self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE)) 151 self.assertEqual(chr(0) * 4, fdt.Prop.GetEmpty(fdt.TYPE_INT)) 152 self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING)) 153 154 def testGetOffset(self): 155 """Test we can get the offset of a property""" 156 prop = self.node.props['longbytearray'] 157 158 # Add 12, which is sizeof(struct fdt_property), to get to start of data 159 offset = prop.GetOffset() + 12 160 data = self.dtb.GetContents()[offset:offset + len(prop.value)] 161 bytes = [chr(x) for x in data] 162 self.assertEqual(bytes, prop.value) 163 164 def testWiden(self): 165 """Test widening of values""" 166 node2 = self.dtb.GetNode('/spl-test2') 167 prop = self.node.props['intval'] 168 169 # No action 170 prop2 = node2.props['intval'] 171 prop.Widen(prop2) 172 self.assertEqual(fdt.TYPE_INT, prop.type) 173 self.assertEqual(1, fdt32_to_cpu(prop.value)) 174 175 # Convert singla value to array 176 prop2 = self.node.props['intarray'] 177 prop.Widen(prop2) 178 self.assertEqual(fdt.TYPE_INT, prop.type) 179 self.assertTrue(isinstance(prop.value, list)) 180 181 # A 4-byte array looks like a single integer. When widened by a longer 182 # byte array, it should turn into an array. 183 prop = self.node.props['longbytearray'] 184 prop2 = node2.props['longbytearray'] 185 self.assertFalse(isinstance(prop2.value, list)) 186 self.assertEqual(4, len(prop2.value)) 187 prop2.Widen(prop) 188 self.assertTrue(isinstance(prop2.value, list)) 189 self.assertEqual(9, len(prop2.value)) 190 191 # Similarly for a string array 192 prop = self.node.props['stringval'] 193 prop2 = node2.props['stringarray'] 194 self.assertFalse(isinstance(prop.value, list)) 195 self.assertEqual(7, len(prop.value)) 196 prop.Widen(prop2) 197 self.assertTrue(isinstance(prop.value, list)) 198 self.assertEqual(3, len(prop.value)) 199 200 # Enlarging an existing array 201 prop = self.node.props['stringarray'] 202 prop2 = node2.props['stringarray'] 203 self.assertTrue(isinstance(prop.value, list)) 204 self.assertEqual(2, len(prop.value)) 205 prop.Widen(prop2) 206 self.assertTrue(isinstance(prop.value, list)) 207 self.assertEqual(3, len(prop.value)) 208 209 210def RunTests(args): 211 """Run all the test we have for the fdt model 212 213 Args: 214 args: List of positional args provided to fdt. This can hold a test 215 name to execute (as in 'fdt -t testFdt', for example) 216 """ 217 result = unittest.TestResult() 218 sys.argv = [sys.argv[0]] 219 test_name = args and args[0] or None 220 for module in (TestFdt, TestNode, TestProp): 221 if test_name: 222 try: 223 suite = unittest.TestLoader().loadTestsFromName(test_name, module) 224 except AttributeError: 225 continue 226 else: 227 suite = unittest.TestLoader().loadTestsFromTestCase(module) 228 suite.run(result) 229 230 print result 231 for _, err in result.errors: 232 print err 233 for _, err in result.failures: 234 print err 235 236if __name__ != '__main__': 237 sys.exit(1) 238 239parser = OptionParser() 240parser.add_option('-t', '--test', action='store_true', dest='test', 241 default=False, help='run tests') 242(options, args) = parser.parse_args() 243 244# Run our meagre tests 245if options.test: 246 RunTests(args) 247