1 /*- 2 * Copyright (c) 2013 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <sys/wait.h> 35 #include <sys/nv.h> 36 37 #include <err.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 static int ntest = 1; 45 46 #define CHECK(expr) do { \ 47 if ((expr)) \ 48 printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ 49 else \ 50 printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ 51 ntest++; \ 52 } while (0) 53 54 #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) 55 56 static void 57 child(int sock) 58 { 59 nvlist_t *nvl; 60 nvlist_t *empty; 61 62 nvl = nvlist_create(0); 63 empty = nvlist_create(0); 64 65 nvlist_add_bool(nvl, "nvlist/bool/true", true); 66 nvlist_add_bool(nvl, "nvlist/bool/false", false); 67 nvlist_add_number(nvl, "nvlist/number/0", 0); 68 nvlist_add_number(nvl, "nvlist/number/1", 1); 69 nvlist_add_number(nvl, "nvlist/number/-1", -1); 70 nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); 71 nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); 72 nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); 73 nvlist_add_string(nvl, "nvlist/string/", ""); 74 nvlist_add_string(nvl, "nvlist/string/x", "x"); 75 nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); 76 nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); 77 nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); 78 nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); 79 nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty); 80 nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); 81 82 nvlist_send(sock, nvl); 83 84 nvlist_destroy(nvl); 85 } 86 87 static void 88 parent(int sock) 89 { 90 nvlist_t *nvl; 91 const nvlist_t *cnvl, *empty; 92 const char *name, *cname; 93 void *cookie, *ccookie; 94 int type, ctype; 95 size_t size; 96 97 nvl = nvlist_recv(sock, 0); 98 CHECK(nvlist_error(nvl) == 0); 99 if (nvlist_error(nvl) != 0) 100 err(1, "nvlist_recv() failed"); 101 102 cookie = NULL; 103 104 name = nvlist_next(nvl, &type, &cookie); 105 CHECK(name != NULL); 106 CHECK(type == NV_TYPE_BOOL); 107 CHECK(strcmp(name, "nvlist/bool/true") == 0); 108 CHECK(nvlist_get_bool(nvl, name) == true); 109 110 name = nvlist_next(nvl, &type, &cookie); 111 CHECK(name != NULL); 112 CHECK(type == NV_TYPE_BOOL); 113 CHECK(strcmp(name, "nvlist/bool/false") == 0); 114 CHECK(nvlist_get_bool(nvl, name) == false); 115 116 name = nvlist_next(nvl, &type, &cookie); 117 CHECK(name != NULL); 118 CHECK(type == NV_TYPE_NUMBER); 119 CHECK(strcmp(name, "nvlist/number/0") == 0); 120 CHECK(nvlist_get_number(nvl, name) == 0); 121 122 name = nvlist_next(nvl, &type, &cookie); 123 CHECK(name != NULL); 124 CHECK(type == NV_TYPE_NUMBER); 125 CHECK(strcmp(name, "nvlist/number/1") == 0); 126 CHECK(nvlist_get_number(nvl, name) == 1); 127 128 name = nvlist_next(nvl, &type, &cookie); 129 CHECK(name != NULL); 130 CHECK(type == NV_TYPE_NUMBER); 131 CHECK(strcmp(name, "nvlist/number/-1") == 0); 132 CHECK((int)nvlist_get_number(nvl, name) == -1); 133 134 name = nvlist_next(nvl, &type, &cookie); 135 CHECK(name != NULL); 136 CHECK(type == NV_TYPE_NUMBER); 137 CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0); 138 CHECK(nvlist_get_number(nvl, name) == UINT64_MAX); 139 140 name = nvlist_next(nvl, &type, &cookie); 141 CHECK(name != NULL); 142 CHECK(type == NV_TYPE_NUMBER); 143 CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0); 144 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN); 145 146 name = nvlist_next(nvl, &type, &cookie); 147 CHECK(name != NULL); 148 CHECK(type == NV_TYPE_NUMBER); 149 CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0); 150 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX); 151 152 name = nvlist_next(nvl, &type, &cookie); 153 CHECK(name != NULL); 154 CHECK(type == NV_TYPE_STRING); 155 CHECK(strcmp(name, "nvlist/string/") == 0); 156 CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0); 157 158 name = nvlist_next(nvl, &type, &cookie); 159 CHECK(name != NULL); 160 CHECK(type == NV_TYPE_STRING); 161 CHECK(strcmp(name, "nvlist/string/x") == 0); 162 CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0); 163 164 name = nvlist_next(nvl, &type, &cookie); 165 CHECK(name != NULL); 166 CHECK(type == NV_TYPE_STRING); 167 CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); 168 CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0); 169 170 name = nvlist_next(nvl, &type, &cookie); 171 CHECK(name != NULL); 172 CHECK(type == NV_TYPE_DESCRIPTOR); 173 CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0); 174 CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name))); 175 176 name = nvlist_next(nvl, &type, &cookie); 177 CHECK(name != NULL); 178 CHECK(type == NV_TYPE_BINARY); 179 CHECK(strcmp(name, "nvlist/binary/x") == 0); 180 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0); 181 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0); 182 CHECK(size == 1); 183 184 name = nvlist_next(nvl, &type, &cookie); 185 CHECK(name != NULL); 186 CHECK(type == NV_TYPE_BINARY); 187 CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); 188 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 189 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 190 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); 191 192 name = nvlist_next(nvl, &type, &cookie); 193 CHECK(name != NULL); 194 CHECK(type == NV_TYPE_NVLIST); 195 CHECK(strcmp(name, "nvlist/nvlist/empty") == 0); 196 cnvl = nvlist_get_nvlist(nvl, name); 197 CHECK(nvlist_empty(cnvl)); 198 199 name = nvlist_next(nvl, &type, &cookie); 200 CHECK(name != NULL); 201 CHECK(type == NV_TYPE_NVLIST); 202 CHECK(strcmp(name, "nvlist/nvlist") == 0); 203 cnvl = nvlist_get_nvlist(nvl, name); 204 205 ccookie = NULL; 206 207 cname = nvlist_next(cnvl, &ctype, &ccookie); 208 CHECK(cname != NULL); 209 CHECK(ctype == NV_TYPE_BOOL); 210 CHECK(strcmp(cname, "nvlist/bool/true") == 0); 211 CHECK(nvlist_get_bool(cnvl, cname) == true); 212 213 cname = nvlist_next(cnvl, &ctype, &ccookie); 214 CHECK(cname != NULL); 215 CHECK(ctype == NV_TYPE_BOOL); 216 CHECK(strcmp(cname, "nvlist/bool/false") == 0); 217 CHECK(nvlist_get_bool(cnvl, cname) == false); 218 219 cname = nvlist_next(cnvl, &ctype, &ccookie); 220 CHECK(cname != NULL); 221 CHECK(ctype == NV_TYPE_NUMBER); 222 CHECK(strcmp(cname, "nvlist/number/0") == 0); 223 CHECK(nvlist_get_number(cnvl, cname) == 0); 224 225 cname = nvlist_next(cnvl, &ctype, &ccookie); 226 CHECK(cname != NULL); 227 CHECK(ctype == NV_TYPE_NUMBER); 228 CHECK(strcmp(cname, "nvlist/number/1") == 0); 229 CHECK(nvlist_get_number(cnvl, cname) == 1); 230 231 cname = nvlist_next(cnvl, &ctype, &ccookie); 232 CHECK(cname != NULL); 233 CHECK(ctype == NV_TYPE_NUMBER); 234 CHECK(strcmp(cname, "nvlist/number/-1") == 0); 235 CHECK((int)nvlist_get_number(cnvl, cname) == -1); 236 237 cname = nvlist_next(cnvl, &ctype, &ccookie); 238 CHECK(cname != NULL); 239 CHECK(ctype == NV_TYPE_NUMBER); 240 CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0); 241 CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX); 242 243 cname = nvlist_next(cnvl, &ctype, &ccookie); 244 CHECK(cname != NULL); 245 CHECK(ctype == NV_TYPE_NUMBER); 246 CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0); 247 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN); 248 249 cname = nvlist_next(cnvl, &ctype, &ccookie); 250 CHECK(cname != NULL); 251 CHECK(ctype == NV_TYPE_NUMBER); 252 CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0); 253 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX); 254 255 cname = nvlist_next(cnvl, &ctype, &ccookie); 256 CHECK(cname != NULL); 257 CHECK(ctype == NV_TYPE_STRING); 258 CHECK(strcmp(cname, "nvlist/string/") == 0); 259 CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0); 260 261 cname = nvlist_next(cnvl, &ctype, &ccookie); 262 CHECK(cname != NULL); 263 CHECK(ctype == NV_TYPE_STRING); 264 CHECK(strcmp(cname, "nvlist/string/x") == 0); 265 CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0); 266 267 cname = nvlist_next(cnvl, &ctype, &ccookie); 268 CHECK(cname != NULL); 269 CHECK(ctype == NV_TYPE_STRING); 270 CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); 271 CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0); 272 273 cname = nvlist_next(cnvl, &ctype, &ccookie); 274 CHECK(cname != NULL); 275 CHECK(ctype == NV_TYPE_DESCRIPTOR); 276 CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0); 277 CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname))); 278 279 cname = nvlist_next(cnvl, &ctype, &ccookie); 280 CHECK(cname != NULL); 281 CHECK(ctype == NV_TYPE_BINARY); 282 CHECK(strcmp(cname, "nvlist/binary/x") == 0); 283 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0); 284 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0); 285 CHECK(size == 1); 286 287 cname = nvlist_next(cnvl, &ctype, &ccookie); 288 CHECK(cname != NULL); 289 CHECK(ctype == NV_TYPE_BINARY); 290 CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); 291 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 292 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 293 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); 294 295 cname = nvlist_next(cnvl, &ctype, &ccookie); 296 CHECK(cname != NULL); 297 CHECK(ctype == NV_TYPE_NVLIST); 298 CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0); 299 empty = nvlist_get_nvlist(cnvl, cname); 300 CHECK(nvlist_empty(empty)); 301 302 cname = nvlist_next(cnvl, &ctype, &ccookie); 303 CHECK(cname == NULL); 304 305 name = nvlist_next(nvl, &type, &cookie); 306 CHECK(name == NULL); 307 } 308 309 int 310 main(void) 311 { 312 int status, socks[2]; 313 pid_t pid; 314 315 printf("1..134\n"); 316 fflush(stdout); 317 318 if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) 319 err(1, "socketpair() failed"); 320 pid = fork(); 321 switch (pid) { 322 case -1: 323 /* Failure. */ 324 err(1, "unable to fork"); 325 case 0: 326 /* Child. */ 327 close(socks[0]); 328 child(socks[1]); 329 return (0); 330 default: 331 /* Parent. */ 332 close(socks[1]); 333 parent(socks[0]); 334 break; 335 } 336 337 if (waitpid(pid, &status, 0) < 0) 338 err(1, "waitpid() failed"); 339 340 return (0); 341 } 342