|
1 /* |
|
2 * libfdt - Flat Device Tree manipulation |
|
3 * Testcase for fdt_supernode_atdepth_offset() |
|
4 * Copyright (C) 2006 David Gibson, IBM Corporation. |
|
5 * |
|
6 * This library is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU Lesser General Public License |
|
8 * as published by the Free Software Foundation; either version 2.1 of |
|
9 * the License, or (at your option) any later version. |
|
10 * |
|
11 * This library is distributed in the hope that it will be useful, but |
|
12 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 * Lesser General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU Lesser General Public |
|
17 * License along with this library; if not, write to the Free Software |
|
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 */ |
|
20 #include <stdlib.h> |
|
21 #include <stdio.h> |
|
22 #include <string.h> |
|
23 #include <stdint.h> |
|
24 |
|
25 #include <fdt.h> |
|
26 #include <libfdt.h> |
|
27 |
|
28 #include "tests.h" |
|
29 #include "testdata.h" |
|
30 |
|
31 int path_depth(const char *path) |
|
32 { |
|
33 const char *p; |
|
34 int depth = 0; |
|
35 |
|
36 if (path[0] != '/') |
|
37 TEST_BUG(); |
|
38 |
|
39 if (strcmp(path, "/") == 0) |
|
40 return 0; |
|
41 for (p = path; *p; p++) |
|
42 if (*p == '/') |
|
43 depth++; |
|
44 |
|
45 /* Special case for path == "/" */ |
|
46 if (p == (path + 1)) |
|
47 return 0; |
|
48 else |
|
49 return depth; |
|
50 } |
|
51 |
|
52 int path_prefix(const char *path, int depth) |
|
53 { |
|
54 const char *p; |
|
55 int i; |
|
56 |
|
57 if (path[0] != '/') |
|
58 TEST_BUG(); |
|
59 |
|
60 if (depth == 0) |
|
61 return 1; |
|
62 |
|
63 p = path; |
|
64 for (i = 0; i < depth; i++) |
|
65 p = p+1 + strcspn(p+1, "/"); |
|
66 |
|
67 return p - path; |
|
68 } |
|
69 |
|
70 void check_supernode_atdepth(struct fdt_header *fdt, const char *path, |
|
71 int depth) |
|
72 { |
|
73 int pdepth = path_depth(path); |
|
74 char *superpath; |
|
75 int nodeoffset, supernodeoffset, superpathoffset, pathprefixlen; |
|
76 int nodedepth; |
|
77 |
|
78 pathprefixlen = path_prefix(path, depth); |
|
79 superpath = alloca(pathprefixlen + 1); |
|
80 strncpy(superpath, path, pathprefixlen); |
|
81 superpath[pathprefixlen] = '\0'; |
|
82 |
|
83 verbose_printf("Path %s (%d), depth %d, supernode is %s\n", |
|
84 path, pdepth, depth, superpath); |
|
85 |
|
86 nodeoffset = fdt_path_offset(fdt, path); |
|
87 if (nodeoffset < 0) |
|
88 FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); |
|
89 superpathoffset = fdt_path_offset(fdt, superpath); |
|
90 if (superpathoffset < 0) |
|
91 FAIL("fdt_path_offset(%s): %s", superpath, |
|
92 fdt_strerror(superpathoffset)); |
|
93 |
|
94 supernodeoffset = fdt_supernode_atdepth_offset(fdt, nodeoffset, |
|
95 depth, &nodedepth); |
|
96 if (supernodeoffset < 0) |
|
97 FAIL("fdt_supernode_atdepth_offset(): %s", |
|
98 fdt_strerror(supernodeoffset)); |
|
99 |
|
100 if (supernodeoffset != superpathoffset) |
|
101 FAIL("fdt_supernode_atdepth_offset() returns %d instead of %d", |
|
102 supernodeoffset, superpathoffset); |
|
103 |
|
104 if (nodedepth != pdepth) |
|
105 FAIL("fdt_supernode_atdept_offset() returns node depth %d " |
|
106 "instead of %d", nodedepth, pdepth); |
|
107 } |
|
108 |
|
109 void check_supernode_overdepth(struct fdt_header *fdt, const char *path) |
|
110 { |
|
111 int pdepth = path_depth(path); |
|
112 int nodeoffset, err; |
|
113 |
|
114 nodeoffset = fdt_path_offset(fdt, path); |
|
115 if (nodeoffset < 0) |
|
116 FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); |
|
117 |
|
118 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, pdepth + 1, NULL); |
|
119 if (err != -FDT_ERR_NOTFOUND) |
|
120 FAIL("fdt_supernode_atdept_offset(%s, %d) returns %d instead " |
|
121 "of FDT_ERR_NOTFOUND", path, pdepth+1, err); |
|
122 } |
|
123 |
|
124 void check_path(struct fdt_header *fdt, const char *path) |
|
125 { |
|
126 int i; |
|
127 |
|
128 for (i = 0; i <= path_depth(path); i++) |
|
129 check_supernode_atdepth(fdt, path, i); |
|
130 check_supernode_overdepth(fdt, path); |
|
131 } |
|
132 int main(int argc, char *argv[]) |
|
133 { |
|
134 void *fdt; |
|
135 |
|
136 test_init(argc, argv); |
|
137 fdt = load_blob_arg(argc, argv); |
|
138 |
|
139 check_path(fdt, "/"); |
|
140 check_path(fdt, "/subnode@1"); |
|
141 check_path(fdt, "/subnode@2"); |
|
142 check_path(fdt, "/subnode@1/subsubnode"); |
|
143 check_path(fdt, "/subnode@2/subsubnode@0"); |
|
144 |
|
145 PASS(); |
|
146 } |