blob: 73f41aecf93c77460084bcdbd6c715362b9ff21a [file] [log] [blame]
David Gibson12482372007-08-30 14:54:04 +10001/*
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 */
David Gibson12482372007-08-30 14:54:04 +100020#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
David Gibson01a2d8a2008-08-04 15:30:13 +100031static int path_depth(const char *path)
David Gibson12482372007-08-30 14:54:04 +100032{
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
David Gibson01a2d8a2008-08-04 15:30:13 +100052static int path_prefix(const char *path, int depth)
David Gibson12482372007-08-30 14:54:04 +100053{
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++)
David Gibsoncdcb4152008-06-26 11:03:49 +100065 p = p+1 + strcspn(p+1, "/");
David Gibson12482372007-08-30 14:54:04 +100066
67 return p - path;
68}
69
David Gibson01a2d8a2008-08-04 15:30:13 +100070static void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
David Gibson12482372007-08-30 14:54:04 +100071 int depth)
72{
73 int pdepth = path_depth(path);
74 char *superpath;
David Gibsoncdcb4152008-06-26 11:03:49 +100075 int nodeoffset, supernodeoffset, superpathoffset, pathprefixlen;
David Gibson12482372007-08-30 14:54:04 +100076 int nodedepth;
77
David Gibsoncdcb4152008-06-26 11:03:49 +100078 pathprefixlen = path_prefix(path, depth);
79 superpath = alloca(pathprefixlen + 1);
80 strncpy(superpath, path, pathprefixlen);
81 superpath[pathprefixlen] = '\0';
82
David Gibson12482372007-08-30 14:54:04 +100083 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
David Gibson01a2d8a2008-08-04 15:30:13 +1000109static void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
David Gibson12482372007-08-30 14:54:04 +1000110{
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
David Gibson01a2d8a2008-08-04 15:30:13 +1000124static void check_path(struct fdt_header *fdt, const char *path)
David Gibson12482372007-08-30 14:54:04 +1000125{
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}
132int 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, "/");
David Gibsond2a9da02007-09-28 15:51:04 +1000140 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");
David Gibson12482372007-08-30 14:54:04 +1000144
145 PASS();
146}