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 <libfdt.h> 26 27#include "tests.h" 28#include "testdata.h" 29 30static int path_depth(const char *path) 31{ 32 const char *p; 33 int depth = 0; 34 35 if (path[0] != '/') 36 TEST_BUG(); 37 38 if (strcmp(path, "/") == 0) 39 return 0; 40 for (p = path; *p; p++) 41 if (*p == '/') 42 depth++; 43 44 /* Special case for path == "/" */ 45 if (p == (path + 1)) 46 return 0; 47 else 48 return depth; 49} 50 51static int path_prefix(const char *path, int depth) 52{ 53 const char *p; 54 int i; 55 56 if (path[0] != '/') 57 TEST_BUG(); 58 59 if (depth == 0) 60 return 1; 61 62 p = path; 63 for (i = 0; i < depth; i++) 64 p = p+1 + strcspn(p+1, "/"); 65 66 return p - path; 67} 68 69static void check_supernode_atdepth(struct fdt_header *fdt, const char *path, 70 int depth) 71{ 72 int pdepth = path_depth(path); 73 char *superpath; 74 int nodeoffset, supernodeoffset, superpathoffset, pathprefixlen; 75 int nodedepth; 76 77 pathprefixlen = path_prefix(path, depth); 78 superpath = alloca(pathprefixlen + 1); 79 strncpy(superpath, path, pathprefixlen); 80 superpath[pathprefixlen] = '\0'; 81 82 verbose_printf("Path %s (%d), depth %d, supernode is %s\n", 83 path, pdepth, depth, superpath); 84 85 nodeoffset = fdt_path_offset(fdt, path); 86 if (nodeoffset < 0) 87 FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); 88 superpathoffset = fdt_path_offset(fdt, superpath); 89 if (superpathoffset < 0) 90 FAIL("fdt_path_offset(%s): %s", superpath, 91 fdt_strerror(superpathoffset)); 92 93 supernodeoffset = fdt_supernode_atdepth_offset(fdt, nodeoffset, 94 depth, &nodedepth); 95 if (supernodeoffset < 0) 96 FAIL("fdt_supernode_atdepth_offset(): %s", 97 fdt_strerror(supernodeoffset)); 98 99 if (supernodeoffset != superpathoffset) 100 FAIL("fdt_supernode_atdepth_offset() returns %d instead of %d", 101 supernodeoffset, superpathoffset); 102 103 if (nodedepth != pdepth) 104 FAIL("fdt_supernode_atdept_offset() returns node depth %d " 105 "instead of %d", nodedepth, pdepth); 106} 107 108static void check_supernode_overdepth(struct fdt_header *fdt, const char *path) 109{ 110 int pdepth = path_depth(path); 111 int nodeoffset, err; 112 113 nodeoffset = fdt_path_offset(fdt, path); 114 if (nodeoffset < 0) 115 FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); 116 117 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, pdepth + 1, NULL); 118 if (err != -FDT_ERR_NOTFOUND) 119 FAIL("fdt_supernode_atdept_offset(%s, %d) returns %d instead " 120 "of FDT_ERR_NOTFOUND", path, pdepth+1, err); 121} 122 123static void check_path(struct fdt_header *fdt, const char *path) 124{ 125 int i; 126 127 for (i = 0; i <= path_depth(path); i++) 128 check_supernode_atdepth(fdt, path, i); 129 check_supernode_overdepth(fdt, path); 130} 131int main(int argc, char *argv[]) 132{ 133 void *fdt; 134 135 test_init(argc, argv); 136 fdt = load_blob_arg(argc, argv); 137 138 check_path(fdt, "/"); 139 check_path(fdt, "/subnode@1"); 140 check_path(fdt, "/subnode@2"); 141 check_path(fdt, "/subnode@1/subsubnode"); 142 check_path(fdt, "/subnode@2/subsubnode@0"); 143 144 PASS(); 145} 146