1 | /* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | |
3 | This program is free software; you can redistribute it and/or |
4 | modify it under the terms of the GNU General Public License as |
5 | published by the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, but |
8 | WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10 | General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | |
16 | #include <my_global.h> |
17 | #include <m_string.h> |
18 | #include <tap.h> |
19 | |
20 | char buf[1024]; /* let's hope that's enough */ |
21 | |
22 | static void test_w_len(const char *res, size_t buflen, const char *fmt, ...) |
23 | { |
24 | va_list args; |
25 | size_t len; |
26 | va_start(args,fmt); |
27 | len= my_vsnprintf(buf, buflen, fmt, args); |
28 | va_end(args); |
29 | ok(strlen(res) == len && strcmp(buf, res) == 0, "\"%s\"" , buf); |
30 | } |
31 | |
32 | static void test1(const char *res, const char *fmt, ...) |
33 | { |
34 | va_list args; |
35 | size_t len; |
36 | va_start(args,fmt); |
37 | len= my_vsnprintf(buf, sizeof(buf)-1, fmt, args); |
38 | va_end(args); |
39 | ok(strlen(res) == len && strcmp(buf, res) == 0, "\"%s\"" , buf); |
40 | } |
41 | |
42 | static void test_many(const char **res, const char *fmt, ...) |
43 | { |
44 | va_list args; |
45 | size_t len; |
46 | va_start(args,fmt); |
47 | len= my_vsnprintf(buf, sizeof(buf)-1, fmt, args); |
48 | va_end(args); |
49 | |
50 | for (; *res ; res++) |
51 | { |
52 | if (strlen(*res) == len && strcmp(buf, *res) == 0) |
53 | { |
54 | ok(1, "\"%s\"" , buf); |
55 | return; |
56 | } |
57 | } |
58 | ok(0, "\"%s\"" , buf); |
59 | } |
60 | |
61 | |
62 | int main(void) |
63 | { |
64 | plan(39); |
65 | |
66 | test1("Constant string" , |
67 | "Constant string" ); |
68 | |
69 | test1("Format specifier s works" , |
70 | "Format specifier s %s" , "works" ); |
71 | test1("Format specifier b works (mysql extension)" , |
72 | "Format specifier b %.5b (mysql extension)" , "works!!!" ); |
73 | test1("Format specifier c !" , |
74 | "Format specifier c %c" , '!'); |
75 | test1("Format specifier d 1" , |
76 | "Format specifier d %d" , 1); |
77 | test1("Format specifier i 1" , |
78 | "Format specifier i %i" , 1); |
79 | test1("Format specifier u 2" , |
80 | "Format specifier u %u" , 2); |
81 | test1("Format specifier o 375" , |
82 | "Format specifier o %o" , 0375); |
83 | test1("Format specifier x a" , |
84 | "Format specifier x %x" , 10); |
85 | test1("Format specifier X B" , |
86 | "Format specifier X %X" , 11); |
87 | test1("Format specifier p 0x5" , |
88 | "Format specifier p %p" , 5); |
89 | test1("Format specifier f 3.141593" , |
90 | "Format specifier f %f" , 3.1415926); |
91 | test1("Format specifier g 3.1416" , |
92 | "Format specifier g %g" , 3.1415926); |
93 | |
94 | test1("Flag '-' is ignored < 1>" , |
95 | "Flag '-' is ignored <%-4d>" , 1); |
96 | test1("Flag '0' works <0006>" , |
97 | "Flag '0' works <%04d>" , 6); |
98 | |
99 | test1("Width is ignored for strings <x> <y>" , |
100 | "Width is ignored for strings <%04s> <%5s>" , "x" , "y" ); |
101 | |
102 | test1("Precision works for strings <abcde>" , |
103 | "Precision works for strings <%.5s>" , "abcdef!" ); |
104 | |
105 | test1("Flag '`' (backtick) works: `abcd` `op``q` (mysql extension)" , |
106 | "Flag '`' (backtick) works: %`s %`.4s (mysql extension)" , |
107 | "abcd" , "op`qrst" ); |
108 | |
109 | test1("Length modifiers work: 1 * -1 * 2 * 3" , |
110 | "Length modifiers work: %d * %ld * %lld * %zd" , 1, -1L, 2LL, (size_t)3); |
111 | |
112 | test1("Length modifiers work: 1 * -1 * 2 * 3" , |
113 | "Length modifiers work: %i * %li * %lli * %zd" , 1, -1L, 2LL, (size_t)3); |
114 | |
115 | test1("long long X: 123456789abcdef0" , |
116 | "long long X: %llx" , 0x123456789abcdef0LL); |
117 | |
118 | test1("(null) pointer is fine" , |
119 | "%s pointer is fine" , NULL); |
120 | |
121 | test1("Positional arguments work: on the dark side they are" , |
122 | "Positional arguments work: %3$s %1$s %2$s" , |
123 | "they" , "are" , "on the dark side" ); |
124 | |
125 | test1("Asterisk '*' as a width works: < 4>" , |
126 | "Asterisk '*' as a width works: <%*d>" , 5, 4); |
127 | |
128 | test1("Asterisk '*' as a precision works: <qwerty>" , |
129 | "Asterisk '*' as a precision works: <%.*s>" , 6, "qwertyuiop" ); |
130 | |
131 | test1("Positional arguments for a width: < 4>" , |
132 | "Positional arguments for a width: <%1$*2$d>" , 4, 5); |
133 | |
134 | test1("Positional arguments for a precision: <qwerty>" , |
135 | "Positional arguments for a precision: <%1$.*2$s>" , "qwertyuiop" , 6); |
136 | |
137 | test1("Positional arguments and a width: <0000ab>" , |
138 | "Positional arguments and a width: <%1$06x>" , 0xab); |
139 | |
140 | test1("Positional arguments octal: <7777>" , |
141 | "Positional arguments octal: <%1$o>" , 07777); |
142 | |
143 | /* Can't use int arguments, as they may be different size from pointers */ |
144 | |
145 | test1("Padding and %p <0x12> <0x034> <0x0000ab> < 0xcd>" , |
146 | "Padding and %%p <%04p> <%05p> <%08p> <%8p>" , |
147 | (void*) 0x12, (void*) 0x34, (void*) 0xab, (void*) 0xcd); |
148 | |
149 | test1("F with a width (ignored) and precision: <12.34568>" , |
150 | "F with a width (ignored) and precision: <%10.5f>" , 12.3456789); |
151 | test1("G with a width (ignored) and precision: <12.35>" , |
152 | "G with a width (ignored) and precision: <%10.5g>" , 12.3456789); |
153 | |
154 | { |
155 | /* Test that %M works */ |
156 | const char *results[]= |
157 | { |
158 | "Error 1 \"Operation not permitted\"" , /* Linux */ |
159 | "Error 1 \"Not owner\"" , /* Solaris */ |
160 | NullS |
161 | }; |
162 | test_many(results, "Error %M" , 1); |
163 | } |
164 | |
165 | test1("M with 0 error code: 0 \"Internal error/check (Not system error)\"" , |
166 | "M with 0 error code: %M" , 0); |
167 | |
168 | test1("M with positional: 0 \"Internal error/check (Not system error)\"" , |
169 | "M with positional: %1$M" , 0); |
170 | |
171 | test1("M with width: 0 \"Internal error/ch" , |
172 | "M with width: %.20M" , 0); |
173 | test1("M with width positional: 0 \"Internal error/ch" , |
174 | "M with width positional: %2$.*1$M" , 20, 0); |
175 | |
176 | test_w_len("M small buf: 0 \"In" , |
177 | 19, "M small buf: %M" , 0); |
178 | test_w_len("M small buf positional: 0 \"In" , |
179 | 30, "M small buf positional: %1$M" , 0); |
180 | |
181 | return exit_status(); |
182 | } |
183 | |
184 | |