TestUConv.cpp 13 KB

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