1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "test.h"
16 #include <errno.h>
17 #include <iconv.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #define BUFFER_SIZE 200
22 
23 static int g_encodeNum = 77;
24 static char *g_encodeArray[] = {
25     "utf8",      "wchart",      "ucs2be",   "ucs2le",      "utf16be",   "utf16le",     "ucs4be",    "utf32be",
26     "ucs4le",    "utf32le",     "ascii",    "usascii",     "iso646",    "iso646us",    "utf16",     "ucs4",
27     "utf32",     "ucs2",        "eucjp",    "shiftjis",    "sjis",      "cp932",       "iso2022jp", "gb18030",
28     "gbk",       "gb2312",      "big5",     "bigfive",     "cp950",     "big5hkscs",   "euckr",     "ksc5601",
29     "ksx1001",   "cp949",       "iso88591", "latin1",      "iso88592",  "iso88593",    "iso88594",  "iso88595",
30     "iso88596",  "iso88597",    "iso88598", "iso88599",    "iso885910", "iso885911",   "tis620",    "iso885913",
31     "iso885914", "iso885915",   "latin9",   "iso885916",   "cp1250",    "windows1250", "cp1251",    "windows1251",
32     "cp1252",    "windows1252", "cp1253",   "windows1253", "cp1254",    "windows1254", "cp1255",    "windows1255",
33     "cp1256",    "windows1256", "cp1257",   "windows1257", "cp1258",    "windows1258", "koi8r",     "koi8u",
34     "cp437",     "cp850",       "cp866",    "cp1047",      "ibm1047"};
35 static int g_excludeToEncodeNum = 11;
36 static char *g_excludeToEncodeArray[] = {"gb18030",   "gbk",   "gb2312",  "big5",    "bigfive", "cp950",
37                                          "big5hkscs", "euckr", "ksc5601", "ksx1001", "cp949"};
38 struct IconvParam {
39     char *to;
40     char *from;
41     char *input;
42     size_t inputLen;
43     char *output;
44     size_t outputLen;
45 };
CloseIconv(iconv_t cd)46 void CloseIconv(iconv_t cd)
47 {
48     if (iconv_close(cd)) {
49         printf("closed iconv failed, error: %s \n", strerror(errno));
50     }
51 }
52 
IconvTest(struct IconvParam *param)53 int IconvTest(struct IconvParam *param)
54 {
55     iconv_t cd = iconv_open(param->to, param->from);
56     if (cd == (iconv_t)-1) {
57         t_error("iconv opened failed, from: %s, to: %s, error: %s \n", param->from, param->to, strerror(errno));
58         CloseIconv(cd);
59         return 1;
60     }
61     char *input = param->input;
62     size_t inputLen = param->inputLen;
63     char *output = param->output;
64     size_t outputLen = param->outputLen;
65     if (iconv(cd, &input, &inputLen, &output, &outputLen)) {
66         t_error("iconv converted failed, from: %s, to: %s, error: %s \n", param->from, param->to, strerror(errno));
67         CloseIconv(cd);
68         return 1;
69     }
70     param->outputLen = outputLen;
71     CloseIconv(cd);
72     return 0;
73 }
74 
IsExcludeToEncode(char *ecode)75 int IsExcludeToEncode(char *ecode)
76 {
77     for (int i = 0; i < g_excludeToEncodeNum; i++) {
78         if (strcmp(ecode, g_excludeToEncodeArray[i]) == 0) {
79             return 0;
80         }
81     }
82     return 1;
83 }
84 
CompareIconvResult(char *to, char *from, char *src, size_t srcLen)85 void CompareIconvResult(char *to, char *from, char *src, size_t srcLen)
86 {
87     if (IsExcludeToEncode(to) == 0) {
88         return;
89     }
90     struct IconvParam param;
91     param.input = src;
92     param.inputLen = srcLen;
93     char output[BUFFER_SIZE];
94     param.output = output;
95     param.outputLen = BUFFER_SIZE;
96     param.to = to;
97     param.from = from;
98     if (IconvTest(&param)) {
99         return;
100     }
101 
102     if (IsExcludeToEncode(from) == 0) {
103         return;
104     }
105     param.input = param.output;
106     param.inputLen = BUFFER_SIZE - param.outputLen;
107     char newOutput[BUFFER_SIZE];
108     param.output = newOutput;
109     param.outputLen = BUFFER_SIZE;
110     param.to = from;
111     param.from = to;
112     if (IconvTest(&param)) {
113         return;
114     }
115 
116     if (srcLen != BUFFER_SIZE - param.outputLen) {
117         t_error("compare error,from: %s, to: %s, newOutput: %s,\n", from, to, param.output);
118         return;
119     }
120     char *l = src;
121     char *r = param.output;
122     size_t step = sizeof(char);
123     for (size_t i = 0; i < srcLen; i += step) {
124         if (*l != *r) {
125             t_error("compare error,from: %s, to: %s, newOutput: %s,\n", from, to, param.output);
126             return;
127         }
128         l++;
129         r++;
130     }
131 }
132 
main(void)133 int main(void)
134 {
135     struct IconvParam param;
136     char *str = "Hello world";
137     for (int i = 0; i < g_encodeNum; i++) {
138         char *from = g_encodeArray[i];
139         char *input = str;
140         size_t inputLen = strlen(input);
141 
142         if (IsExcludeToEncode(from) != 0) {
143             param.input = input;
144             param.inputLen = inputLen;
145             char output[BUFFER_SIZE];
146             param.output = output;
147             param.outputLen = BUFFER_SIZE;
148             param.to = from;
149             param.from = "utf8";
150             if (IconvTest(&param)) {
151                 continue;
152             }
153             input = param.output;
154             inputLen = BUFFER_SIZE - param.outputLen;
155         }
156 
157         for (int j = 0; j < g_encodeNum; j++) {
158             char *to = g_encodeArray[j];
159             CompareIconvResult(to, from, input, inputLen);
160         }
161     }
162 
163     return t_status;
164 }