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 36 #include <err.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include <nv.h> 44 45 static int ntest = 1; 46 47 #define CHECK(expr) do { \ 48 if ((expr)) \ 49 printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ 50 else \ 51 printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ 52 ntest++; \ 53 } while (0) 54 55 #define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) 56 57 static void 58 child(int sock) 59 { 60 nvlist_t *nvl; 61 nvlist_t *empty; 62 63 nvl = nvlist_create(0); 64 empty = nvlist_create(0); 65 66 nvlist_add_bool(nvl, "nvlist/bool/true", true); 67 nvlist_add_bool(nvl, "nvlist/bool/false", false); 68 nvlist_add_number(nvl, "nvlist/number/0", 0); 69 nvlist_add_number(nvl, "nvlist/number/1", 1); 70 nvlist_add_number(nvl, "nvlist/number/-1", -1); 71 nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); 72 nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); 73 nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); 74 nvlist_add_string(nvl, "nvlist/string/", ""); 75 nvlist_add_string(nvl, "nvlist/string/x", "x"); 76 nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); 77 nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); 78 nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); 79 nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); 80 nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty); 81 nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); 82 83 nvlist_send(sock, nvl); 84 85 nvlist_destroy(nvl); 86 } 87 88 static void 89 parent(int sock) 90 { 91 nvlist_t *nvl; 92 const nvlist_t *cnvl, *empty; 93 const char *name, *cname; 94 void *cookie, *ccookie; 95 int type, ctype; 96 size_t size; 97 98 nvl = nvlist_recv(sock); 99 CHECK(nvlist_error(nvl) == 0); 100 if (nvlist_error(nvl) != 0) 101 err(1, "nvlist_recv() failed"); 102 103 cookie = NULL; 104 105 name = nvlist_next(nvl, &type, &cookie); 106 CHECK(name != NULL); 107 CHECK(type == NV_TYPE_BOOL); 108 CHECK(strcmp(name, "nvlist/bool/true") == 0); 109 CHECK(nvlist_get_bool(nvl, name) == true); 110 111 name = nvlist_next(nvl, &type, &cookie); 112 CHECK(name != NULL); 113 CHECK(type == NV_TYPE_BOOL); 114 CHECK(strcmp(name, "nvlist/bool/false") == 0); 115 CHECK(nvlist_get_bool(nvl, name) == false); 116 117 name = nvlist_next(nvl, &type, &cookie); 118 CHECK(name != NULL); 119 CHECK(type == NV_TYPE_NUMBER); 120 CHECK(strcmp(name, "nvlist/number/0") == 0); 121 CHECK(nvlist_get_number(nvl, name) == 0); 122 123 name = nvlist_next(nvl, &type, &cookie); 124 CHECK(name != NULL); 125 CHECK(type == NV_TYPE_NUMBER); 126 CHECK(strcmp(name, "nvlist/number/1") == 0); 127 CHECK(nvlist_get_number(nvl, name) == 1); 128 129 name = nvlist_next(nvl, &type, &cookie); 130 CHECK(name != NULL); 131 CHECK(type == NV_TYPE_NUMBER); 132 CHECK(strcmp(name, "nvlist/number/-1") == 0); 133 CHECK((int)nvlist_get_number(nvl, name) == -1); 134 135 name = nvlist_next(nvl, &type, &cookie); 136 CHECK(name != NULL); 137 CHECK(type == NV_TYPE_NUMBER); 138 CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0); 139 CHECK(nvlist_get_number(nvl, name) == UINT64_MAX); 140 141 name = nvlist_next(nvl, &type, &cookie); 142 CHECK(name != NULL); 143 CHECK(type == NV_TYPE_NUMBER); 144 CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0); 145 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN); 146 147 name = nvlist_next(nvl, &type, &cookie); 148 CHECK(name != NULL); 149 CHECK(type == NV_TYPE_NUMBER); 150 CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0); 151 CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX); 152 153 name = nvlist_next(nvl, &type, &cookie); 154 CHECK(name != NULL); 155 CHECK(type == NV_TYPE_STRING); 156 CHECK(strcmp(name, "nvlist/string/") == 0); 157 CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0); 158 159 name = nvlist_next(nvl, &type, &cookie); 160 CHECK(name != NULL); 161 CHECK(type == NV_TYPE_STRING); 162 CHECK(strcmp(name, "nvlist/string/x") == 0); 163 CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0); 164 165 name = nvlist_next(nvl, &type, &cookie); 166 CHECK(name != NULL); 167 CHECK(type == NV_TYPE_STRING); 168 CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); 169 CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0); 170 171 name = nvlist_next(nvl, &type, &cookie); 172 CHECK(name != NULL); 173 CHECK(type == NV_TYPE_DESCRIPTOR); 174 CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0); 175 CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name))); 176 177 name = nvlist_next(nvl, &type, &cookie); 178 CHECK(name != NULL); 179 CHECK(type == NV_TYPE_BINARY); 180 CHECK(strcmp(name, "nvlist/binary/x") == 0); 181 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0); 182 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0); 183 CHECK(size == 1); 184 185 name = nvlist_next(nvl, &type, &cookie); 186 CHECK(name != NULL); 187 CHECK(type == NV_TYPE_BINARY); 188 CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); 189 CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 190 CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 191 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); 192 193 name = nvlist_next(nvl, &type, &cookie); 194 CHECK(name != NULL); 195 CHECK(type == NV_TYPE_NVLIST); 196 CHECK(strcmp(name, "nvlist/nvlist/empty") == 0); 197 cnvl = nvlist_get_nvlist(nvl, name); 198 CHECK(nvlist_empty(cnvl)); 199 200 name = nvlist_next(nvl, &type, &cookie); 201 CHECK(name != NULL); 202 CHECK(type == NV_TYPE_NVLIST); 203 CHECK(strcmp(name, "nvlist/nvlist") == 0); 204 cnvl = nvlist_get_nvlist(nvl, name); 205 206 ccookie = NULL; 207 208 cname = nvlist_next(cnvl, &ctype, &ccookie); 209 CHECK(cname != NULL); 210 CHECK(ctype == NV_TYPE_BOOL); 211 CHECK(strcmp(cname, "nvlist/bool/true") == 0); 212 CHECK(nvlist_get_bool(cnvl, cname) == true); 213 214 cname = nvlist_next(cnvl, &ctype, &ccookie); 215 CHECK(cname != NULL); 216 CHECK(ctype == NV_TYPE_BOOL); 217 CHECK(strcmp(cname, "nvlist/bool/false") == 0); 218 CHECK(nvlist_get_bool(cnvl, cname) == false); 219 220 cname = nvlist_next(cnvl, &ctype, &ccookie); 221 CHECK(cname != NULL); 222 CHECK(ctype == NV_TYPE_NUMBER); 223 CHECK(strcmp(cname, "nvlist/number/0") == 0); 224 CHECK(nvlist_get_number(cnvl, cname) == 0); 225 226 cname = nvlist_next(cnvl, &ctype, &ccookie); 227 CHECK(cname != NULL); 228 CHECK(ctype == NV_TYPE_NUMBER); 229 CHECK(strcmp(cname, "nvlist/number/1") == 0); 230 CHECK(nvlist_get_number(cnvl, cname) == 1); 231 232 cname = nvlist_next(cnvl, &ctype, &ccookie); 233 CHECK(cname != NULL); 234 CHECK(ctype == NV_TYPE_NUMBER); 235 CHECK(strcmp(cname, "nvlist/number/-1") == 0); 236 CHECK((int)nvlist_get_number(cnvl, cname) == -1); 237 238 cname = nvlist_next(cnvl, &ctype, &ccookie); 239 CHECK(cname != NULL); 240 CHECK(ctype == NV_TYPE_NUMBER); 241 CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0); 242 CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX); 243 244 cname = nvlist_next(cnvl, &ctype, &ccookie); 245 CHECK(cname != NULL); 246 CHECK(ctype == NV_TYPE_NUMBER); 247 CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0); 248 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN); 249 250 cname = nvlist_next(cnvl, &ctype, &ccookie); 251 CHECK(cname != NULL); 252 CHECK(ctype == NV_TYPE_NUMBER); 253 CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0); 254 CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX); 255 256 cname = nvlist_next(cnvl, &ctype, &ccookie); 257 CHECK(cname != NULL); 258 CHECK(ctype == NV_TYPE_STRING); 259 CHECK(strcmp(cname, "nvlist/string/") == 0); 260 CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0); 261 262 cname = nvlist_next(cnvl, &ctype, &ccookie); 263 CHECK(cname != NULL); 264 CHECK(ctype == NV_TYPE_STRING); 265 CHECK(strcmp(cname, "nvlist/string/x") == 0); 266 CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0); 267 268 cname = nvlist_next(cnvl, &ctype, &ccookie); 269 CHECK(cname != NULL); 270 CHECK(ctype == NV_TYPE_STRING); 271 CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); 272 CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0); 273 274 cname = nvlist_next(cnvl, &ctype, &ccookie); 275 CHECK(cname != NULL); 276 CHECK(ctype == NV_TYPE_DESCRIPTOR); 277 CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0); 278 CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname))); 279 280 cname = nvlist_next(cnvl, &ctype, &ccookie); 281 CHECK(cname != NULL); 282 CHECK(ctype == NV_TYPE_BINARY); 283 CHECK(strcmp(cname, "nvlist/binary/x") == 0); 284 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0); 285 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0); 286 CHECK(size == 1); 287 288 cname = nvlist_next(cnvl, &ctype, &ccookie); 289 CHECK(cname != NULL); 290 CHECK(ctype == NV_TYPE_BINARY); 291 CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); 292 CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 293 CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); 294 CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); 295 296 cname = nvlist_next(cnvl, &ctype, &ccookie); 297 CHECK(cname != NULL); 298 CHECK(ctype == NV_TYPE_NVLIST); 299 CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0); 300 empty = nvlist_get_nvlist(cnvl, cname); 301 CHECK(nvlist_empty(empty)); 302 303 cname = nvlist_next(cnvl, &ctype, &ccookie); 304 CHECK(cname == NULL); 305 306 name = nvlist_next(nvl, &type, &cookie); 307 CHECK(name == NULL); 308 } 309 310 int 311 main(void) 312 { 313 int status, socks[2]; 314 pid_t pid; 315 316 printf("1..134\n"); 317 fflush(stdout); 318 319 if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) 320 err(1, "socketpair() failed"); 321 pid = fork(); 322 switch (pid) { 323 case -1: 324 /* Failure. */ 325 err(1, "unable to fork"); 326 case 0: 327 /* Child. */ 328 close(socks[0]); 329 child(socks[1]); 330 return (0); 331 default: 332 /* Parent. */ 333 close(socks[1]); 334 parent(socks[0]); 335 break; 336 } 337 338 if (waitpid(pid, &status, 0) < 0) 339 err(1, "waitpid() failed"); 340 341 return (0); 342 } 343