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