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