1 #define COMMON_TEST_C
2 #include <stdlib.h>
3 #include <stddef.h>
4 #include <locale.h>
5 #include "tests_common.h"
6 #include "../../src/codepages.h"
7 #include "../../src/common.c"
8 #include "../../programs/escape.c"
9
10 static void
11 common_memmem_tests (void)
12 {
13 static char *hay = (char *)"0123456789";
14 char *needle = (char *)"01";
15 void *p;
16
17 // positive
18 if (my_memmem (hay, 10, needle, 2) != hay)
19 fail ("memmem %s not at 0", needle);
20 needle = (char *)"1234567890";
21 if (my_memmem (hay, 10, needle, 9) != &hay[1])
22 fail ("memmem %s not at 0", needle);
23 needle = (char *)"789";
24 if ((p = my_memmem (hay, 10, needle, 3)) != &hay[7])
25 fail ("memmem %s not at 7 but at %p of %p", needle, p, hay);
26
27 // not found
28 needle = (char *)"012344567890";
29 if (my_memmem (hay, 10, needle, 11))
30 fail ("memmem %s found", needle);
31 needle = (char *)"1234456780";
32 if (my_memmem (hay, 10, needle, 9))
33 fail ("memmem %s found", needle);
34 needle = (char *)"7890";
35 if (my_memmem (hay, 10, needle, 4))
36 fail ("memmem %s found", needle);
37 else
38 ok ("memmem");
39 }
40
41 // test versions:
42 // strict ordering of dwg_version
43 // matching enum <=> release type
44 static void
45 common_versions_tests (void)
46 {
47 uint8_t prev_version = 0;
48 assert (R_AFTER + 1 == ARRAY_SIZE (dwg_versions));
49 assert (strEQc (dwg_versions[R_2018].type, "r2018"));
50 assert (strEQc (dwg_versions[R_2007].type, "r2007"));
51 assert (strEQc (dwg_versions[R_2004].type, "r2004"));
52 assert (strEQc (dwg_versions[R_2000].type, "r2000"));
53 assert (strEQc (dwg_versions[R_13].type, "r13"));
54 assert (strEQc (dwg_versions[R_11].type, "r11"));
55 assert (strEQc (dwg_versions[R_2_0].type, "r2.0"));
56 assert (strEQc (dwg_versions[R_AFTER].type, "r>2022"));
57 assert (!dwg_versions[R_AFTER].hdr);
58 if (!failed)
59 ok ("dwg_versions messup");
60
61 for (int i = 0; i < R_AFTER; i++)
62 {
63 const uint8_t dwg_version = dwg_versions[i].dwg_version;
64 // strict ordering of dwg_versions
65 if (dwg_version < prev_version)
66 fail ("dwg_versions[%d].dwg_version %x >= %x", i, dwg_version,
67 prev_version);
68 prev_version = dwg_version;
69 }
70 if (!failed)
71 ok ("dwg_versions ordered");
72
73 if (!dwg_version_struct (R_AFTER))
74 ok ("!dwg_version_struct (R_AFTER)");
75 else
76 fail ("!dwg_version_struct (R_AFTER)");
77
78 assert (strEQc (dwg_version_codes (R_2018), "AC1032"));
79 assert (strEQc (dwg_version_codes (R_2000), "AC1015"));
80 assert (dwg_version_as ("r2000") == R_2000);
81 assert (dwg_version_as ("r2018") == R_2018);
82
83 assert (dwg_version_hdr_type ("AC1032") == R_2018);
84 assert (dwg_version_hdr_type ("AC1015") == R_2000);
85 assert (dwg_version_hdr_type2 ("AC1500", 0x16) == R_2000b);
86 assert (dwg_version_hdr_type2 ("AC1016", 0x17) == R_2000i);
87 assert (dwg_version_hdr_type2 ("AC1017", 0x17) == R_2002);
88 assert (dwg_version_hdr_type2 ("AC1018", 0x18) == R_2004c);
89 assert (dwg_version_hdr_type2 ("AC402b", 0) == R_2004b);
90 assert (dwg_version_hdr_type2 ("AC1018", 0x19) == R_2004);
91 assert (dwg_version_hdr_type2 ("AC1019", 0x18) == R_INVALID);
92 assert (dwg_version_hdr_type2 ("AC1021", 0x1a) == R_2007b);
93 assert (dwg_version_hdr_type2 ("AC1021", 0x1b) == R_2007);
94 assert (dwg_version_hdr_type ("AC1018") == R_2004);
95
96 ok ("versions");
97 }
98
99 // basic sanity: no illegal struct tm fields
100 static void
101 common_cvt_TIMEBLL_tests (void)
102 {
103 const unsigned long maxtries = 10000000LU;
104 static struct tm tm = { 0 };
105 static BITCODE_TIMEBLL date = { 0U, 0U, 0.0 };
106 int g_failed = failed;
107 failed = 0;
108 setlocale (LC_TIME, "en_UK.utf8");
109
110 date.days = 2456795;
111 date.ms = 18527023;
112 cvt_TIMEBLL (&tm, date);
113 if (tm.tm_year + 1900 != 2014)
114 fail ("tm.tm_year %d != 2014 with 2456795.18527023", tm.tm_year + 1900);
115
116 // check over- and underflows of each field
117 for (unsigned long i = 0; i < maxtries; i++)
118 {
119 time_t time;
120 struct tm tm1;
121 char buf[30];
122 char buf1[30];
123
124 date.days = rand ();
125 date.ms = rand ();
126 if (sizeof (long) > sizeof (int))
127 {
128 date.days |= (uint64_t)rand () << 32;
129 date.ms |= (uint64_t)rand () << 32;
130 }
131 // 2020 is the latest possible year for these tests
132 if (date.days > 2459191)
133 date.days %= 2459191;
134 // 1970 is the oldest possible year for gmtime cross-checks
135 if (date.days < 25567)
136 date.days += 25567;
137 if (date.ms > 24 * 60 * 60 * 1000)
138 date.ms %= 24 * 60 * 60 * 1000;
139
140 cvt_TIMEBLL (&tm, date);
141
142 if (tm.tm_mon < 0 || tm.tm_mon > 11)
143 fail ("tm.tm_mon %d [0-11] with %u.%u", tm.tm_mon, date.days, date.ms);
144 if (tm.tm_mday < 1 || tm.tm_mday > 31)
145 fail ("tm.tm_mday %d [1-31] with %u.%u", tm.tm_mday, date.days,
146 date.ms);
147 if (tm.tm_hour < 0 || tm.tm_hour > 23)
148 fail ("tm.tm_hour %d [0-23] with %u.%u", tm.tm_hour, date.days,
149 date.ms);
150 if (tm.tm_min < 0 || tm.tm_min > 60)
151 fail ("tm.tm_min %d [0-60] with %u.%u", tm.tm_min, date.days, date.ms);
152 if (tm.tm_sec < 0 || tm.tm_sec > 60)
153 fail ("tm.tm_sec %d [0-60] with %u.%u", tm.tm_sec, date.days, date.ms);
154
155 #if 0
156 // and compare against UTC time
157 time = 3600 * (date.days - 25567); // 1970 - 1900 in days => seconds since 1970
158 time += (date.ms / 1000);
159 tm1 = *gmtime(&time);
160 strftime (buf, sizeof (buf), "%F %X", &tm);
161 strftime (buf1, sizeof (buf1), "%F %X", &tm1);
162
163 if (tm.tm_year != tm1.tm_year)
164 fail ("tm.tm_year %d != %d with %u.%u\n %s vs %s", tm.tm_year + 1900,
165 tm1.tm_year + 1900, date.days, date.ms, buf, buf1);
166 if (tm.tm_mon != tm1.tm_mon)
167 fail ("tm.tm_mon %d != %d", tm.tm_mon, tm1.tm_mon);
168 if (tm.tm_mday != tm1.tm_mday)
169 fail ("tm.tm_mday %d != %d", tm.tm_mday, tm1.tm_mday);
170 if (tm.tm_hour != tm1.tm_hour)
171 fail ("tm.tm_hour %d != %d", tm.tm_hour, tm1.tm_hour);
172 if (tm.tm_min != tm1.tm_min)
173 fail ("tm.tm_mon %d != %d", tm.tm_mon, tm1.tm_mon);
174 if (tm.tm_sec != tm1.tm_sec)
175 fail ("tm.tm_sec %d != %d", tm.tm_sec, tm1.tm_sec);
176 #endif
177
178 if (failed)
179 break;
180 }
181
182 failed += g_failed;
183 if (g_failed == failed)
184 ok ("cvt_TIMEBLL");
185 }
186
187 static void
188 dwg_find_color_index_tests (void)
189 {
190 BITCODE_BL rgb;
191 BITCODE_BS ret;
192
193 #define test_rgb_case(_rgb, _ret) \
194 rgb = _rgb; \
195 ret = dwg_find_color_index (rgb); \
196 if (ret == _ret) \
197 ok ("dwg_find_color_index (0x%0x) -> %u", rgb, ret); \
198 else \
199 fail ("dwg_find_color_index (0x%0x) -> %u != %u", rgb, ret, _ret);
200
201 test_rgb_case (0xabff0000, 1);
202 test_rgb_case (0xab00ff00, 3);
203 test_rgb_case (0xab0000ff, 5);
204 test_rgb_case (0xabffffff, 7);
205 test_rgb_case (0xabbebebe, 254);
206 test_rgb_case (0xab000007, 256);
207 }
208
209 static void
210 escape_htmlescape_tests (void)
211 {
212 char *s = htmlescape ("'test'&{}", CP_ISO_8859_1); // forces a realloc
213 if (strEQc (s, "'test'&{}"))
214 pass ();
215 else
216 fail ("htmlescape => %s", s);
217 free (s);
218
219 // to multi-byte
220 s = htmlescape ("'%test'&{}", CP_CP864);
221 if (strEQc (s, "'٪test'&{}"))
222 pass ();
223 else
224 fail ("htmlescape CP864 => %s", s);
225 free (s);
226
227 // from multi-byte: echo -n "시험" | iconv -f utf-8 -t cp949 | od -t x1
228 // to: echo -n "시험" | iconv -f utf-8 -t ucs-2 | od -t x2
229 s = htmlescape ("'\xbc\xc3\xc7\xe8", CP_CP949); // "시험"
230 if (strEQc (s, "'셌험"))
231 pass ();
232 else
233 fail ("htmlescape CP949 => %s", s);
234 free (s);
235 }
236
237 static void
238 escape_htmlwescape_tests (void)
239 {
240 uint16_t tu[] = { 'T', 'e', 'i', 'g', 'h', 'a', 0x2122, 0 };
241 char *s = htmlwescape (tu);
242 if (strEQc (s, "Teigha™"))
243 pass ();
244 else
245 fail ("htmlwescape => %s", s);
246 free (s);
247 }
248
249 int
250 main (int argc, char const *argv[])
251 {
252 loglevel = is_make_silent () ? 0 : 2;
253 common_memmem_tests ();
254 common_versions_tests ();
255 common_cvt_TIMEBLL_tests ();
256 dwg_find_color_index_tests ();
257 escape_htmlescape_tests ();
258 escape_htmlwescape_tests ();
259 return failed;
260 }