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         int option_2;
39         char *pattern;
40         int length;
41         int ret;
42         int expected_rows;
43         int expected_width;
44     };
45     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
46     struct item data[] = {
47         /*  0*/ { BARCODE_C25STANDARD, -1, "1", 80, 0, 1, 817 },
48         /*  1*/ { BARCODE_C25STANDARD, -1, "1", 81, ZINT_ERROR_TOO_LONG, -1, -1 },
49         /*  2*/ { BARCODE_C25STANDARD, 1, "1", 80, 0, 1, 827 },
50         /*  3*/ { BARCODE_C25STANDARD, 1, "1", 81, ZINT_ERROR_TOO_LONG, -1, -1 },
51         /*  4*/ { BARCODE_C25INTER, -1, "1", 90, 0, 1, 819 },
52         /*  5*/ { BARCODE_C25INTER, -1, "1", 91, ZINT_ERROR_TOO_LONG, -1, -1 },
53         /*  6*/ { BARCODE_C25INTER, 1, "1", 90, 0, 1, 837 },
54         /*  7*/ { BARCODE_C25INTER, 1, "1", 91, ZINT_ERROR_TOO_LONG, -1, -1 },
55         /*  8*/ { BARCODE_C25IATA, -1, "1", 45, 0, 1, 639 },
56         /*  9*/ { BARCODE_C25IATA, -1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 },
57         /* 10*/ { BARCODE_C25IATA, 1, "1", 45, 0, 1, 653 },
58         /* 11*/ { BARCODE_C25IATA, 1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 },
59         /* 12*/ { BARCODE_C25LOGIC, -1, "1", 80, 0, 1, 809 },
60         /* 13*/ { BARCODE_C25LOGIC, -1, "1", 81, ZINT_ERROR_TOO_LONG, -1, -1 },
61         /* 14*/ { BARCODE_C25LOGIC, 1, "1", 80, 0, 1, 819 },
62         /* 15*/ { BARCODE_C25LOGIC, 1, "1", 81, ZINT_ERROR_TOO_LONG, -1, -1 },
63         /* 16*/ { BARCODE_C25IND, -1, "1", 45, 0, 1, 649 },
64         /* 17*/ { BARCODE_C25IND, -1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 },
65         /* 18*/ { BARCODE_C25IND, 1, "1", 45, 0, 1, 663 },
66         /* 19*/ { BARCODE_C25IND, 1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 },
67         /* 20*/ { BARCODE_DPLEIT, -1, "1", 13, 0, 1, 135 },
68         /* 21*/ { BARCODE_DPLEIT, -1, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1 },
69         /* 22*/ { BARCODE_DPIDENT, -1, "1", 11, 0, 1, 117 },
70         /* 23*/ { BARCODE_DPIDENT, -1, "1", 12, ZINT_ERROR_TOO_LONG, -1, -1 },
71         /* 24*/ { BARCODE_ITF14, -1, "1", 13, 0, 1, 135 },
72         /* 25*/ { BARCODE_ITF14, -1, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1 },
73     };
74     int data_size = ARRAY_SIZE(data);
75     int i, length, ret;
76     struct zint_symbol *symbol;
77 
78     char data_buf[4096];
79 
80     testStart("test_large");
81 
82     for (i = 0; i < data_size; i++) {
83 
84         if (index != -1 && i != index) continue;
85 
86         symbol = ZBarcode_Create();
87         assert_nonnull(symbol, "Symbol not created\n");
88 
89         testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length);
90         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));
91 
92         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug);
93 
94         ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length);
95         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
96 
97         if (ret < ZINT_ERROR) {
98             assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
99             assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
100         }
101 
102         ZBarcode_Delete(symbol);
103     }
104 
105     testFinish();
106 }
107 
test_hrt(int index,int debug)108 static void test_hrt(int index, int debug) {
109 
110     struct item {
111         int symbology;
112         int option_2;
113         char *data;
114         char *expected;
115     };
116     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
117     struct item data[] = {
118         /*  0*/ { BARCODE_C25STANDARD, -1, "123456789", "123456789" },
119         /*  1*/ { BARCODE_C25STANDARD, 1, "123456789", "1234567895" },
120         /*  2*/ { BARCODE_C25STANDARD, 2, "123456789", "123456789" }, // Suppresses printing of check digit
121         /*  3*/ { BARCODE_C25INTER, -1, "123456789", "0123456789" }, // Adds leading zero if odd
122         /*  4*/ { BARCODE_C25INTER, 1, "123456789", "1234567895" }, // Unless check digit added when it becomes even
123         /*  5*/ { BARCODE_C25INTER, 2, "123456789", "123456789" },
124         /*  6*/ { BARCODE_C25INTER, -1, "1234567890", "1234567890" }, // No leading zero if even
125         /*  7*/ { BARCODE_C25INTER, 1, "1234567890", "012345678905" }, // Unless check digit added when it becomes odd
126         /*  8*/ { BARCODE_C25INTER, 2, "1234567890", "01234567890" },
127         /*  9*/ { BARCODE_C25IATA, -1, "123456789", "123456789" },
128         /* 10*/ { BARCODE_C25IATA, 1, "123456789", "1234567895" },
129         /* 11*/ { BARCODE_C25IATA, 2, "123456789", "123456789" },
130         /* 12*/ { BARCODE_C25LOGIC, -1, "123456789", "123456789" },
131         /* 13*/ { BARCODE_C25LOGIC, 1, "123456789", "1234567895" },
132         /* 14*/ { BARCODE_C25LOGIC, 2, "123456789", "123456789" },
133         /* 15*/ { BARCODE_C25IND, -1, "123456789", "123456789" },
134         /* 16*/ { BARCODE_C25IND, 1, "123456789", "1234567895" },
135         /* 17*/ { BARCODE_C25IND, 2, "123456789", "123456789" },
136         /* 18*/ { BARCODE_DPLEIT, -1, "123456789", "00001234567890" }, // Leading zeroes added to make 13 + appended checksum
137         /* 19*/ { BARCODE_DPLEIT, -1, "1234567890123", "12345678901236" },
138         /* 20*/ { BARCODE_DPIDENT, -1, "123456789", "001234567890" }, // Leading zeroes added to make 11 + appended checksum
139         /* 21*/ { BARCODE_DPIDENT, -1, "12345678901", "123456789016" },
140         /* 22*/ { BARCODE_ITF14, -1, "123456789", "00001234567895" }, // Leading zeroes added to make 13 + appended checksum
141         /* 23*/ { BARCODE_ITF14, -1, "1234567890123", "12345678901231" },
142     };
143     int data_size = ARRAY_SIZE(data);
144     int i, length, ret;
145     struct zint_symbol *symbol;
146 
147     testStart("test_hrt");
148 
149     for (i = 0; i < data_size; i++) {
150 
151         if (index != -1 && i != index) continue;
152 
153         symbol = ZBarcode_Create();
154         assert_nonnull(symbol, "Symbol not created\n");
155 
156         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
157 
158         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
159         assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt);
160 
161         assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected);
162 
163         ZBarcode_Delete(symbol);
164     }
165 
166     testFinish();
167 }
168 
test_input(int index,int debug)169 static void test_input(int index, int debug) {
170 
171     struct item {
172         int symbology;
173         char *data;
174         int ret;
175         int expected_rows;
176         int expected_width;
177     };
178     // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
179     struct item data[] = {
180         /*  0*/ { BARCODE_C25STANDARD, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
181         /*  1*/ { BARCODE_C25INTER, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
182         /*  2*/ { BARCODE_C25IATA, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
183         /*  3*/ { BARCODE_C25LOGIC, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
184         /*  4*/ { BARCODE_C25IND, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
185         /*  5*/ { BARCODE_DPLEIT, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
186         /*  6*/ { BARCODE_DPIDENT, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
187         /*  7*/ { BARCODE_ITF14, "A", ZINT_ERROR_INVALID_DATA, -1, -1 },
188     };
189     int data_size = ARRAY_SIZE(data);
190     int i, length, ret;
191     struct zint_symbol *symbol;
192 
193     testStart("test_input");
194 
195     for (i = 0; i < data_size; i++) {
196 
197         if (index != -1 && i != index) continue;
198 
199         symbol = ZBarcode_Create();
200         assert_nonnull(symbol, "Symbol not created\n");
201 
202         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1 /*option_2*/, -1, -1 /*output_options*/, data[i].data, -1, debug);
203 
204         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
205         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
206 
207         if (ret < ZINT_ERROR) {
208             assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
209             assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
210         }
211 
212         ZBarcode_Delete(symbol);
213     }
214 
215     testFinish();
216 }
217 
test_encode(int index,int generate,int debug)218 static void test_encode(int index, int generate, int debug) {
219 
220     struct item {
221         int symbology;
222         int option_2;
223         char *data;
224         int ret;
225 
226         int expected_rows;
227         int expected_width;
228         char *comment;
229         char *expected;
230     };
231     // BARCODE_ITF14 examples verified manually against GS1 General Specifications 21.0.1
232     struct item data[] = {
233         /*  0*/ { BARCODE_C25STANDARD, -1, "87654321", 0, 1, 97, "Standard Code 2 of 5; note zint uses 4X start/end wides while BWIPP uses 3X",
234                     "1111010101110100010101000111010001110101110111010101110111011100010101000101110111010111011110101"
235                 },
236         /*  1*/ { BARCODE_C25STANDARD, 1, "87654321", 0, 1, 107, "With check digit",
237                     "11110101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011110101"
238                 },
239         /*  2*/ { BARCODE_C25INTER, -1, "87654321", 0, 1, 81, "Interleaved Code 2 of 5, even; verified manually against tec-it",
240                     "101011101010111000100010001110111000101010001000111010111010001110101011100011101"
241                 },
242         /*  3*/ { BARCODE_C25INTER, 1, "87654321", 0, 1, 99, "With check digit",
243                     "101010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101"
244                 },
245         /*  4*/ { BARCODE_C25INTER, -1, "7654321", 0, 1, 81, "Interleaved Code 2 of 5, odd",
246                     "101010101110111000100010001110111000101010001000111010111010001110101011100011101"
247                 },
248         /*  5*/ { BARCODE_C25INTER, 1, "7654321", 0, 1, 81, "With check digit",
249                     "101010100010001110111011101011100010100011101110001010100011101010001000111011101"
250                 },
251         /*  6*/ { BARCODE_C25INTER, -1, "602003", 0, 1, 63, "DX cartridge barcode https://en.wikipedia.org/wiki/Interleaved_2_of_5 example",
252                     "101010111011100010001010111010001000111010001000111011101011101"
253                 },
254         /*  7*/ { BARCODE_C25IATA, -1, "87654321", 0, 1, 121, "IATA Code 2 of 5; verified manually against tec-it",
255                     "1010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111011101"
256                 },
257         /*  8*/ { BARCODE_C25IATA, 1, "87654321", 0, 1, 135, "With check digit",
258                     "101011101010111010101010111011101011101110101011101011101010101011101011101110111010101010111010101110111010101011101011101010111011101"
259                 },
260         /*  9*/ { BARCODE_C25LOGIC, -1, "87654321", 0, 1, 89, "Code 2 of 5 Data Logic; verified manually against tec-it",
261                     "10101110100010101000111010001110101110111010101110111011100010101000101110111010111011101"
262                 },
263         /* 10*/ { BARCODE_C25LOGIC, 1, "87654321", 0, 1, 99, "With check digit",
264                     "101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011101"
265                 },
266         /* 11*/ { BARCODE_C25IND, -1, "87654321", 0, 1, 131, "Industrial Code 2 of 5; verified manually against tec-it",
267                     "11101110101110101011101010101011101110101110111010101110101110101010101110101110111011101010101011101010111011101010101110111010111"
268                 },
269         /* 12*/ { BARCODE_C25IND, 1, "87654321", 0, 1, 145, "With check digit",
270                     "1110111010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111010111010101110111010111"
271                 },
272         /* 13*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it",
273                     "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101"
274                 },
275         /* 14*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example",
276                     "101011101011100010001011101000101110100011101110100010001010101110111000100010100011101110100011101010001110001010001011100011101011101"
277                 },
278         /* 15*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it",
279                     "101010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101"
280                 },
281         /* 16*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example",
282                     "101011101110001010001010111011100010001011100010001010111011100010001010111010001011101011100010101110001000111011101"
283                 },
284         /* 17*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it",
285                     "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101"
286                 },
287         /* 18*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2",
288                     "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001010001000111011101011101"
289                 },
290         /* 19*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1",
291                     "101011100010100010111010101110001000111010001011101110100010001011101011100010001110101000111011101010111000100010001110001110101011101"
292                 },
293         /* 20*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1",
294                     "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001011101010001000111011101"
295                 },
296     };
297     int data_size = ARRAY_SIZE(data);
298 
299     char escaped[1024];
300     char bwipp_buf[4096];
301     char bwipp_msg[1024];
302     int i, length, ret;
303     struct zint_symbol *symbol;
304 
305     int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise
306 
307     testStart("test_encode");
308 
309     for (i = 0; i < data_size; i++) {
310 
311         if (index != -1 && i != index) continue;
312 
313         symbol = ZBarcode_Create();
314         assert_nonnull(symbol, "Symbol not created\n");
315 
316         length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
317 
318         ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
319         assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
320 
321         if (generate) {
322             printf("        /*%3d*/ { %s, %d, \"%s\", %s, %d, %d, \"%s\",\n",
323                     i, testUtilBarcodeName(data[i].symbology), data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
324                     testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment);
325             testUtilModulesPrint(symbol, "                    ", "\n");
326             printf("                },\n");
327         } else {
328             if (ret < ZINT_ERROR) {
329                 int width, row;
330 
331                 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);
332                 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);
333 
334                 ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
335                 assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
336 
337                 if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) {
338                     ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf));
339                     assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
340 
341                     ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
342                     assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n  actual: %s\nexpected: %s\n",
343                                    i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected);
344                 }
345             }
346         }
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     };
362 
363     testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
364 
365     testReport();
366 
367     return 0;
368 }
369