|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "nsIServiceManager.h" |
|
7 #include "nsICharsetConverterManager.h" |
|
8 #include "nsUCSupport.h" |
|
9 #include "nsString.h" |
|
10 #include "nsIStringEnumerator.h" |
|
11 #include "nsTArray.h" |
|
12 |
|
13 //---------------------------------------------------------------------------- |
|
14 // Global functions and data [declaration] |
|
15 |
|
16 #define ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0])) |
|
17 #define SMALL_BUFFER_SIZE 512 |
|
18 #define MED_BUFFER_SIZE 1024 |
|
19 #define BIG_BUFFER_SIZE 2048 |
|
20 |
|
21 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); |
|
22 |
|
23 //---------------------------------------------------------------------------- |
|
24 // Class nsTestLog [declaration] |
|
25 |
|
26 /** |
|
27 * A Logging class for test programs. |
|
28 * |
|
29 * This simple test program will not trigger a component registration. So |
|
30 * Mozilla has to be run once before running this, so that the necessary |
|
31 * components will be registered. Also, please observe that the ContractID's are |
|
32 * case sensitive now! |
|
33 * |
|
34 * @created 28/Mar/2000 |
|
35 * @author Catalin Rotaru [CATA] |
|
36 */ |
|
37 class nsTestLog |
|
38 { |
|
39 private: |
|
40 |
|
41 static const char * kTraceDelimiter; |
|
42 |
|
43 nsAutoCString mTrace; |
|
44 |
|
45 public: |
|
46 |
|
47 void AddTrace(const char * aTrace); |
|
48 void DelTrace(const char * aTrace); |
|
49 void PrintError(const char * aCall, const int aError); |
|
50 void PrintError(const char * aCall, const char * aMessage); |
|
51 }; |
|
52 |
|
53 //---------------------------------------------------------------------------- |
|
54 // Class nsTestUConv [declaration] |
|
55 |
|
56 /** |
|
57 * The main class of the program. |
|
58 * |
|
59 * XXX Create a very general set of "bug and regression" test cases and the |
|
60 * one in TestTempBug() |
|
61 * XXX Apply the new argument style (pointers) to the converters interfaces |
|
62 * |
|
63 * @created 28/Mar/2000 |
|
64 * @author Catalin Rotaru [CATA] |
|
65 */ |
|
66 class nsTestUConv |
|
67 { |
|
68 private: |
|
69 |
|
70 nsTestLog mLog; |
|
71 |
|
72 /** |
|
73 * Run the built-in set of self tests for encoders. |
|
74 */ |
|
75 nsresult TestEncoders(); |
|
76 |
|
77 /** |
|
78 * Run the built-in set of self tests for decoders. |
|
79 */ |
|
80 nsresult TestDecoders(); |
|
81 |
|
82 /** |
|
83 * Run the built-in set of self tests for the CharsetManager. |
|
84 */ |
|
85 nsresult TestCharsetManager(); |
|
86 |
|
87 /** |
|
88 * Display charset detectors and their attributes. |
|
89 */ |
|
90 nsresult DisplayDetectors(); |
|
91 |
|
92 /** |
|
93 * Display charsets and their attributes. |
|
94 */ |
|
95 nsresult DisplayCharsets(); |
|
96 |
|
97 /** |
|
98 * Run a temporary debug test. This method is ment as a placeholder when some |
|
99 * quick debugging is needed. |
|
100 */ |
|
101 nsresult TestTempBug(); |
|
102 |
|
103 nsresult Encode(char16_t ** aSrc, char16_t * aSrcEnd, char ** aDest, |
|
104 char * aDestEnd, const nsAFlatCString& aCharset); |
|
105 |
|
106 /** |
|
107 * Bridge methods between the new argument style (poiters) and the old one |
|
108 * (lengths). To be removed when the converter interfaces will switch to the |
|
109 * new style. |
|
110 * |
|
111 * This wraps an encoder Convert() call. |
|
112 */ |
|
113 nsresult ConvertEncode(char16_t ** aSrc, char16_t * aSrcEnd, char ** aDest, |
|
114 char * aDestEnd, nsIUnicodeEncoder * aEncoder); |
|
115 |
|
116 /** |
|
117 * This wraps an encoder Finish() call. |
|
118 */ |
|
119 nsresult FinishEncode(char ** aDest, char * aDestEnd, |
|
120 nsIUnicodeEncoder * aEncoder); |
|
121 |
|
122 void PrintSpaces(int aCount); |
|
123 |
|
124 public: |
|
125 |
|
126 /** |
|
127 * Main method of the program. |
|
128 */ |
|
129 nsresult Main(int aArgC, char ** aArgV); |
|
130 }; |
|
131 |
|
132 //---------------------------------------------------------------------------- |
|
133 // Global functions and data [implementation] |
|
134 |
|
135 int main(int argc, char ** argv) |
|
136 { |
|
137 nsTestUConv testObj; |
|
138 nsresult res; |
|
139 |
|
140 res = testObj.Main(argc, argv); |
|
141 return (NS_FAILED(res)); |
|
142 } |
|
143 |
|
144 //---------------------------------------------------------------------------- |
|
145 // Class nsTestLog [implementation] |
|
146 |
|
147 const char * nsTestLog::kTraceDelimiter = "."; |
|
148 |
|
149 void nsTestLog::AddTrace(const char * aTrace) |
|
150 { |
|
151 mTrace.Append(aTrace); |
|
152 mTrace.Append(kTraceDelimiter); |
|
153 } |
|
154 |
|
155 void nsTestLog::DelTrace(const char * aTrace) |
|
156 { |
|
157 mTrace.Truncate(mTrace.Length() - strlen(aTrace) - strlen(kTraceDelimiter)); |
|
158 } |
|
159 |
|
160 void nsTestLog::PrintError(const char * aCall, const int aError) |
|
161 { |
|
162 const char * trace = mTrace.get(); |
|
163 printf("ERROR at %s%s code=0x%x.\n", trace, aCall, aError); |
|
164 } |
|
165 |
|
166 void nsTestLog::PrintError(const char * aCall, const char * aMessage) |
|
167 { |
|
168 const char * trace = mTrace.get(); |
|
169 printf("ERROR at %s%s reason: %s.\n", trace, aCall, aMessage); |
|
170 } |
|
171 |
|
172 //---------------------------------------------------------------------------- |
|
173 // Class nsTestUConv [implementation] |
|
174 |
|
175 nsresult nsTestUConv::TestEncoders() |
|
176 { |
|
177 const char * trace = "TestEncoders"; |
|
178 mLog.AddTrace(trace); |
|
179 nsresult res = NS_OK; |
|
180 |
|
181 nsCOMPtr<nsICharsetConverterManager> ccMan = |
|
182 do_GetService(kCharsetConverterManagerCID, &res); |
|
183 if (NS_FAILED(res)) return res; |
|
184 |
|
185 nsCOMPtr<nsIUTF8StringEnumerator> encoders; |
|
186 res = ccMan->GetEncoderList(getter_AddRefs(encoders)); |
|
187 if (NS_FAILED(res)) return res; |
|
188 |
|
189 bool hasMore; |
|
190 encoders->HasMore(&hasMore); |
|
191 |
|
192 nsAutoCString charset; |
|
193 while (hasMore) { |
|
194 encoders->GetNext(charset); |
|
195 |
|
196 encoders->HasMore(&hasMore); |
|
197 } |
|
198 |
|
199 mLog.DelTrace(trace); |
|
200 return res; |
|
201 } |
|
202 |
|
203 nsresult nsTestUConv::TestDecoders() |
|
204 { |
|
205 const char * trace = "TestDecoders"; |
|
206 mLog.AddTrace(trace); |
|
207 nsresult res = NS_OK; |
|
208 |
|
209 // XXX write me |
|
210 |
|
211 mLog.DelTrace(trace); |
|
212 return res; |
|
213 } |
|
214 |
|
215 nsresult nsTestUConv::TestCharsetManager() |
|
216 { |
|
217 const char * trace = "TestCharsetManager"; |
|
218 mLog.AddTrace(trace); |
|
219 nsresult res = NS_OK; |
|
220 nsAutoString name; |
|
221 nsCOMPtr<nsIAtom> csAtom; |
|
222 |
|
223 nsCOMPtr<nsICharsetConverterManager> ccMan = |
|
224 do_GetService(kCharsetConverterManagerCID, &res); |
|
225 if (NS_FAILED(res)) { |
|
226 mLog.PrintError("NS_WITH_SERVICE", res); |
|
227 return res; |
|
228 } |
|
229 |
|
230 mLog.DelTrace(trace); |
|
231 return res; |
|
232 } |
|
233 |
|
234 nsresult nsTestUConv::DisplayDetectors() |
|
235 { |
|
236 const char * trace = "DisplayDetectors"; |
|
237 mLog.AddTrace(trace); |
|
238 nsresult res = NS_OK; |
|
239 |
|
240 nsCOMPtr<nsICharsetConverterManager> ccMan = |
|
241 do_GetService(kCharsetConverterManagerCID, &res); |
|
242 if (NS_FAILED(res)) { |
|
243 mLog.PrintError("NS_WITH_SERVICE", res); |
|
244 return res; |
|
245 } |
|
246 |
|
247 // charset detectors |
|
248 nsCOMPtr<nsIUTF8StringEnumerator> detectors; |
|
249 |
|
250 res = ccMan->GetCharsetDetectorList(getter_AddRefs(detectors)); |
|
251 if (NS_FAILED(res)) { |
|
252 mLog.PrintError("GetCharsetDetectorList()", res); |
|
253 return res; |
|
254 } |
|
255 |
|
256 printf("***** Character Set Detectors *****\n"); |
|
257 |
|
258 bool hasMore; |
|
259 detectors->HasMore(&hasMore); |
|
260 while (hasMore) { |
|
261 nsAutoCString detectorName; |
|
262 res = detectors->GetNext(detectorName); |
|
263 if (NS_FAILED(res)) { |
|
264 mLog.PrintError("GetNext()", res); |
|
265 return res; |
|
266 } |
|
267 |
|
268 printf("%s", detectorName.get()); |
|
269 PrintSpaces(36 - detectorName.Length()); // align to hard coded column number |
|
270 |
|
271 nsAutoString title; |
|
272 res = ccMan->GetCharsetTitle(detectorName.get(), title); |
|
273 if (NS_FAILED(res)) title.SetLength(0); |
|
274 printf("\"%s\"\n", NS_LossyConvertUTF16toASCII(title).get()); |
|
275 |
|
276 detectors->HasMore(&hasMore); |
|
277 } |
|
278 |
|
279 mLog.DelTrace(trace); |
|
280 return NS_OK; |
|
281 } |
|
282 |
|
283 nsresult nsTestUConv::DisplayCharsets() |
|
284 { |
|
285 const char * trace = "DisplayCharsets"; |
|
286 mLog.AddTrace(trace); |
|
287 nsresult res = NS_OK; |
|
288 |
|
289 nsCOMPtr<nsICharsetConverterManager> ccMan = |
|
290 do_GetService(kCharsetConverterManagerCID, &res); |
|
291 if (NS_FAILED(res)) { |
|
292 mLog.PrintError("NS_WITH_SERVICE", res); |
|
293 return res; |
|
294 } |
|
295 |
|
296 nsCOMPtr<nsIUTF8StringEnumerator> decoders; |
|
297 nsCOMPtr<nsIUTF8StringEnumerator> encoders; |
|
298 |
|
299 res = ccMan->GetDecoderList(getter_AddRefs(decoders)); |
|
300 if (NS_FAILED(res)) { |
|
301 mLog.PrintError("GetDecoderList()", res); |
|
302 return res; |
|
303 } |
|
304 |
|
305 res = ccMan->GetEncoderList(getter_AddRefs(encoders)); |
|
306 if (NS_FAILED(res)) { |
|
307 mLog.PrintError("GetEncoderList()", res); |
|
308 return res; |
|
309 } |
|
310 |
|
311 |
|
312 printf("***** Character Sets *****\n"); |
|
313 |
|
314 uint32_t encCount = 0, decCount = 0; |
|
315 uint32_t basicEncCount = 0, basicDecCount = 0; |
|
316 |
|
317 nsTArray<nsCString> allCharsets; |
|
318 |
|
319 nsAutoCString charset; |
|
320 bool hasMore; |
|
321 encoders->HasMore(&hasMore); |
|
322 while (hasMore) { |
|
323 res = encoders->GetNext(charset); |
|
324 if (NS_SUCCEEDED(res)) |
|
325 allCharsets.AppendElement(charset); |
|
326 |
|
327 encoders->HasMore(&hasMore); |
|
328 } |
|
329 |
|
330 nsAutoString prop, str; |
|
331 uint32_t count = allCharsets.Length(); |
|
332 for (uint32_t i = 0; i < count; i++) { |
|
333 |
|
334 const nsCString& charset = allCharsets[i]; |
|
335 printf("%s", charset.get()); |
|
336 PrintSpaces(24 - charset.Length()); // align to hard coded column number |
|
337 |
|
338 |
|
339 nsCOMPtr<nsIUnicodeDecoder> dec; |
|
340 res = ccMan->GetUnicodeDecoder(charset.get(), getter_AddRefs(dec)); |
|
341 if (NS_FAILED(res)) printf (" "); |
|
342 else { |
|
343 printf("D"); |
|
344 decCount++; |
|
345 } |
|
346 #ifdef DEBUG |
|
347 // show the "basic" decoder classes |
|
348 if (dec) { |
|
349 nsCOMPtr<nsIBasicDecoder> isBasic = do_QueryInterface(dec); |
|
350 if (isBasic) { |
|
351 basicDecCount++; |
|
352 printf("b"); |
|
353 } |
|
354 else printf(" "); |
|
355 } |
|
356 else printf(" "); |
|
357 #endif |
|
358 |
|
359 nsCOMPtr<nsIUnicodeEncoder> enc; |
|
360 res = ccMan->GetUnicodeEncoder(charset.get(), getter_AddRefs(enc)); |
|
361 if (NS_FAILED(res)) printf (" "); |
|
362 else { |
|
363 printf("E"); |
|
364 encCount++; |
|
365 } |
|
366 |
|
367 #ifdef DEBUG |
|
368 if (enc) { |
|
369 nsCOMPtr<nsIBasicEncoder> isBasic = do_QueryInterface(enc); |
|
370 if (isBasic) { |
|
371 basicEncCount++; |
|
372 printf("b"); |
|
373 } |
|
374 else printf(" "); |
|
375 } |
|
376 else printf(" "); |
|
377 #endif |
|
378 |
|
379 printf(" "); |
|
380 |
|
381 prop.AssignLiteral(".notForBrowser"); |
|
382 res = ccMan->GetCharsetData(charset.get(), prop.get(), str); |
|
383 if (dec && (NS_FAILED(res))) printf ("B"); |
|
384 else printf("X"); |
|
385 |
|
386 prop.AssignLiteral(".notForComposer"); |
|
387 res = ccMan->GetCharsetData(charset.get(), prop.get(), str); |
|
388 if (enc && (NS_FAILED(res))) printf ("C"); |
|
389 else printf("X"); |
|
390 |
|
391 prop.AssignLiteral(".notForMailView"); |
|
392 res = ccMan->GetCharsetData(charset.get(), prop.get(), str); |
|
393 if (dec && (NS_FAILED(res))) printf ("V"); |
|
394 else printf("X"); |
|
395 |
|
396 prop.AssignLiteral(".notForMailEdit"); |
|
397 res = ccMan->GetCharsetData(charset.get(), prop.get(), str); |
|
398 if (enc && (NS_FAILED(res))) printf ("E"); |
|
399 else printf("X"); |
|
400 |
|
401 printf("(%3d, %3d) ", encCount, decCount); |
|
402 res = ccMan->GetCharsetTitle(charset.get(), str); |
|
403 if (NS_FAILED(res)) str.SetLength(0); |
|
404 NS_LossyConvertUTF16toASCII buff2(str); |
|
405 printf(" \"%s\"\n", buff2.get()); |
|
406 } |
|
407 |
|
408 printf("%u of %u decoders are basic (%d%%)\n", |
|
409 basicDecCount, decCount, (basicDecCount * 100) / decCount); |
|
410 |
|
411 printf("%u of %u encoders are basic (%d%%)\n", |
|
412 basicEncCount, encCount, (basicEncCount * 100) / encCount); |
|
413 mLog.DelTrace(trace); |
|
414 return NS_OK; |
|
415 } |
|
416 |
|
417 nsresult nsTestUConv::TestTempBug() |
|
418 { |
|
419 const char * trace = "TestTempBug"; |
|
420 mLog.AddTrace(trace); |
|
421 nsresult res = NS_OK; |
|
422 |
|
423 NS_NAMED_LITERAL_CSTRING(charset, "ISO-2022-JP"); |
|
424 char16_t src[] = {0x0043, 0x004e, 0x0045, 0x0054, 0x0020, 0x004A, 0x0061, |
|
425 0x0070, 0x0061, 0x006E, 0x0020, 0x7DE8, 0x96C6, 0x5C40}; |
|
426 char16_t * srcEnd = src + ARRAY_SIZE(src); |
|
427 char dest[BIG_BUFFER_SIZE]; |
|
428 char * destEnd = dest + BIG_BUFFER_SIZE; |
|
429 |
|
430 char16_t * p = src; |
|
431 char * q = dest; |
|
432 res = Encode(&p, srcEnd, &q, destEnd, charset); |
|
433 |
|
434 mLog.DelTrace(trace); |
|
435 return res; |
|
436 } |
|
437 |
|
438 nsresult nsTestUConv::Encode(char16_t ** aSrc, char16_t * aSrcEnd, |
|
439 char ** aDest, char * aDestEnd, |
|
440 const nsAFlatCString& aCharset) |
|
441 { |
|
442 const char * trace = "Encode"; |
|
443 mLog.AddTrace(trace); |
|
444 nsresult res = NS_OK; |
|
445 |
|
446 nsCOMPtr<nsICharsetConverterManager> ccMan = |
|
447 do_GetService(kCharsetConverterManagerCID, &res); |
|
448 if (NS_FAILED(res)) { |
|
449 mLog.PrintError("NS_WITH_SERVICE", res); |
|
450 return res; |
|
451 } |
|
452 |
|
453 nsCOMPtr<nsIUnicodeEncoder> enc; |
|
454 res = ccMan->GetUnicodeEncoder(aCharset.get(), getter_AddRefs(enc)); |
|
455 if (NS_FAILED(res)) { |
|
456 mLog.PrintError("GetUnicodeEncoder()", res); |
|
457 return res; |
|
458 } |
|
459 |
|
460 res = ConvertEncode(aSrc, aSrcEnd, aDest, aDestEnd, enc); |
|
461 if (NS_FAILED(res)) { |
|
462 mLog.PrintError("Convert()", res); |
|
463 return res; |
|
464 } |
|
465 |
|
466 res = FinishEncode(aDest, aDestEnd, enc); |
|
467 if (NS_FAILED(res)) { |
|
468 mLog.PrintError("Finish()", res); |
|
469 return res; |
|
470 } |
|
471 |
|
472 mLog.DelTrace(trace); |
|
473 return res; |
|
474 } |
|
475 |
|
476 nsresult nsTestUConv::ConvertEncode(char16_t ** aSrc, char16_t * aSrcEnd, |
|
477 char ** aDest, char * aDestEnd, |
|
478 nsIUnicodeEncoder * aEncoder) |
|
479 { |
|
480 char16_t * src = (*aSrc); |
|
481 char * dest = (*aDest); |
|
482 int32_t srcLen = aSrcEnd - src; |
|
483 int32_t destLen = aDestEnd - dest; |
|
484 |
|
485 nsresult res = aEncoder->Convert(src, &srcLen, dest, &destLen); |
|
486 |
|
487 (*aSrc) = src + srcLen; |
|
488 (*aDest) = dest + destLen; |
|
489 return res; |
|
490 } |
|
491 |
|
492 nsresult nsTestUConv::FinishEncode(char ** aDest, char * aDestEnd, |
|
493 nsIUnicodeEncoder * aEncoder) |
|
494 { |
|
495 char * dest = (*aDest); |
|
496 int32_t destLen = aDestEnd - dest; |
|
497 |
|
498 nsresult res = aEncoder->Finish(dest, &destLen); |
|
499 |
|
500 (*aDest) = dest + destLen; |
|
501 return res; |
|
502 } |
|
503 |
|
504 void nsTestUConv::PrintSpaces(int aCount) |
|
505 { |
|
506 for (int i = 0; i < aCount; i++) printf(" "); |
|
507 } |
|
508 |
|
509 nsresult nsTestUConv::Main(int aArgC, char ** aArgV) |
|
510 { |
|
511 const char * trace = "Main"; |
|
512 mLog.AddTrace(trace); |
|
513 nsresult res = NS_OK; |
|
514 |
|
515 if (aArgC < 2) { |
|
516 // no arguments were passed to the program, so we just run the self tests |
|
517 res = TestCharsetManager(); |
|
518 if (NS_SUCCEEDED(res)) res = TestEncoders(); |
|
519 if (NS_SUCCEEDED(res)) res = TestDecoders(); |
|
520 } else if (!strcmp(aArgV[1], "-tempbug")) { |
|
521 // we are testing a temporary bug |
|
522 res = TestTempBug(); |
|
523 } else if (!strcmp(aArgV[1], "-display")) { |
|
524 // display all the available data |
|
525 res = DisplayDetectors(); |
|
526 if (NS_SUCCEEDED(res)) res = DisplayCharsets(); |
|
527 } |
|
528 |
|
529 mLog.DelTrace(trace); |
|
530 return res; |
|
531 } |