Home | History | Annotate | Line # | Download | only in libutil
t_snprintb.c revision 1.11
      1 /* $NetBSD: t_snprintb.c,v 1.11 2024/01/27 10:32:03 rillig Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2002, 2004, 2008, 2010, 2024 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code was contributed to The NetBSD Foundation by Christos Zoulas and
      8  * Roland Illig.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
     34  The NetBSD Foundation, inc. All rights reserved.");
     35 __RCSID("$NetBSD: t_snprintb.c,v 1.11 2024/01/27 10:32:03 rillig Exp $");
     36 
     37 #include <stdio.h>
     38 #include <string.h>
     39 #include <util.h>
     40 #include <vis.h>
     41 
     42 #include <atf-c.h>
     43 
     44 static const char *
     45 vis_arr(const char *arr, size_t arrlen)
     46 {
     47 	static char buf[6][1024];
     48 	static size_t i;
     49 
     50 	i = (i + 1) % (sizeof(buf) / sizeof(buf[0]));
     51 	int rv = strnvisx(buf[i], sizeof(buf[i]), arr, arrlen,
     52 	    VIS_WHITE | VIS_OCTAL);
     53 	ATF_REQUIRE_MSG(rv >= 0, "strnvisx failed for length %zu", arrlen);
     54 	return buf[i];
     55 }
     56 
     57 static void
     58 h_snprintb_loc(const char *file, size_t line,
     59     size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val,
     60     int exp_rv, const char *res, size_t reslen)
     61 {
     62 	char buf[1024];
     63 
     64 	// Calling snprintb with bufsize == 0 invokes undefined
     65 	// behavior due to out-of-range 'bp'.
     66 	ATF_REQUIRE(bufsize > 0);
     67 	ATF_REQUIRE(bufsize <= sizeof(buf));
     68 
     69 	memset(buf, 'Z', sizeof(buf));
     70 	int rv = snprintb(buf, bufsize, fmt, val);
     71 	ATF_REQUIRE(rv >= 0);
     72 	size_t rlen = rv;
     73 
     74 	ATF_CHECK_MSG(
     75 	    rv == exp_rv && memcmp(buf, res, reslen) == 0
     76 	    && buf[rlen < bufsize ? rlen : bufsize - 1] == '\0',
     77 	    "failed:\n"
     78 	    "\ttest case: %s:%zu\n"
     79 	    "\tformat: %s\n"
     80 	    "\tvalue: %#jx\n"
     81 	    "\twant: %d bytes %s\n"
     82 	    "\thave: %d bytes %s\n",
     83 	    file, line,
     84 	    vis_arr(fmt, fmtlen),
     85 	    (uintmax_t)val,
     86 	    exp_rv, vis_arr(res, reslen),
     87 	    rv, vis_arr(buf, reslen));
     88 }
     89 
     90 #define	h_snprintb_len(bufsize, fmt, val, exp_rv, res)			\
     91 	h_snprintb_loc(__FILE__, __LINE__,				\
     92 	    bufsize, fmt, sizeof(fmt) - 1, val,				\
     93 	    exp_rv, res, sizeof(res) - 1)
     94 #define	h_snprintb(fmt, val, res)					\
     95 	h_snprintb_len(1024, fmt, val, sizeof(res) - 1, res)
     96 
     97 static void
     98 h_snprintb_error_loc(const char *file, size_t line,
     99     const char *fmt, size_t fmtlen)
    100 {
    101 	char buf[1024];
    102 
    103 	memset(buf, 'Z', sizeof(buf));
    104 	int rv = snprintb(buf, sizeof(buf), fmt, 0);
    105 	size_t buflen = rv;
    106 
    107 	ATF_REQUIRE(rv >= -1);
    108 	ATF_CHECK_MSG(rv == -1,
    109 	    "expected error but got success:\n"
    110 	    "\ttest case: %s:%zu\n"
    111 	    "\tformat: %s\n"
    112 	    "\tresult: %zu bytes %s\n",
    113 	    file, line,
    114 	    vis_arr(fmt, fmtlen),
    115 	    buflen, vis_arr(buf, buflen));
    116 }
    117 
    118 #define	h_snprintb_error(fmt)						\
    119 	h_snprintb_error_loc(__FILE__, __LINE__, fmt, sizeof(fmt) - 1)
    120 
    121 ATF_TC(snprintb);
    122 ATF_TC_HEAD(snprintb, tc)
    123 {
    124 	atf_tc_set_md_var(tc, "descr", "Checks snprintb(3)");
    125 }
    126 ATF_TC_BODY(snprintb, tc)
    127 {
    128 
    129 	// old-style format, octal
    130 	h_snprintb(
    131 	    "\010"
    132 	    "\002BITTWO"
    133 	    "\001BITONE",
    134 	    3,
    135 	    "03<BITTWO,BITONE>");
    136 
    137 	// old-style format, decimal
    138 	h_snprintb(
    139 	    "\012"
    140 	    "\0011"
    141 	    "\0119"
    142 	    "\02117"
    143 	    "\04032",
    144 	    0xffffffff,
    145 	    "4294967295<1,9,17,32>");
    146 
    147 	// old-style format, hexadecimal, from msb downto lsb
    148 	h_snprintb(
    149 	    "\020"
    150 	    "\04032"
    151 	    "\03024"
    152 	    "\02016"
    153 	    "\0108"
    154 	    "\0077"
    155 	    "\0066"
    156 	    "\0055"
    157 	    "\0044"
    158 	    "\0033"
    159 	    "\0022"
    160 	    "\0011"
    161 	    // The old-style format supports only 32 bits, interpreting the
    162 	    // \041 as part of the text belonging to bit 1.
    163 	    "\04133",
    164 	    0x0000ffff00ff0f35ULL,
    165 	    "0xffff00ff0f35<24,6,5,3,1!33>");
    166 
    167 	// old-style format, hexadecimal, from lsb to msb
    168 	h_snprintb(
    169 	    "\020"
    170 	    "\0011"
    171 	    "\0022"
    172 	    "\0033"
    173 	    "\0044"
    174 	    "\0055"
    175 	    "\0066"
    176 	    "\0077"
    177 	    "\0108"
    178 	    "\02016"
    179 	    "\03024"
    180 	    "\04032"
    181 	    // The old-style format supports only 32 bits, interpreting the
    182 	    // \041 as part of the text belonging to bit 32.
    183 	    "\04133",
    184 	    0xffff0000ff00f0caULL,
    185 	    "0xffff0000ff00f0ca<2,4,7,8,16,32!33>");
    186 
    187 	// The bits can be listed in arbitrary order, there can also be
    188 	// duplicates. A bit's description can be empty, resulting in several
    189 	// commas in a row.
    190 	h_snprintb(
    191 	    "\020"
    192 	    "\001lsb"
    193 	    "\040msb"
    194 	    "\011"
    195 	    "\012"
    196 	    "\002above-lsb"
    197 	    "\037below-msb"
    198 	    "\001lsb-again"
    199 	    "\040msb-again",
    200 	    0xc0000303,
    201 	    "0xc0000303<lsb,msb,,,above-lsb,below-msb,lsb-again,msb-again>");
    202 
    203 #if 0
    204 	// If the first bit number is 33 or more, snprintb invokes undefined
    205 	// behavior due to an out-of-bounds bit shift, though undetected by
    206 	// -ftrapv. Later bit numbers are properly checked.
    207 	h_snprintb(
    208 	    "\020"
    209 	    "\177undefined_behavior"
    210 	    "\001lsb",
    211 	    0xffffffffffffffffULL,
    212 	    "0xffffffffffffffff<?>");
    213 #endif
    214 
    215 	// old-style format, invalid number base 0
    216 	h_snprintb_error(
    217 	    "");
    218 
    219 	// old-style format, invalid number base 2
    220 	h_snprintb_error(
    221 	    "\002");
    222 
    223 	// old-style format, invalid number base 255 or -1
    224 	h_snprintb_error(
    225 	    "\377");
    226 
    227 	// old-style format, small buffer
    228 #if 0
    229 	// FIXME: Calling snprintb with buffer size 0 invokes undefined
    230 	// behavior due to out-of-bounds 'bp' pointer.
    231 	h_snprintb_len(
    232 	    0, "\020", 0,
    233 	    1, "ZZZ");
    234 #endif
    235 	h_snprintb_len(
    236 	    1, "\020", 0,
    237 	    1, "\0ZZZ");
    238 	h_snprintb_len(
    239 	    2, "\020", 0,
    240 	    1, "0\0ZZZ");
    241 	h_snprintb_len(
    242 	    3, "\020", 0,
    243 	    1, "0\0ZZZ");
    244 	h_snprintb_len(
    245 	    3, "\020", 7,
    246 	    3, "0x\0ZZZ");
    247 	h_snprintb_len(
    248 	    4, "\020", 7,
    249 	    3, "0x7\0ZZZ");
    250 	h_snprintb_len(
    251 	    7, "\020\001lsb", 7,
    252 	    8, "0x7<ls\0ZZZ");
    253 	h_snprintb_len(
    254 	    8, "\020\001lsb", 7,
    255 	    8, "0x7<lsb\0ZZZ");
    256 	h_snprintb_len(
    257 	    9, "\020\001lsb", 7,
    258 	    8, "0x7<lsb>\0ZZZ");
    259 	h_snprintb_len(
    260 	    9, "\020\001one\002two", 7,
    261 	    12, "0x7<one,\0ZZZ");
    262 	h_snprintb_len(
    263 	    10, "\020\001one\002two", 7,
    264 	    12, "0x7<one,t\0ZZZ");
    265 	h_snprintb_len(
    266 	    12, "\020\001one\002two", 7,
    267 	    12, "0x7<one,two\0ZZZ");
    268 	h_snprintb_len(
    269 	    13, "\020\001one\002two", 7,
    270 	    12, "0x7<one,two>\0ZZZ");
    271 
    272 	// new-style format, single bits, octal
    273 	h_snprintb(
    274 	    "\177\010"
    275 	    "b\000bit0\0"
    276 	    "b\037bit31\0"
    277 	    "b\040bit32\0"
    278 	    "b\077bit63\0",
    279 	    0xf000000ff000000fULL,
    280 	    "01700000000776000000017<bit0,bit31,bit32,bit63>");
    281 
    282 	// new-style format, single bits, decimal
    283 	h_snprintb(
    284 	    "\177\012"
    285 	    "b\000bit0\0"
    286 	    "b\037bit31\0"
    287 	    "b\040bit32\0"
    288 	    "b\077bit63\0",
    289 	    0xf000000ff000000fULL,
    290 	    "17293822637553745935<bit0,bit31,bit32,bit63>");
    291 
    292 	// new-style format, single bits, hexadecimal
    293 	h_snprintb(
    294 	    "\177\020"
    295 	    "b\000bit0\0"
    296 	    "b\037bit31\0"
    297 	    "b\040bit32\0"
    298 	    "b\077bit63\0",
    299 	    0xf000000ff000000fULL,
    300 	    "0xf000000ff000000f<bit0,bit31,bit32,bit63>");
    301 
    302 	// new-style format, invalid number base 2
    303 	h_snprintb_error(
    304 	    "\177\002");
    305 
    306 	// new-style format, invalid number base 255 or -1
    307 	h_snprintb_error(
    308 	    "\177\377");
    309 
    310 	// new-style format, single bits, edge cases
    311 	//
    312 	// The bits can be listed in arbitrary order, there can also be
    313 	// duplicates. A bit's description can be empty, resulting in several
    314 	// commas in a row.
    315 	h_snprintb(
    316 	    "\177\020"
    317 	    "b\01lsb\0"
    318 	    "b\02\0"
    319 	    "b\03\0"
    320 	    "b\05NOTBOOT\0"
    321 	    "b\06FPP\0"
    322 	    "b\13SDVMA\0"
    323 	    "b\15VIDEO\0"
    324 	    "b\20LORES\0"
    325 	    "b\21FPA\0"
    326 	    "b\22DIAG\0"
    327 	    "b\16CACHE\0"
    328 	    "b\17IOCACHE\0"
    329 	    "b\22LOOPBACK\0"
    330 	    "b\04DBGCACHE\0",
    331 	    0xe86f,
    332 	    "0xe86f<lsb,,,NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
    333 
    334 	// new-style format, octal, named bit-field
    335 	h_snprintb(
    336 	    "\177\010"
    337 	    "f\010\004Field\0"
    338 		"=\001one\0"
    339 		"=\002two\0",
    340 	    0x100,
    341 	    "0400<Field=01=one>");
    342 
    343 	// new-style format, decimal, named bit-field
    344 	h_snprintb(
    345 	    "\177\012"
    346 	    "f\010\004Field\0"
    347 		"=\1one\0"
    348 		"=\2two\0",
    349 	    0x100,
    350 	    "256<Field=1=one>");
    351 
    352 	// new-style format, hexadecimal, named bit-field
    353 	h_snprintb(
    354 	    "\177\020"
    355 	    "f\010\004Field\0"
    356 		"=\1one\0"
    357 		"=\2two\0",
    358 	    0x100,
    359 	    "0x100<Field=0x1=one>");
    360 
    361 	// new-style format, octal, unnamed bit-field
    362 	h_snprintb(
    363 	    "\177\010"
    364 	    "F\010\004Field\0"
    365 		":\001one\0"
    366 		":\002two\0",
    367 	    0x100,
    368 	    "0400<one>");
    369 
    370 	// new-style format, decimal, unnamed bit-field
    371 	h_snprintb(
    372 	    "\177\012"
    373 	    "F\010\004Field\0"
    374 		":\1one\0"
    375 		":\2two\0",
    376 	    0x100,
    377 	    "256<one>");
    378 
    379 	// new-style format, hexadecimal, unnamed bit-field
    380 	h_snprintb(
    381 	    "\177\020"
    382 	    "F\010\004Field\0"
    383 		":\1one\0"
    384 		":\2two\0",
    385 	    0x100,
    386 	    "0x100<one>");
    387 
    388 	// new-style format, hexadecimal, named bit-field, edge cases
    389 	//
    390 	// Field values can be listed in arbitrary order, there can also be
    391 	// duplicates. A field value's description can be empty, resulting in
    392 	// several '=' in a row. The ':' directive can emulate the '='
    393 	// directive, but not vice versa.
    394 	h_snprintb(
    395 	    "\177\20"
    396 	    "f\0\4Field\0"
    397 		"=\1one\0"
    398 		"=\1one-again\0"
    399 		"=\1\0"
    400 		"=\1\0"
    401 		":\1double\0"
    402 		":\1-colon\0"
    403 		":\1=equal\0"
    404 		"=\2TWO\0",
    405 	    1,
    406 	    "0x1<Field=0x1=one=one-again==double-colon=equal>");
    407 
    408 	// new-style format, hexadecimal, unnamed bit-field, edge cases
    409 	//
    410 	// Combining the 'F' and '=' directives generates output that doesn't
    411 	// look well-formed.
    412 	h_snprintb(
    413 	    "\177\20"
    414 	        "=\0all-zero\0"
    415 	        "=\1all-one\0"
    416 	        ":\1-continued\0"
    417 	    "F\0\4Field\0"
    418 		"=\1one\0"
    419 		"=\1one-again\0"
    420 		"=\1\0"
    421 		"=\1\0"
    422 		":\1double\0"
    423 		":\1-colon\0"
    424 		":\1=equal\0"
    425 		"=\2TWO\0",
    426 	    1,
    427 	    "0x1=all-one-continued<=one=one-again==double-colon=equal>");
    428 
    429 	// new-style format, bit-fields with fixed fallback value
    430 	//
    431 	// Only the first fallback value is used, all others are ignored.
    432 	h_snprintb(
    433 	    "\177\020"
    434 	    "f\0\4Field\0"
    435 		"=\1one\0"
    436 		"=\2two\0"
    437 		"*=other\0"
    438 		"*=yet-another\0"
    439 	    "b\1separator\0"
    440 	    "F\0\4Field\0"
    441 		":\1one\0"
    442 		":\2two\0"
    443 		"*other\0"
    444 		"*yet-another\0",
    445 	    3,
    446 	    "0x3<Field=0x3=other,separator,other>");
    447 
    448 	// new-style format, bit-fields with numeric fallback value
    449 	h_snprintb(
    450 	    "\177\020"
    451 	    "f\010\004Field\0"
    452 		"*=other(%04ju)\0"
    453 	    "b\000separator\0"
    454 	    "F\010\004Field\0"
    455 		"*other(%04ju)\0",
    456 	    0x301,
    457 	    "0x301<Field=0x3=other(0003),separator,other(0003)>");
    458 
    459 	// new-style format, bit-field with more than 8 bits
    460 	//
    461 	// The '=' and ':' directives can only match values from 0 to 255, so
    462 	// the fallback value always steps in. The complete value of the
    463 	// bit-field appears in the output, though.
    464 	h_snprintb(
    465 	    "\177\020"
    466 	    "f\010\020Field\0"
    467 		"=\377ones\0"
    468 		"*=other(%jx)\0"
    469 	    "F\010\020\0"
    470 		":\377ones\0"
    471 		"*other(%jx)\0",
    472 	    0x77ff55,
    473 	    "0x77ff55<Field=0x77ff=other(77ff),other(77ff)>");
    474 
    475 	// new-style format, bit-fields with no match
    476 	h_snprintb(
    477 	    "\177\020"
    478 	    "f\010\004Field\0"
    479 		"=\1one\0"
    480 		"=\2two\0",
    481 	    0x301,
    482 	    "0x301<Field=0x3>");
    483 	h_snprintb(
    484 	    "\177\020"
    485 	    "F\010\004\0"
    486 		":\1one\0"
    487 		":\2two\0",
    488 	    0x301,
    489 	    "0x301<>");
    490 	h_snprintb(
    491 	    "\177\020"
    492 	    "f\010\004Field\0"
    493 		"=\1one\0"
    494 		"=\2two\0"
    495 	    "b\000separator\0"
    496 	    "F\010\004\0"
    497 		":\1one\0"
    498 		":\2two\0",
    499 	    0x301,
    500 	    "0x301<Field=0x3,separator,>");
    501 
    502 	// new-style format, two separate bit-fields
    503 	h_snprintb(
    504 	    "\177\20"
    505 	    "f\0\4Field_1\0"
    506 		"=\1ONE\0"
    507 		"=\2TWO\0"
    508 	    "f\4\4Field_2\0"
    509 		"=\1ONE\0"
    510 		"=\2TWO\0",
    511 	    0x12,
    512 	    "0x12<Field_1=0x2=TWO,Field_2=0x1=ONE>");
    513 
    514 	// new-style format, mixed named and unnamed bit-fields
    515 	h_snprintb(
    516 	    "\177\20"
    517 	    "f\0\4Field_1\0"
    518 		"=\1ONE\0"
    519 		"=\2TWO\0"
    520 	    "F\x8\4\0"
    521 		"*Field_3=%jd\0"
    522 	    "f\4\4Field_2\0"
    523 		":\1:ONE\0"
    524 		":\2:TWO\0",
    525 	    0xD12,
    526 	    "0xd12<Field_1=0x2=TWO,Field_3=13,Field_2=0x1:ONE>");
    527 
    528 	// new-style format, descriptions with spaces
    529 	h_snprintb(
    530 	    "\177\020"
    531 	    "b\000has std options\0"
    532 	    "f\010\004std options\0"
    533 		"=\000no options\0"
    534 		"=\017all options\0"
    535 	    "F\020\004ext options\0"
    536 		":\000no ext options\0"
    537 		":\017all ext options\0",
    538 	    0x000001,
    539 	    "0x1<has std options,std options=0=no options,no ext options>");
    540 	h_snprintb(
    541 	    "\177\020"
    542 	    "f\010\004std options\0"
    543 		"*=other std options\0"
    544 	    "F\020\004ext\toptions\0"
    545 		"*other\text\toptions\0",
    546 	    0x000001,
    547 	    "0x1<std options=0=other std options,other\text\toptions>");
    548 
    549 	// It is possible but cumbersome to implement a reduced variant of
    550 	// rot13 using snprintb, shown here for lowercase letters only.
    551 	for (char ch = 'A'; ch <= '~'; ch++) {
    552 		char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
    553 		    : ch >= 'n' && ch <= 'z' ? ch - 13
    554 		    : '?';
    555 		char expected[8];
    556 		ATF_REQUIRE_EQ(7,
    557 		    snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
    558 		h_snprintb(
    559 		    "\177\020"
    560 		    "F\000\010\0"
    561 		    ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
    562 		    ":iv\0:jw\0:kx\0:ly\0:mz\0"
    563 		    ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
    564 		    ":vi\0:wj\0:xk\0:yl\0:zm\0"
    565 		    // If snprintf accepted "%jc", it would be possible to
    566 		    // echo the non-alphabetic characters instead of a
    567 		    // catchall question mark.
    568 		    "*?\0",
    569 		    ch,
    570 		    expected);
    571 	}
    572 }
    573 
    574 static void
    575 h_snprintb_m_loc(const char *file, size_t line,
    576     const char *fmt, size_t fmtlen, uint64_t val, int line_max,
    577     const char *res, size_t reslen)
    578 {
    579 	char buf[1024];
    580 
    581 	int rv = snprintb_m(buf, sizeof(buf), fmt, val, line_max);
    582 
    583 	ATF_REQUIRE_MSG(rv >= 0, "formatting %jx with '%s' returns error %d",
    584 	    (uintmax_t)val, vis_arr(fmt, fmtlen), rv);
    585 
    586 	size_t buflen = rv;
    587 	ATF_CHECK_MSG(
    588 	    buflen == reslen && memcmp(buf, res, reslen) == 0,
    589 	    "failed:\n"
    590 	    "\ttest case: %s:%zu\n"
    591 	    "\tformat: %s\n"
    592 	    "\tvalue: %#jx\n"
    593 	    "\twant: %zu bytes %s\n"
    594 	    "\thave: %zu bytes %s\n",
    595 	    file, line,
    596 	    vis_arr(fmt, fmtlen),
    597 	    (uintmax_t)val,
    598 	    reslen, vis_arr(res, reslen),
    599 	    buflen, vis_arr(buf, buflen));
    600 }
    601 
    602 #define	h_snprintb_m(fmt, val, line_max, res)				\
    603 	h_snprintb_m_loc(__FILE__, __LINE__,				\
    604 	    fmt, sizeof(fmt) - 1, val, line_max,			\
    605 	    res, sizeof(res) - 1)
    606 
    607 ATF_TC(snprintb_m);
    608 ATF_TC_HEAD(snprintb_m, tc)
    609 {
    610 	atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
    611 }
    612 ATF_TC_BODY(snprintb_m, tc)
    613 {
    614 	h_snprintb_m(
    615 	    "\177\020"
    616 	    "b\0LSB\0"
    617 	    "b\1_BITONE\0"
    618 	    "f\4\4NIBBLE2\0"
    619 	    "f\x10\4BURST\0"
    620 		"=\04FOUR\0"
    621 		"=\17FIFTEEN\0"
    622 	    "b\x1fMSB\0",
    623 	    0x800f0701,
    624 	    33,
    625 	    "0x800f0701<LSB,NIBBLE2=0>\0"
    626 	    "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
    627 
    628 	h_snprintb_m(
    629 	    "\177\020"
    630 	    "b\0LSB\0"
    631 	    "b\1_BITONE\0"
    632 	    "f\4\4NIBBLE2\0"
    633 	    "f\x10\4BURST\0"
    634 		"=\04FOUR\0"
    635 		"=\17FIFTEEN\0"
    636 	    "b\x1fMSB\0",
    637 	    0x800f0701,
    638 	    32,
    639 	    "0x800f0701<LSB,NIBBLE2=0>\0"
    640 	    "0x800f0701<BURST=0xf=FIFTEEN>\0"
    641 	    "0x800f0701<MSB>\0");
    642 }
    643 
    644 ATF_TP_ADD_TCS(tp)
    645 {
    646 
    647 	ATF_TP_ADD_TC(tp, snprintb);
    648 	ATF_TP_ADD_TC(tp, snprintb_m);
    649 
    650 	return atf_no_error();
    651 }
    652