Fossil SCM

Add a test program for MSVC C89 implementations of rint() and snprintf()

developer 2021-06-16 20:24 trunk
Commit c945679735b0c973499021e6ae772c2e8423484928d7c5f8a39e1bcf519fefd2
--- a/test/test-msc89-rint-snprintf.c
+++ b/test/test-msc89-rint-snprintf.c
@@ -0,0 +1,316 @@
1
+/*
2
+** Test MSVC C89 compatible implementations of the following C99 functions:
3
+** - double rint( double x )
4
+** Rounds a floating-point value to the nearest integer in floating-point
5
+** format.
6
+** - int snprintf( char *buffer, size_t count, const char *format, ... )
7
+** Writes formatted data to a string.
8
+**
9
+** NOTE: These implementations aim to provide the main functionality, not
10
+** the exact behavior as specified in C99 standard.
11
+**
12
+** BUILD: cl test-msc98-rint-snprintf.c
13
+** gcc test-msc98-rint-snprintf.c -lm ## for reference vs. non-MSVC
14
+*/
15
+
16
+#include <stdio.h>
17
+#include <stdlib.h>
18
+#include <string.h>
19
+#include <math.h>
20
+#include <limits.h>
21
+
22
+#define TEST_MSC89 1
23
+
24
+#if defined(_MSC_VER)
25
+#if (defined(TEST_MSC89) || (_MSC_VER < 1900)) /* before MSVC 2015 */
26
+#include <stdarg.h>
27
+
28
+/* NOTE: On truncation, this version of snprintf returns the input count, not
29
+** the expected number of chars to fully output the requested format (as
30
+** done in the C99 standard implementation). However the truncation test should
31
+** still be applicable (nret >= count).
32
+*/
33
+static __forceinline
34
+int c89_snprintf(char *buf, size_t count, const char *fmt, ...){
35
+ va_list argptr;
36
+ int n;
37
+ if( count==0 ) return 0;
38
+ va_start(argptr, fmt);
39
+ n = _vsprintf_p(buf, count, fmt, argptr);
40
+ va_end(argptr);
41
+
42
+ /* force zero-termination to avoid some known MSVC bugs */
43
+ if( count>0 ){
44
+ buf[count - 1] = '\0';
45
+ if( n<0 ) n = count;
46
+ }
47
+ return n;
48
+}
49
+
50
+#if defined(_WIN64)
51
+#include <emmintrin.h>
52
+#include <limits.h>
53
+
54
+static __forceinline
55
+double c89_rint(double v){
56
+ return ( v<0.0 && v>=-0.5 ? -0.0
57
+ : ( v!=0 && v>LLONG_MIN && v<LLONG_MAX
58
+ ? _mm_cvtsd_si64(_mm_load_sd(&v)) : v ) ); /* SSE2 */
59
+}
60
+#else
61
+static __forceinline
62
+double c89_rint(double v){
63
+ double rn;
64
+ __asm
65
+ {
66
+ FLD v
67
+ FRNDINT
68
+ FSTP rn
69
+ FWAIT
70
+ };
71
+ return rn;
72
+}
73
+#endif /* _WIN64 */
74
+#endif /* (defined(TEST_MSC89) || (_MSC_VER < 1900)) */
75
+
76
+#if (_MSC_VER < 1900) /* before MSVC 2015 */
77
+# define snprintf c89_snprintf
78
+# define rint c89_rint
79
+#else
80
+# define HAVE_C99_RINT 1
81
+#endif
82
+
83
+#elif !defined(_MSC_VER)
84
+# define HAVE_C99_RINT 1
85
+# define c89_snprintf snprintf
86
+# define c89_rint rint
87
+#endif /* defined(_MSC_VER) */
88
+
89
+
90
+#include <assert.h>
91
+
92
+#define SNPRINTF c89_snprintf
93
+#define RINT c89_rint
94
+
95
+int test_rint()
96
+{
97
+ const char *TESTNAME = "rint";
98
+ const struct test_data {
99
+ double v, expected;
100
+ } data[] = { /* round to the nearest or even integer */
101
+#ifdef HAVE_C99_RINT
102
+ {INFINITY,INFINITY},
103
+#endif
104
+ {(double)(LLONG_MAX/10000LL) + 0.7,(double)(LLONG_MAX/10000LL) + 1.},
105
+ {5.5,6.},{5.4,5.},{5.2,5.},{5.,5.},
106
+ {4.9,5.},{4.5,4.},{4.4,4.},{4.0,4.},
107
+ {3.7,4.},{3.5,4.},{3.2,3.},{3.0,3.},
108
+ {2.7,3.},{2.5,2.},{2.2,2.},{2.0,2.},
109
+ {1.6,2.},{1.5,2.0},{1.3,1.0},{1.0,1.0},
110
+ {0.9,1.},{0.8,1.},{0.5,0.},{0.49999999999999994,0.},
111
+ {0.4,0.},{0.1,0.},{0.,0.}
112
+ };
113
+ const size_t ndata = sizeof(data)/sizeof(data[0]);
114
+ int nfailed = 0;
115
+ int start = 0, end = ndata;
116
+ int i;
117
+ int done = 0;
118
+
119
+ /* do two passes over the test data (positives, negatives) */
120
+ do {
121
+ double sign = ( start<end ? 1. : -1. );
122
+ for(i=start; ( start< end ? i<end : i>end ); ( start< end ? ++i : --i )){
123
+ int passed = 0;
124
+ double v = sign*data[i].v;
125
+ double rn = c89_rint(v);
126
+ double expected = sign*data[i].expected;
127
+#ifdef HAVE_C99_RINT
128
+ {
129
+ double rint_expected = rint(v);
130
+ int matched = ( expected==rint_expected );
131
+ if( !matched ){
132
+ fprintf(stderr, "E:%s|Expected test data[%d]={%.17lf,%.1lf} does not match the actual rint() value=%.1lf\n",__FUNCTION__,
133
+ i, v, expected, rint_expected);
134
+ }
135
+ assert(matched);
136
+ expected = rint_expected;
137
+ }
138
+#endif
139
+ passed = ( rn==expected );
140
+ fprintf(( passed ? stdout : stderr ),
141
+ "T:%s|c89_rint(%.17lf)=%.1lf expected=%.1lf\t[%s]\n", TESTNAME,
142
+ v, rn, expected,
143
+ ( passed ? "PASS" : "FAIL" ));
144
+ if( !passed ) ++nfailed;
145
+ }
146
+
147
+ if( start<end ){
148
+ int swap = start;
149
+ start = end - 1; end = swap - 1;
150
+ }else{
151
+ done = 1;
152
+ }
153
+ }while( !done );
154
+
155
+ if( nfailed ){
156
+ fprintf(stderr,"T:%s|FAILED %d test\n\n", TESTNAME, nfailed);
157
+ }else{
158
+ printf("T:%s|PASSED\n\n", TESTNAME);
159
+ }
160
+
161
+ return nfailed;
162
+}
163
+
164
+int test_snprintf()
165
+{
166
+ const char *TESTNAME = "snprintf";
167
+ int nfailed = 0;
168
+#define TEST_BUF_MAXSIZE 256
169
+ const struct test_data {
170
+ size_t bufsize;
171
+ const char *fmt, *expected, *full;
172
+ } data[] = {
173
+ {TEST_BUF_MAXSIZE,"snprintf(buf, %d)","snprintf(buf, 17)","snprintf(buf, 17)"},
174
+ {17,"snprintf(buf, %d)","snprintf(buf, 17","snprintf(buf, 17)"},
175
+ {2,"snprintf(buf, %d)","s","snprintf(buf, 17)"},
176
+ {0,"snprintf(buf, %d)","","snprintf(buf, 17)"},
177
+ };
178
+ const size_t ndata = sizeof(data)/sizeof(data[0]);
179
+ char buf[TEST_BUF_MAXSIZE] = {0};
180
+ int i;
181
+
182
+ for(i=0; i<ndata; ++i){
183
+ int passed = 0;
184
+ size_t count = data[i].bufsize;
185
+ const char *fmt = data[i].fmt;
186
+ const char *full = data[i].full;
187
+ const char *expected = data[i].expected;
188
+ const int truncate_expected = ( count<=strlen(full) );
189
+ const int expected_nret = ( !truncate_expected
190
+ ? strlen(expected) : count );
191
+ const int expected_zero_at = ( !truncate_expected
192
+ ? expected_nret : expected_nret - 1 );
193
+ int nret;
194
+ buf[( count>0 ? count - 1 : 0 )] = '\0';
195
+ nret = c89_snprintf(buf, count, fmt, strlen(fmt));
196
+#ifdef HAVE_C99_RINT
197
+ {
198
+ char snprintf_expected[TEST_BUF_MAXSIZE] = {0};
199
+ int snprintf_expected_nret = snprintf(snprintf_expected, count, fmt, strlen(fmt));
200
+ int matched = ( strcmp(expected, snprintf_expected)==0 );
201
+ int matched_nret = ( expected_nret==snprintf_expected_nret );
202
+ if( !matched ){
203
+ fprintf(stderr, "E:%s|Expected test data[%d]={'%s','%s'} does not match the actual snprintf() value='%s'\n",__FUNCTION__,
204
+ i, buf, expected, snprintf_expected);
205
+ }
206
+
207
+ /* NOTE: This implementation of c89_snprintf() on truncation returns
208
+ ** the input count, not the expected number of chars needed to fully
209
+ ** output the requested format. So warn, only ifthe expected nret is
210
+ ** less than the count.
211
+ */
212
+ if( !matched_nret && expected_nret<count ){
213
+ fprintf(stderr, "W:%s|Expected return value=%d for test data[%d]={'%s','%s'} does not match the actual snprintf() return value=%d\n",__FUNCTION__,
214
+ expected_nret, i, buf, expected, snprintf_expected_nret);
215
+ }
216
+ assert(matched);
217
+ expected = snprintf_expected;
218
+ }
219
+#endif
220
+ passed = ( nret==expected_nret );
221
+ fprintf(( passed ? stdout : stderr ),
222
+ "T:%s|c89_snprintf(%lu,\"%s\", %d) nret=%d expected=%d\t[%s]\n", TESTNAME,
223
+ (unsigned long)count, fmt, (int)strlen(fmt), nret, expected_nret,
224
+ ( passed ? "PASS" : "FAIL" ));
225
+ if( !passed ) ++nfailed;
226
+
227
+ if( count ){
228
+ passed = ( buf[expected_zero_at]=='\0' );
229
+ fprintf(( passed ? stdout : stderr ),
230
+ "T:%s|c89_snprintf(%lu,\"%s\", %d) s[%d]=%d expected=%d\t[%s]\n", TESTNAME,
231
+ (unsigned long)count, fmt, (int)strlen(fmt), expected_zero_at, buf[expected_zero_at],'\0',
232
+ ( passed ? "PASS" : "FAIL" ));
233
+ if( !passed ) ++nfailed;
234
+ }
235
+
236
+ passed = ( strcmp(buf, expected)==0 );
237
+ fprintf((passed ? stdout : stderr),
238
+ "T:%s|c89_snprintf(%lu,\"%s\", %d)=\"%s\" expected=\"%s\"\t[%s]\n", TESTNAME,
239
+ (unsigned long)count, fmt, (int)strlen(fmt), buf, expected,
240
+ ( passed ? "PASS" : "FAIL" ));
241
+ if( !passed ) ++nfailed;
242
+ }
243
+
244
+ if( nfailed ){
245
+ fprintf(stderr,"T:%s|FAILED %d tests\n\n", TESTNAME, nfailed);
246
+ }else{
247
+ printf("T:%s|PASSED\n\n", TESTNAME);
248
+ }
249
+ return nfailed;
250
+}
251
+
252
+int main(int argc, char *argv[])
253
+{
254
+ int iarg;
255
+ struct testrun {
256
+ char rint, snprintf;
257
+ int status;
258
+ } testrun = {0, 0, 0};
259
+
260
+ printf("Usage: %s [TEST]...\n", argv[0]);
261
+ printf("Test MSVC C89 compatible implementations of selected C99 functions.\n"
262
+ "Run the selected TEST, by default 'all'; optionally exclude tests from the run.\n");
263
+ printf("Example: %s all -snprintf\n", argv[0]);
264
+ printf("\nTests:\n"
265
+ " all, rint, snprintf\n"
266
+ "\n -TEST\t\texclude the test from the run\n"
267
+ "\n"
268
+ );
269
+ if( argc>1
270
+ && ( strcmp(argv[1], "/?")==0 || strcmp(argv[1], "/h")==0
271
+ || strcmp(argv[1], "/H")==0 || strcmp(argv[1], "--help")==0 ) ){
272
+ return 0;
273
+ }
274
+
275
+ testrun.rint = testrun.snprintf = ( argc==1 );
276
+ for(iarg=1; iarg<argc; ++iarg){
277
+ const char *name = argv[iarg];
278
+ char runit = 1;
279
+ if( argv[iarg][0]=='-' ){
280
+ runit = 0;
281
+ name = &(argv[iarg][1]);
282
+ }
283
+
284
+ if( strcmp(name, "all")==0 ){
285
+ testrun.rint = testrun.snprintf = runit;
286
+ }else if( strcmp(name, "rint")==0 ){
287
+ testrun.rint = runit;
288
+ }else if( strcmp(name, "snprintf")==0 ){
289
+ testrun.snprintf = runit;
290
+ }else{
291
+ testrun.status = 2;
292
+ fprintf(stderr, "\nE|Invalid test requested: '%s'\n", name);
293
+ }
294
+ }
295
+
296
+ if( testrun.status==2 ){
297
+ return testrun.status;
298
+ }
299
+
300
+#ifndef _MSC_VER
301
+ fprintf(stderr, "W|Non-MSVC mode: testing against the native implementations\n\n");
302
+#endif
303
+
304
+ if( testrun.rint )
305
+ testrun.status |= test_rint();
306
+
307
+ if( testrun.snprintf )
308
+ testrun.status |= test_snprintf();
309
+
310
+ if( testrun.status==0 )
311
+ printf("\nI|All selected tests completed successfully\n");
312
+ else
313
+ fprintf(stderr, "\nE|Some of the selected tests failed\n");
314
+ return testrun.status;
315
+}
316
+
--- a/test/test-msc89-rint-snprintf.c
+++ b/test/test-msc89-rint-snprintf.c
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/test-msc89-rint-snprintf.c
+++ b/test/test-msc89-rint-snprintf.c
@@ -0,0 +1,316 @@
1 /*
2 ** Test MSVC C89 compatible implementations of the following C99 functions:
3 ** - double rint( double x )
4 ** Rounds a floating-point value to the nearest integer in floating-point
5 ** format.
6 ** - int snprintf( char *buffer, size_t count, const char *format, ... )
7 ** Writes formatted data to a string.
8 **
9 ** NOTE: These implementations aim to provide the main functionality, not
10 ** the exact behavior as specified in C99 standard.
11 **
12 ** BUILD: cl test-msc98-rint-snprintf.c
13 ** gcc test-msc98-rint-snprintf.c -lm ## for reference vs. non-MSVC
14 */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <math.h>
20 #include <limits.h>
21
22 #define TEST_MSC89 1
23
24 #if defined(_MSC_VER)
25 #if (defined(TEST_MSC89) || (_MSC_VER < 1900)) /* before MSVC 2015 */
26 #include <stdarg.h>
27
28 /* NOTE: On truncation, this version of snprintf returns the input count, not
29 ** the expected number of chars to fully output the requested format (as
30 ** done in the C99 standard implementation). However the truncation test should
31 ** still be applicable (nret >= count).
32 */
33 static __forceinline
34 int c89_snprintf(char *buf, size_t count, const char *fmt, ...){
35 va_list argptr;
36 int n;
37 if( count==0 ) return 0;
38 va_start(argptr, fmt);
39 n = _vsprintf_p(buf, count, fmt, argptr);
40 va_end(argptr);
41
42 /* force zero-termination to avoid some known MSVC bugs */
43 if( count>0 ){
44 buf[count - 1] = '\0';
45 if( n<0 ) n = count;
46 }
47 return n;
48 }
49
50 #if defined(_WIN64)
51 #include <emmintrin.h>
52 #include <limits.h>
53
54 static __forceinline
55 double c89_rint(double v){
56 return ( v<0.0 && v>=-0.5 ? -0.0
57 : ( v!=0 && v>LLONG_MIN && v<LLONG_MAX
58 ? _mm_cvtsd_si64(_mm_load_sd(&v)) : v ) ); /* SSE2 */
59 }
60 #else
61 static __forceinline
62 double c89_rint(double v){
63 double rn;
64 __asm
65 {
66 FLD v
67 FRNDINT
68 FSTP rn
69 FWAIT
70 };
71 return rn;
72 }
73 #endif /* _WIN64 */
74 #endif /* (defined(TEST_MSC89) || (_MSC_VER < 1900)) */
75
76 #if (_MSC_VER < 1900) /* before MSVC 2015 */
77 # define snprintf c89_snprintf
78 # define rint c89_rint
79 #else
80 # define HAVE_C99_RINT 1
81 #endif
82
83 #elif !defined(_MSC_VER)
84 # define HAVE_C99_RINT 1
85 # define c89_snprintf snprintf
86 # define c89_rint rint
87 #endif /* defined(_MSC_VER) */
88
89
90 #include <assert.h>
91
92 #define SNPRINTF c89_snprintf
93 #define RINT c89_rint
94
95 int test_rint()
96 {
97 const char *TESTNAME = "rint";
98 const struct test_data {
99 double v, expected;
100 } data[] = { /* round to the nearest or even integer */
101 #ifdef HAVE_C99_RINT
102 {INFINITY,INFINITY},
103 #endif
104 {(double)(LLONG_MAX/10000LL) + 0.7,(double)(LLONG_MAX/10000LL) + 1.},
105 {5.5,6.},{5.4,5.},{5.2,5.},{5.,5.},
106 {4.9,5.},{4.5,4.},{4.4,4.},{4.0,4.},
107 {3.7,4.},{3.5,4.},{3.2,3.},{3.0,3.},
108 {2.7,3.},{2.5,2.},{2.2,2.},{2.0,2.},
109 {1.6,2.},{1.5,2.0},{1.3,1.0},{1.0,1.0},
110 {0.9,1.},{0.8,1.},{0.5,0.},{0.49999999999999994,0.},
111 {0.4,0.},{0.1,0.},{0.,0.}
112 };
113 const size_t ndata = sizeof(data)/sizeof(data[0]);
114 int nfailed = 0;
115 int start = 0, end = ndata;
116 int i;
117 int done = 0;
118
119 /* do two passes over the test data (positives, negatives) */
120 do {
121 double sign = ( start<end ? 1. : -1. );
122 for(i=start; ( start< end ? i<end : i>end ); ( start< end ? ++i : --i )){
123 int passed = 0;
124 double v = sign*data[i].v;
125 double rn = c89_rint(v);
126 double expected = sign*data[i].expected;
127 #ifdef HAVE_C99_RINT
128 {
129 double rint_expected = rint(v);
130 int matched = ( expected==rint_expected );
131 if( !matched ){
132 fprintf(stderr, "E:%s|Expected test data[%d]={%.17lf,%.1lf} does not match the actual rint() value=%.1lf\n",__FUNCTION__,
133 i, v, expected, rint_expected);
134 }
135 assert(matched);
136 expected = rint_expected;
137 }
138 #endif
139 passed = ( rn==expected );
140 fprintf(( passed ? stdout : stderr ),
141 "T:%s|c89_rint(%.17lf)=%.1lf expected=%.1lf\t[%s]\n", TESTNAME,
142 v, rn, expected,
143 ( passed ? "PASS" : "FAIL" ));
144 if( !passed ) ++nfailed;
145 }
146
147 if( start<end ){
148 int swap = start;
149 start = end - 1; end = swap - 1;
150 }else{
151 done = 1;
152 }
153 }while( !done );
154
155 if( nfailed ){
156 fprintf(stderr,"T:%s|FAILED %d test\n\n", TESTNAME, nfailed);
157 }else{
158 printf("T:%s|PASSED\n\n", TESTNAME);
159 }
160
161 return nfailed;
162 }
163
164 int test_snprintf()
165 {
166 const char *TESTNAME = "snprintf";
167 int nfailed = 0;
168 #define TEST_BUF_MAXSIZE 256
169 const struct test_data {
170 size_t bufsize;
171 const char *fmt, *expected, *full;
172 } data[] = {
173 {TEST_BUF_MAXSIZE,"snprintf(buf, %d)","snprintf(buf, 17)","snprintf(buf, 17)"},
174 {17,"snprintf(buf, %d)","snprintf(buf, 17","snprintf(buf, 17)"},
175 {2,"snprintf(buf, %d)","s","snprintf(buf, 17)"},
176 {0,"snprintf(buf, %d)","","snprintf(buf, 17)"},
177 };
178 const size_t ndata = sizeof(data)/sizeof(data[0]);
179 char buf[TEST_BUF_MAXSIZE] = {0};
180 int i;
181
182 for(i=0; i<ndata; ++i){
183 int passed = 0;
184 size_t count = data[i].bufsize;
185 const char *fmt = data[i].fmt;
186 const char *full = data[i].full;
187 const char *expected = data[i].expected;
188 const int truncate_expected = ( count<=strlen(full) );
189 const int expected_nret = ( !truncate_expected
190 ? strlen(expected) : count );
191 const int expected_zero_at = ( !truncate_expected
192 ? expected_nret : expected_nret - 1 );
193 int nret;
194 buf[( count>0 ? count - 1 : 0 )] = '\0';
195 nret = c89_snprintf(buf, count, fmt, strlen(fmt));
196 #ifdef HAVE_C99_RINT
197 {
198 char snprintf_expected[TEST_BUF_MAXSIZE] = {0};
199 int snprintf_expected_nret = snprintf(snprintf_expected, count, fmt, strlen(fmt));
200 int matched = ( strcmp(expected, snprintf_expected)==0 );
201 int matched_nret = ( expected_nret==snprintf_expected_nret );
202 if( !matched ){
203 fprintf(stderr, "E:%s|Expected test data[%d]={'%s','%s'} does not match the actual snprintf() value='%s'\n",__FUNCTION__,
204 i, buf, expected, snprintf_expected);
205 }
206
207 /* NOTE: This implementation of c89_snprintf() on truncation returns
208 ** the input count, not the expected number of chars needed to fully
209 ** output the requested format. So warn, only ifthe expected nret is
210 ** less than the count.
211 */
212 if( !matched_nret && expected_nret<count ){
213 fprintf(stderr, "W:%s|Expected return value=%d for test data[%d]={'%s','%s'} does not match the actual snprintf() return value=%d\n",__FUNCTION__,
214 expected_nret, i, buf, expected, snprintf_expected_nret);
215 }
216 assert(matched);
217 expected = snprintf_expected;
218 }
219 #endif
220 passed = ( nret==expected_nret );
221 fprintf(( passed ? stdout : stderr ),
222 "T:%s|c89_snprintf(%lu,\"%s\", %d) nret=%d expected=%d\t[%s]\n", TESTNAME,
223 (unsigned long)count, fmt, (int)strlen(fmt), nret, expected_nret,
224 ( passed ? "PASS" : "FAIL" ));
225 if( !passed ) ++nfailed;
226
227 if( count ){
228 passed = ( buf[expected_zero_at]=='\0' );
229 fprintf(( passed ? stdout : stderr ),
230 "T:%s|c89_snprintf(%lu,\"%s\", %d) s[%d]=%d expected=%d\t[%s]\n", TESTNAME,
231 (unsigned long)count, fmt, (int)strlen(fmt), expected_zero_at, buf[expected_zero_at],'\0',
232 ( passed ? "PASS" : "FAIL" ));
233 if( !passed ) ++nfailed;
234 }
235
236 passed = ( strcmp(buf, expected)==0 );
237 fprintf((passed ? stdout : stderr),
238 "T:%s|c89_snprintf(%lu,\"%s\", %d)=\"%s\" expected=\"%s\"\t[%s]\n", TESTNAME,
239 (unsigned long)count, fmt, (int)strlen(fmt), buf, expected,
240 ( passed ? "PASS" : "FAIL" ));
241 if( !passed ) ++nfailed;
242 }
243
244 if( nfailed ){
245 fprintf(stderr,"T:%s|FAILED %d tests\n\n", TESTNAME, nfailed);
246 }else{
247 printf("T:%s|PASSED\n\n", TESTNAME);
248 }
249 return nfailed;
250 }
251
252 int main(int argc, char *argv[])
253 {
254 int iarg;
255 struct testrun {
256 char rint, snprintf;
257 int status;
258 } testrun = {0, 0, 0};
259
260 printf("Usage: %s [TEST]...\n", argv[0]);
261 printf("Test MSVC C89 compatible implementations of selected C99 functions.\n"
262 "Run the selected TEST, by default 'all'; optionally exclude tests from the run.\n");
263 printf("Example: %s all -snprintf\n", argv[0]);
264 printf("\nTests:\n"
265 " all, rint, snprintf\n"
266 "\n -TEST\t\texclude the test from the run\n"
267 "\n"
268 );
269 if( argc>1
270 && ( strcmp(argv[1], "/?")==0 || strcmp(argv[1], "/h")==0
271 || strcmp(argv[1], "/H")==0 || strcmp(argv[1], "--help")==0 ) ){
272 return 0;
273 }
274
275 testrun.rint = testrun.snprintf = ( argc==1 );
276 for(iarg=1; iarg<argc; ++iarg){
277 const char *name = argv[iarg];
278 char runit = 1;
279 if( argv[iarg][0]=='-' ){
280 runit = 0;
281 name = &(argv[iarg][1]);
282 }
283
284 if( strcmp(name, "all")==0 ){
285 testrun.rint = testrun.snprintf = runit;
286 }else if( strcmp(name, "rint")==0 ){
287 testrun.rint = runit;
288 }else if( strcmp(name, "snprintf")==0 ){
289 testrun.snprintf = runit;
290 }else{
291 testrun.status = 2;
292 fprintf(stderr, "\nE|Invalid test requested: '%s'\n", name);
293 }
294 }
295
296 if( testrun.status==2 ){
297 return testrun.status;
298 }
299
300 #ifndef _MSC_VER
301 fprintf(stderr, "W|Non-MSVC mode: testing against the native implementations\n\n");
302 #endif
303
304 if( testrun.rint )
305 testrun.status |= test_rint();
306
307 if( testrun.snprintf )
308 testrun.status |= test_snprintf();
309
310 if( testrun.status==0 )
311 printf("\nI|All selected tests completed successfully\n");
312 else
313 fprintf(stderr, "\nE|Some of the selected tests failed\n");
314 return testrun.status;
315 }
316

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button