xref: /netbsd-src/external/gpl2/dtc/dist/tests/stringlist.c (revision cc7d2833ecf67da5a5ddc470841931eb9f6723e4)
1 /*	$NetBSD: stringlist.c,v 1.1.1.3 2019/12/22 12:34:06 skrll Exp $	*/
2 
3 // SPDX-License-Identifier: LGPL-2.1-or-later
4 /*
5  * libfdt - Flat Device Tree manipulation
6  *	Testcase for string handling
7  * Copyright (C) 2015 NVIDIA Corporation
8  */
9 
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdint.h>
14 
15 #include <libfdt.h>
16 
17 #include "tests.h"
18 #include "testdata.h"
19 
check_expected_failure(const void * fdt,const char * path,const char * property)20 static void check_expected_failure(const void *fdt, const char *path,
21 				   const char *property)
22 {
23 	int offset, err;
24 
25 	offset = fdt_path_offset(fdt, "/");
26 	if (offset < 0)
27 		FAIL("Couldn't find path %s", path);
28 
29 	err = fdt_stringlist_count(fdt, offset, "#address-cells");
30 	if (err != -FDT_ERR_BADVALUE)
31 		FAIL("unexpectedly succeeded in parsing #address-cells\n");
32 
33 	err = fdt_stringlist_search(fdt, offset, "#address-cells", "foo");
34 	if (err != -FDT_ERR_BADVALUE)
35 		FAIL("found string in #address-cells: %d\n", err);
36 
37 	/*
38 	 * Note that the #address-cells property contains a small 32-bit
39 	 * unsigned integer, hence some bytes will be zero, and searching for
40 	 * the empty string will succeed.
41 	 *
42 	 * The reason for this oddity is that the function will exit when the
43 	 * first occurrence of the string is found, but in order to determine
44 	 * that the property does not contain a valid string list it would
45 	 * need to process the whole value.
46 	 */
47 	err = fdt_stringlist_search(fdt, offset, "#address-cells", "");
48 	if (err != 0)
49 		FAIL("empty string not found in #address-cells: %d\n", err);
50 
51 	/*
52 	 * fdt_getprop_string() can successfully extract strings from
53 	 * non-string properties. This is because it doesn't
54 	 * necessarily parse the whole property value, which would be
55 	 * necessary for it to determine if a valid string or string
56 	 * list is present.
57 	 */
58 }
59 
check_string_count(const void * fdt,const char * path,const char * property,int count)60 static void check_string_count(const void *fdt, const char *path,
61 			       const char *property, int count)
62 {
63 	int offset, err;
64 
65 	offset = fdt_path_offset(fdt, path);
66 	if (offset < 0)
67 		FAIL("Couldn't find path %s", path);
68 
69 	err = fdt_stringlist_count(fdt, offset, property);
70 	if (err < 0)
71 		FAIL("Couldn't count strings in property %s of node %s: %d\n",
72 		     property, path, err);
73 
74 	if (err != count)
75 		FAIL("String count for property %s of node %s is %d instead of %d\n",
76 		     path, property, err, count);
77 }
78 
check_string_index(const void * fdt,const char * path,const char * property,const char * string,int idx)79 static void check_string_index(const void *fdt, const char *path,
80 			       const char *property, const char *string,
81 			       int idx)
82 {
83 	int offset, err;
84 
85 	offset = fdt_path_offset(fdt, path);
86 	if (offset < 0)
87 		FAIL("Couldn't find path %s", path);
88 
89 	err = fdt_stringlist_search(fdt, offset, property, string);
90 
91 	if (err != idx)
92 		FAIL("Index of %s in property %s of node %s is %d, expected %d\n",
93 		     string, property, path, err, idx);
94 }
95 
check_string(const void * fdt,const char * path,const char * property,int idx,const char * string)96 static void check_string(const void *fdt, const char *path,
97 			 const char *property, int idx,
98 			 const char *string)
99 {
100 	const char *result;
101 	int offset, len;
102 
103 	offset = fdt_path_offset(fdt, path);
104 	if (offset < 0)
105 		FAIL("Couldn't find path %s", path);
106 
107 	result = fdt_stringlist_get(fdt, offset, property, idx, &len);
108 	if (!result)
109 		FAIL("Couldn't extract string %d from property %s of node %s: %d\n",
110 		     idx, property, path, len);
111 
112 	if (strcmp(string, result) != 0)
113 		FAIL("String %d in property %s of node %s is %s, expected %s\n",
114 		     idx, property, path, result, string);
115 }
116 
main(int argc,char * argv[])117 int main(int argc, char *argv[])
118 {
119 	void *fdt;
120 
121 	if (argc != 2)
122 		CONFIG("Usage: %s <dtb file>\n", argv[0]);
123 
124 	test_init(argc, argv);
125 	fdt = load_blob(argv[1]);
126 
127 	check_expected_failure(fdt, "/", "#address-cells");
128 	check_expected_failure(fdt, "/", "#size-cells");
129 
130 	check_string_count(fdt, "/", "compatible", 1);
131 	check_string_count(fdt, "/device", "compatible", 2);
132 	check_string_count(fdt, "/device", "big-endian", 0);
133 
134 	check_string_index(fdt, "/", "compatible", "test-strings", 0);
135 	check_string_index(fdt, "/device", "compatible", "foo", 0);
136 	check_string_index(fdt, "/device", "compatible", "bar", 1);
137 	check_string_index(fdt, "/device", "big-endian", "baz", -1);
138 
139 	check_string(fdt, "/", "compatible", 0, "test-strings");
140 	check_string(fdt, "/device", "compatible", 0, "foo");
141 	check_string(fdt, "/device", "compatible", 1, "bar");
142 
143 	PASS();
144 }
145