1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2023 Oxide Computer Company
14 */
15
16 /*
17 * Test the implementation of strtonum() and strtonumx()
18 */
19
20 #include <limits.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 bool fail = false;
27
28 static void
runtestx(const char * nstr,long long minval,long long maxval,int base,long long expval,bool expect_pass)29 runtestx(const char *nstr, long long minval, long long maxval,
30 int base, long long expval, bool expect_pass)
31 {
32 const char *errstr;
33 char key[0x100];
34 long long val;
35
36 if (base == -1) {
37 val = strtonum(nstr, minval, maxval, &errstr);
38 (void) snprintf(key, sizeof (key), "strtonum(%s)", nstr);
39 } else {
40 val = strtonumx(nstr, minval, maxval, &errstr, base);
41 (void) snprintf(key, sizeof (key), "strtonumx(%s, %d)",
42 nstr, base);
43 }
44
45 if (expect_pass) {
46 if (errstr != NULL) {
47 fprintf(stderr, "FAIL %s was rejected: "
48 "%s [%lld,%lld]\n",
49 key, errstr, minval, maxval);
50 fail = true;
51 } else {
52 fprintf(stdout, "PASS %s was accepted: "
53 "[%lld,%lld] = %lld\n",
54 key, minval, maxval, val);
55 if (val != expval) {
56 fprintf(stderr, "FAIL %s returned wrong value: "
57 "[%lld,%lld] = %lld vs. %lld\n", key,
58 minval, maxval, val, expval);
59 fail = true;
60 }
61 }
62 } else {
63 if (errstr == NULL) {
64 fprintf(stderr, "FAIL %s was accepted: "
65 "[%lld,%lld] = %lld\n",
66 key, minval, maxval, val);
67 fail = true;
68 } else {
69 fprintf(stdout, "PASS %s was rejected: "
70 "%s [%lld,%lld]\n",
71 key, errstr, minval, maxval);
72 }
73 }
74 }
75
76 static void
runtest(const char * nstr,long long minval,long long maxval,long long expval,bool expect_pass)77 runtest(const char *nstr, long long minval, long long maxval, long long expval,
78 bool expect_pass)
79 {
80 runtestx(nstr, minval, maxval, -1, expval, expect_pass);
81 runtestx(nstr, minval, maxval, 10, expval, expect_pass);
82 runtestx(nstr, minval, maxval, 0, expval, expect_pass);
83 }
84
85 int
main(void)86 main(void)
87 {
88 runtest("1", 0, 100, 1, true);
89 runtest("0", -3, 7, 0, true);
90 runtest("0", 2, 10, 0, false);
91 runtest("0", 2, LLONG_MAX, 0, false);
92 runtest("-2", 0, LLONG_MAX, 0, false);
93 runtest("0", -5, LLONG_MAX, 0, true);
94 runtest("-3", -3, LLONG_MAX, -3, true);
95 runtest("-2", 10, -1, 0, false);
96 runtest("-2", -10, -1, -2, true);
97 runtest("-20", -10, -1, 0, false);
98 runtest("20", -10, -1, 0, false);
99
100 runtest("-9223372036854775808", LLONG_MIN, LLONG_MAX, LLONG_MIN, true);
101 runtest("-9223372036854775809", LLONG_MIN, LLONG_MAX, 0, false);
102
103 runtest("9223372036854775807", LLONG_MIN, LLONG_MAX, LLONG_MAX, true);
104 runtest("9223372036854775808", LLONG_MIN, LLONG_MAX, 0, false);
105
106 for (int base = 2; base <= 36; base++)
107 runtestx("1", 0, 100, base, 1, true);
108
109 runtestx("1", 0, 100, -2, 0, false);
110 runtestx("1", 0, 100, 1, 0, false);
111 runtestx("1", 0, 100, 37, 0, false);
112
113 runtestx("0x1234", 0, LLONG_MAX, 16, 0x1234, true);
114 runtestx("0x1234", 0, LLONG_MAX, 0, 0x1234, true);
115 runtestx("0x1234", 0, LLONG_MAX, 10, 0, false);
116
117 runtestx("AZbc123", 0, LLONG_MAX, 36, 23903176539, true);
118 runtestx("AZbc123", 0, LLONG_MAX, 35, 0, false);
119 runtestx("AYBC123", 0, LLONG_MAX, 35, 20185422673, true);
120 runtestx("AYBC123", 0, LLONG_MAX, 34, 0, false);
121
122 runtestx("01234", 0, LLONG_MAX, 8, 01234, true);
123 runtestx("01234", 0, LLONG_MAX, 0, 01234, true);
124 runtestx("01234", 0, LLONG_MAX, 10, 1234, true);
125
126 if (fail) {
127 printf("\nOverall status: FAIL\n");
128 return (EXIT_FAILURE);
129 }
130
131 printf("\nOverall status: PASS\n");
132 return (EXIT_SUCCESS);
133 }
134