ICU-7247 finish testing LocalPointer variants, and improve API docs

X-SVN-Rev: 26960
This commit is contained in:
Markus Scherer 2009-11-20 23:28:47 +00:00
parent a7f460e761
commit e89977c0b6
4 changed files with 260 additions and 3 deletions

View File

@ -20,6 +20,20 @@
/**
* \file
* \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
*
* These classes are inspired by
* - std::auto_ptr
* - boost::scoped_ptr & boost::scoped_array
* - Taligent Safe Pointers (TOnlyPointerTo)
*
* but none of those provide for all of the goals for ICU smart pointers:
* - Smart pointer owns the object and releases it when it goes out of scope.
* - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust.
* - ICU-compatible: No exceptions.
* - Need to be able to orphan/release the pointer and its ownership.
* - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects.
*
* For details see http://site.icu-project.org/design/cpp/scoped_ptr
*/
#include "unicode/utypes.h"
@ -150,6 +164,17 @@ private:
* "Smart pointer" class, deletes objects via the standard C++ delete operator.
* For most methods see the LocalPointerBase base class.
*
* Usage example:
* \code
* LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
* int32_t length=s->length(); // 2
* UChar lead=s->charAt(0); // 0xd900
* if(some condition) { return; } // no need to explicitly delete the pointer
* s.adoptInstead(new UnicodeString((UChar)0xfffc));
* length=s->length(); // 1
* // no need to explicitly delete the pointer
* \endcode
*
* @see LocalPointerBase
* @draft ICU 4.4
*/
@ -186,6 +211,16 @@ public:
* For most methods see the LocalPointerBase base class.
* Adds operator[] for array item access.
*
* Usage example:
* \code
* LocalArray<UnicodeString> a(new UnicodeString[2]);
* a[0].append((UChar)0x61);
* if(some condition) { return; } // no need to explicitly delete the array
* a.adoptInstead(new UnicodeString[4]);
* a[3].append((UChar)0x62).append((UChar)0x63).reverse();
* // no need to explicitly delete the array
* \endcode
*
* @see LocalPointerBase
* @draft ICU 4.4
*/
@ -235,6 +270,15 @@ public:
* Requirement: The closeFunction must tolerate a NULL pointer.
* (We could add a NULL check here but it is normally redundant.)
*
* Usage example:
* \code
* LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
* utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
* utf8Out, (int32_t)sizeof(utf8Out),
* utf8In, utf8InLength, &errorCode);
* if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap
* \endcode
*
* @see LocalPointerBase
* @see LocalPointer
* @draft ICU 4.4

View File

@ -15,6 +15,7 @@
***********************************************************************/
#include "unicode/utypes.h"
#include "unicode/localpointer.h"
#include "itmajor.h"
#include "itutil.h"
@ -198,9 +199,8 @@ void MajorTestLevel::runIndexedTest( int32_t index, UBool exec, const char* &nam
case 15: name = "bidi";
if (exec) {
logln("TestSuite bidi---"); logln();
IntlTest *test = createBiDiConformanceTest();
LocalPointer<IntlTest> test(createBiDiConformanceTest());
callTest(*test, par);
delete test;
}
break;

View File

@ -11,6 +11,7 @@
#include "unicode/utypes.h"
#include "unicode/errorcode.h"
#include "unicode/localpointer.h"
#include "itutil.h"
#include "strtest.h"
#include "loctest.h"
@ -28,6 +29,7 @@
#include "aliastst.h"
#include "usettest.h"
static IntlTest *createLocalPointerTest();
#define CASE(id, test) case id: \
name = #test; \
@ -58,6 +60,14 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* &
CASE(13, LocaleAliasTest);
CASE(14, UnicodeSetTest);
CASE(15, ErrorCodeTest);
case 16:
name = "LocalPointerTest";
if (exec) {
logln("TestSuite LocalPointerTest---"); logln();
LocalPointer<IntlTest> test(createLocalPointerTest());
callTest(*test, par);
}
break;
default: name = ""; break; //needed to end loop
}
}
@ -177,3 +187,206 @@ void ErrorCodeTest::TestSubclass() {
errln("MyErrorCode destructor failed to detect failure");
}
}
class LocalPointerTest : public IntlTest {
public:
LocalPointerTest() {}
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=NULL);
void TestLocalPointer();
void TestLocalArray();
void TestLocalXyzPointer();
void TestLocalXyzPointerNull();
};
static IntlTest *createLocalPointerTest() {
return new LocalPointerTest();
}
void LocalPointerTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *par) {
if(exec) {
logln("TestSuite LocalPointerTest: ");
}
switch (index) {
TESTCASE(0, TestLocalPointer);
TESTCASE(1, TestLocalArray);
TESTCASE(2, TestLocalXyzPointer);
TESTCASE(3, TestLocalXyzPointerNull);
default:
name="";
break; // needed to end the loop
}
}
// Exercise every LocalPointer and LocalPointerBase method.
void LocalPointerTest::TestLocalPointer() {
// constructor
LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
// isNULL(), isValid(), operator==(), operator!=()
if(s.isNull() || !s.isValid() || s==NULL || !(s!=NULL)) {
errln("LocalPointer constructor or NULL test failure");
return;
}
// getAlias(), operator->, operator*
if(s.getAlias()->length()!=2 || s->length()!=2 || (*s).length()!=2) {
errln("LocalPointer access failure");
}
// adoptInstead(), orphan()
s.adoptInstead(new UnicodeString((UChar)0xfffc));
if(s->length()!=1) {
errln("LocalPointer adoptInstead(U+FFFC) failure");
}
UnicodeString *orphan=s.orphan();
if(orphan==NULL || orphan->length()!=1 || s.isValid() || s!=NULL) {
errln("LocalPointer orphan() failure");
}
// destructor
s.adoptInstead(new UnicodeString());
if(s->length()!=0) {
errln("LocalPointer adoptInstead(empty) failure");
}
}
// Exercise every LocalArray method (but not LocalPointerBase).
void LocalPointerTest::TestLocalArray() {
// constructor
LocalArray<UnicodeString> a(new UnicodeString[2]);
// operator[]()
a[0].append((UChar)0x61);
a[1].append((UChar32)0x60006);
if(a[0].length()!=1 || a[1].length()!=2) {
errln("LocalArray access failure");
}
// adoptInstead()
a.adoptInstead(new UnicodeString[4]);
a[3].append((UChar)0x62).append((UChar)0x63).reverse();
if(a[3].length()!=2 || a[3][1]!=0x62) {
errln("LocalArray adoptInstead() failure");
}
// destructor
}
#include "unicode/ucnvsel.h"
#include "unicode/ucal.h"
#include "unicode/udatpg.h"
#include "unicode/umsg.h"
#include "unicode/uregex.h"
#include "unicode/utrans.h"
// Use LocalXyzPointer types that are not covered elsewhere in the intltest suite.
void LocalPointerTest::TestLocalXyzPointer() {
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointer");
static const char *const encoding="ISO-8859-1";
LocalUConverterSelectorPointer sel(
ucnvsel_open(&encoding, 1, NULL, UCNV_ROUNDTRIP_SET, errorCode));
if(errorCode.logIfFailureAndReset("ucnvsel_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalUConverterSelectorPointer failure");
return;
}
LocalUCalendarPointer cal(ucal_open(NULL, 0, "root", UCAL_GREGORIAN, errorCode));
if(errorCode.logIfFailureAndReset("ucal_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalUCalendarPointer failure");
return;
}
LocalUDateTimePatternGeneratorPointer patgen(udatpg_open("root", errorCode));
if(errorCode.logIfFailureAndReset("udatpg_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalUDateTimePatternGeneratorPointer failure");
return;
}
UnicodeString hello=UNICODE_STRING_SIMPLE("Hello {0}!");
LocalUMessageFormatPointer msg(
umsg_open(hello.getBuffer(), hello.length(), "root", NULL, errorCode));
if(errorCode.logIfFailureAndReset("umsg_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalUMessageFormatPointer failure");
return;
}
UnicodeString pattern=UNICODE_STRING_SIMPLE("abc|xy+z");
LocalURegularExpressionPointer regex(
uregex_open(pattern.getBuffer(), pattern.length(), 0, NULL, errorCode));
if(errorCode.logIfFailureAndReset("uregex_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalURegularExpressionPointer failure");
return;
}
UnicodeString id=UNICODE_STRING_SIMPLE("Grek-Latn");
LocalUTransliteratorPointer trans(
utrans_openU(id.getBuffer(), id.length(), UTRANS_FORWARD, NULL, 0, NULL, errorCode));
if(errorCode.logIfFailureAndReset("utrans_open()")) {
return;
}
if(sel.isNull()) {
errln("LocalUTransliteratorPointer failure");
return;
}
// destructors
}
// Try LocalXyzPointer types with NULL pointers.
void LocalPointerTest::TestLocalXyzPointerNull() {
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalUConverterSelectorPointer");
static const char *const encoding="ISO-8859-1";
LocalUConverterSelectorPointer null;
LocalUConverterSelectorPointer sel(
ucnvsel_open(&encoding, 1, NULL, UCNV_ROUNDTRIP_SET, errorCode));
sel.adoptInstead(NULL);
}
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalUCalendarPointer");
LocalUCalendarPointer null;
LocalUCalendarPointer cal(ucal_open(NULL, 0, "root", UCAL_GREGORIAN, errorCode));
cal.adoptInstead(NULL);
}
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalUDateTimePatternGeneratorPointer");
LocalUDateTimePatternGeneratorPointer null;
LocalUDateTimePatternGeneratorPointer patgen(udatpg_open("root", errorCode));
patgen.adoptInstead(NULL);
}
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalUMessageFormatPointer");
UnicodeString hello=UNICODE_STRING_SIMPLE("Hello {0}!");
LocalUMessageFormatPointer null;
LocalUMessageFormatPointer msg(
umsg_open(hello.getBuffer(), hello.length(), "root", NULL, errorCode));
msg.adoptInstead(NULL);
}
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalURegularExpressionPointer");
UnicodeString pattern=UNICODE_STRING_SIMPLE("abc|xy+z");
LocalURegularExpressionPointer null;
LocalURegularExpressionPointer regex(
uregex_open(pattern.getBuffer(), pattern.length(), 0, NULL, errorCode));
regex.adoptInstead(NULL);
}
{
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerNull/LocalUTransliteratorPointer");
UnicodeString id=UNICODE_STRING_SIMPLE("Grek-Latn");
LocalUTransliteratorPointer null;
LocalUTransliteratorPointer trans(
utrans_openU(id.getBuffer(), id.length(), UTRANS_FORWARD, NULL, 0, NULL, errorCode));
trans.adoptInstead(NULL);
}
}

View File

@ -40,7 +40,7 @@ UBool IcuTestErrorCode::logIfFailureAndReset(const char *fmt, ...) {
void IcuTestErrorCode::handleFailure() const {
// testClass.errln("%s failure - %s", testName, errorName());
UnicodeString msg(testName, -1, US_INV);
msg.append(UNICODE_STRING_SIMPLE(" failure - ")).append(UnicodeString(errorName(), -1, US_INV));
msg.append(UNICODE_STRING_SIMPLE(" failure: ")).append(UnicodeString(errorName(), -1, US_INV));
testClass.errln(msg);
}