1 /*
2 libzint - the open source barcode library
3 Copyright (C) 2020 - 2021 Robin Stuart <rstuart114@gmail.com>
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the project nor the names of its contributors
15 may be used to endorse or promote products derived from this software
16 without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 SUCH DAMAGE.
29 */
30 /* vim: set ts=4 sw=4 et : */
31
32 #include "testcommon.h"
33
test_large(int index,int debug)34 static void test_large(int index, int debug) {
35
36 struct item {
37 int symbology;
38 char *pattern;
39 int length;
40 int ret;
41 int expected_rows;
42 int expected_width;
43 };
44 // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
45 struct item data[] = {
46 /* 0*/ { BARCODE_AUSPOST, "1", 23, 0, 3, 133 },
47 /* 1*/ { BARCODE_AUSPOST, "1", 24, ZINT_ERROR_TOO_LONG, -1, -1 },
48 /* 2*/ { BARCODE_AUSPOST, "1", 18, 0, 3, 133 },
49 /* 3*/ { BARCODE_AUSPOST, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 },
50 /* 4*/ { BARCODE_AUSPOST, "1", 16, 0, 3, 103 },
51 /* 5*/ { BARCODE_AUSPOST, "1", 17, ZINT_ERROR_TOO_LONG, -1, -1 },
52 /* 6*/ { BARCODE_AUSPOST, "1", 13, 0, 3, 103 },
53 /* 7*/ { BARCODE_AUSPOST, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1 },
54 /* 8*/ { BARCODE_AUSPOST, "1", 8, 0, 3, 73 },
55 /* 9*/ { BARCODE_AUSPOST, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
56 /* 10*/ { BARCODE_AUSREPLY, "1", 8, 0, 3, 73 },
57 /* 11*/ { BARCODE_AUSREPLY, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
58 /* 12*/ { BARCODE_AUSROUTE, "1", 8, 0, 3, 73 },
59 /* 13*/ { BARCODE_AUSROUTE, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
60 /* 14*/ { BARCODE_AUSREDIRECT, "1", 8, 0, 3, 73 },
61 /* 15*/ { BARCODE_AUSREDIRECT, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 },
62 };
63 int data_size = ARRAY_SIZE(data);
64 int i, length, ret;
65 struct zint_symbol *symbol;
66
67 char data_buf[64];
68
69 testStart("test_large");
70
71 for (i = 0; i < data_size; i++) {
72
73 if (index != -1 && i != index) continue;
74
75 symbol = ZBarcode_Create();
76 assert_nonnull(symbol, "Symbol not created\n");
77
78 testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length);
79 assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf));
80
81 length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug);
82
83 ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length);
84 assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
85
86 if (ret < ZINT_ERROR) {
87 assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
88 assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
89 }
90
91 ZBarcode_Delete(symbol);
92 }
93
94 testFinish();
95 }
96
test_hrt(int index,int debug)97 static void test_hrt(int index, int debug) {
98
99 struct item {
100 int symbology;
101 char *data;
102
103 char *expected;
104 };
105 // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
106 struct item data[] = {
107 /* 0*/ { BARCODE_AUSPOST, "12345678901234567890123", "" }, // None
108 };
109 int data_size = ARRAY_SIZE(data);
110 int i, length, ret;
111 struct zint_symbol *symbol;
112
113 testStart("test_hrt");
114
115 for (i = 0; i < data_size; i++) {
116
117 if (index != -1 && i != index) continue;
118
119 symbol = ZBarcode_Create();
120 assert_nonnull(symbol, "Symbol not created\n");
121
122 length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
123
124 ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
125 assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt);
126
127 assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected);
128
129 ZBarcode_Delete(symbol);
130 }
131
132 testFinish();
133 }
134
test_input(int index,int debug)135 static void test_input(int index, int debug) {
136
137 struct item {
138 int symbology;
139 char *data;
140 int ret;
141 int expected_rows;
142 int expected_width;
143 char *expected_errtxt;
144 };
145 // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
146 struct item data[] = {
147 /* 0*/ { BARCODE_AUSPOST, "12345678", 0, 3, 73, "" },
148 /* 1*/ { BARCODE_AUSPOST, "1234567A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 405: Invalid character in DPID (first 8 characters) (digits only)" },
149 /* 2*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
150 /* 3*/ { BARCODE_AUSPOST, "12345678ABcd!", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 404: Invalid character in data (alphanumerics, space and \"#\" only)" },
151 /* 4*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
152 /* 5*/ { BARCODE_AUSPOST, "1234567890123456", 0, 3, 103, "" },
153 /* 6*/ { BARCODE_AUSPOST, "123456789012345A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character in data (digits only for lengths 16 and 23)" },
154 /* 7*/ { BARCODE_AUSPOST, "12345678ABCDefgh #", 0, 3, 133, "" }, // Length 18
155 /* 8*/ { BARCODE_AUSPOST, "12345678901234567890123", 0, 3, 133, "" },
156 /* 9*/ { BARCODE_AUSPOST, "1234567890123456789012A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character in data (digits only for lengths 16 and 23)" },
157 /* 10*/ { BARCODE_AUSPOST, "1234567", ZINT_ERROR_TOO_LONG, -1, -1, "Error 401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)" }, // No leading zeroes added
158 /* 11*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "" },
159 /* 12*/ { BARCODE_AUSREPLY, "1234567", 0, 3, 73, "" }, // Leading zeroes added
160 /* 13*/ { BARCODE_AUSREPLY, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
161 /* 14*/ { BARCODE_AUSROUTE, "123456", 0, 3, 73, "" },
162 /* 15*/ { BARCODE_AUSROUTE, "12345", 0, 3, 73, "" },
163 /* 16*/ { BARCODE_AUSROUTE, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
164 /* 17*/ { BARCODE_AUSREDIRECT, "1234", 0, 3, 73, "" },
165 /* 18*/ { BARCODE_AUSREDIRECT, "123", 0, 3, 73, "" },
166 /* 19*/ { BARCODE_AUSREDIRECT, "0", 0, 3, 73, "" },
167 /* 20*/ { BARCODE_AUSREDIRECT, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Auspost input is too long (8 character maximum)" },
168 };
169 int data_size = ARRAY_SIZE(data);
170 int i, length, ret;
171 struct zint_symbol *symbol;
172
173 testStart("test_input");
174
175 for (i = 0; i < data_size; i++) {
176
177 if (index != -1 && i != index) continue;
178
179 symbol = ZBarcode_Create();
180 assert_nonnull(symbol, "Symbol not created\n");
181
182 length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
183
184 ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
185 assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
186
187 if (ret < ZINT_ERROR) {
188 assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
189 assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
190 }
191 assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt);
192
193 ZBarcode_Delete(symbol);
194 }
195
196 testFinish();
197 }
198
199 // Australia Post Customer Barcoding Technical Specifications (Revised Aug 2012)
200 // https://auspost.com.au/content/dam/auspost_corp/media/documents/customer-barcode-technical-specifications-aug2012.pdf
test_encode(int index,int generate,int debug)201 static void test_encode(int index, int generate, int debug) {
202
203 struct item {
204 int symbology;
205 char *data;
206 int ret;
207
208 int expected_rows;
209 int expected_width;
210 char *comment;
211 char *expected;
212 };
213 struct item data[] = {
214 /* 0*/ { BARCODE_AUSPOST, "96184209", 0, 3, 73, "Australia Post Customer Barcoding Tech Specs Diagram 1; verified manually against tec-it",
215 "1000101010100010001010100000101010001010001000001010000010001000001000100"
216 "1010101010101010101010101010101010101010101010101010101010101010101010101"
217 "0000100010000010101010001010000010101010001000101010001000100010000010000"
218 },
219 /* 1*/ { BARCODE_AUSPOST, "3221132412345678", 0, 3, 103, "59 Custom 2 N encoding",
220 "1000100000101010100010001010101010101000101010101000101010101000001000100000101000000000001000000000100"
221 "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
222 "0000001000100010101010101000100000101010000010001010001000000010101010001010000010001010101000100000000"
223 },
224 /* 2*/ { BARCODE_AUSPOST, "32211324Ab #2", 0, 3, 103, "59 Custom 2 C encoding",
225 "1000100000101010100010001010101010101000101010101010001010100010100000101000100000000010100000100010100"
226 "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
227 "0000001000100010101010101000100000101010000010101010001010100010000000100000001000101010000010000000000"
228 },
229 /* 3*/ { BARCODE_AUSPOST, "32211324123456789012345", 0, 3, 133, "62 Custom 3 N encoding",
230 "1000001010001010100010001010101010101000101010101000101010101000001000100000001010101010100010101010100000100000100010101010100010100"
231 "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
232 "0000101010100010101010101000100000101010000010001010001000000010101010001010001010101000101000100000001000001010000010001010100010000"
233 },
234 /* 4*/ { BARCODE_AUSPOST, "32211324aBCd#F hIz", 0, 3, 133, "62 Custom 3 C encoding",
235 "1000001010001010100010001010101010101000101010000010101010100010000010100010100010100010000010000000000000100010100010101010000000100"
236 "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
237 "0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000"
238 },
239 /* 5*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it",
240 "1000101010001010100010101010100000100010000000001000001000000000100010100"
241 "1010101010101010101010101010101010101010101010101010101010101010101010101"
242 "0000000000101000101000100000001010101000101000000000100010101000101000000"
243 },
244 /* 6*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it",
245 "1000000000101010101010000010001000000010101000100010101010000000101000100"
246 "1010101010101010101010101010101010101010101010101010101010101010101010101"
247 "0000101010000010000000101010100010100010101000100010101010001010001000000"
248 },
249 /* 7*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it",
250 "1000001010000010000000100010100010101010100000101010101000100010100010100"
251 "1010101010101010101010101010101010101010101010101010101010101010101010101"
252 "0000001010100010101010001010001000000010101000000000001010101000001010000"
253 },
254 };
255 int data_size = ARRAY_SIZE(data);
256 int i, length, ret;
257 struct zint_symbol *symbol;
258
259 char escaped[1024];
260 char bwipp_buf[8192];
261 char bwipp_msg[1024];
262
263 int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise
264
265 testStart("test_encode");
266
267 for (i = 0; i < data_size; i++) {
268
269 if (index != -1 && i != index) continue;
270
271 symbol = ZBarcode_Create();
272 assert_nonnull(symbol, "Symbol not created\n");
273
274 length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
275
276 ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
277 assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
278
279 if (generate) {
280 printf(" /*%3d*/ { %s, \"%s\", %s, %d, %d, \"%s\",\n",
281 i, testUtilBarcodeName(data[i].symbology), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
282 testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment);
283 testUtilModulesPrint(symbol, " ", "\n");
284 printf(" },\n");
285 } else {
286 if (ret < ZINT_ERROR) {
287 int width, row;
288
289 assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data);
290 assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
291
292 ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
293 assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
294
295 if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) {
296 ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf));
297 assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
298
299 ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
300 assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
301 i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected);
302 }
303 }
304 }
305
306 ZBarcode_Delete(symbol);
307 }
308
309 testFinish();
310 }
311
312 // #181 Christian Hartlage OSS-Fuzz
test_fuzz(int index,int debug)313 static void test_fuzz(int index, int debug) {
314
315 struct item {
316 int symbology;
317 char *data;
318 int length;
319 int ret;
320 };
321 // s/\/\*[ 0-9]*\*\//\=printf("\/*%2d*\/", line(".") - line("'<"))
322 struct item data[] = {
323 /* 0*/ { BARCODE_AUSROUTE, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
324 /* 1*/ { BARCODE_AUSROUTE, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
325 /* 2*/ { BARCODE_AUSREPLY, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
326 /* 3*/ { BARCODE_AUSREPLY, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
327 /* 4*/ { BARCODE_AUSREDIRECT, "A\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
328 /* 5*/ { BARCODE_AUSREDIRECT, "1\000\000\000", 4, ZINT_ERROR_INVALID_DATA },
329 };
330 int data_size = ARRAY_SIZE(data);
331 int i, length, ret;
332 struct zint_symbol *symbol;
333
334 testStart("test_fuzz");
335
336 for (i = 0; i < data_size; i++) {
337
338 if (index != -1 && i != index) continue;
339
340 symbol = ZBarcode_Create();
341 assert_nonnull(symbol, "Symbol not created\n");
342
343 length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
344
345 ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
346 assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
347
348 ZBarcode_Delete(symbol);
349 }
350
351 testFinish();
352 }
353
main(int argc,char * argv[])354 int main(int argc, char *argv[]) {
355
356 testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
357 { "test_large", test_large, 1, 0, 1 },
358 { "test_hrt", test_hrt, 1, 0, 1 },
359 { "test_input", test_input, 1, 0, 1 },
360 { "test_encode", test_encode, 1, 1, 1 },
361 { "test_fuzz", test_fuzz, 1, 0, 1 },
362 };
363
364 testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
365
366 testReport();
367
368 return 0;
369 }
370