• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef __LITEOS__
23 #include "test.h"
24 #include <errno.h>
25 #include <iconv.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #define EXTRA_LARGE_SIZE (30*1024*1024)
30 #define BUFFER_SIZE 1024
31 #define IGNORE_SIZE 9
32 
33 int set_iconv_icu_enable(void);
34 
35 typedef struct StatefulCombined {
36     unsigned sign;
37     const unsigned char* to;
38     const unsigned char* from;
39     iconv_t base_cd;
40     unsigned state;
41 } StatefulCombined;
42 
43 typedef struct NameMap {
44     const char* source;
45     const char* target;
46 } NameMap;
47 
48 
49 // Global Variables
50 static NameMap g_mappings[] = {
51     {"utf8\0char\0\0", "UTF-8"},
52     {"utf7\0\0", "UTF-7"},
53     {"ucs2\0utf16\0ucs2be\0utf16be\0\0", "UTF-16BE"},
54     {"ucs2le\0utf16le\0\0", "UTF-16LE"},
55     {"ucs4\0utf32\0ucs4be\0utf32be\0\0", "UTF-32BE"},
56     {"wchart\0ucs4le\0utf32le\0\0", "UTF-32LE"},
57     {"ascii\0usascii\0""20127\0iso646\0iso646us\0\0", "US-ASCII"},
58     {"eucjp\0eucjp2007\0\0", "euc-jp-2007"},
59     {"shiftjis\0sjis\0cp932\0ibm943p15a2003\0\0", "ibm-943_P15A-2003"},
60     {"gb18030\0\0", "gb18030"},
61     {"gbk\0""54936\0windows9362000\0\0", "windows-936-2000"},
62     {"gb2312\0""52936\0ibm1383p1101999\0\0", "ibm-1383_P110-1999"},
63     {"big5\0""950\0bigfive\0cp950\0windows9502000\0\0", "windows-950-2000"},
64     {"big5hk\0big5hkscs\0""951\0ibm1375p1002008\0\0", "ibm-1375_P100-2008"},
65     {"euckr\0ibm970p110p1102006u2\0\0", "ibm-970_P110_P110-2006_U2"},
66     {"ksc5601\0ksx1001\0cp949\0windows9492000\0\0", "windows-949-2000"},
67     {"iso88591\0latin1\0\0", "ISO-8859-1"},
68     {"iso88592\0ibm912p1001995\0\0", "ibm-912_P100-1995"},
69     {"iso88593\0ibm913p1002000\0\0", "ibm-913_P100-2000"},
70     {"iso88594\0ibm914p1001995\0\0", "ibm-914_P100-1995"},
71     {"iso88595\0ibm915p1001995\0\0", "ibm-915_P100-1995"},
72     {"iso88596\0ibm1089p1001995\0\0", "ibm-1089_P100-1995"},
73     {"iso88597\0ibm9005x1102007\0\0", "ibm-9005_X110-2007"},
74     {"iso88598\0ibm5012p1001999\0\0", "ibm-5012_P100-1999"},
75     {"iso88599\0ibm920p1001995\0\0", "ibm-920_P100-1995"},
76     {"iso885910\0iso8859101998\0\0", "iso-8859_10-1998"},
77     {"iso885911\0iso8859112001\0\0", "iso-8859_11-2001"},
78     {"tis620\0windows8742000\0\0", "windows-874-2000"},
79     {"iso885913\0ibm921p1001995\0\0", "ibm-921_P100-1995"},
80     {"iso885914\0iso8859141998\0\0", "iso-8859_14-1998"},
81     {"iso885915\0latin9\0ibm923p1001998\0\0", "ibm-923_P100-1998"},
82     {"cp1250\0windows1250\0ibm5346p1001998\0\0", "ibm-5346_P100-1998"},
83     {"cp1251\0windows1251\0ibm5347p1001998\0\0", "ibm-5347_P100-1998"},
84     {"cp1252\0windows1252\0ibm5348p1001997\0\0", "ibm-5348_P100-1997"},
85     {"cp1253\0windows1253\0ibm5349p1001998\0\0", "ibm-5349_P100-1998"},
86     {"cp1254\0windows1254\0ibm5350p1001998\0\0", "ibm-5350_P100-1998"},
87     {"cp1255\0windows1255\0ibm9447p1002002\0\0", "ibm-9447_P100-2002"},
88     {"cp1256\0windows1256\0ibm9448x1002005\0\0", "ibm-9448_X100-2005"},
89     {"cp1257\0windows1257\0ibm9449p1002002\0\0", "ibm-9449_P100-2002"},
90     {"cp1258\0windows1258\0ibm5354p1001998\0\0", "ibm-5354_P100-1998"},
91     {"koi8r\0ibm878p1001996\0\0", "ibm-878_P100-1996"},
92     {"koi8u\0ibm1168p1002002\0\0", "ibm-1168_P100-2002"},
93     {"cp437\0ibm437p1001995\0\0", "ibm-437_P100-1995"},
94     {"cp850\0ibm850p1001995\0\0", "ibm-850_P100-1995"},
95     {"cp866\0ibm866p1001995\0\0", "ibm-866_P100-1995"},
96     {"ibm1047\0cp1047\0ibm1047p1001995\0\0", "ibm-1047_P100-1995"},
97 };
98 char* g_source_str;
99 char* g_target_str;
100 char g_mids[BUFFER_SIZE];
101 char g_outs[BUFFER_SIZE];
102 int32_t g_target_num = sizeof(g_mappings) / sizeof(g_mappings[0]);
103 char g_ins[] = {
104     0x00, 0x20, // ' ' (space)
105     0x00, 0x21, // '!'
106     0x00, 0x22, // '"'
107     0x00, 0x23, // '#'
108     0x00, 0x24, // '$'
109     0x00, 0x25, // '%'
110     0x00, 0x26, // '&'
111     0x00, 0x27, // '''
112     0x00, 0x28, // '('
113     0x00, 0x29, // ')'
114     0x00, 0x2A, // '*'
115     0x00, 0x2B, // '+'
116     0x00, 0x2C, // ','
117     0x00, 0x2D, // '-'
118     0x00, 0x2E, // '.'
119     0x00, 0x2F, // '/'
120     0x00, 0x30, // '0'
121     0x00, 0x31, // '1'
122     0x00, 0x32, // '2'
123     0x00, 0x33, // '3'
124     0x00, 0x34, // '4'
125     0x00, 0x35, // '5'
126     0x00, 0x36, // '6'
127     0x00, 0x37, // '7'
128     0x00, 0x38, // '8'
129     0x00, 0x39, // '9'
130     0x00, 0x3A, // ':'
131     0x00, 0x3B, // ';'
132     0x00, 0x3C, // '<'
133     0x00, 0x3D, // '='
134     0x00, 0x3E, // '>'
135     0x00, 0x3F, // '?'
136     0x00, 0x40, // '@'
137     0x00, 0x41, // 'A'
138     0x00, 0x42, // 'B'
139     0x00, 0x43, // 'C'
140     0x00, 0x44, // 'D'
141     0x00, 0x45, // 'E'
142     0x00, 0x46, // 'F'
143     0x00, 0x47, // 'G'
144     0x00, 0x48, // 'H'
145     0x00, 0x49, // 'I'
146     0x00, 0x4A, // 'J'
147     0x00, 0x4B, // 'K'
148     0x00, 0x4C, // 'L'
149     0x00, 0x4D, // 'M'
150     0x00, 0x4E, // 'N'
151     0x00, 0x4F, // 'O'
152     0x00, 0x50, // 'P'
153     0x00, 0x51, // 'Q'
154     0x00, 0x52, // 'R'
155     0x00, 0x53, // 'S'
156     0x00, 0x54, // 'T'
157     0x00, 0x55, // 'U'
158     0x00, 0x56, // 'V'
159     0x00, 0x57, // 'W'
160     0x00, 0x58, // 'X'
161     0x00, 0x59, // 'Y'
162     0x00, 0x5A, // 'Z'
163     0x00, 0x5B, // '['
164     0x00, 0x5C, // '\\'
165     0x00, 0x5D, // ']'
166     0x00, 0x5E, // '^'
167     0x00, 0x5F, // '_'
168     0x00, 0x60, // '`'
169     0x00, 0x61, // 'a'
170     0x00, 0x62, // 'b'
171     0x00, 0x63, // 'c'
172     0x00, 0x64, // 'd'
173     0x00, 0x65, // 'e'
174     0x00, 0x66, // 'f'
175     0x00, 0x67, // 'g'
176     0x00, 0x68, // 'h'
177     0x00, 0x69, // 'i'
178     0x00, 0x6A, // 'j'
179     0x00, 0x6B, // 'k'
180     0x00, 0x6C, // 'l'
181     0x00, 0x6D, // 'm'
182     0x00, 0x6E, // 'n'
183     0x00, 0x6F, // 'o'
184     0x00, 0x70, // 'p'
185     0x00, 0x71, // 'q'
186     0x00, 0x72, // 'r'
187     0x00, 0x73, // 's'
188     0x00, 0x74, // 't'
189     0x00, 0x75, // 'u'
190     0x00, 0x76, // 'v'
191     0x00, 0x77, // 'w'
192     0x00, 0x78, // 'x'
193     0x00, 0x79, // 'y'
194     0x00, 0x7A, // 'z'
195     0x00, 0x7B, // '{'
196     0x00, 0x7C, // '|'
197     0x00, 0x7D, // '}'
198     0x00, 0x7E  // '~'
199 };
200 size_t g_ins_len = sizeof(g_ins);
201 char* g_ins_zh = "Big5 编码示例";
202 size_t g_ins_zh_len;
203 
iconv_close_with_strerror(iconv_t cd)204 void iconv_close_with_strerror(iconv_t cd)
205 {
206     if (iconv_close(cd)) {
207         t_error("closed iconv failed, error: %s \n", strerror(errno));
208     }
209 }
210 
alias_test(void)211 void alias_test(void)
212 {
213     char* s;
214     StatefulCombined *scd = 0;
215     for (s = g_source_str; *s;) {
216         scd = (void *)iconv_open(s, s);
217         if (scd == (iconv_t)-1) {
218             t_error("iconv opened failed, from: %s, to: %s, error: %s \n", s, s, strerror(errno));
219             return;
220         }
221         if (strcmp((void*)scd->to, g_target_str) != 0) {
222             t_error("verify error: [input]%s, [actual_to]%s  [expect_to]%s\n", s, scd->to, g_target_str);
223         }
224         if (strcmp((void*)scd->from, g_target_str) != 0) {
225             t_error("verify error: [input]%s, [actual_from]%s  [expect_from]%s\n", s, scd->from, g_target_str);
226         }
227         s += strlen(s) + 1;
228         iconv_close_with_strerror(scd);
229     }
230 }
231 
iconv_test(char * from,char * to,char ** inptrptr,size_t * input_len_ptr,char ** outptrptr,size_t * output_len_ptr)232 size_t iconv_test(char* from, char* to,
233     char** inptrptr, size_t* input_len_ptr, char** outptrptr, size_t* output_len_ptr)
234 {
235     iconv_t cd = iconv_open((void*)to, (void*)from);
236     if (cd == (iconv_t)-1) {
237         t_error("iconv opened failed, from: %s, to: %s, error: %s \n", from, to, strerror(errno));
238         return (size_t)-1;
239     }
240 
241     size_t res = iconv(cd, inptrptr, input_len_ptr, outptrptr, output_len_ptr);
242     if (res) {
243         iconv_close_with_strerror(cd);
244         return res;
245     }
246 
247     iconv_close_with_strerror(cd);
248     return res;
249 }
250 
iconv_exchange(char * from,char * to,char * ins,size_t ins_len)251 void iconv_exchange(char* from, char* to, char* ins, size_t ins_len)
252 {
253     char* ins_ptr = ins;
254     char* mids_ptr = g_mids;
255     char* outs_ptr = g_outs;
256     size_t ins_bytes = ins_len;
257     size_t mids_bytes = BUFFER_SIZE;
258     size_t outs_bytes = BUFFER_SIZE;
259 
260     iconv_test(from, to, &ins_ptr, &ins_bytes, &mids_ptr, &mids_bytes);
261 
262     ins_ptr = g_mids;
263     ins_bytes = BUFFER_SIZE - mids_bytes;
264     iconv_test(to, from, &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
265 }
266 
charcmp(char * a,char * b)267 static int charcmp(char* a, char* b)
268 {
269     for (; *a && *b; a++, b++) {
270         if (*a != *b) {return 1;}
271     }
272     return *a != *b;
273 }
274 
iconv_exchange_with_charcmp(char * from,char * to,char * ins,size_t ins_len)275 void iconv_exchange_with_charcmp(char* from, char* to, char* ins, size_t ins_len)
276 {
277     iconv_exchange(from, to, ins, ins_len);
278     if (charcmp(ins, g_outs) != 0) {
279         t_error("compare error [type]%s, [ins] %s, [outs] %s\n",
280             to, ins, g_outs);
281     }
282 }
283 
test_to_ignore_skip(void)284 void test_to_ignore_skip(void)
285 {
286     char* expect = "Big5 示例";
287     iconv_exchange("utf8", "big5//IGNORE", g_ins_zh, g_ins_zh_len);
288     if (strcmp(expect, g_outs) != 0) {
289         t_error("iconv with ignore error: [ins] %s  [outs] %s  [expect] %s\n",
290             g_ins_zh, g_outs, expect);
291     }
292 }
293 
test_to_translit_skip(void)294 void test_to_translit_skip(void)
295 {
296     char* expect = "Big5 ??示例";
297     iconv_exchange("utf8", "big5//TRANSLIT", g_ins_zh, g_ins_zh_len);
298     if (strcmp(expect, g_outs) != 0) {
299         t_error("iconv with translit error: [ins] %s  [outs] %s  [expect] %s\n",
300             g_ins_zh, g_outs, expect);
301     }
302 }
303 
test_errno_ilseq(void)304 void test_errno_ilseq(void)
305 {
306     char* ins_ptr = g_ins_zh;
307     size_t ins_bytes = g_ins_zh_len;
308     char* outs_ptr = g_outs;
309     size_t outs_bytes = BUFFER_SIZE;
310     size_t res = iconv_test("utf8", "big5", &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
311     if (res != (size_t)-1 || errno != EILSEQ) {
312         t_error("Failed: [ins] %s  [outs] %s  [res] %d [errno] %s\n",
313             g_ins_zh, g_outs, res, strerror(errno));
314     }
315 }
316 
test_errno_e2big(void)317 void test_errno_e2big(void)
318 {
319     char* ins_ptr = g_ins_zh;
320     size_t ins_bytes = g_ins_zh_len;
321     char* outs_ptr = g_outs;
322     size_t outs_bytes = 10;
323     size_t res = iconv_test("utf8", "utf16", &ins_ptr, &ins_bytes, &outs_ptr, &outs_bytes);
324     if (res != (size_t)-1 || errno != E2BIG) {
325         t_error("Failed: [ins] %s  [outs] %s  [res] %d [errno] %s\n",
326             g_ins_zh, g_outs, res, strerror(errno));
327     }
328 }
329 
test_empty_type(void)330 void test_empty_type(void)
331 {
332     StatefulCombined *scd = 0;
333     scd = (void *)iconv_open("", "");
334     if (strcmp((void*)scd->to, "UTF-8") != 0 || strcmp((void*)scd->from, "UTF-8") != 0) {
335         t_error("verify error: empty type not default fill utf8");
336     }
337     iconv_close_with_strerror(scd);
338 }
339 
test_large_string(void)340 void test_large_string(void)
341 {
342     iconv_t cd = iconv_open("utf8", "utf16");
343     if (cd == (iconv_t)-1) {
344         t_error("iconv open failed, from utf8 to utf16,error: %s \n", strerror(errno));
345         return;
346     }
347     char* inptr = malloc(EXTRA_LARGE_SIZE);
348     if (inptr == NULL) {
349         t_error("malloc failed, errno : %s \n", strerror(errno));
350         return;
351     }
352     memset(inptr, 'A', EXTRA_LARGE_SIZE - 1);
353     size_t input_len_ptr = EXTRA_LARGE_SIZE;
354     char* outptr = malloc(EXTRA_LARGE_SIZE * 4);
355     if (outptr == NULL) {
356         t_error("malloc failed, errno : %s \n", strerror(errno));
357         return;
358     }
359     size_t output_len_ptr = EXTRA_LARGE_SIZE * 4;
360     size_t res = iconv(cd, &inptr, &input_len_ptr, &outptr, &output_len_ptr);
361     if (res == -1) {
362         t_error("iconv failed, error: %s \n", strerror(errno));
363     }
364     iconv_close_with_strerror(cd);
365 }
366 
main(void)367 int main(void)
368 {
369     int icu_res = set_iconv_icu_enable();
370     if (icu_res != 0) {
371         t_error("set_iconv_icu_enable failed, error: %d \n", icu_res);
372         return t_status;
373     }
374     icu_res = set_iconv_icu_enable();
375     if (icu_res != 0) {
376         t_error("set_iconv_icu_enable twice failed, error: %d \n", icu_res);
377         return t_status;
378     }
379     g_ins_zh_len = strlen(g_ins_zh);
380 
381     for (int i = 0; i < g_target_num; i++) {
382         g_target_str = (void*)g_mappings[i].target;
383         g_source_str = (void*)g_mappings[i].source;
384 
385         // test all avail alias with iconv_open
386         alias_test();
387 
388         // test iconv without ignore
389         iconv_exchange_with_charcmp("utf16", g_target_str, g_ins, g_ins_len);
390 
391         // test iconv with ignore (norm input->not skip)
392         char* target_str_with_ignore = malloc(strlen(g_target_str) + IGNORE_SIZE);
393         strcpy(target_str_with_ignore, g_target_str);
394         strcat(target_str_with_ignore, "//IGNORE");
395         iconv_exchange_with_charcmp("utf16", target_str_with_ignore, g_ins, g_ins_len);
396         iconv_exchange_with_charcmp("utf16//IGNORE", target_str_with_ignore, g_ins, g_ins_len);
397         free(target_str_with_ignore);
398     }
399 
400     // test iconv with ignore (special input -> skip)
401     test_to_ignore_skip();
402 
403     // test iconv with translit (special input -> translit)
404     test_to_translit_skip();
405 
406     // test basic type (iso885916)
407     iconv_exchange_with_charcmp("utf16", "iso885916", g_ins, g_ins_len);
408 
409     // test errno
410     test_errno_ilseq();
411     test_errno_e2big();
412 
413     // empty type -> fill UTF-8
414     test_empty_type();
415 
416     // test extra large string convert
417     test_large_string();
418 
419     return t_status;
420 }
421 #endif