1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 2003-2012, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 * file name: spreptst.c
9 * encoding: US-ASCII
10 * tab size: 8 (not used)
11 * indentation:4
12 *
13 * created on: 2003jul11
14 * created by: Ram Viswanadha
15 */
16 #define USPREP_TYPE_NAMES_ARRAY
17
18 #include "unicode/utypes.h"
19
20 #if !UCONFIG_NO_IDNA
21
22 #include "unicode/ustring.h"
23 #include "unicode/putil.h"
24 #include "cintltst.h"
25 #include "unicode/usprep.h"
26 #include "unicode/utf16.h"
27 #include "sprpimpl.h"
28 #include "uparse.h"
29 #include "cmemory.h"
30 #include "ustr_imp.h"
31 #include "cstring.h"
32
33 static void
34 parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode);
35
36 static void
37 compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping, int32_t mapLength,
38 UStringPrepType option);
39
40 static void
41 compareFlagsForRange(UStringPrepProfile* data, uint32_t start, uint32_t end,UStringPrepType option);
42
43 void
44 doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode);
45
46 static void U_CALLCONV
strprepProfileLineFn(void * context,char * fields[][2],int32_t fieldCount,UErrorCode * pErrorCode)47 strprepProfileLineFn(void *context,
48 char *fields[][2], int32_t fieldCount,
49 UErrorCode *pErrorCode) {
50 uint32_t mapping[40];
51 char *end, *map;
52 uint32_t code;
53 int32_t length;
54 UStringPrepProfile* data = (UStringPrepProfile*) context;
55 const char* typeName;
56 uint32_t rangeStart=0,rangeEnd =0;
57
58 typeName = fields[2][0];
59 map = fields[1][0];
60
61 if(strstr(typeName, usprepTypeNames[USPREP_UNASSIGNED])!=NULL){
62
63 u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode);
64
65 /* store the range */
66 compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_UNASSIGNED);
67
68 }else if(strstr(typeName, usprepTypeNames[USPREP_PROHIBITED])!=NULL){
69
70 u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode);
71
72 /* store the range */
73 compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_PROHIBITED);
74
75 }else if(strstr(typeName, usprepTypeNames[USPREP_MAP])!=NULL){
76 /* get the character code, field 0 */
77 code=(uint32_t)uprv_strtoul(fields[0][0], &end, 16);
78
79 /* parse the mapping string */
80 length=u_parseCodePoints(map, mapping, sizeof(mapping)/4, pErrorCode);
81
82 /* compare the mapping */
83 compareMapping(data, code,mapping, length,USPREP_MAP);
84 }else{
85 *pErrorCode = U_INVALID_FORMAT_ERROR;
86 }
87
88 }
89
90
91
92 static void
parseMappings(const char * filename,UStringPrepProfile * data,UBool reportError,UErrorCode * pErrorCode)93 parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode) {
94 char *fields[3][2];
95
96 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
97 return;
98 }
99
100 u_parseDelimitedFile(filename, ';', fields, 3, strprepProfileLineFn, (void*)data, pErrorCode);
101
102 /*fprintf(stdout,"Number of code points that have mappings with length >1 : %i\n",len);*/
103
104 if(U_FAILURE(*pErrorCode) && (reportError || *pErrorCode!=U_FILE_ACCESS_ERROR)) {
105 log_err( "testidn error: u_parseDelimitedFile(\"%s\") failed - %s\n", filename, u_errorName(*pErrorCode));
106 }
107 }
108
109
110 static UStringPrepType
getValues(uint32_t result,int32_t * value,UBool * isIndex)111 getValues(uint32_t result, int32_t* value, UBool* isIndex){
112
113 UStringPrepType type;
114 if(result == 0){
115 /*
116 * Initial value stored in the mapping table
117 * just return USPREP_TYPE_LIMIT .. so that
118 * the source codepoint is copied to the destination
119 */
120 type = USPREP_TYPE_LIMIT;
121 }else if(result >= _SPREP_TYPE_THRESHOLD){
122 type = (UStringPrepType) (result - _SPREP_TYPE_THRESHOLD);
123 }else{
124 /* get the type */
125 type = USPREP_MAP;
126 /* ascertain if the value is index or delta */
127 if(result & 0x02){
128 *isIndex = TRUE;
129 *value = result >> 2;
130
131 }else{
132 *isIndex = FALSE;
133 *value = (int16_t)result;
134 *value = (*value >> 2);
135
136 }
137 if((result>>2) == _SPREP_MAX_INDEX_VALUE){
138 type = USPREP_DELETE;
139 isIndex =FALSE;
140 value = 0;
141 }
142 }
143 return type;
144 }
145
146 static void
compareMapping(UStringPrepProfile * data,uint32_t codepoint,uint32_t * mapping,int32_t mapLength,UStringPrepType type)147 compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping,int32_t mapLength,
148 UStringPrepType type){
149 uint32_t result = 0;
150 int32_t length=0;
151 UBool isIndex = FALSE;
152 UStringPrepType retType;
153 int32_t value=0, idx=0, delta=0;
154 int32_t* indexes = data->indexes;
155 UTrie trie = data->sprepTrie;
156 const uint16_t* mappingData = data->mappingData;
157 int32_t realLength =0;
158 int32_t j=0;
159 int8_t i=0;
160
161 UTRIE_GET16(&trie, codepoint, result);
162 retType = getValues(result,&value,&isIndex);
163
164
165 if(type != retType && retType != USPREP_DELETE){
166
167 log_err( "Did not get the assigned type for codepoint 0x%08X. Expected: %i Got: %i\n",codepoint, USPREP_MAP, type);
168
169 }
170
171 if(isIndex){
172 idx = value;
173 if(idx >= indexes[_SPREP_ONE_UCHAR_MAPPING_INDEX_START] &&
174 idx < indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START]){
175 length = 1;
176 }else if(idx >= indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START] &&
177 idx < indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START]){
178 length = 2;
179 }else if(idx >= indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START] &&
180 idx < indexes[_SPREP_FOUR_UCHARS_MAPPING_INDEX_START]){
181 length = 3;
182 }else{
183 length = mappingData[idx++];
184 }
185 }else{
186 delta = value;
187 length = (retType == USPREP_DELETE)? 0 : 1;
188 }
189
190 /* figure out the real length */
191 for(j=0; j<mapLength; j++){
192 if(mapping[j] > 0xFFFF){
193 realLength +=2;
194 }else{
195 realLength++;
196 }
197 }
198
199 if(realLength != length){
200 log_err( "Did not get the expected length. Expected: %i Got: %i\n", mapLength, length);
201 }
202
203 if(isIndex){
204 for(i =0; i< mapLength; i++){
205 if(mapping[i] <= 0xFFFF){
206 if(mappingData[idx+i] != (uint16_t)mapping[i]){
207 log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[i], mappingData[idx+i]);
208 }
209 }else{
210 UChar lead = U16_LEAD(mapping[i]);
211 UChar trail = U16_TRAIL(mapping[i]);
212 if(mappingData[idx+i] != lead ||
213 mappingData[idx+i+1] != trail){
214 log_err( "Did not get the expected result. Expected: 0x%04X 0x%04X Got: 0x%04X 0x%04X\n", lead, trail, mappingData[idx+i], mappingData[idx+i+1]);
215 }
216 }
217 }
218 }else{
219 if(retType!=USPREP_DELETE && (codepoint-delta) != (uint16_t)mapping[0]){
220 log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[0],(codepoint-delta));
221 }
222 }
223
224 }
225
226 static void
compareFlagsForRange(UStringPrepProfile * data,uint32_t start,uint32_t end,UStringPrepType type)227 compareFlagsForRange(UStringPrepProfile* data,
228 uint32_t start, uint32_t end,
229 UStringPrepType type){
230
231 uint32_t result =0 ;
232 UStringPrepType retType;
233 UBool isIndex=FALSE;
234 int32_t value=0;
235 UTrie trie = data->sprepTrie;
236 /*
237 // supplementary code point
238 UChar __lead16=U16_LEAD(0x2323E);
239 int32_t __offset;
240
241 // get data for lead surrogate
242 (result)=_UTRIE_GET_RAW((&idnTrie), index, 0, (__lead16));
243 __offset=(&idnTrie)->getFoldingOffset(result);
244
245 // get the real data from the folded lead/trail units
246 if(__offset>0) {
247 (result)=_UTRIE_GET_RAW((&idnTrie), index, __offset, (0x2323E)&0x3ff);
248 } else {
249 (result)=(uint32_t)((&idnTrie)->initialValue);
250 }
251
252 UTRIE_GET16(&idnTrie,0x2323E, result);
253 */
254 while(start < end+1){
255 UTRIE_GET16(&trie,start, result);
256 retType = getValues(result, &value, &isIndex);
257 if(result > _SPREP_TYPE_THRESHOLD){
258 if(retType != type){
259 log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]);
260 }
261 }else{
262 if(type == USPREP_PROHIBITED && ((result & 0x01) != 0x01)){
263 log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]);
264 }
265 }
266
267 start++;
268 }
269
270 }
271
272 void
doStringPrepTest(const char * binFileName,const char * txtFileName,int32_t options,UErrorCode * errorCode)273 doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode){
274
275 const char *testdatapath = loadTestData(errorCode);
276 const char *srcdatapath = NULL;
277 const char *relativepath = NULL;
278 char *filename = NULL;
279 UStringPrepProfile* profile = NULL;
280
281 #ifdef U_TOPSRCDIR
282 srcdatapath = U_TOPSRCDIR;
283 relativepath = U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
284 #else
285 srcdatapath = ctest_dataOutDir();
286 relativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
287 #endif
288
289 profile = usprep_open(testdatapath, binFileName, errorCode);
290
291 if(*errorCode == U_FILE_ACCESS_ERROR) {
292 log_data_err("Failed to load %s data file. Error: %s \n", binFileName, u_errorName(*errorCode));
293 return;
294 } else if(U_FAILURE(*errorCode)){
295 log_err("Failed to load %s data file. Error: %s \n", binFileName, u_errorName(*errorCode));
296 return;
297 }
298 filename = (char*) malloc(strlen(srcdatapath)+strlen(relativepath)+strlen(txtFileName)+10 );
299 /* open and load the txt file */
300 strcpy(filename,srcdatapath);
301 strcat(filename,relativepath);
302 strcat(filename,txtFileName);
303
304 parseMappings(filename,profile, TRUE,errorCode);
305
306 free(filename);
307 }
308 #endif
309 /*
310 * Hey, Emacs, please set the following:
311 *
312 * Local Variables:
313 * indent-tabs-mode: nil
314 * End:
315 *
316 */
317