diff --git a/intl/uconv/tests/TestUConv.cpp b/intl/uconv/tests/TestUConv.cpp new file mode 100644 index 00000000000..383773ac665 --- /dev/null +++ b/intl/uconv/tests/TestUConv.cpp @@ -0,0 +1,580 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsIServiceManager.h" +#include "nsICharsetConverterManager.h" +#include "nsICharsetConverterManager2.h" +#include "nsString.h" + +//---------------------------------------------------------------------------- +// Global functions and data [declaration] + +#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0])) +#define BUFFER_SIZE 256 +#define SMALL_BUFFER_SIZE 512 +#define MED_BUFFER_SIZE 1024 +#define BIG_BUFFER_SIZE 2048 + +static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); + +//---------------------------------------------------------------------------- +// Class nsTestLog [declaration] + +/** + * A Logging class for test programs. + * + * This simple test program will not trigger a component registration. So + * Mozilla has to be run once before running this, so that the necessary + * components will be registered. Also, please observe that the ProgID's are + * case sensitive now! + * + * @created 28/Mar/2000 + * @author Catalin Rotaru [CATA] + */ +class nsTestLog +{ +private: + + static const char * kTraceDelimiter; + + nsCAutoString mTrace; + +public: + + void AddTrace(char * aTrace); + void DelTrace(char * aTrace); + void PrintError(char * aCall, int aError); + void PrintError(char * aCall, char * aMessage); +}; + +//---------------------------------------------------------------------------- +// Class nsTestUConv [declaration] + +/** + * The main class of the program. + * + * XXX Create a very general set of "bug and regression" test cases and the + * one in TestTempBug() + * XXX Apply the new argument style (pointers) to the converters interfaces + * + * @created 28/Mar/2000 + * @author Catalin Rotaru [CATA] + */ +class nsTestUConv +{ +private: + + nsTestLog mLog; + + /** + * Run the built-in set of self tests for encoders. + */ + nsresult TestEncoders(); + + /** + * Run the built-in set of self tests for decoders. + */ + nsresult TestDecoders(); + + /** + * Run the built-in set of self tests for the CharsetManager. + */ + nsresult TestCharsetManager(); + + /** + * Display charset detectors and their attributes. + */ + nsresult DisplayDetectors(); + + /** + * Display charsets and their attributes. + */ + nsresult DisplayCharsets(); + + /** + * Run a temporary debug test. This method is ment as a placeholder when some + * quick debugging is needed. + */ + nsresult TestTempBug(); + + nsresult Encode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, char ** aDest, + char * aDestEnd, nsString * aCharset); + + /** + * Bridge methods between the new argument style (poiters) and the old one + * (lengths). To be removed when the converter interfaces will switch to the + * new style. + * + * This wraps an encoder Convert() call. + */ + nsresult ConvertEncode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, char ** aDest, + char * aDestEnd, nsIUnicodeEncoder * aEncoder); + + /** + * This wraps an encoder Finish() call. + */ + nsresult FinishEncode(char ** aDest, char * aDestEnd, + nsIUnicodeEncoder * aEncoder); + + void PrintSpaces(int aCount); + + nsresult AddArray(nsISupportsArray * aDest, nsISupportsArray * aSrc); + +public: + + /** + * Main method of the program. + */ + nsresult Main(int aArgC, char ** aArgV); +}; + +//---------------------------------------------------------------------------- +// Global functions and data [implementation] + +int main(int argc, char ** argv) +{ + nsTestUConv testObj; + nsresult res; + + res = testObj.Main(argc, argv); + return (NS_FAILED(res)); +} + +//---------------------------------------------------------------------------- +// Class nsTestLog [implementation] + +const char * nsTestLog::kTraceDelimiter = "."; + +void nsTestLog::AddTrace(char * aTrace) +{ + mTrace.Append(aTrace); + mTrace.Append(kTraceDelimiter); +} + +void nsTestLog::DelTrace(char * aTrace) +{ + mTrace.Truncate(mTrace.Length() - strlen(aTrace) - strlen(kTraceDelimiter)); +} + +void nsTestLog::PrintError(char * aCall, int aError) +{ + const char * trace = mTrace.GetBuffer(); + printf("ERROR at %s%s code=0x%x.\n", trace, aCall, aError); +} + +void nsTestLog::PrintError(char * aCall, char * aMessage) +{ + const char * trace = mTrace.GetBuffer(); + printf("ERROR at %s%s reason: %s.\n", trace, aCall, aMessage); +} + +//---------------------------------------------------------------------------- +// Class nsTestUConv [implementation] + +nsresult nsTestUConv::TestEncoders() +{ + char * trace = "TestEncoders"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + // XXX write me + + mLog.DelTrace(trace); + return res; +} + +nsresult nsTestUConv::TestDecoders() +{ + char * trace = "TestDecoders"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + // XXX write me + + mLog.DelTrace(trace); + return res; +} + +nsresult nsTestUConv::TestCharsetManager() +{ + char * trace = "TestCharsetManager"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + const PRUnichar * name; + nsCOMPtr csAtom; + + NS_WITH_SERVICE(nsICharsetConverterManager2, ccMan, kCharsetConverterManagerCID, &res); + if (NS_FAILED(res)) { + mLog.PrintError("NS_WITH_SERVICE", res); + return res; + } + + // test alias resolving capability + nsAutoString csAlias("iso-10646-ucs-basic"); + nsAutoString csName("UTF-16BE"); + res = ccMan->GetCharsetAtom(csAlias.GetUnicode(), getter_AddRefs(csAtom)); + if (NS_FAILED(res)) { + mLog.PrintError("GetCharsetAtom()", res); + return res; + } + res = csAtom->GetUnicode(&name); + if (NS_FAILED(res)) { + mLog.PrintError("GetUnicode()", res); + return res; + } + if (!csName.Equals(name)) { + mLog.PrintError("Equals()", "unexpected charset name"); + return NS_ERROR_UNEXPECTED; + } + + // test self returning if alias was not found + nsAutoString csAlias2("Totally_dummy_charset_name"); + res = ccMan->GetCharsetAtom(csAlias2.GetUnicode(), getter_AddRefs(csAtom)); + if (NS_FAILED(res)) { + mLog.PrintError("GetCharsetAtom()", res); + return res; + } + res = csAtom->GetUnicode(&name); + if (NS_FAILED(res)) { + mLog.PrintError("GetUnicode()", res); + return res; + } + if (!csAlias2.Equals(name)) { + mLog.PrintError("Equals()", "unexpected charset name"); + return NS_ERROR_UNEXPECTED; + } + + mLog.DelTrace(trace); + return res; +} + +nsresult nsTestUConv::DisplayDetectors() +{ + char * trace = "DisplayDetectors"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + NS_WITH_SERVICE(nsICharsetConverterManager2, ccMan, kCharsetConverterManagerCID, &res); + if (NS_FAILED(res)) { + mLog.PrintError("NS_WITH_SERVICE", res); + return res; + } + + // charset detectors + nsCOMPtr array; + + res = ccMan->GetCharsetDetectorList(getter_AddRefs(array)); + if (NS_FAILED(res)) { + mLog.PrintError("GetCharsetDetectorList()", res); + return res; + } + + PRUint32 count; + res = array->Count(&count); + if (NS_FAILED(res)) { + mLog.PrintError("Count()", res); + return res; + } + + printf("***** Character Set Detectors [%d] *****\n", count); + + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr cs; + nsAutoString str; + char buff[BUFFER_SIZE]; + char buff2[BUFFER_SIZE]; + + res = array->GetElementAt(i, getter_AddRefs(cs)); + if (NS_FAILED(res)) { + mLog.PrintError("GetElementAt()", res); + return res; + } + + const PRUnichar * name; + res = cs->GetUnicode(&name); + if (NS_FAILED(res)) { + mLog.PrintError("GetUnicode()", res); + return res; + } + + str.Assign(name); + str.ToCString(buff, BUFFER_SIZE); + + res = ccMan->GetCharsetTitle2(cs, &str); + if (NS_FAILED(res)) str.Assign(""); + str.ToCString(buff2, BUFFER_SIZE); + + printf("%s", buff); + PrintSpaces(36 - PL_strlen(buff)); // align to hard coded column number + printf("\"%s\"\n", buff2); + } + + mLog.DelTrace(trace); + return NS_OK; +} + +nsresult nsTestUConv::DisplayCharsets() +{ + char * trace = "DisplayCharsets"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + NS_WITH_SERVICE(nsICharsetConverterManager2, ccMan, kCharsetConverterManagerCID, &res); + if (NS_FAILED(res)) { + mLog.PrintError("NS_WITH_SERVICE", res); + return res; + } + + nsCOMPtr array; + nsCOMPtr encArray; + + res = ccMan->GetDecoderList(getter_AddRefs(array)); + if (NS_FAILED(res)) { + mLog.PrintError("GetDecoderList()", res); + return res; + } + + res = ccMan->GetEncoderList(getter_AddRefs(encArray)); + if (NS_FAILED(res)) { + mLog.PrintError("GetEncoderList()", res); + return res; + } + + res = AddArray(array, encArray); + if (NS_FAILED(res)) return res; + + PRUint32 count; + res = array->Count(&count); + if (NS_FAILED(res)) { + mLog.PrintError("Count()", res); + return res; + } + + printf("***** Character Sets [%d] *****\n", count); + + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr cs; + nsAutoString str; + nsAutoString prop; + char buff[BUFFER_SIZE]; + char buff2[BUFFER_SIZE]; + + res = array->GetElementAt(i, getter_AddRefs(cs)); + if (NS_FAILED(res)) { + mLog.PrintError("GetElementAt()", res); + return res; + } + + const PRUnichar * name; + res = cs->GetUnicode(&name); + if (NS_FAILED(res)) { + mLog.PrintError("GetUnicode()", res); + return res; + } + + str.Assign(name); + str.ToCString(buff, BUFFER_SIZE); + + res = ccMan->GetCharsetTitle2(cs, &str); + if (NS_FAILED(res)) str.Assign(""); + str.ToCString(buff2, BUFFER_SIZE); + + printf("%s", buff); + PrintSpaces(24 - PL_strlen(buff)); // align to hard coded column number + + nsCOMPtr dec = NULL; + res = ccMan->GetUnicodeDecoder(cs, getter_AddRefs(dec)); + if (NS_FAILED(res)) printf (" "); + else printf("D"); + + nsCOMPtr enc = NULL; + res = ccMan->GetUnicodeEncoder(cs, getter_AddRefs(enc)); + if (NS_FAILED(res)) printf (" "); + else printf("E"); + + printf(" "); + + prop.Assign(".notForBrowser"); + res = ccMan->GetCharsetData2(cs, prop.GetUnicode(), &str); + if ((dec != NULL) && (NS_FAILED(res))) printf ("B"); + else printf("X"); + + prop.Assign(".notForComposer"); + res = ccMan->GetCharsetData2(cs, prop.GetUnicode(), &str); + if ((enc != NULL) && (NS_FAILED(res))) printf ("C"); + else printf("X"); + + prop.Assign(".notForMailView"); + res = ccMan->GetCharsetData2(cs, prop.GetUnicode(), &str); + if ((dec != NULL) && (NS_FAILED(res))) printf ("V"); + else printf("X"); + + prop.Assign(".notForMailEdit"); + res = ccMan->GetCharsetData2(cs, prop.GetUnicode(), &str); + if ((enc != NULL) && (NS_FAILED(res))) printf ("E"); + else printf("X"); + + printf(" \"%s\"\n", buff2); + } + + mLog.DelTrace(trace); + return NS_OK; +} + +nsresult nsTestUConv::TestTempBug() +{ + char * trace = "TestTempBug"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + nsAutoString charset("ISO-2022-JP"); + PRUnichar src[] = {0x0043, 0x004e, 0x0045, 0x0054, 0x0020, 0x004A, 0x0061, + 0x0070, 0x0061, 0x006E, 0x0020, 0x7DE8, 0x96C6, 0x5C40}; + PRUnichar * srcEnd = src + ARRAY_SIZE(src); + char dest[BIG_BUFFER_SIZE]; + char * destEnd = dest + BIG_BUFFER_SIZE; + + PRUnichar * p = src; + char * q = dest; + res = Encode(&p, srcEnd, &q, destEnd, &charset); + + mLog.DelTrace(trace); + return res; +} + +nsresult nsTestUConv::Encode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, + char ** aDest, char * aDestEnd, + nsString * aCharset) +{ + char * trace = "Encode"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + NS_WITH_SERVICE(nsICharsetConverterManager, ccMan, kCharsetConverterManagerCID, &res); + if (NS_FAILED(res)) { + mLog.PrintError("NS_WITH_SERVICE", res); + return res; + } + + nsCOMPtr enc; + res = ccMan->GetUnicodeEncoder(aCharset, getter_AddRefs(enc)); + if (NS_FAILED(res)) { + mLog.PrintError("GetUnicodeEncoder()", res); + return res; + } + + res = ConvertEncode(aSrc, aSrcEnd, aDest, aDestEnd, enc); + if (NS_FAILED(res)) { + mLog.PrintError("Convert()", res); + return res; + } + + res = FinishEncode(aDest, aDestEnd, enc); + if (NS_FAILED(res)) { + mLog.PrintError("Finish()", res); + return res; + } + + mLog.DelTrace(trace); + return res; +} + +nsresult nsTestUConv::ConvertEncode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, + char ** aDest, char * aDestEnd, + nsIUnicodeEncoder * aEncoder) +{ + PRUnichar * src = (*aSrc); + char * dest = (*aDest); + PRInt32 srcLen = aSrcEnd - src; + PRInt32 destLen = aDestEnd - dest; + + nsresult res = aEncoder->Convert(src, &srcLen, dest, &destLen); + + (*aSrc) = src + srcLen; + (*aDest) = dest + destLen; + return res; +} + +nsresult nsTestUConv::FinishEncode(char ** aDest, char * aDestEnd, + nsIUnicodeEncoder * aEncoder) +{ + char * dest = (*aDest); + PRInt32 destLen = aDestEnd - dest; + + nsresult res = aEncoder->Finish(dest, &destLen); + + (*aDest) = dest + destLen; + return res; +} + +void nsTestUConv::PrintSpaces(int aCount) +{ + for (int i = 0; i < aCount; i++) printf(" "); +} + +nsresult nsTestUConv::AddArray(nsISupportsArray * aDest, + nsISupportsArray * aSrc) +{ + nsresult res = NS_OK; + PRUint32 count, i; + + res = aSrc->Count(&count); + if (NS_FAILED(res)) return res; + + for (i = 0; i < count; i++) { + nsCOMPtr elem; + res = aSrc->GetElementAt(i, getter_AddRefs(elem)); + if (NS_FAILED(res)) return res; + + PRInt32 index; + res = aDest->GetIndexOf(elem, &index); + if (NS_FAILED(res)) return res; + + if (index < 0) res = aDest->AppendElement(elem); + } + + return NS_OK; +} + +nsresult nsTestUConv::Main(int aArgC, char ** aArgV) +{ + char * trace = "Main"; + mLog.AddTrace(trace); + nsresult res = NS_OK; + + if (aArgC < 2) { + // no arguments were passed to the program, so we just run the self tests + res = TestCharsetManager(); + if (NS_SUCCEEDED(res)) res = TestEncoders(); + if (NS_SUCCEEDED(res)) res = TestDecoders(); + } else if (!strcmp(aArgV[1], "-tempbug")) { + // we are testing a temporary bug + res = TestTempBug(); + } else if (!strcmp(aArgV[1], "-display")) { + // display all the available data + res = DisplayDetectors(); + if (NS_SUCCEEDED(res)) res = DisplayCharsets(); + } + + mLog.DelTrace(trace); + return res; +}