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