diff options
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/test/cintltst')
113 files changed, 77709 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in b/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in new file mode 100644 index 00000000000..262b7abf1bc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in @@ -0,0 +1,109 @@ +#****************************************************************************** +# +# Copyright (C) 1999-2006, International Business Machines +# Corporation and others. All Rights Reserved. +# +#****************************************************************************** +## Makefile.in for ICU - test/cintltst + +## Source directory information +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +top_builddir = ../.. + +## All the flags and other definitions are included here. +include $(top_builddir)/icudefs.mk + +## Build directory information +subdir = test/cintltst + +## Extra files to remove for 'make clean' +CLEANFILES = *~ $(DEPS) + +## Target information +TARGET = cintltst$(EXEEXT) + +BUILDDIR := $(CURR_SRCCODE_FULL_DIR)/../../ +# Simplify the path for Unix +BUILDDIR := $(BUILDDIR:test/cintltst/../../=) +# Simplify the path for Windows +BUILDDIR := $(BUILDDIR:test\\cintltst/../../=) +# Simplify the path for Windows 98 +BUILDDIR := $(BUILDDIR:TEST\\CINTLTST/../../=) + +ifneq ($(top_builddir),$(top_srcdir)) +CPPFLAGS += -I$(top_builddir)/common +endif +# we define ICU_UNICODE_VERSION so we can test it +CPPFLAGS += -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/tools/ctestfw -I$(top_srcdir)/tools/toolutil +DEFS += -D'ICU_UNICODE_VERSION="$(UNICODE_VERSION)"' -D'ICU_VERSION="@VERSION@"' -D'ICUDATA_NAME="$(ICUDATA_PLATFORM_NAME)"' -D'U_TOPSRCDIR="$(top_srcdir)/"' -D'U_TOPBUILDDIR="$(BUILDDIR)"' +LIBS = $(LIBCTESTFW) $(LIBICUI18N) $(LIBICUUC) $(LIBICUTOOLUTIL) $(DEFAULT_LIBS) $(LIB_M) + +OBJECTS = callcoll.o calltest.o colutil.o capitst.o cbiapts.o cbkittst.o \ +ccaltst.o cctest.o ccapitst.o ccolltst.o encoll.o cconvtst.o ccurrtst.o \ +cdattst.o cdetst.o cdtdptst.o cdtrgtst.o cestst.o cfintst.o cformtst.o \ +cfrtst.o cg7coll.o chashtst.o cintltst.o citertst.o cjaptst.o cloctst.o \ +cmsccoll.o cmsgtst.o cposxtst.o cldrtest.o \ +cnmdptst.o cnormtst.o cnumtst.o crestst.o creststn.o cturtst.o \ +cucdapi.o cucdtst.o custrtst.o cstrcase.o cutiltst.o nucnvtst.o nccbtst.o bocu1tst.o \ +cbiditst.o cbididat.o eurocreg.o udatatst.o utf16tst.o utransts.o \ +ncnvfbts.o ncnvtst.o putiltst.o cstrtest.o udatpg_test.o utf8tst.o \ +stdnmtst.o usrchtst.o custrtrn.o sorttest.o trietest.o usettest.o \ +uenumtst.o utmstest.o currtest.o \ +idnatest.o nfsprep.o spreptst.o sprpdata.o \ +hpmufn.o tracetst.o reapits.o utexttst.o ucsdetst.o + +DEPS = $(OBJECTS:.o=.d) + +-include Makefile.local + +## List of phony targets +.PHONY : all all-local install install-local clean clean-local \ +distclean distclean-local dist dist-local check check-local + +## Clear suffix list +.SUFFIXES : + +## List of standard targets +all: all-local +install: install-local +clean: clean-local +distclean : distclean-local +dist: dist-local +check: all check-local + +all-local: $(TARGET) + +install-local: + +dist-local: + +clean-local: + test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES) + $(RMV) $(OBJECTS) $(TARGET) + +distclean-local: clean-local + $(RMV) Makefile + +check-local: all-local + $(INVOKE) ./$(TARGET) $(CINTLTST_OPTS) + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(TARGET) : $(OBJECTS) + $(LINK.c) $(OUTOPT)$@ $^ $(LIBS) + $(POST_BUILD_STEP) + +ifeq (,$(MAKECMDGOALS)) +-include $(DEPS) +else +ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),) +ifneq ($(patsubst %install,,$(MAKECMDGOALS)),) +-include $(DEPS) +endif +endif +endif + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c new file mode 100644 index 00000000000..0616b1cff9e --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c @@ -0,0 +1,1031 @@ +/* +****************************************************************************** +* +* Copyright (C) 2002-2007, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* file name: bocu1tst.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2002may27 +* created by: Markus W. Scherer +* +* This is the reference implementation of BOCU-1, +* the MIME-friendly form of the Binary Ordered Compression for Unicode, +* taken directly from ### http://source.icu-project.org/repos/icu/icuhtml/trunk/design/conversion/bocu1/ +* The files bocu1.h and bocu1.c from the design folder are taken +* verbatim (minus copyright and #include) and copied together into this file. +* The reference code and some of the reference bocu1tst.c +* is modified to run as part of the ICU cintltst +* test framework (minus main(), log_ln() etc. instead of printf()). +* +* This reference implementation is used here to verify +* the ICU BOCU-1 implementation, which is +* adapted for ICU conversion APIs and optimized. +* ### links in design doc to here and to ucnvbocu.c +*/ + +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "cmemory.h" +#include "cintltst.h" + +#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) + +/* icuhtml/design/conversion/bocu1/bocu1.h ---------------------------------- */ + +/* BOCU-1 constants and macros ---------------------------------------------- */ + +/* + * BOCU-1 encodes the code points of a Unicode string as + * a sequence of byte-encoded differences (slope detection), + * preserving lexical order. + * + * Optimize the difference-taking for runs of Unicode text within + * small scripts: + * + * Most small scripts are allocated within aligned 128-blocks of Unicode + * code points. Lexical order is preserved if the "previous code point" state + * is always moved into the middle of such a block. + * + * Additionally, "prev" is moved from anywhere in the Unihan and Hangul + * areas into the middle of those areas. + * + * C0 control codes and space are encoded with their US-ASCII bytes. + * "prev" is reset for C0 controls but not for space. + */ + +/* initial value for "prev": middle of the ASCII range */ +#define BOCU1_ASCII_PREV 0x40 + +/* bounding byte values for differences */ +#define BOCU1_MIN 0x21 +#define BOCU1_MIDDLE 0x90 +#define BOCU1_MAX_LEAD 0xfe + +/* add the L suffix to make computations with BOCU1_MAX_TRAIL work on 16-bit compilers */ +#define BOCU1_MAX_TRAIL 0xffL +#define BOCU1_RESET 0xff + +/* number of lead bytes */ +#define BOCU1_COUNT (BOCU1_MAX_LEAD-BOCU1_MIN+1) + +/* adjust trail byte counts for the use of some C0 control byte values */ +#define BOCU1_TRAIL_CONTROLS_COUNT 20 +#define BOCU1_TRAIL_BYTE_OFFSET (BOCU1_MIN-BOCU1_TRAIL_CONTROLS_COUNT) + +/* number of trail bytes */ +#define BOCU1_TRAIL_COUNT ((BOCU1_MAX_TRAIL-BOCU1_MIN+1)+BOCU1_TRAIL_CONTROLS_COUNT) + +/* + * number of positive and negative single-byte codes + * (counting 0==BOCU1_MIDDLE among the positive ones) + */ +#define BOCU1_SINGLE 64 + +/* number of lead bytes for positive and negative 2/3/4-byte sequences */ +#define BOCU1_LEAD_2 43 +#define BOCU1_LEAD_3 3 +#define BOCU1_LEAD_4 1 + +/* The difference value range for single-byters. */ +#define BOCU1_REACH_POS_1 (BOCU1_SINGLE-1) +#define BOCU1_REACH_NEG_1 (-BOCU1_SINGLE) + +/* The difference value range for double-byters. */ +#define BOCU1_REACH_POS_2 (BOCU1_REACH_POS_1+BOCU1_LEAD_2*BOCU1_TRAIL_COUNT) +#define BOCU1_REACH_NEG_2 (BOCU1_REACH_NEG_1-BOCU1_LEAD_2*BOCU1_TRAIL_COUNT) + +/* The difference value range for 3-byters. */ +#define BOCU1_REACH_POS_3 \ + (BOCU1_REACH_POS_2+BOCU1_LEAD_3*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT) + +#define BOCU1_REACH_NEG_3 (BOCU1_REACH_NEG_2-BOCU1_LEAD_3*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT) + +/* The lead byte start values. */ +#define BOCU1_START_POS_2 (BOCU1_MIDDLE+BOCU1_REACH_POS_1+1) +#define BOCU1_START_POS_3 (BOCU1_START_POS_2+BOCU1_LEAD_2) +#define BOCU1_START_POS_4 (BOCU1_START_POS_3+BOCU1_LEAD_3) + /* ==BOCU1_MAX_LEAD */ + +#define BOCU1_START_NEG_2 (BOCU1_MIDDLE+BOCU1_REACH_NEG_1) +#define BOCU1_START_NEG_3 (BOCU1_START_NEG_2-BOCU1_LEAD_2) +#define BOCU1_START_NEG_4 (BOCU1_START_NEG_3-BOCU1_LEAD_3) + /* ==BOCU1_MIN+1 */ + +/* The length of a byte sequence, according to the lead byte (!=BOCU1_RESET). */ +#define BOCU1_LENGTH_FROM_LEAD(lead) \ + ((BOCU1_START_NEG_2<=(lead) && (lead)<BOCU1_START_POS_2) ? 1 : \ + (BOCU1_START_NEG_3<=(lead) && (lead)<BOCU1_START_POS_3) ? 2 : \ + (BOCU1_START_NEG_4<=(lead) && (lead)<BOCU1_START_POS_4) ? 3 : 4) + +/* The length of a byte sequence, according to its packed form. */ +#define BOCU1_LENGTH_FROM_PACKED(packed) \ + ((uint32_t)(packed)<0x04000000 ? (packed)>>24 : 4) + +/* + * 12 commonly used C0 control codes (and space) are only used to encode + * themselves directly, + * which makes BOCU-1 MIME-usable and reasonably safe for + * ASCII-oriented software. + * + * These controls are + * 0 NUL + * + * 7 BEL + * 8 BS + * + * 9 TAB + * a LF + * b VT + * c FF + * d CR + * + * e SO + * f SI + * + * 1a SUB + * 1b ESC + * + * The other 20 C0 controls are also encoded directly (to preserve order) + * but are also used as trail bytes in difference encoding + * (for better compression). + */ +#define BOCU1_TRAIL_TO_BYTE(t) ((t)>=BOCU1_TRAIL_CONTROLS_COUNT ? (t)+BOCU1_TRAIL_BYTE_OFFSET : bocu1TrailToByte[t]) + +/* + * Byte value map for control codes, + * from external byte values 0x00..0x20 + * to trail byte values 0..19 (0..0x13) as used in the difference calculation. + * External byte values that are illegal as trail bytes are mapped to -1. + */ +static const int8_t +bocu1ByteToTrail[BOCU1_MIN]={ +/* 0 1 2 3 4 5 6 7 */ + -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, -1, + +/* 8 9 a b c d e f */ + -1, -1, -1, -1, -1, -1, -1, -1, + +/* 10 11 12 13 14 15 16 17 */ + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + +/* 18 19 1a 1b 1c 1d 1e 1f */ + 0x0e, 0x0f, -1, -1, 0x10, 0x11, 0x12, 0x13, + +/* 20 */ + -1 +}; + +/* + * Byte value map for control codes, + * from trail byte values 0..19 (0..0x13) as used in the difference calculation + * to external byte values 0x00..0x20. + */ +static const int8_t +bocu1TrailToByte[BOCU1_TRAIL_CONTROLS_COUNT]={ +/* 0 1 2 3 4 5 6 7 */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x10, 0x11, + +/* 8 9 a b c d e f */ + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + +/* 10 11 12 13 */ + 0x1c, 0x1d, 0x1e, 0x1f +}; + +/** + * Integer division and modulo with negative numerators + * yields negative modulo results and quotients that are one more than + * what we need here. + * This macro adjust the results so that the modulo-value m is always >=0. + * + * For positive n, the if() condition is always FALSE. + * + * @param n Number to be split into quotient and rest. + * Will be modified to contain the quotient. + * @param d Divisor. + * @param m Output variable for the rest (modulo result). + */ +#define NEGDIVMOD(n, d, m) { \ + (m)=(n)%(d); \ + (n)/=(d); \ + if((m)<0) { \ + --(n); \ + (m)+=(d); \ + } \ +} + +/* State for BOCU-1 decoder function. */ +struct Bocu1Rx { + int32_t prev, count, diff; +}; + +typedef struct Bocu1Rx Bocu1Rx; + +/* Function prototypes ------------------------------------------------------ */ + +/* see bocu1.c */ +U_CFUNC int32_t +packDiff(int32_t diff); + +U_CFUNC int32_t +encodeBocu1(int32_t *pPrev, int32_t c); + +U_CFUNC int32_t +decodeBocu1(Bocu1Rx *pRx, uint8_t b); + +/* icuhtml/design/conversion/bocu1/bocu1.c ---------------------------------- */ + +/* BOCU-1 implementation functions ------------------------------------------ */ + +/** + * Compute the next "previous" value for differencing + * from the current code point. + * + * @param c current code point, 0..0x10ffff + * @return "previous code point" state value + */ +static U_INLINE int32_t +bocu1Prev(int32_t c) { + /* compute new prev */ + if(0x3040<=c && c<=0x309f) { + /* Hiragana is not 128-aligned */ + return 0x3070; + } else if(0x4e00<=c && c<=0x9fa5) { + /* CJK Unihan */ + return 0x4e00-BOCU1_REACH_NEG_2; + } else if(0xac00<=c && c<=0xd7a3) { + /* Korean Hangul (cast to int32_t to avoid wraparound on 16-bit compilers) */ + return ((int32_t)0xd7a3+(int32_t)0xac00)/2; + } else { + /* mostly small scripts */ + return (c&~0x7f)+BOCU1_ASCII_PREV; + } +} + +/** + * Encode a difference -0x10ffff..0x10ffff in 1..4 bytes + * and return a packed integer with them. + * + * The encoding favors small absolut differences with short encodings + * to compress runs of same-script characters. + * + * @param diff difference value -0x10ffff..0x10ffff + * @return + * 0x010000zz for 1-byte sequence zz + * 0x0200yyzz for 2-byte sequence yy zz + * 0x03xxyyzz for 3-byte sequence xx yy zz + * 0xwwxxyyzz for 4-byte sequence ww xx yy zz (ww>0x03) + */ +U_CFUNC int32_t +packDiff(int32_t diff) { + int32_t result, m, lead, count, shift; + + if(diff>=BOCU1_REACH_NEG_1) { + /* mostly positive differences, and single-byte negative ones */ + if(diff<=BOCU1_REACH_POS_1) { + /* single byte */ + return 0x01000000|(BOCU1_MIDDLE+diff); + } else if(diff<=BOCU1_REACH_POS_2) { + /* two bytes */ + diff-=BOCU1_REACH_POS_1+1; + lead=BOCU1_START_POS_2; + count=1; + } else if(diff<=BOCU1_REACH_POS_3) { + /* three bytes */ + diff-=BOCU1_REACH_POS_2+1; + lead=BOCU1_START_POS_3; + count=2; + } else { + /* four bytes */ + diff-=BOCU1_REACH_POS_3+1; + lead=BOCU1_START_POS_4; + count=3; + } + } else { + /* two- and four-byte negative differences */ + if(diff>=BOCU1_REACH_NEG_2) { + /* two bytes */ + diff-=BOCU1_REACH_NEG_1; + lead=BOCU1_START_NEG_2; + count=1; + } else if(diff>=BOCU1_REACH_NEG_3) { + /* three bytes */ + diff-=BOCU1_REACH_NEG_2; + lead=BOCU1_START_NEG_3; + count=2; + } else { + /* four bytes */ + diff-=BOCU1_REACH_NEG_3; + lead=BOCU1_START_NEG_4; + count=3; + } + } + + /* encode the length of the packed result */ + if(count<3) { + result=(count+1)<<24; + } else /* count==3, MSB used for the lead byte */ { + result=0; + } + + /* calculate trail bytes like digits in itoa() */ + shift=0; + do { + NEGDIVMOD(diff, BOCU1_TRAIL_COUNT, m); + result|=BOCU1_TRAIL_TO_BYTE(m)<<shift; + shift+=8; + } while(--count>0); + + /* add lead byte */ + result|=(lead+diff)<<shift; + + return result; +} + +/** + * BOCU-1 encoder function. + * + * @param pPrev pointer to the integer that holds + * the "previous code point" state; + * the initial value should be 0 which + * encodeBocu1 will set to the actual BOCU-1 initial state value + * @param c the code point to encode + * @return the packed 1/2/3/4-byte encoding, see packDiff(), + * or 0 if an error occurs + * + * @see packDiff + */ +U_CFUNC int32_t +encodeBocu1(int32_t *pPrev, int32_t c) { + int32_t prev; + + if(pPrev==NULL || c<0 || c>0x10ffff) { + /* illegal argument */ + return 0; + } + + prev=*pPrev; + if(prev==0) { + /* lenient handling of initial value 0 */ + prev=*pPrev=BOCU1_ASCII_PREV; + } + + if(c<=0x20) { + /* + * ISO C0 control & space: + * Encode directly for MIME compatibility, + * and reset state except for space, to not disrupt compression. + */ + if(c!=0x20) { + *pPrev=BOCU1_ASCII_PREV; + } + return 0x01000000|c; + } + + /* + * all other Unicode code points c==U+0021..U+10ffff + * are encoded with the difference c-prev + * + * a new prev is computed from c, + * placed in the middle of a 0x80-block (for most small scripts) or + * in the middle of the Unihan and Hangul blocks + * to statistically minimize the following difference + */ + *pPrev=bocu1Prev(c); + return packDiff(c-prev); +} + +/** + * Function for BOCU-1 decoder; handles multi-byte lead bytes. + * + * @param pRx pointer to the decoder state structure + * @param b lead byte; + * BOCU1_MIN<=b<BOCU1_START_NEG_2 or BOCU1_START_POS_2<=b<=BOCU1_MAX_LEAD + * @return -1 (state change only) + * + * @see decodeBocu1 + */ +static int32_t +decodeBocu1LeadByte(Bocu1Rx *pRx, uint8_t b) { + int32_t c, count; + + if(b>=BOCU1_START_NEG_2) { + /* positive difference */ + if(b<BOCU1_START_POS_3) { + /* two bytes */ + c=((int32_t)b-BOCU1_START_POS_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_1+1; + count=1; + } else if(b<BOCU1_START_POS_4) { + /* three bytes */ + c=((int32_t)b-BOCU1_START_POS_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_2+1; + count=2; + } else { + /* four bytes */ + c=BOCU1_REACH_POS_3+1; + count=3; + } + } else { + /* negative difference */ + if(b>=BOCU1_START_NEG_3) { + /* two bytes */ + c=((int32_t)b-BOCU1_START_NEG_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_1; + count=1; + } else if(b>BOCU1_MIN) { + /* three bytes */ + c=((int32_t)b-BOCU1_START_NEG_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_2; + count=2; + } else { + /* four bytes */ + c=-BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_3; + count=3; + } + } + + /* set the state for decoding the trail byte(s) */ + pRx->diff=c; + pRx->count=count; + return -1; +} + +/** + * Function for BOCU-1 decoder; handles multi-byte trail bytes. + * + * @param pRx pointer to the decoder state structure + * @param b trail byte + * @return result value, same as decodeBocu1 + * + * @see decodeBocu1 + */ +static int32_t +decodeBocu1TrailByte(Bocu1Rx *pRx, uint8_t b) { + int32_t t, c, count; + + if(b<=0x20) { + /* skip some C0 controls and make the trail byte range contiguous */ + t=bocu1ByteToTrail[b]; + if(t<0) { + /* illegal trail byte value */ + pRx->prev=BOCU1_ASCII_PREV; + pRx->count=0; + return -99; + } +#if BOCU1_MAX_TRAIL<0xff + } else if(b>BOCU1_MAX_TRAIL) { + return -99; +#endif + } else { + t=(int32_t)b-BOCU1_TRAIL_BYTE_OFFSET; + } + + /* add trail byte into difference and decrement count */ + c=pRx->diff; + count=pRx->count; + + if(count==1) { + /* final trail byte, deliver a code point */ + c=pRx->prev+c+t; + if(0<=c && c<=0x10ffff) { + /* valid code point result */ + pRx->prev=bocu1Prev(c); + pRx->count=0; + return c; + } else { + /* illegal code point result */ + pRx->prev=BOCU1_ASCII_PREV; + pRx->count=0; + return -99; + } + } + + /* intermediate trail byte */ + if(count==2) { + pRx->diff=c+t*BOCU1_TRAIL_COUNT; + } else /* count==3 */ { + pRx->diff=c+t*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT; + } + pRx->count=count-1; + return -1; +} + +/** + * BOCU-1 decoder function. + * + * @param pRx pointer to the decoder state structure; + * the initial values should be 0 which + * decodeBocu1 will set to actual initial state values + * @param b an input byte + * @return + * 0..0x10ffff for a result code point + * -1 if only the state changed without code point output + * <-1 if an error occurs + */ +U_CFUNC int32_t +decodeBocu1(Bocu1Rx *pRx, uint8_t b) { + int32_t prev, c, count; + + if(pRx==NULL) { + /* illegal argument */ + return -99; + } + + prev=pRx->prev; + if(prev==0) { + /* lenient handling of initial 0 values */ + prev=pRx->prev=BOCU1_ASCII_PREV; + count=pRx->count=0; + } else { + count=pRx->count; + } + + if(count==0) { + /* byte in lead position */ + if(b<=0x20) { + /* + * Direct-encoded C0 control code or space. + * Reset prev for C0 control codes but not for space. + */ + if(b!=0x20) { + pRx->prev=BOCU1_ASCII_PREV; + } + return b; + } + + /* + * b is a difference lead byte. + * + * Return a code point directly from a single-byte difference. + * + * For multi-byte difference lead bytes, set the decoder state + * with the partial difference value from the lead byte and + * with the number of trail bytes. + * + * For four-byte differences, the signedness also affects the + * first trail byte, which has special handling farther below. + */ + if(b>=BOCU1_START_NEG_2 && b<BOCU1_START_POS_2) { + /* single-byte difference */ + c=prev+((int32_t)b-BOCU1_MIDDLE); + pRx->prev=bocu1Prev(c); + return c; + } else if(b==BOCU1_RESET) { + /* only reset the state, no code point */ + pRx->prev=BOCU1_ASCII_PREV; + return -1; + } else { + return decodeBocu1LeadByte(pRx, b); + } + } else { + /* trail byte in any position */ + return decodeBocu1TrailByte(pRx, b); + } +} + +/* icuhtml/design/conversion/bocu1/bocu1tst.c ------------------------------- */ + +/* test code ---------------------------------------------------------------- */ + +/* test code options */ + +/* ignore comma when processing name lists in testText() */ +#define TEST_IGNORE_COMMA 1 + +/** + * Write a packed BOCU-1 byte sequence into a byte array, + * without overflow check. + * Test function. + * + * @param packed packed BOCU-1 byte sequence, see packDiff() + * @param p pointer to byte array + * @return number of bytes + * + * @see packDiff + */ +static int32_t +writePacked(int32_t packed, uint8_t *p) { + int32_t count=BOCU1_LENGTH_FROM_PACKED(packed); + switch(count) { + case 4: + *p++=(uint8_t)(packed>>24); + case 3: + *p++=(uint8_t)(packed>>16); + case 2: + *p++=(uint8_t)(packed>>8); + case 1: + *p++=(uint8_t)packed; + default: + break; + } + + return count; +} + +/** + * Unpack a packed BOCU-1 non-C0/space byte sequence and get + * the difference to initialPrev. + * Used only for round-trip testing of the difference encoding and decoding. + * Test function. + * + * @param initialPrev bogus "previous code point" value to make sure that + * the resulting code point is in the range 0..0x10ffff + * @param packed packed BOCU-1 byte sequence + * @return the difference to initialPrev + * + * @see packDiff + * @see writeDiff + */ +static int32_t +unpackDiff(int32_t initialPrev, int32_t packed) { + Bocu1Rx rx={ 0, 0, 0 }; + int32_t count; + + rx.prev=initialPrev; + count=BOCU1_LENGTH_FROM_PACKED(packed); + switch(count) { + case 4: + decodeBocu1(&rx, (uint8_t)(packed>>24)); + case 3: + decodeBocu1(&rx, (uint8_t)(packed>>16)); + case 2: + decodeBocu1(&rx, (uint8_t)(packed>>8)); + case 1: + /* subtract initial prev */ + return decodeBocu1(&rx, (uint8_t)packed)-initialPrev; + default: + return -0x7fffffff; + } +} + +/** + * Encode one difference value -0x10ffff..+0x10ffff in 1..4 bytes, + * preserving lexical order. + * Also checks for roundtripping of the difference encoding. + * Test function. + * + * @param diff difference value to test, -0x10ffff..0x10ffff + * @param p pointer to output byte array + * @return p advanced by number of bytes output + * + * @see unpackDiff + */ +static uint8_t * +writeDiff(int32_t diff, uint8_t *p) { + /* generate the difference as a packed value and serialize it */ + int32_t packed, initialPrev; + + packed=packDiff(diff); + + /* + * bogus initial "prev" to work around + * code point range check in decodeBocu1() + */ + if(diff<=0) { + initialPrev=0x10ffff; + } else { + initialPrev=-1; + } + + if(diff!=unpackDiff(initialPrev, packed)) { + log_err("error: unpackDiff(packDiff(diff=%ld)=0x%08lx)=%ld!=diff\n", + diff, packed, unpackDiff(initialPrev, packed)); + } + return p+writePacked(packed, p); +} + +/** + * Encode a UTF-16 string in BOCU-1. + * Does not check for overflows, but otherwise useful function. + * + * @param s input UTF-16 string + * @param length number of UChar code units in s + * @param p pointer to output byte array + * @return number of bytes output + */ +static int32_t +writeString(const UChar *s, int32_t length, uint8_t *p) { + uint8_t *p0; + int32_t c, prev, i; + + prev=0; + p0=p; + i=0; + while(i<length) { + UTF_NEXT_CHAR(s, i, length, c); + p+=writePacked(encodeBocu1(&prev, c), p); + } + return (int32_t)(p-p0); +} + +/** + * Decode a BOCU-1 byte sequence to a UTF-16 string. + * Does not check for overflows, but otherwise useful function. + * + * @param p pointer to input BOCU-1 bytes + * @param length number of input bytes + * @param s point to output UTF-16 string array + * @return number of UChar code units output + */ +static int32_t +readString(const uint8_t *p, int32_t length, UChar *s) { + Bocu1Rx rx={ 0, 0, 0 }; + int32_t c, i, sLength; + + i=sLength=0; + while(i<length) { + c=decodeBocu1(&rx, p[i++]); + if(c<-1) { + log_err("error: readString detects encoding error at string index %ld\n", i); + return -1; + } + if(c>=0) { + UTF_APPEND_CHAR_UNSAFE(s, sLength, c); + } + } + return sLength; +} + +static U_INLINE char +hexDigit(uint8_t digit) { + return digit<=9 ? (char)('0'+digit) : (char)('a'-10+digit); +} + +/** + * Pretty-print 0-terminated byte values. + * Helper function for test output. + * + * @param bytes 0-terminated byte array to print + */ +static void +printBytes(uint8_t *bytes, char *out) { + int i; + uint8_t b; + + i=0; + while((b=*bytes++)!=0) { + *out++=' '; + *out++=hexDigit((uint8_t)(b>>4)); + *out++=hexDigit((uint8_t)(b&0xf)); + ++i; + } + i=3*(5-i); + while(i>0) { + *out++=' '; + --i; + } + *out=0; +} + +/** + * Basic BOCU-1 test function, called when there are no command line arguments. + * Prints some of the #define values and performs round-trip tests of the + * difference encoding and decoding. + */ +static void +TestBOCU1RefDiff(void) { + char buf1[80], buf2[80]; + uint8_t prev[5], level[5]; + int32_t i, cmp, countErrors; + + log_verbose("reach of single bytes: %ld\n", 1+BOCU1_REACH_POS_1-BOCU1_REACH_NEG_1); + log_verbose("reach of 2 bytes : %ld\n", 1+BOCU1_REACH_POS_2-BOCU1_REACH_NEG_2); + log_verbose("reach of 3 bytes : %ld\n\n", 1+BOCU1_REACH_POS_3-BOCU1_REACH_NEG_3); + + log_verbose(" BOCU1_REACH_NEG_1 %8ld BOCU1_REACH_POS_1 %8ld\n", BOCU1_REACH_NEG_1, BOCU1_REACH_POS_1); + log_verbose(" BOCU1_REACH_NEG_2 %8ld BOCU1_REACH_POS_2 %8ld\n", BOCU1_REACH_NEG_2, BOCU1_REACH_POS_2); + log_verbose(" BOCU1_REACH_NEG_3 %8ld BOCU1_REACH_POS_3 %8ld\n\n", BOCU1_REACH_NEG_3, BOCU1_REACH_POS_3); + + log_verbose(" BOCU1_MIDDLE 0x%02x\n", BOCU1_MIDDLE); + log_verbose(" BOCU1_START_NEG_2 0x%02x BOCU1_START_POS_2 0x%02x\n", BOCU1_START_NEG_2, BOCU1_START_POS_2); + log_verbose(" BOCU1_START_NEG_3 0x%02x BOCU1_START_POS_3 0x%02x\n\n", BOCU1_START_NEG_3, BOCU1_START_POS_3); + + /* test packDiff() & unpackDiff() with some specific values */ + writeDiff(0, level); + writeDiff(1, level); + writeDiff(65, level); + writeDiff(130, level); + writeDiff(30000, level); + writeDiff(1000000, level); + writeDiff(-65, level); + writeDiff(-130, level); + writeDiff(-30000, level); + writeDiff(-1000000, level); + + /* test that each value is smaller than any following one */ + countErrors=0; + i=-0x10ffff; + *writeDiff(i, prev)=0; + + /* show first number and bytes */ + printBytes(prev, buf1); + log_verbose(" wD(%8ld) %s\n", i, buf1); + + for(++i; i<=0x10ffff; ++i) { + *writeDiff(i, level)=0; + cmp=strcmp((const char *)prev, (const char *)level); + if(BOCU1_LENGTH_FROM_LEAD(level[0])!=(int32_t)strlen((const char *)level)) { + log_verbose("BOCU1_LENGTH_FROM_LEAD(0x%02x)=%ld!=%ld=strlen(writeDiff(%ld))\n", + level[0], BOCU1_LENGTH_FROM_LEAD(level[0]), strlen((const char *)level), i); + } + if(cmp<0) { + if(i==0 || i==1 || strlen((const char *)prev)!=strlen((const char *)level)) { + /* + * if the result is good, then print only if the length changed + * to get little but interesting output + */ + printBytes(prev, buf1); + printBytes(level, buf2); + log_verbose("ok: strcmp(wD(%8ld), wD(%8ld))=%2d %s%s\n", i-1, i, cmp, buf1, buf2); + } + } else { + ++countErrors; + printBytes(prev, buf1); + printBytes(level, buf2); + log_verbose("wrong: strcmp(wD(%8ld), wD(%8ld))=%2d %s%s\n", i-1, i, cmp, buf1, buf2); + } + /* remember the previous bytes */ + memcpy(prev, level, 4); + } + + /* show last number and bytes */ + printBytes((uint8_t *)"", buf1); + printBytes(prev, buf2); + log_verbose(" wD(%8ld) %s%s\n", i-1, buf1, buf2); + + if(countErrors==0) { + log_verbose("writeDiff(-0x10ffff..0x10ffff) works fine\n"); + } else { + log_err("writeDiff(-0x10ffff..0x10ffff) violates lexical ordering in %d cases\n", countErrors); + } + + /* output signature byte sequence */ + i=0; + writePacked(encodeBocu1(&i, 0xfeff), level); + log_verbose("\nBOCU-1 signature byte sequence: %02x %02x %02x\n", + level[0], level[1], level[2]); +} + +/* cintltst code ------------------------------------------------------------ */ + +static const int32_t DEFAULT_BUFFER_SIZE = 30000; + + +/* test one string with the ICU and the reference BOCU-1 implementations */ +static void +roundtripBOCU1(UConverter *bocu1, int32_t number, const UChar *text, int32_t length) { + UChar *roundtripRef, *roundtripICU; + char *bocu1Ref, *bocu1ICU; + + int32_t bocu1RefLength, bocu1ICULength, roundtripRefLength, roundtripICULength; + UErrorCode errorCode; + + roundtripRef = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar)); + roundtripICU = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar)); + bocu1Ref = malloc(DEFAULT_BUFFER_SIZE); + bocu1ICU = malloc(DEFAULT_BUFFER_SIZE); + + /* Unicode -> BOCU-1 */ + bocu1RefLength=writeString(text, length, (uint8_t *)bocu1Ref); + + errorCode=U_ZERO_ERROR; + bocu1ICULength=ucnv_fromUChars(bocu1, bocu1ICU, DEFAULT_BUFFER_SIZE, text, length, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_fromUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode)); + return; + } + + if(bocu1RefLength!=bocu1ICULength || 0!=uprv_memcmp(bocu1Ref, bocu1ICU, bocu1RefLength)) { + log_err("Unicode(%d)[%d] -> BOCU-1: reference[%d]!=ICU[%d]\n", number, length, bocu1RefLength, bocu1ICULength); + return; + } + + /* BOCU-1 -> Unicode */ + roundtripRefLength=readString((uint8_t *)bocu1Ref, bocu1RefLength, roundtripRef); + if(roundtripRefLength<0) { + return; /* readString() found an error and reported it */ + } + + roundtripICULength=ucnv_toUChars(bocu1, roundtripICU, DEFAULT_BUFFER_SIZE, bocu1ICU, bocu1ICULength, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_toUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode)); + return; + } + + if(length!=roundtripRefLength || 0!=u_memcmp(text, roundtripRef, length)) { + log_err("BOCU-1 -> Unicode: original(%d)[%d]!=reference[%d]\n", number, length, roundtripRefLength); + return; + } + if(roundtripRefLength!=roundtripICULength || 0!=u_memcmp(roundtripRef, roundtripICU, roundtripRefLength)) { + log_err("BOCU-1 -> Unicode: reference(%d)[%d]!=ICU[%d]\n", number, roundtripRefLength, roundtripICULength); + return; + } + free(roundtripRef); + free(roundtripICU); + free(bocu1Ref); + free(bocu1ICU); +} + +static const UChar feff[]={ 0xfeff }; +static const UChar ascii[]={ 0x61, 0x62, 0x20, 0x63, 0x61 }; +static const UChar crlf[]={ 0xd, 0xa, 0x20 }; +static const UChar nul[]={ 0 }; +static const UChar latin[]={ 0xdf, 0xe6 }; +static const UChar devanagari[]={ 0x930, 0x20, 0x918, 0x909 }; +static const UChar hiragana[]={ 0x3086, 0x304d, 0x20, 0x3053, 0x4000 }; +static const UChar unihan[]={ 0x4e00, 0x7777, 0x20, 0x9fa5, 0x4e00 }; +static const UChar hangul[]={ 0xac00, 0xbcde, 0x20, 0xd7a3 }; +static const UChar surrogates[]={ 0xdc00, 0xd800 }; /* single surrogates, unmatched! */ +static const UChar plane1[]={ 0xd800, 0xdc00 }; +static const UChar plane2[]={ 0xd845, 0xdddd }; +static const UChar plane15[]={ 0xdbbb, 0xddee, 0x20 }; +static const UChar plane16[]={ 0xdbff, 0xdfff }; +static const UChar c0[]={ 1, 0xe40, 0x20, 9 }; + +static const struct { + const UChar *s; + int32_t length; +} strings[]={ + { feff, LENGTHOF(feff) }, + { ascii, LENGTHOF(ascii) }, + { crlf, LENGTHOF(crlf) }, + { nul, LENGTHOF(nul) }, + { latin, LENGTHOF(latin) }, + { devanagari, LENGTHOF(devanagari) }, + { hiragana, LENGTHOF(hiragana) }, + { unihan, LENGTHOF(unihan) }, + { hangul, LENGTHOF(hangul) }, + { surrogates, LENGTHOF(surrogates) }, + { plane1, LENGTHOF(plane1) }, + { plane2, LENGTHOF(plane2) }, + { plane15, LENGTHOF(plane15) }, + { plane16, LENGTHOF(plane16) }, + { c0, LENGTHOF(c0) } +}; + +/* + * Verify that the ICU BOCU-1 implementation produces the same results as + * the reference implementation from the design folder. + * Generate some texts and convert them with both converters, verifying + * identical results and roundtripping. + */ +static void +TestBOCU1(void) { + UChar *text; + int32_t i, length; + + UConverter *bocu1; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + bocu1=ucnv_open("BOCU-1", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: unable to open BOCU-1 converter: %s\n", u_errorName(errorCode)); + return; + } + + text = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar)); + + /* text 1: each of strings[] once */ + length=0; + for(i=0; i<LENGTHOF(strings); ++i) { + u_memcpy(text+length, strings[i].s, strings[i].length); + length+=strings[i].length; + } + roundtripBOCU1(bocu1, 1, text, length); + + /* text 2: each of strings[] twice */ + length=0; + for(i=0; i<LENGTHOF(strings); ++i) { + u_memcpy(text+length, strings[i].s, strings[i].length); + length+=strings[i].length; + u_memcpy(text+length, strings[i].s, strings[i].length); + length+=strings[i].length; + } + roundtripBOCU1(bocu1, 2, text, length); + + /* text 3: each of strings[] many times (set step vs. |strings| so that all strings are used) */ + length=0; + for(i=1; length<5000; i+=7) { + if(i>=LENGTHOF(strings)) { + i-=LENGTHOF(strings); + } + u_memcpy(text+length, strings[i].s, strings[i].length); + length+=strings[i].length; + } + roundtripBOCU1(bocu1, 3, text, length); + + ucnv_close(bocu1); + free(text); +} + +U_CFUNC void addBOCU1Tests(TestNode** root); + +U_CFUNC void +addBOCU1Tests(TestNode** root) { + addTest(root, TestBOCU1RefDiff, "tsconv/bocu1tst/TestBOCU1RefDiff"); + addTest(root, TestBOCU1, "tsconv/bocu1tst/TestBOCU1"); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c new file mode 100644 index 00000000000..d898eea25f2 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c @@ -0,0 +1,1303 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CALLCOLL.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +******************************************************************************** +*/ + +/* + * Important: This file is included into intltest/allcoll.cpp so that the + * test data is shared. This makes it easier to maintain the test data, + * especially since the Unicode data must be portable and quoted character + * literals will not work. + * If it is included, then there will be a #define INCLUDE_CALLCOLL_C + * that must prevent the actual code in here from being part of the + * allcoll.cpp compilation. + */ + +/** + * CollationDummyTest is a third level test class. This tests creation of + * a customized collator object. For example, number 1 to be sorted + * equlivalent to word 'one'. + */ + +#include <string.h> +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "unicode/ucoleitr.h" +#include "unicode/ustring.h" +#include "unicode/uclean.h" +#include "unicode/putil.h" +#include "unicode/uenum.h" + +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "calldata.h" +#include "cstring.h" +#include "cmemory.h" +#include "ucol_imp.h" + +/* perform test with strength PRIMARY */ +static void TestPrimary(void); + +/* perform test with strength SECONDARY */ +static void TestSecondary(void); + +/* perform test with strength tertiary */ +static void TestTertiary(void); + +/*perform tests with strength Identical */ +static void TestIdentical(void); + +/* perform extra tests */ +static void TestExtra(void); + +/* Test jitterbug 581 */ +static void TestJB581(void); + +/* Test jitterbug 1401 */ +static void TestJB1401(void); + +/* Test [variable top] in the rule syntax */ +static void TestVariableTop(void); + +/* Test surrogates */ +static void TestSurrogates(void); + +static void TestInvalidRules(void); + +static void TestJitterbug1098(void); + +static void TestFCDCrash(void); + +static void TestJ5298(void); + +const UCollationResult results[] = { + UCOL_LESS, + UCOL_LESS, /*UCOL_GREATER,*/ + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_LESS, /* 10 */ + UCOL_GREATER, + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + /* test primary > 17 */ + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, /* 20 */ + UCOL_LESS, + UCOL_LESS, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_LESS, + /* test secondary > 26 */ + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, /* 30 */ + UCOL_EQUAL, + UCOL_LESS, + UCOL_EQUAL, /* 34 */ + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_LESS /* 37 */ +}; + + +static +void uprv_appendByteToHexString(char *dst, uint8_t val) { + uint32_t len = (uint32_t)uprv_strlen(dst); + *(dst+len) = T_CString_itosOffset((val >> 4)); + *(dst+len+1) = T_CString_itosOffset((val & 0xF)); + *(dst+len+2) = 0; +} + +/* this function makes a string with representation of a sortkey */ +static char* U_EXPORT2 sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) { + int32_t strength = UCOL_PRIMARY; + uint32_t res_size = 0; + UBool doneCase = FALSE; + + char *current = buffer; + const uint8_t *currentSk = sortkey; + + uprv_strcpy(current, "["); + + while(strength <= UCOL_QUATERNARY && strength <= coll->strength) { + if(strength > UCOL_PRIMARY) { + uprv_strcat(current, " . "); + } + while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */ + uprv_appendByteToHexString(current, *currentSk++); + uprv_strcat(current, " "); + } + if(coll->caseLevel == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) { + doneCase = TRUE; + } else if(coll->caseLevel == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) { + strength ++; + } + uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */ + if(strength == UCOL_QUATERNARY && coll->alternateHandling == UCOL_NON_IGNORABLE) { + break; + } + } + + if(coll->strength == UCOL_IDENTICAL) { + uprv_strcat(current, " . "); + while(*currentSk != 0) { + uprv_appendByteToHexString(current, *currentSk++); + uprv_strcat(current, " "); + } + + uprv_appendByteToHexString(current, *currentSk++); + } + uprv_strcat(current, "]"); + + if(res_size > *len) { + return NULL; + } + + return buffer; +} + +void addAllCollTest(TestNode** root) +{ + + + addTest(root, &TestPrimary, "tscoll/callcoll/TestPrimary"); + addTest(root, &TestSecondary, "tscoll/callcoll/TestSecondary"); + addTest(root, &TestTertiary, "tscoll/callcoll/TestTertiary"); + addTest(root, &TestIdentical, "tscoll/callcoll/TestIdentical"); + addTest(root, &TestExtra, "tscoll/callcoll/TestExtra"); + addTest(root, &TestJB581, "tscoll/callcoll/TestJB581"); + addTest(root, &TestVariableTop, "tscoll/callcoll/TestVariableTop"); + addTest(root, &TestSurrogates, "tscoll/callcoll/TestSurrogates"); + addTest(root, &TestInvalidRules, "tscoll/callcoll/TestInvalidRules"); + addTest(root, &TestJB1401, "tscoll/callcoll/TestJB1401"); + addTest(root, &TestJitterbug1098, "tscoll/callcoll/TestJitterbug1098"); + addTest(root, &TestFCDCrash, "tscoll/callcoll/TestFCDCrash"); + addTest(root, &TestJ5298, "tscoll/callcoll/TestJ5298"); +} + +UBool hasCollationElements(const char *locName) { + + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *ColEl = NULL; + + UResourceBundle *loc = ures_open(U_ICUDATA_COLL, locName, &status);; + + if(U_SUCCESS(status)) { + status = U_ZERO_ERROR; + ColEl = ures_getByKey(loc, "collations", ColEl, &status); + if(status == U_ZERO_ERROR) { /* do the test - there are real elements */ + ures_close(ColEl); + ures_close(loc); + return TRUE; + } + ures_close(ColEl); + ures_close(loc); + } + return FALSE; +} + +static UCollationResult compareUsingPartials(UCollator *coll, const UChar source[], int32_t sLen, const UChar target[], int32_t tLen, int32_t pieceSize, UErrorCode *status) { + int32_t partialSKResult = 0; + UCharIterator sIter, tIter; + uint32_t sState[2], tState[2]; + int32_t sSize = pieceSize, tSize = pieceSize; + /*int32_t i = 0;*/ + uint8_t sBuf[16384], tBuf[16384]; + if(pieceSize > 16384) { + log_err("Partial sortkey size buffer too small. Please consider increasing the buffer!\n"); + *status = U_BUFFER_OVERFLOW_ERROR; + return UCOL_EQUAL; + } + *status = U_ZERO_ERROR; + sState[0] = 0; sState[1] = 0; + tState[0] = 0; tState[1] = 0; + while(sSize == pieceSize && tSize == pieceSize && partialSKResult == 0) { + uiter_setString(&sIter, source, sLen); + uiter_setString(&tIter, target, tLen); + sSize = ucol_nextSortKeyPart(coll, &sIter, sState, sBuf, pieceSize, status); + tSize = ucol_nextSortKeyPart(coll, &tIter, tState, tBuf, pieceSize, status); + + if(sState[0] != 0 || tState[0] != 0) { + /*log_verbose("State != 0 : %08X %08X\n", sState[0], tState[0]);*/ + } + /*log_verbose("%i ", i++);*/ + + partialSKResult = memcmp(sBuf, tBuf, pieceSize); + } + + if(partialSKResult < 0) { + return UCOL_LESS; + } else if(partialSKResult > 0) { + return UCOL_GREATER; + } else { + return UCOL_EQUAL; + } +} + +static void doTestVariant(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result) +{ + int32_t sortklen1, sortklen2, sortklenmax, sortklenmin; + int temp=0, gSortklen1=0,gSortklen2=0; + UCollationResult compareResult, compareResulta, keyResult, compareResultIter = result; + uint8_t *sortKey1, *sortKey2, *sortKey1a, *sortKey2a; + uint32_t sLen = u_strlen(source); + uint32_t tLen = u_strlen(target); + char buffer[256]; + uint32_t len; + UErrorCode status = U_ZERO_ERROR; + UColAttributeValue norm = ucol_getAttribute(myCollation, UCOL_NORMALIZATION_MODE, &status); + + UCharIterator sIter, tIter; + uiter_setString(&sIter, source, sLen); + uiter_setString(&tIter, target, tLen); + compareResultIter = ucol_strcollIter(myCollation, &sIter, &tIter, &status); + if(compareResultIter != result) { + log_err("different results in iterative comparison for UTF-16 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1)); + } + + /* convert the strings to UTF-8 and do try comparing with char iterator */ + if(QUICK <= 0) { /*!QUICK*/ + char utf8Source[256], utf8Target[256]; + int32_t utf8SourceLen = 0, utf8TargetLen = 0; + u_strToUTF8(utf8Source, 256, &utf8SourceLen, source, sLen, &status); + if(U_FAILURE(status)) { /* probably buffer is not big enough */ + log_verbose("Src UTF-8 buffer too small! Will not compare!\n"); + } else { + u_strToUTF8(utf8Target, 256, &utf8TargetLen, target, tLen, &status); + if(U_SUCCESS(status)) { /* probably buffer is not big enough */ + UCollationResult compareResultUTF8 = result, compareResultUTF8Norm = result; + /*UCharIterator sIter, tIter;*/ + /*log_verbose("Strings converted to UTF-8:%s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));*/ + uiter_setUTF8(&sIter, utf8Source, utf8SourceLen); + uiter_setUTF8(&tIter, utf8Target, utf8TargetLen); + /*uiter_setString(&sIter, source, sLen); + uiter_setString(&tIter, target, tLen);*/ + compareResultUTF8 = ucol_strcollIter(myCollation, &sIter, &tIter, &status); + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + sIter.move(&sIter, 0, UITER_START); + tIter.move(&tIter, 0, UITER_START); + compareResultUTF8Norm = ucol_strcollIter(myCollation, &sIter, &tIter, &status); + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status); + if(compareResultUTF8 != compareResultIter) { + log_err("different results in iterative comparison for UTF-16 and UTF-8 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1)); + } + if(compareResultUTF8 != compareResultUTF8Norm) { + log_err("different results in iterative when normalization is turned on with UTF-8 strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1)); + } + } else { + log_verbose("Target UTF-8 buffer too small! Did not compare!\n"); + } + if(U_FAILURE(status)) { + log_verbose("UTF-8 strcoll failed! Ignoring result\n"); + } + } + } + + /* testing the partial sortkeys */ + if(1) { /*!QUICK*/ + int32_t i = 0; + int32_t partialSizes[] = { 3, 1, 2, 4, 8, 20, 80 }; /* just size 3 in the quick mode */ + int32_t partialSizesSize = 1; + if(QUICK <= 0) { + partialSizesSize = 7; + } + /*log_verbose("partial sortkey test piecesize=");*/ + for(i = 0; i < partialSizesSize; i++) { + UCollationResult partialSKResult = result, partialNormalizedSKResult = result; + /*log_verbose("%i ", partialSizes[i]);*/ + + partialSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status); + if(partialSKResult != result) { + log_err("Partial sortkey comparison returned wrong result (%i exp. %i): %s, %s (size %i)\n", + partialSKResult, result, + aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]); + } + + if(QUICK <= 0 && norm != UCOL_ON) { + /*log_verbose("N ");*/ + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + partialNormalizedSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status); + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status); + if(partialSKResult != partialNormalizedSKResult) { + log_err("Partial sortkey comparison gets different result when normalization is on: %s, %s (size %i)\n", + aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]); + } + } + } + /*log_verbose("\n");*/ + } + + + compareResult = ucol_strcoll(myCollation, source, sLen, target, tLen); + compareResulta = ucol_strcoll(myCollation, source, -1, target, -1); + if (compareResult != compareResulta) { + log_err("ucol_strcoll result from null terminated and explicit length strings differs.\n"); + } + + sortklen1=ucol_getSortKey(myCollation, source, sLen, NULL, 0); + sortklen2=ucol_getSortKey(myCollation, target, tLen, NULL, 0); + + sortklenmax = (sortklen1>sortklen2?sortklen1:sortklen2); + sortklenmin = (sortklen1<sortklen2?sortklen1:sortklen2); + + sortKey1 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1)); + sortKey1a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1)); + ucol_getSortKey(myCollation, source, sLen, sortKey1, sortklen1+1); + ucol_getSortKey(myCollation, source, -1, sortKey1a, sortklen1+1); + + sortKey2 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1)); + sortKey2a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1)); + ucol_getSortKey(myCollation, target, tLen, sortKey2, sortklen2+1); + ucol_getSortKey(myCollation, target, -1, sortKey2a, sortklen2+1); + + /* Check that sort key generated with null terminated string is identical */ + /* to that generted with a length specified. */ + if (uprv_strcmp((const char *)sortKey1, (const char *)sortKey1a) != 0 || + uprv_strcmp((const char *)sortKey2, (const char *)sortKey2a) != 0 ) { + log_err("Sort Keys from null terminated and explicit length strings differ.\n"); + } + + /*memcmp(sortKey1, sortKey2,sortklenmax);*/ + temp= uprv_strcmp((const char *)sortKey1, (const char *)sortKey2); + gSortklen1 = uprv_strlen((const char *)sortKey1)+1; + gSortklen2 = uprv_strlen((const char *)sortKey2)+1; + if(sortklen1 != gSortklen1){ + log_err("SortKey length does not match Expected: %i Got: %i\n",sortklen1, gSortklen1); + log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey1, buffer, &len)); + } + if(sortklen2!= gSortklen2){ + log_err("SortKey length does not match Expected: %i Got: %i\n", sortklen2, gSortklen2); + log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey2, buffer, &len)); + } + + if(temp < 0) { + keyResult=UCOL_LESS; + } + else if(temp > 0) { + keyResult= UCOL_GREATER; + } + else { + keyResult = UCOL_EQUAL; + } + reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResultIter, result ); + free(sortKey1); + free(sortKey2); + free(sortKey1a); + free(sortKey2a); + +} + +void doTest(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result) +{ + if(myCollation) { + doTestVariant(myCollation, source, target, result); + if(result == UCOL_LESS) { + doTestVariant(myCollation, target, source, UCOL_GREATER); + } else if(result == UCOL_GREATER) { + doTestVariant(myCollation, target, source, UCOL_LESS); + } else { + doTestVariant(myCollation, target, source, UCOL_EQUAL); + } + } else { + log_data_err("No collator! Any data around?\n"); + } +} + + +/** + * Return an integer array containing all of the collation orders + * returned by calls to next on the specified iterator + */ +int32_t* getOrders(UCollationElements *iter, int32_t *orderLength) +{ + UErrorCode status; + int32_t order; + int32_t maxSize = 100; + int32_t size = 0; + int32_t *temp; + int32_t *orders =(int32_t*)malloc(sizeof(int32_t) * maxSize); + status= U_ZERO_ERROR; + + + while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER) + { + if (size == maxSize) + { + maxSize *= 2; + temp = (int32_t*)malloc(sizeof(int32_t) * maxSize); + + memcpy(temp, orders, size * sizeof(int32_t)); + free(orders); + orders = temp; + + } + + orders[size++] = order; + } + + if (maxSize > size && size > 0) + { + temp = (int32_t*)malloc(sizeof(int32_t) * size); + + memcpy(temp, orders, size * sizeof(int32_t)); + free(orders); + orders = temp; + + + } + + *orderLength = size; + return orders; +} + + +void +backAndForth(UCollationElements *iter) +{ + /* Run through the iterator forwards and stick it into an array */ + int32_t index, o; + UErrorCode status = U_ZERO_ERROR; + int32_t orderLength = 0; + int32_t *orders; + orders= getOrders(iter, &orderLength); + + + /* Now go through it backwards and make sure we get the same values */ + index = orderLength; + ucol_reset(iter); + + /* synwee : changed */ + while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) + { + if (o != orders[-- index]) + { + if (o == 0) + index ++; + else + { + while (index > 0 && orders[-- index] == 0) + { + } + if (o != orders[index]) + { + log_err("Mismatch at index : 0x%x\n", index); + return; + } + + } + } + } + + while (index != 0 && orders[index - 1] == 0) { + index --; + } + + if (index != 0) + { + log_err("Didn't get back to beginning - index is %d\n", index); + + ucol_reset(iter); + log_err("\nnext: "); + if ((o = ucol_next(iter, &status)) != UCOL_NULLORDER) + { + log_err("Error at %x\n", o); + } + log_err("\nprev: "); + if ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) + { + log_err("Error at %x\n", o); + } + log_verbose("\n"); + } + + free(orders); +} + +void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result) { + UChar t1[2048] = {0}; + UChar t2[2048] = {0}; + UCollationElements *iter; + UErrorCode status = U_ZERO_ERROR; + + uint32_t i = 0, j = 0; + log_verbose("testing sequence:\n"); + for(i = 0; i < size; i++) { + log_verbose("%s\n", s[i]); + } + + iter = ucol_openElements(coll, t1, u_strlen(t1), &status); + if (U_FAILURE(status)) { + log_err("Creation of iterator failed\n"); + } + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + u_unescape(s[i], t1, 2048); + u_unescape(s[j], t2, 2048); + doTest(coll, t1, t2, result); + /* synwee : added collation element iterator test */ + ucol_setText(iter, t1, u_strlen(t1), &status); + backAndForth(iter); + ucol_setText(iter, t2, u_strlen(t2), &status); + backAndForth(iter); + } + } + ucol_closeElements(iter); +} + +void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size) { + genericOrderingTestWithResult(coll, s, size, UCOL_LESS); +} + +void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size) { + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open(locale, &status); + + log_verbose("Locale starter for %s\n", locale); + + if(U_SUCCESS(status)) { + genericOrderingTest(coll, s, size); + } else if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else { + log_err("Unable to open collator for locale %s\n", locale); + } + ucol_close(coll); +} + +void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result) { + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open(locale, &status); + + log_verbose("Locale starter for %s\n", locale); + + if(U_SUCCESS(status)) { + genericOrderingTestWithResult(coll, s, size, result); + } else if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else { + log_err("Unable to open collator for locale %s\n", locale); + } + ucol_close(coll); +} + +/* currently not used with options */ +void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) { + UErrorCode status = U_ZERO_ERROR; + UChar rlz[RULE_BUFFER_LEN] = { 0 }; + uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN); + uint32_t i; + + UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status); + + log_verbose("Rules starter for %s\n", rules); + + if(U_SUCCESS(status)) { + log_verbose("Setting attributes\n"); + for(i = 0; i < attsize; i++) { + ucol_setAttribute(coll, attrs[i], values[i], &status); + } + + genericOrderingTestWithResult(coll, s, size, result); + } else { + log_err("Unable to open collator with rules %s\n", rules); + } + ucol_close(coll); +} + +void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) { + UErrorCode status = U_ZERO_ERROR; + uint32_t i; + + UCollator *coll = ucol_open(locale, &status); + + log_verbose("Locale starter for %s\n", locale); + + if(U_SUCCESS(status)) { + + log_verbose("Setting attributes\n"); + for(i = 0; i < attsize; i++) { + ucol_setAttribute(coll, attrs[i], values[i], &status); + } + + genericOrderingTestWithResult(coll, s, size, result); + } else { + log_err("Unable to open collator for locale %s\n", locale); + } + ucol_close(coll); +} + +void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize) { + genericLocaleStarterWithOptionsAndResult(locale, s, size, attrs, values, attsize, UCOL_LESS); +} + +void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result) { + UErrorCode status = U_ZERO_ERROR; + UChar rlz[RULE_BUFFER_LEN] = { 0 }; + uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN); + + UCollator *coll = NULL; + coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status); + log_verbose("Rules starter for %s\n", rules); + + if(U_SUCCESS(status)) { + genericOrderingTestWithResult(coll, s, size, result); + ucol_close(coll); + } else if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + } else { + log_err("Unable to open collator with rules %s\n", rules); + } +} + +void genericRulesStarter(const char *rules, const char * const s[], uint32_t size) { + genericRulesStarterWithResult(rules, s, size, UCOL_LESS); +} + +static void TestTertiary() +{ + int32_t len,i; + UChar *rules; + UCollator *myCollation; + UErrorCode status=U_ZERO_ERROR; + const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 "; + len = strlen(str); + rules=(UChar*)malloc(sizeof(UChar*) * (len+1)); + u_uastrcpy(rules, str); + + myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status)); + } + + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 17 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + free(rules); + ucol_close(myCollation); + myCollation = 0; +} + +static void TestPrimary( ) +{ + int32_t len,i; + UChar *rules; + UCollator *myCollation; + UErrorCode status=U_ZERO_ERROR; + const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 "; + len = strlen(str); + rules=(UChar*)malloc(sizeof(UChar*) * (len+1)); + u_uastrcpy(rules, str); + + myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status)); + } + ucol_setStrength(myCollation, UCOL_PRIMARY); + + for (i = 17; i < 26 ; i++) + { + + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + free(rules); + ucol_close(myCollation); + myCollation = 0; +} + +static void TestSecondary() +{ + int32_t i; + int32_t len; + UChar *rules; + UCollator *myCollation; + UErrorCode status=U_ZERO_ERROR; + const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 "; + len = strlen(str); + rules=(UChar*)malloc(sizeof(UChar*) * (len+1)); + u_uastrcpy(rules, str); + + myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status)); + } + ucol_setStrength(myCollation, UCOL_SECONDARY); + for (i = 26; i < 34 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + free(rules); + ucol_close(myCollation); + myCollation = 0; +} + +static void TestIdentical() +{ + int32_t i; + int32_t len; + UChar *rules = 0; + UCollator *myCollation; + UErrorCode status=U_ZERO_ERROR; + const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 "; + len = strlen(str); + rules=(UChar*)malloc(sizeof(UChar*) * (len+1)); + u_uastrcpy(rules, str); + + myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_IDENTICAL, NULL,&status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status)); + } + for(i= 34; i<37; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + free(rules); + ucol_close(myCollation); + myCollation = 0; +} + +static void TestExtra() +{ + int32_t i, j; + int32_t len; + UChar *rules; + UCollator *myCollation; + UErrorCode status = U_ZERO_ERROR; + const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 "; + len = strlen(str); + rules=(UChar*)malloc(sizeof(UChar*) * (len+1)); + u_uastrcpy(rules, str); + + myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status)); + } + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < COUNT_TEST_CASES-1 ; i++) + { + for (j = i + 1; j < COUNT_TEST_CASES; j += 1) + { + + doTest(myCollation, testCases[i], testCases[j], UCOL_LESS); + } + } + free(rules); + ucol_close(myCollation); + myCollation = 0; +} + +static void TestJB581(void) +{ + UChar dispName [100]; + int32_t bufferLen = 0; + UChar source [100]; + UChar target [100]; + UCollationResult result = UCOL_EQUAL; + uint8_t sourceKeyArray [100]; + uint8_t targetKeyArray [100]; + int32_t sourceKeyOut = 0, + targetKeyOut = 0; + UCollator *myCollator = 0; + UErrorCode status = U_ZERO_ERROR; + + /*u_uastrcpy(source, "This is a test.");*/ + /*u_uastrcpy(target, "THISISATEST.");*/ + u_uastrcpy(source, "THISISATEST."); + u_uastrcpy(target, "Thisisatest."); + + myCollator = ucol_open("en_US", &status); + if (U_FAILURE(status)){ + bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status); + /*Report the error with display name... */ + log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName); + return; + } + result = ucol_strcoll(myCollator, source, -1, target, -1); + /* result is 1, secondary differences only for ignorable space characters*/ + if (result != 1) + { + log_err("Comparing two strings with only secondary differences in C failed.\n"); + } + /* To compare them with just primary differences */ + ucol_setStrength(myCollator, UCOL_PRIMARY); + result = ucol_strcoll(myCollator, source, -1, target, -1); + /* result is 0 */ + if (result != 0) + { + log_err("Comparing two strings with no differences in C failed.\n"); + } + /* Now, do the same comparison with keys */ + sourceKeyOut = ucol_getSortKey(myCollator, source, -1, sourceKeyArray, 100); + targetKeyOut = ucol_getSortKey(myCollator, target, -1, targetKeyArray, 100); + bufferLen = ((targetKeyOut > 100) ? 100 : targetKeyOut); + if (memcmp(sourceKeyArray, targetKeyArray, bufferLen) != 0) + { + log_err("Comparing two strings with sort keys in C failed.\n"); + } + ucol_close(myCollator); +} + +static void TestJB1401(void) +{ + UCollator *myCollator = 0; + UErrorCode status = U_ZERO_ERROR; + static UChar NFD_UnsafeStartChars[] = { + 0x0f73, /* Tibetan Vowel Sign II */ + 0x0f75, /* Tibetan Vowel Sign UU */ + 0x0f81, /* Tibetan Vowel Sign Reversed II */ + 0 + }; + int i; + + + myCollator = ucol_open("en_US", &status); + if (U_FAILURE(status)){ + int32_t bufferLen = 0; + UChar dispName [100]; + bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status); + /*Report the error with display name... */ + log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName); + return; + } + ucol_setAttribute(myCollator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + if (U_FAILURE(status)){ + log_err("ERROR: Failed to set normalization mode ON for collator.\n"); + return; + } + + for (i=0; ; i++) { + UChar c; + UChar X[4]; + UChar Y[20]; + UChar Z[20]; + + /* Get the next funny character to be tested, and set up the + * three test strings X, Y, Z, consisting of an A-grave + test char, + * in original form, NFD, and then NFC form. + */ + c = NFD_UnsafeStartChars[i]; + if (c==0) {break;} + + X[0]=0xC0; X[1]=c; X[2]=0; /* \u00C0 is A Grave*/ + + unorm_normalize(X, -1, UNORM_NFD, 0, Y, 20, &status); + unorm_normalize(Y, -1, UNORM_NFC, 0, Z, 20, &status); + if (U_FAILURE(status)){ + log_err("ERROR: Failed to normalize test of character %x\n", c); + return; + } + + /* Collation test. All three strings should be equal. + * doTest does both strcoll and sort keys, with params in both orders. + */ + doTest(myCollator, X, Y, UCOL_EQUAL); + doTest(myCollator, X, Z, UCOL_EQUAL); + doTest(myCollator, Y, Z, UCOL_EQUAL); + + /* Run collation element iterators over the three strings. Results should be same for each. + */ + { + UCollationElements *ceiX, *ceiY, *ceiZ; + int32_t ceX, ceY, ceZ; + int j; + + ceiX = ucol_openElements(myCollator, X, -1, &status); + ceiY = ucol_openElements(myCollator, Y, -1, &status); + ceiZ = ucol_openElements(myCollator, Z, -1, &status); + if (U_FAILURE(status)) { + log_err("ERROR: uucol_openElements failed.\n"); + return; + } + + for (j=0;; j++) { + ceX = ucol_next(ceiX, &status); + ceY = ucol_next(ceiY, &status); + ceZ = ucol_next(ceiZ, &status); + if (U_FAILURE(status)) { + log_err("ERROR: ucol_next failed for iteration #%d.\n", j); + break; + } + if (ceX != ceY || ceY != ceZ) { + log_err("ERROR: ucol_next failed for iteration #%d.\n", j); + break; + } + if (ceX == UCOL_NULLORDER) { + break; + } + } + ucol_closeElements(ceiX); + ucol_closeElements(ceiY); + ucol_closeElements(ceiZ); + } + } + ucol_close(myCollator); +} + + + +/** +* Tests the [variable top] tag in rule syntax. Since the default [alternate] +* tag has the value shifted, any codepoints before [variable top] should give +* a primary ce of 0. +*/ +static void TestVariableTop(void) +{ + const char *str = "&z = [variable top]"; + int len = strlen(str); + UChar *rules; + UCollator *myCollation; + UCollator *enCollation; + UErrorCode status = U_ZERO_ERROR; + UChar source[1]; + UChar ch; + uint8_t result[20]; + uint8_t expected[20]; + + rules = (UChar*)malloc(sizeof(UChar*) * (len + 1)); + u_uastrcpy(rules, str); + + enCollation = ucol_open("en_US", &status); + myCollation = ucol_openRules(rules, len, UCOL_OFF, + UCOL_PRIMARY,NULL, &status); + if (U_FAILURE(status)) { + log_err("ERROR: in creation of rule based collator :%s\n", + myErrorName(status)); + return; + } + + ucol_setStrength(enCollation, UCOL_PRIMARY); + ucol_setAttribute(enCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, + &status); + ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, + &status); + + if (ucol_getAttribute(myCollation, UCOL_ALTERNATE_HANDLING, &status) != + UCOL_SHIFTED || U_FAILURE(status)) { + log_err("ERROR: ALTERNATE_HANDLING value can not be set to SHIFTED\n"); + } + + uprv_memset(expected, 0, 20); + + /* space is supposed to be a variable */ + source[0] = ' '; + len = ucol_getSortKey(enCollation, source, 1, result, + sizeof(result)); + + if (uprv_memcmp(expected, result, len) != 0) { + log_err("ERROR: SHIFTED alternate does not return 0 for primary of space\n"); + } + + ch = 'a'; + while (ch < 'z') { + source[0] = ch; + len = ucol_getSortKey(myCollation, source, 1, result, + sizeof(result)); + if (uprv_memcmp(expected, result, len) != 0) { + log_err("ERROR: SHIFTED alternate does not return 0 for primary of %c\n", + ch); + } + ch ++; + } + + free(rules); + ucol_close(enCollation); + ucol_close(myCollation); + enCollation = NULL; + myCollation = NULL; +} + +/** + * Tests surrogate support. + * NOTE: This test used \\uD801\\uDC01 pair, which is now assigned to Desseret + * Therefore, another (unassigned) code point was used for this test. + */ +static void TestSurrogates(void) +{ + const char *str = + "&z<'\\uD800\\uDC00'<'\\uD800\\uDC0A\\u0308'<A"; + int len = strlen(str); + int rlen = 0; + UChar *rules; + UCollator *myCollation; + UCollator *enCollation; + UErrorCode status = U_ZERO_ERROR; + UChar source[][4] = + {{'z', 0, 0}, {0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {0xD800, 0xDC02}}; + UChar target[][4] = + {{0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {'A', 0, 0}, {0xD800, 0xDC03}}; + int count = 0; + uint8_t enresult[20], myresult[20]; + int enlen, mylen; + + /* tests for open rules with surrogate rules */ + rules = (UChar*)malloc(sizeof(UChar*) * (len + 1)); + rlen = u_unescape(str, rules, len); + + enCollation = ucol_open("en_US", &status); + myCollation = ucol_openRules(rules, rlen, UCOL_OFF, + UCOL_TERTIARY,NULL, &status); + if (U_FAILURE(status)) { + log_err("ERROR: in creation of rule based collator :%s\n", + myErrorName(status)); + return; + } + + /* + this test is to verify the supplementary sort key order in the english + collator + */ + log_verbose("start of english collation supplementary characters test\n"); + while (count < 2) { + doTest(enCollation, source[count], target[count], UCOL_LESS); + count ++; + } + doTest(enCollation, source[count], target[count], UCOL_GREATER); + + log_verbose("start of tailored collation supplementary characters test\n"); + count = 0; + /* tests getting collation elements for surrogates for tailored rules */ + while (count < 4) { + doTest(myCollation, source[count], target[count], UCOL_LESS); + count ++; + } + + /* tests that \uD800\uDC02 still has the same value, not changed */ + enlen = ucol_getSortKey(enCollation, source[3], 2, enresult, 20); + mylen = ucol_getSortKey(myCollation, source[3], 2, myresult, 20); + if (enlen != mylen || + uprv_memcmp(enresult, myresult, enlen) != 0) { + log_verbose("Failed : non-tailored supplementary characters should have the same value\n"); + } + + free(rules); + ucol_close(enCollation); + ucol_close(myCollation); + enCollation = NULL; + myCollation = NULL; +} + +/* + *### TODO: Add more invalid rules to test all different scenarios. + * + */ +static void +TestInvalidRules(){ +#define MAX_ERROR_STATES 2 + + static const char* rulesArr[MAX_ERROR_STATES] = { + "& C < ch, cH, Ch[this should fail]<d", + "& C < ch, cH, & Ch[variable top]" + }; + static const char* preContextArr[MAX_ERROR_STATES] = { + "his should fail", + "& C < ch, cH, ", + + }; + static const char* postContextArr[MAX_ERROR_STATES] = { + "<d", + " Ch[variable t" + }; + int i; + + for(i = 0;i<MAX_ERROR_STATES;i++){ + UChar rules[1000] = { '\0' }; + UChar preContextExp[1000] = { '\0' }; + UChar postContextExp[1000] = { '\0' }; + UParseError parseError; + UErrorCode status = U_ZERO_ERROR; + UCollator* coll=0; + u_charsToUChars(rulesArr[i],rules,uprv_strlen(rulesArr[i])+1); + u_charsToUChars(preContextArr[i],preContextExp,uprv_strlen(preContextArr[i])+1); + u_charsToUChars(postContextArr[i],postContextExp,uprv_strlen(postContextArr[i])+1); + /* clean up stuff in parseError */ + u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN); + u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN); + /* open the rules and test */ + coll = ucol_openRules(rules,u_strlen(rules),UCOL_OFF,UCOL_DEFAULT_STRENGTH,&parseError,&status); + if(u_strcmp(parseError.preContext,preContextExp)!=0){ + log_err("preContext in UParseError for ucol_openRules does not match\n"); + } + if(u_strcmp(parseError.postContext,postContextExp)!=0){ + log_err("postContext in UParseError for ucol_openRules does not match\n"); + } + } +} + +static void +TestJitterbug1098(){ + UChar rule[1000]; + UCollator* c1 = NULL; + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + char preContext[200]={0}; + char postContext[200]={0}; + int i=0; + const char* rules[] = { + "&''<\\\\", + "&\\'<\\\\", + "&\\\"<'\\'", + "&'\"'<\\'", + '\0' + + }; + const UCollationResult results1098[] = { + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + }; + const UChar input[][2]= { + {0x0027,0x005c}, + {0x0027,0x005c}, + {0x0022,0x005c}, + {0x0022,0x0027}, + }; + UChar X[2] ={0}; + UChar Y[2] ={0}; + u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN); + u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN); + for(;rules[i]!=0;i++){ + u_uastrcpy(rule, rules[i]); + c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, &parseError, &status); + if(U_FAILURE(status)){ + log_err("Could not parse the rules syntax. Error: %s ", u_errorName(status)); + + if (status == U_PARSE_ERROR) { + u_UCharsToChars(parseError.preContext,preContext,20); + u_UCharsToChars(parseError.postContext,postContext,20); + log_verbose("\n\tPre-Context: %s \n\tPost-Context:%s \n",preContext,postContext); + } + + return; + } + X[0] = input[i][0]; + Y[0] = input[i][1]; + doTest(c1,X,Y,results1098[i]); + ucol_close(c1); + } +} + +/* These tests do cleanup and reinitialize ICU in the course of their operation. + * The ICU data directory must be preserved across these operations. + * Here is a helper function to assist with that. + */ +static char *safeGetICUDataDirectory() { + const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */ + char *retStr = NULL; + if (dataDir != NULL) { + retStr = (char *)malloc(strlen(dataDir)+1); + strcpy(retStr, dataDir); + } + return retStr; +} + + +static void +TestFCDCrash(void) { + static const char *test[] = { + "Gr\\u00F6\\u00DFe", + "Grossist" + }; + + char *icuDataDir = safeGetICUDataDirectory(); + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("es", &status); + if(U_FAILURE(status)) { + log_err("Couldn't open collator\n"); + return; + } + ucol_close(coll); + coll = NULL; + u_cleanup(); + u_setDataDirectory(icuDataDir); + coll = ucol_open("de_DE", &status); + if(U_FAILURE(status)) { + log_err("Couldn't open collator\n"); + return; + } + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + genericOrderingTest(coll, test, 2); + ucol_close(coll); + free(icuDataDir); + +} + +/*static UBool +find(UEnumeration* list, const char* str, UErrorCode* status){ + const char* value = NULL; + int32_t length=0; + if(U_FAILURE(*status)){ + return FALSE; + } + uenum_reset(list, status); + while( (value= uenum_next(list, &length, status))!=NULL){ + if(strcmp(value, str)==0){ + return TRUE; + } + } + return FALSE; +}*/ + +static void TestJ5298(void) +{ + UErrorCode status = U_ZERO_ERROR; + char input[256], output[256]; + UBool isAvailable; + int32_t i = 0; + UEnumeration* values = NULL; + const char *keywordValue = NULL; + log_verbose("Number of collator locales returned : %i \n", ucol_countAvailable()); + values = ucol_getKeywordValues("collation", &status); + for (i = 0; i < ucol_countAvailable(); i++) { + uenum_reset(values, &status); + while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) { + strcpy(input, ucol_getAvailable(i)); + if (strcmp(keywordValue, "standard") != 0) { + strcat(input, "@collation="); + strcat(input, keywordValue); + } + + ucol_getFunctionalEquivalent(output, 256, "collation", input, &isAvailable, &status); + if (strcmp(input, output) == 0) { /* Unique locale, print it out */ + log_verbose("%s, \n", output); + } + } + } + uenum_close(values); + log_verbose("\n"); +} +#endif /* #if !UCONFIG_NO_COLLATION */ + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h new file mode 100644 index 00000000000..ae07b1257ab --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h @@ -0,0 +1,54 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CALLCOLL.H +* +* Modification History: +* Name Description +* Madhu Katragadda Ported to C +********************************************************************************* +*/ +/** + * CollationDummyTest is a third level test class. This tests creation of + * a customized collator object. For example, number 1 to be sorted + * equlivalent to word 'one'. + */ +#ifndef _CALLCOLLTST +#define _CALLCOLLTST + +#include "unicode/utypes.h" +#include "unicode/ucoleitr.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define RULE_BUFFER_LEN 8192 + + + /* tests comparison of custom collation with different strengths */ +void doTest(UCollator*, const UChar* source, const UChar* target, UCollationResult result); +/* verify that iterating forward and backwards over the string yields same CEs */ +void backAndForth(UCollationElements *iter); +/* gets an array of CEs for a string in UCollationElements iterator. */ +int32_t* getOrders(UCollationElements *iter, int32_t *orderLength); + +void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result); +void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size); +void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size); +void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result); +void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize); +void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result); +void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result); +void genericRulesStarter(const char *rules, const char * const s[], uint32_t size); +void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result); +UBool hasCollationElements(const char *locName); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h b/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h new file mode 100644 index 00000000000..4d3cb3983d2 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h @@ -0,0 +1,109 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2003, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ + +#ifndef COLLATION_TEST_DATA +#define COLLATION_TEST_DATA + +#define COUNT_TEST_CASES 13 + +const UChar testSourceCases[][16] = { + {0x61, 0x62, 0x27, 0x63, 0}, + {0x63, 0x6f, 0x2d, 0x6f, 0x70, 0}, + {0x61, 0x62, 0}, + {0x61, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x61, 0x64, 0}, + {0x61, 0x6c, 0x6c, 0}, + {0x66, 0x6f, 0x75, 0x72, 0}, + {0x66, 0x69, 0x76, 0x65, 0}, + {0x31, 0}, + {0x31, 0}, + {0x31, 0}, /* 10 */ + {0x32, 0}, + {0x32, 0}, + {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0}, + {0x61, 0x3c, 0x62, 0}, + {0x61, 0x3c, 0x62, 0}, + {0x61, 0x63, 0x63, 0}, + {0x61, 0x63, 0x48, 0x63, 0}, /* simple test */ + {0x70, 0x00EA, 0x63, 0x68, 0x65, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x62, 0x63, 0}, /* 20 */ + {0x61, 0x62, 0x63, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x00E6, 0x63, 0}, + {0x61, 0x63, 0x48, 0x63, 0}, /* primary test */ + {0x62, 0x6c, 0x61, 0x63, 0x6b, 0}, + {0x66, 0x6f, 0x75, 0x72, 0}, + {0x66, 0x69, 0x76, 0x65, 0}, + {0x31, 0}, + {0x61, 0x62, 0x63, 0}, /* 30 */ + {0x61, 0x62, 0x63, 0}, + {0x61, 0x62, 0x63, 0x48, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x63, 0x48, 0x63, 0}, /* 34 */ + {0x61, 0x63, 0x65, 0x30}, + {0x31, 0x30}, + {0x70, 0x00EA,0x30} /* 37 */ +}; + +const UChar testTargetCases[][16] = { + {0x61, 0x62, 0x63, 0x27, 0}, + {0x43, 0x4f, 0x4f, 0x50, 0}, + {0x61, 0x62, 0x63, 0}, + {0x26, 0}, + {0x26, 0}, + {0x34, 0}, + {0x35, 0}, + {0x6f, 0x6e, 0x65, 0}, + {0x6e, 0x6e, 0x65, 0}, + {0x70, 0x6e, 0x65, 0}, /* 10 */ + {0x74, 0x77, 0x6f, 0}, + {0x75, 0x77, 0x6f, 0}, + {0x68, 0x65, 0x6c, 0x6c, 0x4f, 0}, + {0x61, 0x3c, 0x3d, 0x62, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x43, 0x48, 0x63, 0}, + {0x61, 0x43, 0x48, 0x63, 0}, /* simple test */ + {0x70, (UChar)0x00E9, 0x63, 0x68, 0x00E9, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x42, 0x43, 0}, /* 20 */ + {0x61, 0x62, 0x63, 0x68, 0}, + {0x61, 0x62, 0x64, 0}, + {(UChar)0x00E4, 0x62, 0x63, 0}, + {0x61, (UChar)0x00C6, 0x63, 0}, + {0x61, 0x43, 0x48, 0x63, 0}, /* primary test */ + {0x62, 0x6c, 0x61, 0x63, 0x6b, 0x2d, 0x62, 0x69, 0x72, 0x64, 0}, + {0x34, 0}, + {0x35, 0}, + {0x6f, 0x6e, 0x65, 0}, + {0x61, 0x62, 0x63, 0}, + {0x61, 0x42, 0x63, 0}, /* 30 */ + {0x61, 0x62, 0x63, 0x68, 0}, + {0x61, 0x62, 0x64, 0}, + {0x61, 0x43, 0x48, 0x63, 0}, /* 34 */ + {0x61, 0x63, 0x65, 0x30}, + {0x31, 0x30}, + {0x70, (UChar)0x00EB,0x30} /* 37 */ +}; + +const UChar testCases[][4] = +{ + {0x61, 0}, + {0x41, 0}, + {0x00e4, 0}, + {0x00c4, 0}, + {0x61, 0x65, 0}, + {0x61, 0x45, 0}, + {0x41, 0x65, 0}, + {0x41, 0x45, 0}, + {(UChar)0x00e6, 0}, + {(UChar)0x00c6, 0}, + {0x62, 0}, + {0x63, 0}, + {0x7a, 0} +}; + +#endif /* #ifndef COLLATION_TEST_DATA */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c new file mode 100644 index 00000000000..8e5f192dbe1 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c @@ -0,0 +1,78 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1996-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CALLTEST.C +* +* Modification History: +* Creation: Madhu Katragadda +********************************************************************************* +*/ +/* THE FILE WHERE ALL C API TESTS ARE ADDED TO THE ROOT */ + + +#include "cintltst.h" + +void addUtility(TestNode** root); +void addBreakIter(TestNode** root); +void addStandardNamesTest(TestNode **root); +void addFormatTest(TestNode** root); +void addConvert(TestNode** root); +void addCollTest(TestNode** root); +void addComplexTest(TestNode** root); +void addUDataTest(TestNode** root); +void addUTF16Test(TestNode** root); +void addUTF8Test(TestNode** root); +void addUTransTest(TestNode** root); +void addPUtilTest(TestNode** root); +void addUCharTransformTest(TestNode** root); +void addUSetTest(TestNode** root); +void addUStringPrepTest(TestNode** root); +void addIDNATest(TestNode** root); +void addHeapMutexTest(TestNode **root); +void addUTraceTest(TestNode** root); +void addURegexTest(TestNode** root); +void addUTextTest(TestNode** root); +void addUCsdetTest(TestNode** root); + + +void addAllTests(TestNode** root) +{ + addUDataTest(root); + addHeapMutexTest(root); + addPUtilTest(root); + addUTF16Test(root); + addUTF8Test(root); + addUtility(root); + addUTraceTest(root); + addUTextTest(root); + addConvert(root); + addUCharTransformTest(root); + addStandardNamesTest(root); + addUCsdetTest(root); + addComplexTest(root); + addUSetTest(root); +#if !UCONFIG_NO_IDNA + addUStringPrepTest(root); + addIDNATest(root); +#endif +#if !UCONFIG_NO_REGULAR_EXPRESSIONS + addURegexTest(root); +#endif +#if !UCONFIG_NO_BREAK_ITERATION + addBreakIter(root); +#endif +#if !UCONFIG_NO_FORMATTING + addFormatTest(root); +#endif +#if !UCONFIG_NO_COLLATION + addCollTest(root); +#endif +#if !UCONFIG_NO_TRANSLITERATION + addUTransTest(root); +#endif +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c new file mode 100644 index 00000000000..db1de56f54a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c @@ -0,0 +1,2148 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CAPITEST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +********************************************************************************* +*//* C API TEST For COLLATOR */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "unicode/uloc.h" +#include "unicode/ustring.h" +#include "unicode/ures.h" +#include "unicode/ucoleitr.h" +#include "cintltst.h" +#include "capitst.h" +#include "ccolltst.h" +#include "putilimp.h" + +static void TestAttribute(void); +static void TestDefault(void); + int TestBufferSize(); /* defined in "colutil.c" */ + + + + +/* next two function is modified from "i18n/ucol.cpp" to avoid include "ucol_imp.h" */ +static void uprv_appendByteToHexString(char *dst, uint8_t val) { + uint32_t len = (uint32_t)strlen(dst); + sprintf(dst+len, "%02X", val); +} + +static char* U_EXPORT2 ucol_sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) { + int32_t strength = UCOL_PRIMARY; + uint32_t res_size = 0; + UBool doneCase = FALSE; + + char *current = buffer; + const uint8_t *currentSk = sortkey; + + UErrorCode error_code = U_ZERO_ERROR; + + strcpy(current, "["); + + while(strength <= UCOL_QUATERNARY && strength <= ucol_getAttribute(coll,UCOL_STRENGTH, &error_code)) { + if(U_FAILURE(error_code)) { + log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code)); + } + if(strength > UCOL_PRIMARY) { + strcat(current, " . "); + } + while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */ + uprv_appendByteToHexString(current, *currentSk++); + strcat(current, " "); + } + if(ucol_getAttribute(coll,UCOL_CASE_LEVEL, &error_code) == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) { + doneCase = TRUE; + } else if(ucol_getAttribute(coll,UCOL_CASE_LEVEL, &error_code) == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) { + strength ++; + } + if(U_FAILURE(error_code)) { + log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code)); + } + uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */ + if(strength == UCOL_QUATERNARY && ucol_getAttribute(coll,UCOL_ALTERNATE_HANDLING, &error_code) == UCOL_NON_IGNORABLE) { + break; + } + } + + if(ucol_getAttribute(coll,UCOL_STRENGTH, &error_code) == UCOL_IDENTICAL) { + strcat(current, " . "); + while(*currentSk != 0) { + uprv_appendByteToHexString(current, *currentSk++); + strcat(current, " "); + } + + uprv_appendByteToHexString(current, *currentSk++); + } + if(U_FAILURE(error_code)) { + log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code)); + } + strcat(current, "]"); + + if(res_size > *len) { + return NULL; + } + + return buffer; +} +/* end of avoid include "ucol_imp.h" */ + + +void addCollAPITest(TestNode** root) +{ + /* WEIVTODO: return tests here */ + addTest(root, &TestProperty, "tscoll/capitst/TestProperty"); + addTest(root, &TestRuleBasedColl, "tscoll/capitst/TestRuleBasedColl"); + addTest(root, &TestCompare, "tscoll/capitst/TestCompare"); + addTest(root, &TestSortKey, "tscoll/capitst/TestSortKey"); + addTest(root, &TestHashCode, "tscoll/capitst/TestHashCode"); + addTest(root, &TestElemIter, "tscoll/capitst/TestElemIter"); + addTest(root, &TestGetAll, "tscoll/capitst/TestGetAll"); + /*addTest(root, &TestGetDefaultRules, "tscoll/capitst/TestGetDefaultRules");*/ + addTest(root, &TestDecomposition, "tscoll/capitst/TestDecomposition"); + addTest(root, &TestSafeClone, "tscoll/capitst/TestSafeClone"); + addTest(root, &TestCloneBinary, "tscoll/capitst/TestCloneBinary"); + addTest(root, &TestGetSetAttr, "tscoll/capitst/TestGetSetAttr"); + addTest(root, &TestBounds, "tscoll/capitst/TestBounds"); + addTest(root, &TestGetLocale, "tscoll/capitst/TestGetLocale"); + addTest(root, &TestSortKeyBufferOverrun, "tscoll/capitst/TestSortKeyBufferOverrun"); + addTest(root, &TestAttribute, "tscoll/capitst/TestAttribute"); + addTest(root, &TestGetTailoredSet, "tscoll/capitst/TestGetTailoredSet"); + addTest(root, &TestMergeSortKeys, "tscoll/capitst/TestMergeSortKeys"); + addTest(root, &TestShortString, "tscoll/capitst/TestShortString"); + addTest(root, &TestGetContractionsAndUnsafes, "tscoll/capitst/TestGetContractionsAndUnsafes"); + addTest(root, &TestOpenBinary, "tscoll/capitst/TestOpenBinary"); + addTest(root, &TestDefault, "tscoll/capitst/TestDefault"); +} + +void TestGetSetAttr(void) { + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open(NULL, &status); + struct attrTest { + UColAttribute att; + UColAttributeValue val[5]; + uint32_t valueSize; + UColAttributeValue nonValue; + } attrs[] = { + {UCOL_FRENCH_COLLATION, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED}, + {UCOL_ALTERNATE_HANDLING, {UCOL_NON_IGNORABLE, UCOL_SHIFTED}, 2, UCOL_OFF},/* attribute for handling variable elements*/ + {UCOL_CASE_FIRST, {UCOL_OFF, UCOL_LOWER_FIRST, UCOL_UPPER_FIRST}, 3, UCOL_SHIFTED},/* who goes first, lower case or uppercase */ + {UCOL_CASE_LEVEL, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* do we have an extra case level */ + {UCOL_NORMALIZATION_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* attribute for normalization */ + {UCOL_DECOMPOSITION_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED}, + {UCOL_STRENGTH, {UCOL_PRIMARY, UCOL_SECONDARY, UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL}, 5, UCOL_SHIFTED},/* attribute for strength */ + {UCOL_HIRAGANA_QUATERNARY_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* when turned on, this attribute */ + }; + UColAttribute currAttr; + UColAttributeValue value; + uint32_t i = 0, j = 0; + + for(i = 0; i<sizeof(attrs)/sizeof(attrs[0]); i++) { + currAttr = attrs[i].att; + ucol_setAttribute(coll, currAttr, UCOL_DEFAULT, &status); + if(U_FAILURE(status)) { + log_err("ucol_setAttribute with the default value returned error: %s\n", u_errorName(status)); + break; + } + value = ucol_getAttribute(coll, currAttr, &status); + if(U_FAILURE(status)) { + log_err("ucol_getAttribute returned error: %s\n", u_errorName(status)); + break; + } + for(j = 0; j<attrs[i].valueSize; j++) { + ucol_setAttribute(coll, currAttr, attrs[i].val[j], &status); + if(U_FAILURE(status)) { + log_err("ucol_setAttribute with the value %i returned error: %s\n", attrs[i].val[j], u_errorName(status)); + break; + } + } + status = U_ZERO_ERROR; + ucol_setAttribute(coll, currAttr, attrs[i].nonValue, &status); + if(U_SUCCESS(status)) { + log_err("ucol_setAttribute with the bad value didn't return an error\n"); + break; + } + status = U_ZERO_ERROR; + + ucol_setAttribute(coll, currAttr, value, &status); + if(U_FAILURE(status)) { + log_err("ucol_setAttribute with the default valuereturned error: %s\n", u_errorName(status)); + break; + } + + } + status = U_ZERO_ERROR; + value = ucol_getAttribute(coll, UCOL_ATTRIBUTE_COUNT, &status); + if(U_SUCCESS(status)) { + log_err("ucol_getAttribute for UCOL_ATTRIBUTE_COUNT didn't return an error\n"); + } + status = U_ZERO_ERROR; + ucol_setAttribute(coll, UCOL_ATTRIBUTE_COUNT, UCOL_DEFAULT, &status); + if(U_SUCCESS(status)) { + log_err("ucol_setAttribute for UCOL_ATTRIBUTE_COUNT didn't return an error\n"); + } + status = U_ZERO_ERROR; + ucol_close(coll); +} + + +static void doAssert(int condition, const char *message) +{ + if (condition==0) { + log_err("ERROR : %s\n", message); + } +} + +#if 0 +/* We don't have default rules, at least not in the previous sense */ +void TestGetDefaultRules(){ + uint32_t size=0; + UErrorCode status=U_ZERO_ERROR; + UCollator *coll=NULL; + int32_t len1 = 0, len2=0; + uint8_t *binColData = NULL; + + UResourceBundle *res = NULL; + UResourceBundle *binColl = NULL; + uint8_t *binResult = NULL; + + + const UChar * defaultRulesArray=ucol_getDefaultRulesArray(&size); + log_verbose("Test the function ucol_getDefaultRulesArray()\n"); + + coll = ucol_openRules(defaultRulesArray, size, UCOL_ON, UCOL_PRIMARY, &status); + if(U_SUCCESS(status) && coll !=NULL) { + binColData = (uint8_t*)ucol_cloneRuleData(coll, &len1, &status); + + } + + + status=U_ZERO_ERROR; + res=ures_open(NULL, "root", &status); + if(U_FAILURE(status)){ + log_err("ERROR: Failed to get resource for \"root Locale\" with %s", myErrorName(status)); + return; + } + binColl=ures_getByKey(res, "%%Collation", binColl, &status); + if(U_SUCCESS(status)){ + binResult=(uint8_t*)ures_getBinary(binColl, &len2, &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_getBinary() failed\n"); + } + }else{ + log_err("ERROR: ures_getByKey(locale(default), %%Collation) failed"); + } + + + if(len1 != len2){ + log_err("Error: ucol_getDefaultRulesArray() failed to return the correct length.\n"); + } + if(memcmp(binColData, binResult, len1) != 0){ + log_err("Error: ucol_getDefaultRulesArray() failed\n"); + } + + free(binColData); + ures_close(binColl); + ures_close(res); + ucol_close(coll); + +} +#endif + +/* Collator Properties + ucol_open, ucol_strcoll, getStrength/setStrength + getDecomposition/setDecomposition, getDisplayName*/ +void TestProperty() +{ + UCollator *col, *ruled; + UChar *disName; + int32_t len = 0, i = 0; + UChar *source, *target; + int32_t tempLength; + UErrorCode status = U_ZERO_ERROR; + /* + All the collations have the same version in an ICU + version. + ICU 2.0 currVersionArray = {0x18, 0xC0, 0x02, 0x02}; + ICU 2.1 currVersionArray = {0x19, 0x00, 0x03, 0x03}; + ICU 2.2 currVersionArray = {0x21, 0x40, 0x04, 0x04}; + ICU 2.4 currVersionArray = {0x21, 0x40, 0x04, 0x04}; + ICU 2.6 currVersionArray = {0x21, 0x40, 0x03, 0x03}; + ICU 2.8 currVersionArray = {0x29, 0x80, 0x00, 0x04}; + ICU 3.4 currVersionArray = {0x31, 0xC0, 0x00, 0x04}; + */ + UVersionInfo currVersionArray = {0x31, 0xC0, 0x00, 0x05}; + /* ICU 3.4 had UCA 4.1 */ + /*UVersionInfo currUCAVersionArray = {4, 1, 0, 0};*/ + UVersionInfo currUCAVersionArray = {5, 0, 0, 0}; + UVersionInfo versionArray = {0, 0, 0, 0}; + UVersionInfo versionUCAArray = {0, 0, 0, 0}; + + log_verbose("The property tests begin : \n"); + log_verbose("Test ucol_strcoll : \n"); + col = ucol_open("en_US", &status); + if (U_FAILURE(status)) { + log_err("Default Collator creation failed.: %s\n", myErrorName(status)); + return; + } + + ucol_getVersion(col, versionArray); + for (i=0; i<4; ++i) { + if (versionArray[i] != currVersionArray[i]) { + log_err("Testing ucol_getVersion() - unexpected result: %hu.%hu.%hu.%hu\n", + versionArray[0], versionArray[1], versionArray[2], versionArray[3]); + break; + } + } + + ucol_getUCAVersion(col, versionUCAArray); + for (i=0; i<4; ++i) { + if (versionUCAArray[i] != currUCAVersionArray[i]) { + log_err("Testing ucol_getUCAVersion() - unexpected result: %hu.%hu.%hu.%hu\n", + versionUCAArray[0], versionUCAArray[1], versionUCAArray[2], versionUCAArray[3]); + break; + } + } + + source=(UChar*)malloc(sizeof(UChar) * 12); + target=(UChar*)malloc(sizeof(UChar) * 12); + + + u_uastrcpy(source, "ab"); + u_uastrcpy(target, "abc"); + + doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS), "ab < abc comparison failed"); + + u_uastrcpy(source, "ab"); + u_uastrcpy(target, "AB"); + + doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS), "ab < AB comparison failed"); +/* u_uastrcpy(source, "black-bird"); + u_uastrcpy(target, "blackbird"); */ + u_uastrcpy(target, "black-bird"); + u_uastrcpy(source, "blackbird"); + + doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_GREATER), + "black-bird > blackbird comparison failed"); + u_uastrcpy(source, "black bird"); + u_uastrcpy(target, "black-bird"); + doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS), + "black bird < black-bird comparison failed"); + u_uastrcpy(source, "Hello"); + u_uastrcpy(target, "hello"); + + doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_GREATER), + "Hello > hello comparison failed"); + free(source); + free(target); + log_verbose("Test ucol_strcoll ends.\n"); + + log_verbose("testing ucol_getStrength() method ...\n"); + doAssert( (ucol_getStrength(col) == UCOL_TERTIARY), "collation object has the wrong strength"); + doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference"); + + log_verbose("testing ucol_setStrength() method ...\n"); + ucol_setStrength(col, UCOL_SECONDARY); + doAssert( (ucol_getStrength(col) != UCOL_TERTIARY), "collation object's strength is secondary difference"); + doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference"); + doAssert( (ucol_getStrength(col) == UCOL_SECONDARY), "collation object has the wrong strength"); + + + log_verbose("Get display name for the default collation in German : \n"); + + len=ucol_getDisplayName("en_US", "de_DE", NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + disName=(UChar*)malloc(sizeof(UChar) * (len+1)); + ucol_getDisplayName("en_US", "de_DE", disName, len+1, &status); + log_verbose("the display name for default collation in german: %s\n", austrdup(disName) ); + free(disName); + } + if(U_FAILURE(status)){ + log_err("ERROR: in getDisplayName: %s\n", myErrorName(status)); + return; + } + log_verbose("Default collation getDisplayName ended.\n"); + + ruled = ucol_open("da_DK", &status); + log_verbose("ucol_getRules() testing ...\n"); + ucol_getRules(ruled, &tempLength); + doAssert( tempLength != 0, "getRules() result incorrect" ); + log_verbose("getRules tests end.\n"); + { + UChar *buffer = (UChar *)malloc(200000*sizeof(UChar)); + int32_t bufLen = 200000; + buffer[0] = '\0'; + log_verbose("ucol_getRulesEx() testing ...\n"); + tempLength = ucol_getRulesEx(col,UCOL_TAILORING_ONLY,buffer,bufLen ); + doAssert( tempLength == 0x0a, "getRulesEx() result incorrect" ); + log_verbose("getRules tests end.\n"); + + log_verbose("ucol_getRulesEx() testing ...\n"); + tempLength=ucol_getRulesEx(col,UCOL_FULL_RULES,buffer,bufLen ); + doAssert( tempLength != 0, "getRulesEx() result incorrect" ); + log_verbose("getRules tests end.\n"); + free(buffer); + } + ucol_close(ruled); + ucol_close(col); + + log_verbose("open an collator for french locale"); + col = ucol_open("fr_FR", &status); + if (U_FAILURE(status)) { + log_err("ERROR: Creating French collation failed.: %s\n", myErrorName(status)); + return; + } + ucol_setStrength(col, UCOL_PRIMARY); + log_verbose("testing ucol_getStrength() method again ...\n"); + doAssert( (ucol_getStrength(col) != UCOL_TERTIARY), "collation object has the wrong strength"); + doAssert( (ucol_getStrength(col) == UCOL_PRIMARY), "collation object's strength is not primary difference"); + + log_verbose("testing French ucol_setStrength() method ...\n"); + ucol_setStrength(col, UCOL_TERTIARY); + doAssert( (ucol_getStrength(col) == UCOL_TERTIARY), "collation object's strength is not tertiary difference"); + doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference"); + doAssert( (ucol_getStrength(col) != UCOL_SECONDARY), "collation object's strength is secondary difference"); + ucol_close(col); + + log_verbose("Get display name for the french collation in english : \n"); + len=ucol_getDisplayName("fr_FR", "en_US", NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + disName=(UChar*)malloc(sizeof(UChar) * (len+1)); + ucol_getDisplayName("fr_FR", "en_US", disName, len+1, &status); + log_verbose("the display name for french collation in english: %s\n", austrdup(disName) ); + free(disName); + } + if(U_FAILURE(status)){ + log_err("ERROR: in getDisplayName: %s\n", myErrorName(status)); + return; + } + log_verbose("Default collation getDisplayName ended.\n"); + +} + +/* Test RuleBasedCollator and getRules*/ +void TestRuleBasedColl() +{ + UCollator *col1, *col2, *col3, *col4; + UCollationElements *iter1, *iter2; + UChar ruleset1[60]; + UChar ruleset2[50]; + UChar teststr[10]; + UChar teststr2[10]; + const UChar *rule1, *rule2, *rule3, *rule4; + int32_t tempLength; + UErrorCode status = U_ZERO_ERROR; + u_uastrcpy(ruleset1, "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E"); + u_uastrcpy(ruleset2, "&9 < a, A < b, B < c, C < d, D, e, E"); + + + col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL,&status); + if (U_FAILURE(status)) { + log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status)); + return; + } + else + log_verbose("PASS: RuleBased Collator creation passed\n"); + + status = U_ZERO_ERROR; + col2 = ucol_openRules(ruleset2, u_strlen(ruleset2), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status); + if (U_FAILURE(status)) { + log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status)); + return; + } + else + log_verbose("PASS: RuleBased Collator creation passed\n"); + + + status = U_ZERO_ERROR; + col3= ucol_open(NULL, &status); + if (U_FAILURE(status)) { + log_err("Default Collator creation failed.: %s\n", myErrorName(status)); + return; + } + else + log_verbose("PASS: Default Collator creation passed\n"); + + rule1 = ucol_getRules(col1, &tempLength); + rule2 = ucol_getRules(col2, &tempLength); + rule3 = ucol_getRules(col3, &tempLength); + + doAssert((u_strcmp(rule1, rule2) != 0), "Default collator getRules failed"); + doAssert((u_strcmp(rule2, rule3) != 0), "Default collator getRules failed"); + doAssert((u_strcmp(rule1, rule3) != 0), "Default collator getRules failed"); + + col4=ucol_openRules(rule2, u_strlen(rule2), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status); + if (U_FAILURE(status)) { + log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status)); + return; + } + rule4= ucol_getRules(col4, &tempLength); + doAssert((u_strcmp(rule2, rule4) == 0), "Default collator getRules failed"); + + ucol_close(col1); + ucol_close(col2); + ucol_close(col3); + ucol_close(col4); + + /* tests that modifier ! is always ignored */ + u_uastrcpy(ruleset1, "!&a<b"); + teststr[0] = 0x0e40; + teststr[1] = 0x0e01; + teststr[2] = 0x0e2d; + col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status); + if (U_FAILURE(status)) { + log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status)); + return; + } + col2 = ucol_open("en_US", &status); + if (U_FAILURE(status)) { + log_err("en_US Collator creation failed.: %s\n", myErrorName(status)); + return; + } + iter1 = ucol_openElements(col1, teststr, 3, &status); + iter2 = ucol_openElements(col2, teststr, 3, &status); + if(U_FAILURE(status)) { + log_err("ERROR: CollationElement iterator creation failed.: %s\n", myErrorName(status)); + return; + } + while (TRUE) { + /* testing with en since thai has its own tailoring */ + uint32_t ce = ucol_next(iter1, &status); + uint32_t ce2 = ucol_next(iter2, &status); + if(U_FAILURE(status)) { + log_err("ERROR: CollationElement iterator creation failed.: %s\n", myErrorName(status)); + return; + } + if (ce2 != ce) { + log_err("! modifier test failed"); + } + if (ce == UCOL_NULLORDER) { + break; + } + } + ucol_closeElements(iter1); + ucol_closeElements(iter2); + ucol_close(col1); + ucol_close(col2); + /* test that we can start a rule without a & or < */ + u_uastrcpy(ruleset1, "< z < a"); + col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status); + if (U_FAILURE(status)) { + log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status)); + return; + } + u_uastrcpy(teststr, "z"); + u_uastrcpy(teststr2, "a"); + if (ucol_greaterOrEqual(col1, teststr, 1, teststr2, 1)) { + log_err("Rule \"z < a\" fails"); + } + ucol_close(col1); +} + +void TestCompare() +{ + UErrorCode status = U_ZERO_ERROR; + UCollator *col; + UChar* test1; + UChar* test2; + + log_verbose("The compare tests begin : \n"); + status=U_ZERO_ERROR; + col = ucol_open("en_US", &status); + if(U_FAILURE(status)) { + log_err("ucal_open() collation creation failed.: %s\n", myErrorName(status)); + return; + } + test1=(UChar*)malloc(sizeof(UChar) * 6); + test2=(UChar*)malloc(sizeof(UChar) * 6); + u_uastrcpy(test1, "Abcda"); + u_uastrcpy(test2, "abcda"); + + log_verbose("Use tertiary comparison level testing ....\n"); + + doAssert( (!ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" != \"abcda\" "); + doAssert( (ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" >>> \"abcda\" "); + doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" >>> \"abcda\""); + + ucol_setStrength(col, UCOL_SECONDARY); + log_verbose("Use secondary comparison level testing ....\n"); + + doAssert( (ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2) )), "Result should be \"Abcda\" == \"abcda\""); + doAssert( (!ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\""); + doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2) )), "Result should be \"Abcda\" == \"abcda\""); + + ucol_setStrength(col, UCOL_PRIMARY); + log_verbose("Use primary comparison level testing ....\n"); + + doAssert( (ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\""); + doAssert( (!ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\""); + doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\""); + + + log_verbose("The compare tests end.\n"); + ucol_close(col); + free(test1); + free(test2); + +} +/* +--------------------------------------------- + tests decomposition setting +*/ +void TestDecomposition() { + UErrorCode status = U_ZERO_ERROR; + UCollator *en_US, *el_GR, *vi_VN; + en_US = ucol_open("en_US", &status); + el_GR = ucol_open("el_GR", &status); + vi_VN = ucol_open("vi_VN", &status); + + if (U_FAILURE(status)) { + log_err("ERROR: collation creation failed.: %s\n", myErrorName(status)); + return; + } + + if (ucol_getAttribute(vi_VN, UCOL_NORMALIZATION_MODE, &status) != UCOL_ON || + U_FAILURE(status)) + { + log_err("ERROR: vi_VN collation did not have cannonical decomposition for normalization!\n"); + } + + status = U_ZERO_ERROR; + if (ucol_getAttribute(el_GR, UCOL_NORMALIZATION_MODE, &status) != UCOL_ON || + U_FAILURE(status)) + { + log_err("ERROR: el_GR collation did not have cannonical decomposition for normalization!\n"); + } + + status = U_ZERO_ERROR; + if (ucol_getAttribute(en_US, UCOL_NORMALIZATION_MODE, &status) != UCOL_OFF || + U_FAILURE(status)) + { + log_err("ERROR: en_US collation had cannonical decomposition for normalization!\n"); + } + + ucol_close(en_US); + ucol_close(el_GR); + ucol_close(vi_VN); +} + +#define CLONETEST_COLLATOR_COUNT 4 + +void TestSafeClone() { + UChar* test1; + UChar* test2; + static const UChar umlautUStr[] = {0x00DC, 0}; + static const UChar oeStr[] = {0x0055, 0x0045, 0}; + UCollator * someCollators [CLONETEST_COLLATOR_COUNT]; + UCollator * someClonedCollators [CLONETEST_COLLATOR_COUNT]; + UCollator * col; + UErrorCode err = U_ZERO_ERROR; + int8_t testSize = 6; /* Leave this here to test buffer alingment in memory*/ + uint8_t buffer [CLONETEST_COLLATOR_COUNT] [U_COL_SAFECLONE_BUFFERSIZE]; + int32_t bufferSize = U_COL_SAFECLONE_BUFFERSIZE; + const char sampleRuleChars[] = "&Z < CH"; + UChar sampleRule[sizeof(sampleRuleChars)]; + int index; + + if (TestBufferSize()) { + log_err("U_COL_SAFECLONE_BUFFERSIZE should be larger than sizeof(UCollator)\n"); + return; + } + + test1=(UChar*)malloc(sizeof(UChar) * testSize); + test2=(UChar*)malloc(sizeof(UChar) * testSize); + u_uastrcpy(test1, "abCda"); + u_uastrcpy(test2, "abcda"); + u_uastrcpy(sampleRule, sampleRuleChars); + + /* one default collator & two complex ones */ + someCollators[0] = ucol_open("en_US", &err); + someCollators[1] = ucol_open("ko", &err); + someCollators[2] = ucol_open("ja_JP", &err); + someCollators[3] = ucol_openRules(sampleRule, -1, UCOL_ON, UCOL_TERTIARY, NULL, &err); + if(U_FAILURE(err)) { + log_data_err("Couldn't open one or more collators\n"); + return; + } + + /* Check the various error & informational states: */ + + /* Null status - just returns NULL */ + if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, 0)) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null status\n"); + } + /* error status - should return 0 & keep error the same */ + err = U_MEMORY_ALLOCATION_ERROR; + if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly with incoming error status\n"); + } + err = U_ZERO_ERROR; + + /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/ + if (0 != ucol_safeClone(someCollators[0], buffer[0], 0, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null bufferSize pointer\n"); + } + err = U_ZERO_ERROR; + + /* buffer size pointer is 0 - fill in pbufferSize with a size */ + bufferSize = 0; + if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0) + { + log_err("FAIL: Cloned Collator failed a sizing request ('preflighting')\n"); + } + /* Verify our define is large enough */ + if (U_COL_SAFECLONE_BUFFERSIZE < bufferSize) + { + log_err("FAIL: Pre-calculated buffer size is too small\n"); + } + /* Verify we can use this run-time calculated size */ + if (0 == (col = ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err)) || U_FAILURE(err)) + { + log_err("FAIL: Collator can't be cloned with run-time size\n"); + } + if (col) ucol_close(col); + /* size one byte too small - should allocate & let us know */ + --bufferSize; + if (0 == (col = ucol_safeClone(someCollators[0], 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned Collator failed to deal correctly with too-small buffer size\n"); + } + if (col) ucol_close(col); + err = U_ZERO_ERROR; + bufferSize = U_COL_SAFECLONE_BUFFERSIZE; + + + /* Null buffer pointer - return Collator & set error to U_SAFECLONE_ALLOCATED_ERROR */ + if (0 == (col = ucol_safeClone(someCollators[0], 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null buffer pointer\n"); + } + if (col) ucol_close(col); + err = U_ZERO_ERROR; + + /* Null Collator - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */ + if (0 != ucol_safeClone(0, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null Collator pointer\n"); + } + + err = U_ZERO_ERROR; + + /* Test that a cloned collator doesn't accidentally use UCA. */ + col=ucol_open("de@collation=phonebook", &err); + bufferSize = U_COL_SAFECLONE_BUFFERSIZE; + someClonedCollators[0] = ucol_safeClone(col, buffer[0], &bufferSize, &err); + doAssert( (ucol_greater(col, umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Original German phonebook collation sorts differently than expected"); + doAssert( (ucol_greater(someClonedCollators[0], umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Cloned German phonebook collation sorts differently than expected"); + if (!ucol_equals(someClonedCollators[0], col)) { + log_err("FAIL: Cloned German phonebook collator is not equal to original.\n"); + } + ucol_close(col); + ucol_close(someClonedCollators[0]); + + err = U_ZERO_ERROR; + + /* change orig & clone & make sure they are independent */ + + for (index = 0; index < CLONETEST_COLLATOR_COUNT; index++) + { + ucol_setStrength(someCollators[index], UCOL_IDENTICAL); + bufferSize = 1; + err = U_ZERO_ERROR; + ucol_close(ucol_safeClone(someCollators[index], buffer[index], &bufferSize, &err)); + if (err != U_SAFECLONE_ALLOCATED_WARNING) { + log_err("FAIL: collator number %d was not allocated.\n", index); + } + + bufferSize = U_COL_SAFECLONE_BUFFERSIZE; + err = U_ZERO_ERROR; + someClonedCollators[index] = ucol_safeClone(someCollators[index], buffer[index], &bufferSize, &err); + if (someClonedCollators[index] == NULL + || someClonedCollators[index] < (UCollator *)buffer[index] + || someClonedCollators[index] > (UCollator *)(buffer[index]+(U_COL_SAFECLONE_BUFFERSIZE-1))) + { + log_err("FAIL: Cloned collator didn't use provided buffer.\n"); + return; + } + if (!ucol_equals(someClonedCollators[index], someCollators[index])) { + log_err("FAIL: Cloned collator is not equal to original at index = %d.\n", index); + } + + /* Check the usability */ + ucol_setStrength(someCollators[index], UCOL_PRIMARY); + ucol_setAttribute(someCollators[index], UCOL_CASE_LEVEL, UCOL_OFF, &err); + + doAssert( (ucol_equal(someCollators[index], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abcda\" == \"abCda\""); + + /* Close the original to make sure that the clone is usable. */ + ucol_close(someCollators[index]); + + ucol_setStrength(someClonedCollators[index], UCOL_TERTIARY); + ucol_setAttribute(someClonedCollators[index], UCOL_CASE_LEVEL, UCOL_OFF, &err); + doAssert( (ucol_greater(someClonedCollators[index], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abCda\" >>> \"abcda\" "); + + ucol_close(someClonedCollators[index]); + } + free(test1); + free(test2); +} + +void TestCloneBinary(){ + UErrorCode err = U_ZERO_ERROR; + UCollator * col = ucol_open("en_US", &err); + UCollator * c; + int32_t size; + uint8_t * buffer; + + if (U_FAILURE(err)) { + log_data_err("Couldn't open collator. Error: %s\n", u_errorName(err)); + return; + } + + size = ucol_cloneBinary(col, NULL, 0, &err); + if(size==0 || err!=U_BUFFER_OVERFLOW_ERROR) { + log_err("ucol_cloneBinary - couldn't check size. Error: %s\n", u_errorName(err)); + return; + } + err = U_ZERO_ERROR; + + buffer = (uint8_t *) malloc(size); + ucol_cloneBinary(col, buffer, size, &err); + if(U_FAILURE(err)) { + log_err("ucol_cloneBinary - couldn't clone.. Error: %s\n", u_errorName(err)); + free(buffer); + return; + } + + /* how to check binary result ? */ + + c = ucol_openBinary(buffer, size, col, &err); + if(U_FAILURE(err)) { + log_err("ucol_openBinary failed. Error: %s\n", u_errorName(err)); + } else { + UChar t[] = {0x41, 0x42, 0x43, 0}; /* ABC */ + uint8_t *k1, *k2; + int l1, l2; + l1 = ucol_getSortKey(col, t, -1, NULL,0); + l2 = ucol_getSortKey(c, t, -1, NULL,0); + k1 = (uint8_t *) malloc(sizeof(uint8_t) * l1); + k2 = (uint8_t *) malloc(sizeof(uint8_t) * l2); + ucol_getSortKey(col, t, -1, k1, l1); + ucol_getSortKey(col, t, -1, k2, l2); + if (strcmp((char *)k1,(char *)k2) != 0){ + log_err("ucol_openBinary - new collator should equal to old one\n"); + }; + free(k1); + free(k2); + } + free(buffer); + ucol_close(c); + ucol_close(col); +} +/* +---------------------------------------------------------------------------- + ctor -- Tests the getSortKey +*/ +void TestSortKey() +{ + uint8_t *sortk1 = NULL, *sortk2 = NULL, *sortk3 = NULL, *sortkEmpty = NULL; + uint8_t sortk2_compat[] = { + /* 3.6 key, from UCA 5.0 */ + 0x29, 0x2b, 0x2d, 0x2f, 0x29, 0x01, + 0x09, 0x01, 0x09, 0x01, 0x28, 0x01, + 0x92, 0x93, 0x94, 0x95, 0x92, 0x00 + /* 3.4 key, from UCA 4.1 */ + /* 0x28, 0x2a, 0x2c, 0x2e, 0x28, 0x01, 0x09, 0x01, 0x09, 0x01, 0x27, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00 */ + /* 2.6.1 key */ + /* 0x26, 0x28, 0x2A, 0x2C, 0x26, 0x01, 0x09, 0x01, 0x09, 0x01, 0x25, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00 */ + /* 2.2 key */ + /*0x1D, 0x1F, 0x21, 0x23, 0x1D, 0x01, 0x09, 0x01, 0x09, 0x01, 0x1C, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/ + /* 2.0 key */ + /*0x19, 0x1B, 0x1D, 0x1F, 0x19, 0x01, 0x09, 0x01, 0x09, 0x01, 0x18, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/ + /* 1.8.1 key.*/ + /*0x19, 0x1B, 0x1D, 0x1F, 0x19, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/ + /*this is a 1.8 sortkey */ + /*0x17, 0x19, 0x1B, 0x1D, 0x17, 0x01, 0x08, 0x01, 0x08, 0x00*/ + /*this is a 1.7 sortkey */ + /*0x02, 0x54, 0x02, 0x55, 0x02, 0x56, 0x02, 0x57, 0x02, 0x54, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00*/ + /* this is a 1.6 sortkey */ + /*0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00*/ + }; + + int32_t sortklen, osortklen; + uint32_t toStringLen=0; + UCollator *col; + UChar *test1, *test2, *test3; + UErrorCode status = U_ZERO_ERROR; + char toStringBuffer[256], *resultP; + + + uint8_t s1[] = { 0x9f, 0x00 }; + uint8_t s2[] = { 0x61, 0x00 }; + int strcmpResult; + + strcmpResult = strcmp((const char *)s1, (const char *)s2); + log_verbose("strcmp(0x9f..., 0x61...) = %d\n", strcmpResult); + + if(strcmpResult <= 0) { + log_err("ERR: expected strcmp(\"9f 00\", \"61 00\") to be >=0 (GREATER).. got %d. Calling strcmp() for sortkeys may not work! \n", + strcmpResult); + } + + + log_verbose("testing SortKey begins...\n"); + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* col = ucol_open(NULL, &status); */ + col = ucol_open("en_US", &status); + if (U_FAILURE(status)) { + log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status)); + return; + } + + + if(ucol_getStrength(col) != UCOL_DEFAULT_STRENGTH) + { + log_err("ERROR: default collation did not have UCOL_DEFAULT_STRENGTH !\n"); + } + /* Need to use identical strength */ + ucol_setAttribute(col, UCOL_STRENGTH, UCOL_IDENTICAL, &status); + + test1=(UChar*)malloc(sizeof(UChar) * 6); + test2=(UChar*)malloc(sizeof(UChar) * 6); + test3=(UChar*)malloc(sizeof(UChar) * 6); + + memset(test1,0xFE, sizeof(UChar)*6); + memset(test2,0xFE, sizeof(UChar)*6); + memset(test3,0xFE, sizeof(UChar)*6); + + + u_uastrcpy(test1, "Abcda"); + u_uastrcpy(test2, "abcda"); + u_uastrcpy(test3, "abcda"); + + log_verbose("Use tertiary comparison level testing ....\n"); + + sortklen=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0); + sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + memset(sortk1,0xFE, sortklen); + ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortklen+1); + + sortklen=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0); + sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + memset(sortk2,0xFE, sortklen); + ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortklen+1); + + osortklen = sortklen; + sortklen=ucol_getSortKey(col, test2, u_strlen(test3), NULL, 0); + sortk3=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + memset(sortk3,0xFE, sortklen); + ucol_getSortKey(col, test2, u_strlen(test2), sortk3, sortklen+1); + + doAssert( (sortklen == osortklen), "Sortkey length should be the same (abcda, abcda)"); + + doAssert( (memcmp(sortk1, sortk2, sortklen) > 0), "Result should be \"Abcda\" > \"abcda\""); + doAssert( (memcmp(sortk2, sortk1, sortklen) < 0), "Result should be \"abcda\" < \"Abcda\""); + doAssert( (memcmp(sortk2, sortk3, sortklen) == 0), "Result should be \"abcda\" == \"abcda\""); + + doAssert( (memcmp(sortk2, sortk2_compat, sortklen) == 0), "Binary format for 'abcda' sortkey different!"); + + resultP = ucol_sortKeyToString(col, sortk2_compat, toStringBuffer, &toStringLen); + doAssert( (resultP != 0), "sortKeyToString failed!"); + +#if 1 /* verobse log of sortkeys */ + { + char junk2[1000]; + char junk3[1000]; + int i; + + strcpy(junk2, "abcda[2] "); + strcpy(junk3, " abcda[3] "); + + for(i=0;i<sortklen;i++) + { + sprintf(junk2+strlen(junk2), "%02X ",(int)( 0xFF & sortk2[i])); + sprintf(junk3+strlen(junk3), "%02X ",(int)( 0xFF & sortk3[i])); + } + + log_verbose("%s\n", junk2); + log_verbose("%s\n", junk3); + } +#endif + + free(sortk1); + free(sortk2); + free(sortk3); + + log_verbose("Use secondary comparision level testing ...\n"); + ucol_setStrength(col, UCOL_SECONDARY); + sortklen=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0); + sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortklen+1); + sortklen=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0); + sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortklen+1); + + doAssert( !(memcmp(sortk1, sortk2, sortklen) > 0), "Result should be \"Abcda\" == \"abcda\""); + doAssert( !(memcmp(sortk2, sortk1, sortklen) < 0), "Result should be \"abcda\" == \"Abcda\""); + doAssert( (memcmp(sortk1, sortk2, sortklen) == 0), "Result should be \"abcda\" == \"abcda\""); + + log_verbose("getting sortkey for an empty string\n"); + ucol_setAttribute(col, UCOL_STRENGTH, UCOL_TERTIARY, &status); + sortklen = ucol_getSortKey(col, test1, 0, NULL, 0); + sortkEmpty = (uint8_t*)malloc(sizeof(uint8_t) * sortklen+1); + sortklen = ucol_getSortKey(col, test1, 0, sortkEmpty, sortklen+1); + if(sortklen != 3 || sortkEmpty[0] != 1 || sortkEmpty[0] != 1 || sortkEmpty[2] != 0) { + log_err("Empty string generated wrong sortkey!\n"); + } + free(sortkEmpty); + + log_verbose("testing passing invalid string\n"); + sortklen = ucol_getSortKey(col, NULL, 0, NULL, 0); + if(sortklen != 0) { + log_err("Invalid string didn't return sortkey size of 0\n"); + } + + + log_verbose("testing sortkey ends...\n"); + ucol_close(col); + free(test1); + free(test2); + free(test3); + free(sortk1); + free(sortk2); + +} +void TestHashCode() +{ + uint8_t *sortk1, *sortk2, *sortk3; + int32_t sortk1len, sortk2len, sortk3len; + UCollator *col; + UChar *test1, *test2, *test3; + UErrorCode status = U_ZERO_ERROR; + log_verbose("testing getHashCode begins...\n"); + col = ucol_open("en_US", &status); + if (U_FAILURE(status)) { + log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status)); + return; + } + test1=(UChar*)malloc(sizeof(UChar) * 6); + test2=(UChar*)malloc(sizeof(UChar) * 6); + test3=(UChar*)malloc(sizeof(UChar) * 6); + u_uastrcpy(test1, "Abcda"); + u_uastrcpy(test2, "abcda"); + u_uastrcpy(test3, "abcda"); + + log_verbose("Use tertiary comparison level testing ....\n"); + sortk1len=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0); + sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortk1len+1)); + ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortk1len+1); + sortk2len=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0); + sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortk2len+1)); + ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortk2len+1); + sortk3len=ucol_getSortKey(col, test2, u_strlen(test3), NULL, 0); + sortk3=(uint8_t*)malloc(sizeof(uint8_t) * (sortk3len+1)); + ucol_getSortKey(col, test2, u_strlen(test2), sortk3, sortk3len+1); + + + log_verbose("ucol_hashCode() testing ...\n"); + + doAssert( ucol_keyHashCode(sortk1, sortk1len) != ucol_keyHashCode(sortk2, sortk2len), "Hash test1 result incorrect" ); + doAssert( !(ucol_keyHashCode(sortk1, sortk1len) == ucol_keyHashCode(sortk2, sortk2len)), "Hash test2 result incorrect" ); + doAssert( ucol_keyHashCode(sortk2, sortk2len) == ucol_keyHashCode(sortk3, sortk3len), "Hash result not equal" ); + + log_verbose("hashCode tests end.\n"); + ucol_close(col); + free(sortk1); + free(sortk2); + free(sortk3); + free(test1); + free(test2); + free(test3); + + +} +/* + *---------------------------------------------------------------------------- + * Tests the UCollatorElements API. + * + */ +void TestElemIter() +{ + int32_t offset; + int32_t order1, order2, order3; + UChar *testString1, *testString2; + UCollator *col; + UCollationElements *iterator1, *iterator2, *iterator3; + UErrorCode status = U_ZERO_ERROR; + log_verbose("testing UCollatorElements begins...\n"); + col = ucol_open("en_US", &status); + ucol_setAttribute(col, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); + if (U_FAILURE(status)) { + log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status)); + return; + } + + testString1=(UChar*)malloc(sizeof(UChar) * 150); + testString2=(UChar*)malloc(sizeof(UChar) * 150); + u_uastrcpy(testString1, "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?"); + u_uastrcpy(testString2, "Xf_ile What subset of all possible test cases has the lowest probability of detecting the least errors?"); + + log_verbose("Constructors and comparison testing....\n"); + + iterator1 = ucol_openElements(col, testString1, u_strlen(testString1), &status); + if(U_FAILURE(status)) { + log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status)); + ucol_close(col); + return; + } + else{ log_verbose("PASS: Default collationElement iterator1 creation passed\n");} + + iterator2 = ucol_openElements(col, testString1, u_strlen(testString1), &status); + if(U_FAILURE(status)) { + log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status)); + ucol_close(col); + return; + } + else{ log_verbose("PASS: Default collationElement iterator2 creation passed\n");} + + iterator3 = ucol_openElements(col, testString2, u_strlen(testString2), &status); + if(U_FAILURE(status)) { + log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status)); + ucol_close(col); + return; + } + else{ log_verbose("PASS: Default collationElement iterator3 creation passed\n");} + + offset=ucol_getOffset(iterator1); + ucol_setOffset(iterator1, 6, &status); + if (U_FAILURE(status)) { + log_err("Error in setOffset for UCollatorElements iterator.: %s\n", myErrorName(status)); + return; + } + if(ucol_getOffset(iterator1)==6) + log_verbose("setOffset and getOffset working fine\n"); + else{ + log_err("error in set and get Offset got %d instead of 6\n", ucol_getOffset(iterator1)); + } + + ucol_setOffset(iterator1, 0, &status); + order1 = ucol_next(iterator1, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator1.: %s\n", myErrorName(status)); + return; + } + order2=ucol_getOffset(iterator2); + doAssert((order1 != order2), "The first iterator advance failed"); + order2 = ucol_next(iterator2, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status)); + return; + } + order3 = ucol_next(iterator3, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator3.: %s\n", myErrorName(status)); + return; + } + + doAssert((order1 == order2), "The second iterator advance failed should be the same as first one"); + +doAssert( (ucol_primaryOrder(order1) == ucol_primaryOrder(order3)), "The primary orders should be identical"); +doAssert( (ucol_secondaryOrder(order1) == ucol_secondaryOrder(order3)), "The secondary orders should be identical"); +doAssert( (ucol_tertiaryOrder(order1) == ucol_tertiaryOrder(order3)), "The tertiary orders should be identical"); + + order1=ucol_next(iterator1, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status)); + return; + } + order3=ucol_next(iterator3, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status)); + return; + } +doAssert( (ucol_primaryOrder(order1) == ucol_primaryOrder(order3)), "The primary orders should be identical"); +doAssert( (ucol_tertiaryOrder(order1) != ucol_tertiaryOrder(order3)), "The tertiary orders should be different"); + + order1=ucol_next(iterator1, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status)); + return; + } + order3=ucol_next(iterator3, &status); + if (U_FAILURE(status)) { + log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status)); + return; + } + /* this here, my friends, is either pure lunacy or something so obsolete that even it's mother + * doesn't care about it. Essentialy, this test complains if secondary values for 'I' and '_' + * are the same. According to the UCA, this is not true. Therefore, remove the test. + * Besides, if primary strengths for two code points are different, it doesn't matter one bit + * what is the relation between secondary or any other strengths. + * killed by weiv 06/11/2002. + */ + /* + doAssert( ((order1 & UCOL_SECONDARYMASK) != (order3 & UCOL_SECONDARYMASK)), "The secondary orders should be different"); + */ + doAssert( (order1 != UCOL_NULLORDER), "Unexpected end of iterator reached"); + + free(testString1); + free(testString2); + ucol_closeElements(iterator1); + ucol_closeElements(iterator2); + ucol_closeElements(iterator3); + ucol_close(col); + + log_verbose("testing CollationElementIterator ends...\n"); +} + +void TestGetLocale() { + UErrorCode status = U_ZERO_ERROR; + const char *rules = "&a<x<y<z"; + UChar rlz[256] = {0}; + uint32_t rlzLen = u_unescape(rules, rlz, 256); + + UCollator *coll = NULL; + const char *locale = NULL; + + int32_t i = 0; + + /* Now that the collation tree is separate, actual==valid at all times. [alan] */ + static const struct { + const char* requestedLocale; + const char* validLocale; + const char* actualLocale; + } testStruct[] = { + { "sr_RS", "sr_Cyrl_RS", "ru" }, + { "sh_YU", "sr_Latn_RS", "hr" }, /* this used to be sh, but now sh collation aliases hr */ + { "en_BE_FOO", "en_BE", "en_BE" }, + { "fr_FR_NONEXISTANT", "fr_FR", "fr" } + }; + + /* test opening collators for different locales */ + for(i = 0; i<sizeof(testStruct)/sizeof(testStruct[0]); i++) { + status = U_ZERO_ERROR; + coll = ucol_open(testStruct[i].requestedLocale, &status); + if(U_FAILURE(status)) { + log_err("Failed to open collator for %s with %s\n", testStruct[i].requestedLocale, u_errorName(status)); + ucol_close(coll); + continue; + } + locale = ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status); + if(strcmp(locale, testStruct[i].requestedLocale) != 0) { + log_err("[Coll %s]: Error in requested locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].requestedLocale, locale); + } + locale = ucol_getLocale(coll, ULOC_VALID_LOCALE, &status); + if(strcmp(locale, testStruct[i].validLocale) != 0) { + log_err("[Coll %s]: Error in valid locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].validLocale, locale); + } + locale = ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status); + if(strcmp(locale, testStruct[i].actualLocale) != 0) { + log_err("[Coll %s]: Error in actual locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].actualLocale, locale); + } + ucol_close(coll); + } + + /* completely non-existant locale for collator should get a default collator */ + { + UCollator *defaultColl = ucol_open(NULL, &status); + coll = ucol_open("blahaha", &status); + if(U_SUCCESS(status)) { + if(strcmp(ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status), "blahaha")) { + log_err("Nonexisting locale didn't preserve the requested locale\n"); + } + if(strcmp(ucol_getLocale(coll, ULOC_VALID_LOCALE, &status), + ucol_getLocale(defaultColl, ULOC_VALID_LOCALE, &status))) { + log_err("Valid locale for nonexisting locale locale collator differs " + "from valid locale for default collator\n"); + } + if(strcmp(ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status), + ucol_getLocale(defaultColl, ULOC_ACTUAL_LOCALE, &status))) { + log_err("Actual locale for nonexisting locale locale collator differs " + "from actual locale for default collator\n"); + } + ucol_close(coll); + ucol_close(defaultColl); + } else { + log_data_err("Couldn't open collators\n"); + } + } + + + + /* collator instantiated from rules should have all three locales NULL */ + coll = ucol_openRules(rlz, rlzLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + locale = ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status); + if(locale != NULL) { + log_err("For collator instantiated from rules, requested locale returned %s instead of NULL\n", locale); + } + locale = ucol_getLocale(coll, ULOC_VALID_LOCALE, &status); + if(locale != NULL) { + log_err("For collator instantiated from rules, valid locale returned %s instead of NULL\n", locale); + } + locale = ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status); + if(locale != NULL) { + log_err("For collator instantiated from rules, actual locale returned %s instead of NULL\n", locale); + } + ucol_close(coll); + +} + + +void TestGetAll() +{ + int32_t i, count; + count=ucol_countAvailable(); + /* use something sensible w/o hardcoding the count */ + if(count < 0){ + log_err("Error in countAvailable(), it returned %d\n", count); + } + else{ + log_verbose("PASS: countAvailable() successful, it returned %d\n", count); + } + for(i=0;i<count;i++) + log_verbose("%s\n", ucol_getAvailable(i)); + + +} + + +struct teststruct { + const char *original; + uint8_t key[256]; +} ; + +static int compare_teststruct(const void *string1, const void *string2) { + return(strcmp((const char *)((struct teststruct *)string1)->key, (const char *)((struct teststruct *)string2)->key)); +} + +void TestBounds() { + UErrorCode status = U_ZERO_ERROR; + + UCollator *coll = ucol_open("sh", &status); + + uint8_t sortkey[512], lower[512], upper[512]; + UChar buffer[512]; + + static const char * const test[] = { + "John Smith", + "JOHN SMITH", + "john SMITH", + "j\\u00F6hn sm\\u00EFth", + "J\\u00F6hn Sm\\u00EFth", + "J\\u00D6HN SM\\u00CFTH", + "john smithsonian", + "John Smithsonian", + }; + + struct teststruct tests[] = { + {"\\u010CAKI MIHALJ" } , + {"\\u010CAKI MIHALJ" } , + {"\\u010CAKI PIRO\\u0160KA" }, + {"\\u010CABAI ANDRIJA" } , + {"\\u010CABAI LAJO\\u0160" } , + {"\\u010CABAI MARIJA" } , + {"\\u010CABAI STEVAN" } , + {"\\u010CABAI STEVAN" } , + {"\\u010CABARKAPA BRANKO" } , + {"\\u010CABARKAPA MILENKO" } , + {"\\u010CABARKAPA MIROSLAV" } , + {"\\u010CABARKAPA SIMO" } , + {"\\u010CABARKAPA STANKO" } , + {"\\u010CABARKAPA TAMARA" } , + {"\\u010CABARKAPA TOMA\\u0160" } , + {"\\u010CABDARI\\u0106 NIKOLA" } , + {"\\u010CABDARI\\u0106 ZORICA" } , + {"\\u010CABI NANDOR" } , + {"\\u010CABOVI\\u0106 MILAN" } , + {"\\u010CABRADI AGNEZIJA" } , + {"\\u010CABRADI IVAN" } , + {"\\u010CABRADI JELENA" } , + {"\\u010CABRADI LJUBICA" } , + {"\\u010CABRADI STEVAN" } , + {"\\u010CABRDA MARTIN" } , + {"\\u010CABRILO BOGDAN" } , + {"\\u010CABRILO BRANISLAV" } , + {"\\u010CABRILO LAZAR" } , + {"\\u010CABRILO LJUBICA" } , + {"\\u010CABRILO SPASOJA" } , + {"\\u010CADE\\u0160 ZDENKA" } , + {"\\u010CADESKI BLAGOJE" } , + {"\\u010CADOVSKI VLADIMIR" } , + {"\\u010CAGLJEVI\\u0106 TOMA" } , + {"\\u010CAGOROVI\\u0106 VLADIMIR" } , + {"\\u010CAJA VANKA" } , + {"\\u010CAJI\\u0106 BOGOLJUB" } , + {"\\u010CAJI\\u0106 BORISLAV" } , + {"\\u010CAJI\\u0106 RADOSLAV" } , + {"\\u010CAK\\u0160IRAN MILADIN" } , + {"\\u010CAKAN EUGEN" } , + {"\\u010CAKAN EVGENIJE" } , + {"\\u010CAKAN IVAN" } , + {"\\u010CAKAN JULIJAN" } , + {"\\u010CAKAN MIHAJLO" } , + {"\\u010CAKAN STEVAN" } , + {"\\u010CAKAN VLADIMIR" } , + {"\\u010CAKAN VLADIMIR" } , + {"\\u010CAKAN VLADIMIR" } , + {"\\u010CAKARA ANA" } , + {"\\u010CAKAREVI\\u0106 MOMIR" } , + {"\\u010CAKAREVI\\u0106 NEDELJKO" } , + {"\\u010CAKI \\u0160ANDOR" } , + {"\\u010CAKI AMALIJA" } , + {"\\u010CAKI ANDRA\\u0160" } , + {"\\u010CAKI LADISLAV" } , + {"\\u010CAKI LAJO\\u0160" } , + {"\\u010CAKI LASLO" } , + }; + + + + int32_t i = 0, j = 0, k = 0, buffSize = 0, skSize = 0, lowerSize = 0, upperSize = 0; + int32_t arraySize = sizeof(tests)/sizeof(tests[0]); + + if(U_SUCCESS(status) && coll) { + for(i = 0; i<arraySize; i++) { + buffSize = u_unescape(tests[i].original, buffer, 512); + skSize = ucol_getSortKey(coll, buffer, buffSize, tests[i].key, 512); + } + + qsort(tests, arraySize, sizeof(struct teststruct), compare_teststruct); + + for(i = 0; i < arraySize-1; i++) { + for(j = i+1; j < arraySize; j++) { + lowerSize = ucol_getBound(tests[i].key, -1, UCOL_BOUND_LOWER, 1, lower, 512, &status); + upperSize = ucol_getBound(tests[j].key, -1, UCOL_BOUND_UPPER, 1, upper, 512, &status); + for(k = i; k <= j; k++) { + if(strcmp((const char *)lower, (const char *)tests[k].key) > 0) { + log_err("Problem with lower! j = %i (%s vs %s)\n", k, tests[k].original, tests[i].original); + } + if(strcmp((const char *)upper, (const char *)tests[k].key) <= 0) { + log_err("Problem with upper! j = %i (%s vs %s)\n", k, tests[k].original, tests[j].original); + } + } + } + } + + +#if 0 + for(i = 0; i < 1000; i++) { + lowerRND = (rand()/(RAND_MAX/arraySize)); + upperRND = lowerRND + (rand()/(RAND_MAX/(arraySize-lowerRND))); + + lowerSize = ucol_getBound(tests[lowerRND].key, -1, UCOL_BOUND_LOWER, 1, lower, 512, &status); + upperSize = ucol_getBound(tests[upperRND].key, -1, UCOL_BOUND_UPPER_LONG, 1, upper, 512, &status); + + for(j = lowerRND; j<=upperRND; j++) { + if(strcmp(lower, tests[j].key) > 0) { + log_err("Problem with lower! j = %i (%s vs %s)\n", j, tests[j].original, tests[lowerRND].original); + } + if(strcmp(upper, tests[j].key) <= 0) { + log_err("Problem with upper! j = %i (%s vs %s)\n", j, tests[j].original, tests[upperRND].original); + } + } + } +#endif + + + + + + for(i = 0; i<sizeof(test)/sizeof(test[0]); i++) { + buffSize = u_unescape(test[i], buffer, 512); + skSize = ucol_getSortKey(coll, buffer, buffSize, sortkey, 512); + lowerSize = ucol_getBound(sortkey, skSize, UCOL_BOUND_LOWER, 1, lower, 512, &status); + upperSize = ucol_getBound(sortkey, skSize, UCOL_BOUND_UPPER_LONG, 1, upper, 512, &status); + for(j = i+1; j<sizeof(test)/sizeof(test[0]); j++) { + buffSize = u_unescape(test[j], buffer, 512); + skSize = ucol_getSortKey(coll, buffer, buffSize, sortkey, 512); + if(strcmp((const char *)lower, (const char *)sortkey) > 0) { + log_err("Problem with lower! i = %i, j = %i (%s vs %s)\n", i, j, test[i], test[j]); + } + if(strcmp((const char *)upper, (const char *)sortkey) <= 0) { + log_err("Problem with upper! i = %i, j = %i (%s vs %s)\n", i, j, test[i], test[j]); + } + } + } + ucol_close(coll); + } else { + log_data_err("Couldn't open collator\n"); + } + +} + +static void doOverrunTest(UCollator *coll, const UChar *uString, int32_t strLen) { + int32_t skLen = 0, skLen2 = 0; + uint8_t sortKey[256]; + int32_t i, j; + uint8_t filler = 0xFF; + + skLen = ucol_getSortKey(coll, uString, strLen, NULL, 0); + + for(i = 0; i < skLen; i++) { + memset(sortKey, filler, 256); + skLen2 = ucol_getSortKey(coll, uString, strLen, sortKey, i); + if(skLen != skLen2) { + log_err("For buffer size %i, got different sortkey length. Expected %i got %i\n", i, skLen, skLen2); + } + for(j = i; j < 256; j++) { + if(sortKey[j] != filler) { + log_err("Something run over index %i\n", j); + break; + } + } + } +} + +/* j1865 reports that if a shorter buffer is passed to +* to get sort key, a buffer overrun happens in some +* cases. This test tries to check this. +*/ +void TestSortKeyBufferOverrun(void) { + UErrorCode status = U_ZERO_ERROR; + const char* cString = "A very Merry liTTle-lamB.."; + UChar uString[256]; + int32_t strLen = 0; + UCollator *coll = ucol_open("root", &status); + strLen = u_unescape(cString, uString, 256); + + if(U_SUCCESS(status)) { + log_verbose("testing non ignorable\n"); + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status); + doOverrunTest(coll, uString, strLen); + + log_verbose("testing shifted\n"); + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + doOverrunTest(coll, uString, strLen); + + log_verbose("testing shifted quaternary\n"); + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &status); + doOverrunTest(coll, uString, strLen); + + log_verbose("testing with french secondaries\n"); + ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_ON, &status); + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &status); + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status); + doOverrunTest(coll, uString, strLen); + + } + ucol_close(coll); +} + +static void TestAttribute() +{ + UErrorCode error = U_ZERO_ERROR; + UCollator *coll = ucol_open(NULL, &error); + + if (U_FAILURE(error)) { + log_err("Creation of default collator failed"); + return; + } + + ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_OFF, &error); + if (ucol_getAttribute(coll, UCOL_FRENCH_COLLATION, &error) != UCOL_OFF || + U_FAILURE(error)) { + log_err("Setting and retrieving of the french collation failed"); + } + + ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_ON, &error); + if (ucol_getAttribute(coll, UCOL_FRENCH_COLLATION, &error) != UCOL_ON || + U_FAILURE(error)) { + log_err("Setting and retrieving of the french collation failed"); + } + + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &error); + if (ucol_getAttribute(coll, UCOL_ALTERNATE_HANDLING, &error) != UCOL_SHIFTED || + U_FAILURE(error)) { + log_err("Setting and retrieving of the alternate handling failed"); + } + + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &error); + if (ucol_getAttribute(coll, UCOL_ALTERNATE_HANDLING, &error) != UCOL_NON_IGNORABLE || + U_FAILURE(error)) { + log_err("Setting and retrieving of the alternate handling failed"); + } + + ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_LOWER_FIRST, &error); + if (ucol_getAttribute(coll, UCOL_CASE_FIRST, &error) != UCOL_LOWER_FIRST || + U_FAILURE(error)) { + log_err("Setting and retrieving of the case first attribute failed"); + } + + ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_UPPER_FIRST, &error); + if (ucol_getAttribute(coll, UCOL_CASE_FIRST, &error) != UCOL_UPPER_FIRST || + U_FAILURE(error)) { + log_err("Setting and retrieving of the case first attribute failed"); + } + + ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &error); + if (ucol_getAttribute(coll, UCOL_CASE_LEVEL, &error) != UCOL_ON || + U_FAILURE(error)) { + log_err("Setting and retrieving of the case level attribute failed"); + } + + ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &error); + if (ucol_getAttribute(coll, UCOL_CASE_LEVEL, &error) != UCOL_OFF || + U_FAILURE(error)) { + log_err("Setting and retrieving of the case level attribute failed"); + } + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &error); + if (ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, &error) != UCOL_ON || + U_FAILURE(error)) { + log_err("Setting and retrieving of the normalization on/off attribute failed"); + } + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &error); + if (ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, &error) != UCOL_OFF || + U_FAILURE(error)) { + log_err("Setting and retrieving of the normalization on/off attribute failed"); + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &error); + if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_PRIMARY || + U_FAILURE(error)) { + log_err("Setting and retrieving of the collation strength failed"); + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_SECONDARY, &error); + if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_SECONDARY || + U_FAILURE(error)) { + log_err("Setting and retrieving of the collation strength failed"); + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &error); + if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_TERTIARY || + U_FAILURE(error)) { + log_err("Setting and retrieving of the collation strength failed"); + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &error); + if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_QUATERNARY || + U_FAILURE(error)) { + log_err("Setting and retrieving of the collation strength failed"); + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_IDENTICAL, &error); + if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_IDENTICAL || + U_FAILURE(error)) { + log_err("Setting and retrieving of the collation strength failed"); + } + + ucol_close(coll); +} + +void TestGetTailoredSet() { + struct { + const char *rules; + const char *tests[20]; + int32_t testsize; + } setTest[] = { + { "&a < \\u212b", { "\\u212b", "A\\u030a", "\\u00c5" }, 3}, + { "& S < \\u0161 <<< \\u0160", { "\\u0161", "s\\u030C", "\\u0160", "S\\u030C" }, 4} + }; + + int32_t i = 0, j = 0; + UErrorCode status = U_ZERO_ERROR; + UParseError pError; + + UCollator *coll = NULL; + UChar buff[1024]; + int32_t buffLen = 0; + USet *set = NULL; + + for(i = 0; i < sizeof(setTest)/sizeof(setTest[0]); i++) { + buffLen = u_unescape(setTest[i].rules, buff, 1024); + coll = ucol_openRules(buff, buffLen, UCOL_DEFAULT, UCOL_DEFAULT, &pError, &status); + if(U_SUCCESS(status)) { + set = ucol_getTailoredSet(coll, &status); + if(uset_size(set) != setTest[i].testsize) { + log_err("Tailored set size different (%d) than expected (%d)\n", uset_size(set), setTest[i].testsize); + } + for(j = 0; j < setTest[i].testsize; j++) { + buffLen = u_unescape(setTest[i].tests[j], buff, 1024); + if(!uset_containsString(set, buff, buffLen)) { + log_err("Tailored set doesn't contain %s... It should\n", setTest[i].tests[j]); + } + } + uset_close(set); + } else { + log_err("Couldn't open collator with rules %s\n", setTest[i].rules); + } + ucol_close(coll); + } +} + +static int tMemCmp(const uint8_t *first, const uint8_t *second) { + int32_t firstLen = (int32_t)strlen((const char *)first); + int32_t secondLen = (int32_t)strlen((const char *)second); + return memcmp(first, second, uprv_min(firstLen, secondLen)); +} +static const char * strengthsC[] = { + "UCOL_PRIMARY", + "UCOL_SECONDARY", + "UCOL_TERTIARY", + "UCOL_QUATERNARY", + "UCOL_IDENTICAL" +}; + +void TestMergeSortKeys(void) { + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("en", &status); + if(U_SUCCESS(status)) { + + const char* cases[] = { + "abc", + "abcd", + "abcde" + }; + uint32_t casesSize = sizeof(cases)/sizeof(cases[0]); + const char* prefix = "foo"; + const char* suffix = "egg"; + char outBuff1[256], outBuff2[256]; + + uint8_t **sortkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *)); + uint8_t **mergedPrefixkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *)); + uint8_t **mergedSuffixkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *)); + uint32_t *sortKeysLen = (uint32_t *)malloc(casesSize*sizeof(uint32_t)); + uint8_t prefixKey[256], suffixKey[256]; + uint32_t prefixKeyLen = 0, suffixKeyLen = 0, i = 0; + UChar buffer[256]; + uint32_t unescapedLen = 0, l1 = 0, l2 = 0; + UColAttributeValue strength; + + log_verbose("ucol_mergeSortkeys test\n"); + log_verbose("Testing order of the test cases\n"); + genericLocaleStarter("en", cases, casesSize); + + for(i = 0; i<casesSize; i++) { + sortkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t)); + mergedPrefixkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t)); + mergedSuffixkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t)); + } + + unescapedLen = u_unescape(prefix, buffer, 256); + prefixKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, prefixKey, 256); + + unescapedLen = u_unescape(suffix, buffer, 256); + suffixKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, suffixKey, 256); + + log_verbose("Massaging data with prefixes and different strengths\n"); + strength = UCOL_PRIMARY; + while(strength <= UCOL_IDENTICAL) { + log_verbose("Strength %s\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]); + ucol_setAttribute(coll, UCOL_STRENGTH, strength, &status); + for(i = 0; i<casesSize; i++) { + unescapedLen = u_unescape(cases[i], buffer, 256); + sortKeysLen[i] = ucol_getSortKey(coll, buffer, unescapedLen, sortkeys[i], 256); + ucol_mergeSortkeys(prefixKey, prefixKeyLen, sortkeys[i], sortKeysLen[i], mergedPrefixkeys[i], 256); + ucol_mergeSortkeys(sortkeys[i], sortKeysLen[i], suffixKey, suffixKeyLen, mergedSuffixkeys[i], 256); + if(i>0) { + if(tMemCmp(mergedPrefixkeys[i-1], mergedPrefixkeys[i]) >= 0) { + log_err("Error while comparing prefixed keys @ strength %s:\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]); + log_err("%s\n%s\n", + ucol_sortKeyToString(coll, mergedPrefixkeys[i-1], outBuff1, &l1), + ucol_sortKeyToString(coll, mergedPrefixkeys[i], outBuff2, &l2)); + } + if(tMemCmp(mergedSuffixkeys[i-1], mergedSuffixkeys[i]) >= 0) { + log_err("Error while comparing suffixed keys @ strength %s:\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]); + log_err("%s\n%s\n", + ucol_sortKeyToString(coll, mergedSuffixkeys[i-1], outBuff1, &l1), + ucol_sortKeyToString(coll, mergedSuffixkeys[i], outBuff2, &l2)); + } + } + } + if(strength == UCOL_QUATERNARY) { + strength = UCOL_IDENTICAL; + } else { + strength++; + } + } + + { + uint8_t smallBuf[3]; + uint32_t reqLen = 0; + log_verbose("testing buffer overflow\n"); + reqLen = ucol_mergeSortkeys(prefixKey, prefixKeyLen, suffixKey, suffixKeyLen, smallBuf, 3); + if(reqLen != (prefixKeyLen+suffixKeyLen-1)) { + log_err("Wrong preflight size for merged sortkey\n"); + } + } + + { + UChar empty = 0; + uint8_t emptyKey[20], abcKey[50], mergedKey[100]; + int32_t emptyKeyLen = 0, abcKeyLen = 0, mergedKeyLen = 0; + + log_verbose("testing merging with sortkeys generated for empty strings\n"); + emptyKeyLen = ucol_getSortKey(coll, &empty, 0, emptyKey, 20); + unescapedLen = u_unescape(cases[0], buffer, 256); + abcKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, abcKey, 50); + mergedKeyLen = ucol_mergeSortkeys(emptyKey, emptyKeyLen, abcKey, abcKeyLen, mergedKey, 100); + if(mergedKey[0] != 2) { + log_err("Empty sortkey didn't produce a level separator\n"); + } + /* try with zeros */ + mergedKeyLen = ucol_mergeSortkeys(emptyKey, 0, abcKey, abcKeyLen, mergedKey, 100); + if(mergedKeyLen != 0 || mergedKey[0] != 0) { + log_err("Empty key didn't produce null mergedKey\n"); + } + mergedKeyLen = ucol_mergeSortkeys(abcKey, abcKeyLen, emptyKey, 0, mergedKey, 100); + if(mergedKeyLen != 0 || mergedKey[0] != 0) { + log_err("Empty key didn't produce null mergedKey\n"); + } + + } + + for(i = 0; i<casesSize; i++) { + free(sortkeys[i]); + free(mergedPrefixkeys[i]); + free(mergedSuffixkeys[i]); + } + free(sortkeys); + free(mergedPrefixkeys); + free(mergedSuffixkeys); + free(sortKeysLen); + ucol_close(coll); + /* need to finish this up */ + } else { + log_data_err("Couldn't open collator"); + } +} +static void TestShortString(void) +{ + struct { + const char *input; + const char *expectedOutput; + const char *locale; + UErrorCode expectedStatus; + int32_t expectedOffset; + uint32_t expectedIdentifier; + } testCases[] = { + {"LDE_RDE_KPHONEBOOK_T0041_ZLATN","B2900_KPHONEBOOK_LDE", "de@collation=phonebook", U_USING_FALLBACK_WARNING, 0, 0 }, + {"LEN_RUS_NO_AS_S4","AS_LEN_NO_S4", NULL, U_USING_FALLBACK_WARNING, 0, 0 }, + {"LDE_VPHONEBOOK_EO_SI","EO_KPHONEBOOK_LDE_SI", "de@collation=phonebook", U_ZERO_ERROR, 0, 0 }, + {"LDE_Kphonebook","KPHONEBOOK_LDE", "de@collation=phonebook", U_ZERO_ERROR, 0, 0 }, + {"Xqde_DE@collation=phonebookq_S3_EX","KPHONEBOOK_LDE", "de@collation=phonebook", U_USING_FALLBACK_WARNING, 0, 0 }, + {"LFR_FO", "LFR", NULL, U_ZERO_ERROR, 0, 0 }, + {"SO_LX_AS", "", NULL, U_ILLEGAL_ARGUMENT_ERROR, 8, 0 }, + {"S3_ASS_MMM", "", NULL, U_ILLEGAL_ARGUMENT_ERROR, 5, 0 } + }; + + int32_t i = 0, j = 0; + UCollator *coll = NULL, *fromID = NULL, *fromNormalized = NULL; + UParseError parseError; + UErrorCode status = U_ZERO_ERROR; + char fromShortBuffer[256], fromIDBuffer[256], fromIDRoundtrip[256], normalizedBuffer[256], fromNormalizedBuffer[256]; + uint32_t identifier = 0, idFromSS = 0; + const char* locale = NULL; + + + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + status = U_ZERO_ERROR; + if(testCases[i].locale) { + locale = testCases[i].locale; + } else { + locale = NULL; + } + + coll = ucol_openFromShortString(testCases[i].input, FALSE, &parseError, &status); + if(status != testCases[i].expectedStatus) { + log_err("Got status '%s' that is different from expected '%s' for '%s'\n", + u_errorName(status), u_errorName(testCases[i].expectedStatus), testCases[i].input); + } + + if(U_SUCCESS(status)) { + ucol_getShortDefinitionString(coll, locale, fromShortBuffer, 256, &status); + + if(strcmp(fromShortBuffer, testCases[i].expectedOutput)) { + log_err("Got short string '%s' from the collator. Expected '%s' for input '%s'\n", + fromShortBuffer, testCases[i].expectedOutput, testCases[i].input); + } + + ucol_normalizeShortDefinitionString(testCases[i].input, normalizedBuffer, 256, &parseError, &status); + fromNormalized = ucol_openFromShortString(normalizedBuffer, FALSE, &parseError, &status); + ucol_getShortDefinitionString(fromNormalized, locale, fromNormalizedBuffer, 256, &status); + + if(strcmp(fromShortBuffer, fromNormalizedBuffer)) { + log_err("Strings obtained from collators instantiated by short string ('%s') and from normalized string ('%s') differ\n", + fromShortBuffer, fromNormalizedBuffer); + } + + + if(!ucol_equals(coll, fromNormalized)) { + log_err("Collator from short string ('%s') differs from one obtained through a normalized version ('%s')\n", + testCases[i].input, normalizedBuffer); + } + + /* test identifiers */ + identifier = ucol_collatorToIdentifier(coll, locale, &status); + if(identifier < UCOL_SIT_COLLATOR_NOT_ENCODABLE) { + ucol_identifierToShortString(identifier, fromIDBuffer, 256, FALSE, &status); + fromID = ucol_openFromIdentifier(identifier, FALSE, &status); + if(!ucol_equals(coll, fromID)) { + log_err("Collator from short string ('%s') differs from one obtained through an identifier ('%s')\n", + testCases[i].input, fromIDBuffer); + } + ucol_close(fromID); + } + + /* round-trip short string - identifier */ + for(j = 1; j < 2; j++) { + idFromSS = ucol_shortStringToIdentifier(testCases[i].input, (UBool)j, &status); + ucol_identifierToShortString(idFromSS, fromIDBuffer, 256, (UBool)j, &status); + identifier = ucol_shortStringToIdentifier(fromIDBuffer, (UBool)j, &status); + ucol_identifierToShortString(identifier, fromIDRoundtrip, 256, (UBool)j, &status); + + if(idFromSS != identifier) { + log_err("FD = %i, id didn't round trip. %08X vs %08X (%s)\n", + j, idFromSS, identifier, testCases[i].input); + } + if(strcmp(fromIDBuffer, fromIDRoundtrip)) { + log_err("FD = %i, SS didn't round trip. %s vs %s (%s)\n", + j, fromIDBuffer, fromIDRoundtrip, testCases[i].input); + } + } + + ucol_close(fromNormalized); + ucol_close(coll); + + } else { + if(parseError.offset != testCases[i].expectedOffset) { + log_err("Got parse error offset %i, but expected %i instead for '%s'\n", + parseError.offset, testCases[i].expectedOffset, testCases[i].input); + } + } + } + +} + +static void +doSetsTest(const char *locale, const USet *ref, USet *set, const char* inSet, const char* outSet, UErrorCode *status) { + UChar buffer[512]; + int32_t bufLen; + + uset_clear(set); + bufLen = u_unescape(inSet, buffer, 512); + uset_applyPattern(set, buffer, bufLen, 0, status); + if(U_FAILURE(*status)) { + log_err("%s: Failure setting pattern %s\n", locale, u_errorName(*status)); + } + + if(!uset_containsAll(ref, set)) { + log_err("%s: Some stuff from %s is not present in the set\n", locale, inSet); + } + + uset_clear(set); + bufLen = u_unescape(outSet, buffer, 512); + uset_applyPattern(set, buffer, bufLen, 0, status); + if(U_FAILURE(*status)) { + log_err("%s: Failure setting pattern %s\n", locale, u_errorName(*status)); + } + + if(!uset_containsNone(ref, set)) { + log_err("%s: Some stuff from %s is present in the set\n", locale, outSet); + } +} + + + + +static void +TestGetContractionsAndUnsafes(void) +{ + static struct { + const char* locale; + const char* inConts; + const char* outConts; + const char* inExp; + const char* outExp; + const char* unsafeCodeUnits; + const char* safeCodeUnits; + } tests[] = { + { "ru", + "[{\\u0474\\u030F}{\\u0475\\u030F}{\\u04D8\\u0308}{\\u04D9\\u0308}{\\u04E8\\u0308}{\\u04E9\\u0308}]", + "[{\\u0430\\u0306}{\\u0410\\u0306}{\\u0430\\u0308}{\\u0410\\u0306}{\\u0433\\u0301}{\\u0413\\u0301}]", + "[\\u00e6]", + "[a]", + "[\\u0474\\u0475\\u04d8\\u04d9\\u04e8\\u04e9]", + "[aAbB\\u0430\\u0410\\u0433\\u0413]" + }, + { "uk", + "[{\\u0474\\u030F}{\\u0475\\u030F}{\\u04D8\\u0308}{\\u04D9\\u0308}{\\u04E8\\u0308}{\\u04E9\\u0308}" + "{\\u0430\\u0306}{\\u0410\\u0306}{\\u0430\\u0308}{\\u0410\\u0306}{\\u0433\\u0301}{\\u0413\\u0301}]", + "[]", + "[\\u00e6]", + "[a]", + "[\\u0474\\u0475\\u04D8\\u04D9\\u04E8\\u04E9\\u0430\\u0410\\u0433\\u0413]", + "[aAbBxv]", + }, + { "sh", + "[{C\\u0301}{C\\u030C}{C\\u0341}{DZ\\u030C}{Dz\\u030C}{D\\u017D}{D\\u017E}{lj}{nj}]", + "[{\\u309d\\u3099}{\\u30fd\\u3099}]", + "[\\u00e6]", + "[a]", + "[nlcdzNLCDZ]", + "[jabv]" + }, + { "ja", + "[{\\u3053\\u3099\\u309D}{\\u3053\\u3099\\u309D\\u3099}{\\u3053\\u3099\\u309E}{\\u3053\\u3099\\u30FC}{\\u3053\\u309D}{\\u3053\\u309D\\u3099}{\\u3053\\u309E}{\\u3053\\u30FC}{\\u30B3\\u3099\\u30FC}{\\u30B3\\u3099\\u30FD}{\\u30B3\\u3099\\u30FD\\u3099}{\\u30B3\\u3099\\u30FE}{\\u30B3\\u30FC}{\\u30B3\\u30FD}{\\u30B3\\u30FD\\u3099}{\\u30B3\\u30FE}]", + "[{\\u30FD\\u3099}{\\u309D\\u3099}{\\u3053\\u3099}{\\u30B3\\u3099}{lj}{nj}]", + "[\\u30FE\\u00e6]", + "[a]", + "[\\u3099]", + "[]" + } + }; + + + + + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = NULL; + int32_t i = 0; + int32_t noConts = 0; + USet *conts = uset_open(0,0); + USet *exp = uset_open(0, 0); + USet *set = uset_open(0,0); + int32_t setBufferLen = 65536; + UChar buffer[65536]; + int32_t setLen = 0; + + for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + log_verbose("Testing locale: %s\n", tests[i].locale); + coll = ucol_open(tests[i].locale, &status); + ucol_getContractionsAndExpansions(coll, conts, exp, TRUE, &status); + doSetsTest(tests[i].locale, conts, set, tests[i].inConts, tests[i].outConts, &status); + setLen = uset_toPattern(conts, buffer, setBufferLen, TRUE, &status); + if(U_SUCCESS(status)) { + /*log_verbose("Contractions %i: %s\n", uset_getItemCount(conts), aescstrdup(buffer, setLen));*/ + } else { + log_err("error %s. %i\n", u_errorName(status), setLen); + status = U_ZERO_ERROR; + } + doSetsTest(tests[i].locale, exp, set, tests[i].inExp, tests[i].outExp, &status); + setLen = uset_toPattern(exp, buffer, setBufferLen, TRUE, &status); + if(U_SUCCESS(status)) { + /*log_verbose("Expansions %i: %s\n", uset_getItemCount(exp), aescstrdup(buffer, setLen));*/ + } else { + log_err("error %s. %i\n", u_errorName(status), setLen); + status = U_ZERO_ERROR; + } + + noConts = ucol_getUnsafeSet(coll, conts, &status); + doSetsTest(tests[i].locale, conts, set, tests[i].unsafeCodeUnits, tests[i].safeCodeUnits, &status); + setLen = uset_toPattern(conts, buffer, setBufferLen, TRUE, &status); + if(U_SUCCESS(status)) { + log_verbose("Unsafe %i: %s\n", uset_getItemCount(exp), aescstrdup(buffer, setLen)); + } else { + log_err("error %s. %i\n", u_errorName(status), setLen); + status = U_ZERO_ERROR; + } + + ucol_close(coll); + } + + + uset_close(conts); + uset_close(exp); + uset_close(set); +} + +static void +TestOpenBinary(void) +{ + UErrorCode status = U_ZERO_ERROR; + /* + char rule[] = "&h < d < c < b"; + char *wUCA[] = { "a", "h", "d", "c", "b", "i" }; + char *noUCA[] = {"d", "c", "b", "a", "h", "i" }; + */ + /* we have to use Cyrillic letters because latin-1 always gets copied */ + const char rule[] = "&\\u0452 < \\u0434 < \\u0433 < \\u0432"; /* &dje < d < g < v */ + const char *wUCA[] = { "\\u0430", "\\u0452", "\\u0434", "\\u0433", "\\u0432", "\\u0435" }; /* a, dje, d, g, v, e */ + const char *noUCA[] = {"\\u0434", "\\u0433", "\\u0432", "\\u0430", "\\u0435", "\\u0452" }; /* d, g, v, a, e, dje */ + + UChar uRules[256]; + int32_t uRulesLen = u_unescape(rule, uRules, 256); + + UCollator *coll = ucol_openRules(uRules, uRulesLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + UCollator *UCA = ucol_open("root", &status); + UCollator *cloneNOUCA = NULL, *cloneWUCA = NULL; + + uint8_t imageBuffer[32768]; + uint8_t *image = imageBuffer; + int32_t imageBufferCapacity = 32768; + + int32_t imageSize; + + if((coll==NULL)||(UCA==NULL)||(U_FAILURE(status))) { + log_data_err("could not load collators or error occured: %s\n", + u_errorName(status)); + return; + } + imageSize = ucol_cloneBinary(coll, image, imageBufferCapacity, &status); + if(U_FAILURE(status)) { + image = (uint8_t *)malloc(imageSize*sizeof(uint8_t)); + status = U_ZERO_ERROR; + imageSize = ucol_cloneBinary(coll, imageBuffer, imageSize, &status); + } + + + cloneWUCA = ucol_openBinary(image, imageSize, UCA, &status); + cloneNOUCA = ucol_openBinary(image, imageSize, NULL, &status); + + genericOrderingTest(coll, wUCA, sizeof(wUCA)/sizeof(wUCA[0])); + + genericOrderingTest(cloneWUCA, wUCA, sizeof(wUCA)/sizeof(wUCA[0])); + genericOrderingTest(cloneNOUCA, noUCA, sizeof(noUCA)/sizeof(noUCA[0])); + + if(image != imageBuffer) { + free(image); + } + ucol_close(coll); + ucol_close(cloneNOUCA); + ucol_close(cloneWUCA); + ucol_close(UCA); +} + +static void TestDefault(void) { + /* Tests for code coverage. */ + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("es@collation=pinyin", &status); + if (status != U_USING_DEFAULT_WARNING) { + /* What do you mean that you know about using pinyin collation in Spanish!? This should be in the zh locale. */ + log_err("es@collation=pinyin should return U_USING_DEFAULT_WARNING, but returned %s\n", u_errorName(status)); + } + ucol_close(coll); + if (ucol_getKeywordValues("funky", &status) != NULL) { + log_err("Collators should not know about the funky keyword.\n"); + } + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("funky keyword didn't fail as expected %s\n", u_errorName(status)); + } + if (ucol_getKeywordValues("collation", &status) != NULL) { + log_err("ucol_getKeywordValues should not work when given a bad status.\n"); + } +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h new file mode 100644 index 00000000000..49f8b7533c6 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h @@ -0,0 +1,124 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CAPITEST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*//* C API TEST For COLLATOR */ + +#ifndef _CCOLLAPITST +#define _CCOLLAPITST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" +#include "callcoll.h" +#define MAX_TOKEN_LEN 16 + + + /** + * error reporting utility method + **/ + + static void doAssert(int condition, const char *message); + /** + * Collator Class Properties + * ctor, dtor, createInstance, compare, getStrength/setStrength + * getDecomposition/setDecomposition, getDisplayName + */ + void TestProperty(void); + /** + * Test RuleBasedCollator and getRules + **/ + void TestRuleBasedColl(void); + + /** + * Test compare + **/ + void TestCompare(void); + /** + * Test hashCode functionality + **/ + void TestHashCode(void); + /** + * Tests the constructor and numerous other methods for CollationKey + **/ + void TestSortKey(void); + /** + * test the CollationElementIterator methods + **/ + void TestElemIter(void); + /** + * Test ucol_getAvailable and ucol_countAvailable() + **/ + void TestGetAll(void); + /** + * Test ucol_GetDefaultRules () + void TestGetDefaultRules(void); + **/ + + void TestDecomposition(void); + /** + * Test ucol_safeClone () + **/ + void TestSafeClone(void); + + /** + * Test ucol_cloneBinary(), ucol_openBinary() + **/ + void TestCloneBinary(void); + + /** + * Test getting bounds for a sortkey + */ + void TestBounds(void); + + /** + * Test ucol_getLocale function + */ + void TestGetLocale(void); + + /** + * Test buffer overrun while having smaller buffer for sortkey (j1865) + */ + void TestSortKeyBufferOverrun(void); + /** + * Test getting and setting of attributes + */ + void TestGetSetAttr(void); + /** + * Test getTailoredSet + */ + void TestGetTailoredSet(void); + + /** + * Test mergeSortKeys + */ + void TestMergeSortKeys(void); + + /** + * test short string and collator identifier functions + */ + static void TestShortString(void); + + /** + * test getContractions and getUnsafeSet + */ + static void TestGetContractionsAndUnsafes(void); + + /** + * Test funny stuff with open binary + */ + static void TestOpenBinary(void); +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c new file mode 100644 index 00000000000..fe597ae1857 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c @@ -0,0 +1,708 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CBIAPTS.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +*********************************************************************************/ +/*C API TEST FOR BREAKITERATOR */ +/** +* This is an API test. It doesn't test very many cases, and doesn't +* try to test the full functionality. It just calls each function in the class and +* verifies that it works on a basic level. +**/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_BREAK_ITERATION + +#include <stdlib.h> +#include <string.h> +#include "unicode/uloc.h" +#include "unicode/ubrk.h" +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "unicode/utext.h" +#include "cintltst.h" +#include "cbiapts.h" + +#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ +log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}} + +#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ +log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}} + +static void TestBreakIteratorSafeClone(void); +static void TestBreakIteratorRules(void); +static void TestBreakIteratorRuleError(void); +static void TestBreakIteratorStatusVec(void); +static void TestBreakIteratorUText(void); + +void addBrkIterAPITest(TestNode** root); + +void addBrkIterAPITest(TestNode** root) +{ + addTest(root, &TestBreakIteratorCAPI, "tstxtbd/cbiapts/TestBreakIteratorCAPI"); + addTest(root, &TestBreakIteratorSafeClone, "tstxtbd/cbiapts/TestBreakIteratorSafeClone"); + addTest(root, &TestBreakIteratorRules, "tstxtbd/cbiapts/TestBreakIteratorRules"); + addTest(root, &TestBreakIteratorRuleError, "tstxtbd/cbiapts/TestBreakIteratorRuleError"); + addTest(root, &TestBreakIteratorStatusVec, "tstxtbd/cbiapts/TestBreakIteratorStatusVec"); + addTest(root, &TestBreakIteratorUText, "tstxtbd/cbiapts/TestBreakIteratorUText"); +} + +#define CLONETEST_ITERATOR_COUNT 2 + +/* + * Utility function for converting char * to UChar * strings, to + * simplify the test code. Converted strings are put in heap allocated + * storage. A hook (probably a local in the caller's code) allows all + * strings converted with that hook to be freed with a single call. + */ +typedef struct StringStruct { + struct StringStruct *link; + UChar str[1]; + } StringStruct; + + +static UChar* toUChar(const char *src, void **freeHook) { + /* Structure of the memory that we allocate on the heap */ + + int32_t numUChars; + int32_t destSize; + UChar stackBuf[2000 + sizeof(void *)/sizeof(UChar)]; + StringStruct *dest; + UConverter *cnv; + + UErrorCode status = U_ZERO_ERROR; + if (src == NULL) { + return NULL; + }; + + cnv = ucnv_open(NULL, &status); + if(U_FAILURE(status) || cnv == NULL) { + return NULL; + } + ucnv_reset(cnv); + numUChars = ucnv_toUChars(cnv, + stackBuf, + 2000, + src, -1, + &status); + + destSize = (numUChars+1) * sizeof(UChar) + sizeof(struct StringStruct); + dest = (StringStruct *)malloc(destSize); + if (dest != NULL) { + if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { + ucnv_toUChars(cnv, dest->str, numUChars+1, src, -1, &status); + } else if (status == U_ZERO_ERROR) { + u_strcpy(dest->str, stackBuf); + } else { + free(dest); + dest = NULL; + } + } + + ucnv_reset(cnv); /* be good citizens */ + ucnv_close(cnv); + if (dest == NULL) { + return NULL; + } + + dest->link = (StringStruct*)(*freeHook); + *freeHook = dest; + return dest->str; +} + +static void freeToUCharStrings(void **hook) { + StringStruct *s = *(StringStruct **)hook; + while (s != NULL) { + StringStruct *next = s->link; + free(s); + s = next; + } +} + + +static void TestBreakIteratorCAPI() +{ + UErrorCode status = U_ZERO_ERROR; + UBreakIterator *word, *sentence, *line, *character, *b, *bogus; + int32_t start,pos,end,to; + int32_t i; + int32_t count = 0; + + UChar text[50]; + + /* Note: the adjacent "" are concatenating strings, not adding a \" to the + string, which is probably what whoever wrote this intended. Don't fix, + because it would throw off the hard coded break positions in the following + tests. */ + u_uastrcpy(text, "He's from Africa. ""Mr. Livingston, I presume?"" Yeah"); + + +/*test ubrk_open()*/ + log_verbose("\nTesting BreakIterator open functions\n"); + + /* Use french for fun */ + word = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Check your data - it doesn't seem to be around\n"); + return; + } else if(U_FAILURE(status)){ + log_err("FAIL: Error in ubrk_open() for word breakiterator: %s\n", myErrorName(status)); + } + else{ + log_verbose("PASS: Successfully opened word breakiterator\n"); + } + + sentence = ubrk_open(UBRK_SENTENCE, "en_US", text, u_strlen(text), &status); + if(U_FAILURE(status)){ + log_err("FAIL: Error in ubrk_open() for sentence breakiterator: %s\n", myErrorName(status)); + return; + } + else{ + log_verbose("PASS: Successfully opened sentence breakiterator\n"); + } + + line = ubrk_open(UBRK_LINE, "en_US", text, u_strlen(text), &status); + if(U_FAILURE(status)){ + log_err("FAIL: Error in ubrk_open() for line breakiterator: %s\n", myErrorName(status)); + return; + } + else{ + log_verbose("PASS: Successfully opened line breakiterator\n"); + } + + character = ubrk_open(UBRK_CHARACTER, "en_US", text, u_strlen(text), &status); + if(U_FAILURE(status)){ + log_err("FAIL: Error in ubrk_open() for character breakiterator: %s\n", myErrorName(status)); + return; + } + else{ + log_verbose("PASS: Successfully opened character breakiterator\n"); + } + /*trying to open an illegal iterator*/ + bogus = ubrk_open((UBreakIteratorType)5, "en_US", text, u_strlen(text), &status); + if(U_SUCCESS(status)){ + log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n"); + } + if(U_FAILURE(status)){ + if(status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n Got %s\n", myErrorName(status)); + } + } + status=U_ZERO_ERROR; + + +/* ======= Test ubrk_countAvialable() and ubrk_getAvialable() */ + + log_verbose("\nTesting ubrk_countAvailable() and ubrk_getAvailable()\n"); + count=ubrk_countAvailable(); + /* use something sensible w/o hardcoding the count */ + if(count < 0){ + log_err("FAIL: Error in ubrk_countAvialable() returned %d\n", count); + } + else{ + log_verbose("PASS: ubrk_countAvialable() successful returned %d\n", count); + } + for(i=0;i<count;i++) + { + log_verbose("%s\n", ubrk_getAvailable(i)); + if (ubrk_getAvailable(i) == 0) + log_err("No locale for which breakiterator is applicable\n"); + else + log_verbose("A locale %s for which breakiterator is applicable\n",ubrk_getAvailable(i)); + } + +/*========Test ubrk_first(), ubrk_last()...... and other functions*/ + + log_verbose("\nTesting the functions for word\n"); + start = ubrk_first(word); + if(start!=0) + log_err("error ubrk_start(word) did not return 0\n"); + log_verbose("first (word = %d\n", (int32_t)start); + pos=ubrk_next(word); + if(pos!=4) + log_err("error ubrk_next(word) did not return 4\n"); + log_verbose("next (word = %d\n", (int32_t)pos); + pos=ubrk_following(word, 4); + if(pos!=5) + log_err("error ubrl_following(word,4) did not return 6\n"); + log_verbose("next (word = %d\n", (int32_t)pos); + end=ubrk_last(word); + if(end!=49) + log_err("error ubrk_last(word) did not return 49\n"); + log_verbose("last (word = %d\n", (int32_t)end); + + pos=ubrk_previous(word); + log_verbose("%d %d\n", end, pos); + + pos=ubrk_previous(word); + log_verbose("%d \n", pos); + + if (ubrk_isBoundary(word, 2) != FALSE) { + log_err("error ubrk_isBoundary(word, 2) did not return FALSE\n"); + } + pos=ubrk_current(word); + if (pos != 4) { + log_err("error ubrk_current() != 4 after ubrk_isBoundary(word, 2)\n"); + } + if (ubrk_isBoundary(word, 4) != TRUE) { + log_err("error ubrk_isBoundary(word, 4) did not return TRUE\n"); + } + + + + log_verbose("\nTesting the functions for character\n"); + ubrk_first(character); + pos = ubrk_following(character, 5); + if(pos!=6) + log_err("error ubrk_following(character,5) did not return 6\n"); + log_verbose("Following (character,5) = %d\n", (int32_t)pos); + pos=ubrk_following(character, 18); + if(pos!=19) + log_err("error ubrk_following(character,18) did not return 19\n"); + log_verbose("Followingcharacter,18) = %d\n", (int32_t)pos); + pos=ubrk_preceding(character, 22); + if(pos!=21) + log_err("error ubrk_preceding(character,22) did not return 21\n"); + log_verbose("preceding(character,22) = %d\n", (int32_t)pos); + + + log_verbose("\nTesting the functions for line\n"); + pos=ubrk_first(line); + if(pos != 0) + log_err("error ubrk_first(line) returned %d, expected 0\n", (int32_t)pos); + pos = ubrk_next(line); + pos=ubrk_following(line, 18); + if(pos!=22) + log_err("error ubrk_following(line) did not return 22\n"); + log_verbose("following (line) = %d\n", (int32_t)pos); + + + log_verbose("\nTesting the functions for sentence\n"); + ubrk_first(sentence); + pos = ubrk_current(sentence); + log_verbose("Current(sentence) = %d\n", (int32_t)pos); + pos = ubrk_last(sentence); + if(pos!=49) + log_err("error ubrk_last for sentence did not return 49\n"); + log_verbose("Last (sentence) = %d\n", (int32_t)pos); + ubrk_first(sentence); + to = ubrk_following( sentence, 0 ); + if (to == 0) log_err("ubrk_following returned 0\n"); + to = ubrk_preceding( sentence, to ); + if (to != 0) log_err("ubrk_preceding didn't return 0\n"); + if (ubrk_first(sentence)!=ubrk_current(sentence)) { + log_err("error in ubrk_first() or ubrk_current()\n"); + } + + + /*---- */ + /*Testing ubrk_open and ubrk_close()*/ + log_verbose("\nTesting open and close for us locale\n"); + b = ubrk_open(UBRK_WORD, "fr_FR", text, u_strlen(text), &status); + if (U_FAILURE(status)) { + log_err("ubrk_open for word returned NULL: %s\n", myErrorName(status)); + } + ubrk_close(b); + + /* Test setText and setUText */ + { + UChar s1[] = {0x41, 0x42, 0x20, 0}; + UChar s2[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0}; + UText *ut = NULL; + UBreakIterator *bb; + int j; + + log_verbose("\nTesting ubrk_setText() and ubrk_setUText()\n"); + status = U_ZERO_ERROR; + bb = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status); + TEST_ASSERT_SUCCESS(status); + ubrk_setText(bb, s1, -1, &status); + TEST_ASSERT_SUCCESS(status); + ubrk_first(bb); + j = ubrk_next(bb); + TEST_ASSERT(j == 2); + ut = utext_openUChars(ut, s2, -1, &status); + ubrk_setUText(bb, ut, &status); + TEST_ASSERT_SUCCESS(status); + j = ubrk_next(bb); + TEST_ASSERT(j == 5); + + ubrk_close(bb); + utext_close(ut); + } + + ubrk_close(word); + ubrk_close(sentence); + ubrk_close(line); + ubrk_close(character); +} + +static void TestBreakIteratorSafeClone(void) +{ + UChar text[51]; /* Keep this odd to test for 64-bit memory alignment */ + /* NOTE: This doesn't reliably force mis-alignment of following items. */ + uint8_t buffer [CLONETEST_ITERATOR_COUNT] [U_BRK_SAFECLONE_BUFFERSIZE]; + int32_t bufferSize = U_BRK_SAFECLONE_BUFFERSIZE; + + UBreakIterator * someIterators [CLONETEST_ITERATOR_COUNT]; + UBreakIterator * someClonedIterators [CLONETEST_ITERATOR_COUNT]; + + UBreakIterator * brk; + UErrorCode status = U_ZERO_ERROR; + int32_t start,pos; + int32_t i; + + /*Testing ubrk_safeClone */ + + /* Note: the adjacent "" are concatenating strings, not adding a \" to the + string, which is probably what whoever wrote this intended. Don't fix, + because it would throw off the hard coded break positions in the following + tests. */ + u_uastrcpy(text, "He's from Africa. ""Mr. Livingston, I presume?"" Yeah"); + + /* US & Thai - rule-based & dictionary based */ + someIterators[0] = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status); + if(!someIterators[0] || U_FAILURE(status)) { + log_data_err("Couldn't open en_US word break iterator - %s\n", u_errorName(status)); + return; + } + + someIterators[1] = ubrk_open(UBRK_WORD, "th_TH", text, u_strlen(text), &status); + if(!someIterators[1] || U_FAILURE(status)) { + log_data_err("Couldn't open th_TH word break iterator - %s\n", u_errorName(status)); + return; + } + + /* test each type of iterator */ + for (i = 0; i < CLONETEST_ITERATOR_COUNT; i++) + { + + /* Check the various error & informational states */ + + /* Null status - just returns NULL */ + if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, 0)) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with null status\n"); + } + /* error status - should return 0 & keep error the same */ + status = U_MEMORY_ALLOCATION_ERROR; + if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status) || status != U_MEMORY_ALLOCATION_ERROR) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with incoming error status\n"); + } + status = U_ZERO_ERROR; + + /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/ + if (0 != ubrk_safeClone(someIterators[i], buffer[i], 0, &status) || status != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with null bufferSize pointer\n"); + } + status = U_ZERO_ERROR; + + /* buffer size pointer is 0 - fill in pbufferSize with a size */ + bufferSize = 0; + if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status) || U_FAILURE(status) || bufferSize <= 0) + { + log_err("FAIL: Cloned Iterator failed a sizing request ('preflighting')\n"); + } + /* Verify our define is large enough */ + if (U_BRK_SAFECLONE_BUFFERSIZE < bufferSize) + { + log_err("FAIL: Pre-calculated buffer size is too small\n"); + } + /* Verify we can use this run-time calculated size */ + if (0 == (brk = ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status)) || U_FAILURE(status)) + { + log_err("FAIL: Iterator can't be cloned with run-time size\n"); + } + if (brk) + ubrk_close(brk); + /* size one byte too small - should allocate & let us know */ + --bufferSize; + if (0 == (brk = ubrk_safeClone(someIterators[i], 0, &bufferSize, &status)) || status != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with too-small buffer size\n"); + } + if (brk) + ubrk_close(brk); + status = U_ZERO_ERROR; + bufferSize = U_BRK_SAFECLONE_BUFFERSIZE; + + /* Null buffer pointer - return Iterator & set error to U_SAFECLONE_ALLOCATED_ERROR */ + if (0 == (brk = ubrk_safeClone(someIterators[i], 0, &bufferSize, &status)) || status != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with null buffer pointer\n"); + } + if (brk) + ubrk_close(brk); + status = U_ZERO_ERROR; + + /* Mis-aligned buffer pointer. */ + { + char stackBuf[U_BRK_SAFECLONE_BUFFERSIZE+sizeof(void *)]; + void *p; + int32_t offset; + + brk = ubrk_safeClone(someIterators[i], &stackBuf[1], &bufferSize, &status); + if (U_FAILURE(status) || brk == 0) { + log_err("FAIL: Cloned Iterator failed with misaligned buffer pointer\n"); + } + if (status == U_SAFECLONE_ALLOCATED_WARNING) { + log_err("FAIL: Cloned Iterator allocated when using a mis-aligned buffer.\n"); + } + offset = (int32_t)((char *)&p-(char*)brk); + if (offset < 0) { + offset = -offset; + } + if (offset % sizeof(void *) != 0) { + log_err("FAIL: Cloned Iterator failed to align correctly with misaligned buffer pointer\n"); + } + if (brk) + ubrk_close(brk); + } + + + /* Null Iterator - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */ + if (0 != ubrk_safeClone(0, buffer[i], &bufferSize, &status) || status != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned Iterator failed to deal correctly with null Iterator pointer\n"); + } + status = U_ZERO_ERROR; + + /* Do these cloned Iterators work at all - make a first & next call */ + bufferSize = U_BRK_SAFECLONE_BUFFERSIZE; + someClonedIterators[i] = ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status); + + start = ubrk_first(someClonedIterators[i]); + if(start!=0) + log_err("error ubrk_start(clone) did not return 0\n"); + pos=ubrk_next(someClonedIterators[i]); + if(pos!=4) + log_err("error ubrk_next(clone) did not return 4\n"); + + ubrk_close(someClonedIterators[i]); + ubrk_close(someIterators[i]); + } +} + + +/* +// Open a break iterator from char * rules. Take care of conversion +// of the rules and error checking. +*/ +static UBreakIterator * testOpenRules(char *rules) { + UErrorCode status = U_ZERO_ERROR; + UChar *ruleSourceU = NULL; + void *strCleanUp = NULL; + UParseError parseErr; + UBreakIterator *bi; + + ruleSourceU = toUChar(rules, &strCleanUp); + + bi = ubrk_openRules(ruleSourceU, -1, /* The rules */ + NULL, -1, /* The text to be iterated over. */ + &parseErr, &status); + + if (U_FAILURE(status)) { + log_err("FAIL: ubrk_openRules: ICU Error \"%s\"\n", u_errorName(status)); + bi = 0; + }; + freeToUCharStrings(&strCleanUp); + return bi; + +} + +/* + * TestBreakIteratorRules - Verify that a break iterator can be created from + * a set of source rules. + */ +static void TestBreakIteratorRules() { + /* Rules will keep together any run of letters not including 'a', OR + * keep together 'abc', but only when followed by 'def', OTHERWISE + * just return one char at a time. + */ + char rules[] = "abc{666}/def;\n [\\p{L} - [a]]* {2}; . {1};"; + /* 0123456789012345678 */ + char data[] = "abcdex abcdefgh-def"; /* the test data string */ + char breaks[] = "** ** * ** *"; /* * the expected break positions */ + char tags[] = "01 21 6 21 2"; /* expected tag values at break positions */ + int32_t tagMap[] = {0, 1, 2, 3, 4, 5, 666}; + + UChar *uData; + void *freeHook = NULL; + UErrorCode status = U_ZERO_ERROR; + int32_t pos; + int i; + + UBreakIterator *bi = testOpenRules(rules); + if (bi == NULL) {return;} + uData = toUChar(data, &freeHook); + ubrk_setText(bi, uData, -1, &status); + + pos = ubrk_first(bi); + for (i=0; i<sizeof(breaks); i++) { + if (pos == i && breaks[i] != '*') { + log_err("FAIL: unexpected break at position %d found\n", pos); + break; + } + if (pos != i && breaks[i] == '*') { + log_err("FAIL: expected break at position %d not found.\n", i); + break; + } + if (pos == i) { + int32_t tag, expectedTag; + tag = ubrk_getRuleStatus(bi); + expectedTag = tagMap[tags[i]&0xf]; + if (tag != expectedTag) { + log_err("FAIL: incorrect tag value. Position = %d; expected tag %d, got %d", + pos, expectedTag, tag); + break; + } + pos = ubrk_next(bi); + } + } + + freeToUCharStrings(&freeHook); + ubrk_close(bi); +} + +static void TestBreakIteratorRuleError() { +/* + * TestBreakIteratorRuleError - Try to create a BI from rules with syntax errors, + * check that the error is reported correctly. + */ + char rules[] = " # This is a rule comment on line 1\n" + "[:L:]; # this rule is OK.\n" + "abcdefg); # Error, mismatched parens\n"; + UChar *uRules; + void *freeHook = NULL; + UErrorCode status = U_ZERO_ERROR; + UParseError parseErr; + UBreakIterator *bi; + + uRules = toUChar(rules, &freeHook); + bi = ubrk_openRules(uRules, -1, /* The rules */ + NULL, -1, /* The text to be iterated over. */ + &parseErr, &status); + if (U_SUCCESS(status)) { + log_err("FAIL: construction of break iterator succeeded when it should have failed.\n"); + ubrk_close(bi); + } else { + if (parseErr.line != 3 || parseErr.offset != 8) { + log_err("FAIL: incorrect error position reported. Got line %d, char %d, expected line 3, char 7", + parseErr.line, parseErr.offset); + } + } + freeToUCharStrings(&freeHook); +} + + +/* +* TestsBreakIteratorStatusVals() Test the ubrk_getRuleStatusVec() funciton +*/ +static void TestBreakIteratorStatusVec() { + #define RULE_STRING_LENGTH 200 + UChar rules[RULE_STRING_LENGTH]; + + #define TEST_STRING_LENGTH 25 + UChar testString[TEST_STRING_LENGTH]; + UBreakIterator *bi = NULL; + int32_t pos = 0; + int32_t vals[10]; + int32_t numVals; + UErrorCode status = U_ZERO_ERROR; + + u_uastrncpy(rules, "[A-N]{100}; \n" + "[a-w]{200}; \n" + "[\\p{L}]{300}; \n" + "[\\p{N}]{400}; \n" + "[0-5]{500}; \n" + "!.*;\n", RULE_STRING_LENGTH); + u_uastrncpy(testString, "ABC", TEST_STRING_LENGTH); + + + bi = ubrk_openRules(rules, -1, testString, -1, NULL, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(bi != NULL); + + /* The TEST_ASSERT above should change too... */ + if (bi != NULL) { + pos = ubrk_next(bi); + TEST_ASSERT(pos == 1); + + memset(vals, -1, sizeof(vals)); + numVals = ubrk_getRuleStatusVec(bi, vals, 10, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(numVals == 2); + TEST_ASSERT(vals[0] == 100); + TEST_ASSERT(vals[1] == 300); + TEST_ASSERT(vals[2] == -1); + + numVals = ubrk_getRuleStatusVec(bi, vals, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(numVals == 2); + } + + ubrk_close(bi); +} + + +/* + * static void TestBreakIteratorUText(void); + * + * Test that ubrk_setUText() is present and works for a simple case. + */ +static void TestBreakIteratorUText(void) { + const char *UTF8Str = "\x41\xc3\x85\x5A\x20\x41\x52\x69\x6E\x67"; /* c3 85 is utf-8 for A with a ring on top */ + /* 0 1 2 34567890 */ + + UErrorCode status = U_ZERO_ERROR; + UBreakIterator *bi = NULL; + int32_t pos = 0; + + + UText *ut = utext_openUTF8(NULL, UTF8Str, -1, &status); + TEST_ASSERT_SUCCESS(status); + + bi = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status); + if (U_FAILURE(status)) { + log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status)); + return; + } + + ubrk_setUText(bi, ut, &status); + if (U_FAILURE(status)) { + log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status)); + return; + } + + pos = ubrk_first(bi); + TEST_ASSERT(pos == 0); + + pos = ubrk_next(bi); + TEST_ASSERT(pos == 4); + + pos = ubrk_next(bi); + TEST_ASSERT(pos == 5); + + pos = ubrk_next(bi); + TEST_ASSERT(pos == 10); + + pos = ubrk_next(bi); + TEST_ASSERT(pos == UBRK_DONE); + ubrk_close(bi); + utext_close(ut); +} + + + +#endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h new file mode 100644 index 00000000000..ea6769fcf08 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h @@ -0,0 +1,35 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CBIAPTS.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +*********************************************************************************/ +/* C API TEST FOR BREAKITERATOR */ + +#ifndef _CBRKITRAPITST +#define _CBRKITRAPITST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_BREAK_ITERATION + +#include "cintltst.h" + +/** +* This is an API test. It doesn't test very many cases, and doesn't +* try to test the full functionality. It just calls each function in the class and +* verifies that it works on a basic level. +**/ +/* The function used to test the BreakIterator API*/ +static void TestBreakIteratorCAPI(void); + +#endif /* #if !UCONFIG_NO_BREAK_ITERATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c new file mode 100644 index 00000000000..a73f3a74655 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c @@ -0,0 +1,434 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* file name: cbididat.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep22 +* created by: Markus W. Scherer +*/ + +#include "unicode/utypes.h" +#include "unicode/uchar.h" +#include "unicode/ubidi.h" +#include "cbiditst.h" + +const char * const +dirPropNames[U_CHAR_DIRECTION_COUNT]={ + "L", "R", "EN", "ES", "ET", "AN", "CS", "B", "S", "WS", "ON", + "LRE", "LRO", "AL", "RLE", "RLO", "PDF", "NSM", "BN" +}; + +UChar +charFromDirProp[U_CHAR_DIRECTION_COUNT]={ + /* L R EN ES ET AN CS B S WS ON */ + 0x61, 0x5d0, 0x30, 0x2f, 0x25, 0x660, 0x2c, 0xa, 0x9, 0x20, 0x26, + /* LRE LRO AL RLE RLO PDF NSM BN */ + 0x202a, 0x202d, 0x627, 0x202b, 0x202e, 0x202c, 0x308, 0x200c +}; + +static const uint8_t +testText1[]={ + L, L, WS, L, WS, EN, L, B +}; + +static const UBiDiLevel +testLevels1[]={ + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint8_t +testVisualMap1[]={ + 0, 1, 2, 3, 4, 5, 6, 7 +}; + +static const uint8_t +testText2[]={ + R, AL, WS, R, AL, WS, R +}; + +static const UBiDiLevel +testLevels2[]={ + 1, 1, 1, 1, 1, 1, 1 +}; + +static const uint8_t +testVisualMap2[]={ + 6, 5, 4, 3, 2, 1, 0 +}; + +static const uint8_t +testText3[]={ + L, L, WS, EN, CS, WS, EN, CS, EN, WS, L, L +}; + +static const UBiDiLevel +testLevels3[]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint8_t +testVisualMap3[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +static const uint8_t +testText4[]={ + L, AL, AL, AL, L, AL, AL, L, WS, EN, CS, WS, EN, CS, EN, WS, L, L +}; + +static const UBiDiLevel +testLevels4[]={ + 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint8_t +testVisualMap4[]={ + 0, 3, 2, 1, 4, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 +}; + +static const uint8_t +testText5[]={ + AL, R, AL, WS, EN, CS, WS, EN, CS, EN, WS, R, R, WS, L, L +}; + +static const UBiDiLevel +testLevels5[]={ + 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2 +}; + +static const uint8_t +testVisualMap5[]={ + 15, 14, 13, 12, 11, 10, 9, 6, 7, 8, 5, 4, 3, 2, 0, 1 +}; + +static const uint8_t +testText6[]={ + R, EN, NSM, ET +}; + +static const UBiDiLevel +testLevels6[]={ + 1, 2, 2, 2 +}; + +static const uint8_t +testVisualMap6[]={ + 3, 0, 1, 2 +}; + +#if 0 +static const uint8_t +testText7[]={ + /* empty */ +}; + +static const UBiDiLevel +testLevels7[]={ +}; + +static const uint8_t +testVisualMap7[]={ +}; + +#endif + +static const uint8_t +testText8[]={ + RLE, WS, R, R, R, WS, PDF, WS, B +}; + +static const UBiDiLevel +testLevels8[]={ + 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const uint8_t +testVisualMap8[]={ + 8, 7, 6, 5, 4, 3, 2, 1, 0 +}; + +static const uint8_t +testText9[]={ + LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, + LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, + AN, RLO, NSM, LRE, PDF, RLE, ES, EN, ON +}; + +static const UBiDiLevel +testLevels9[]={ + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61 +}; + +static const uint8_t +testVisualMap9[]={ + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 7, 6, 5, 4, 3, 2, 1, 0 +}; + +static const uint8_t +testText10[]={ + LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, + LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, + LRE, BN, CS, RLO, S, PDF, EN, LRO, AN, ES +}; + +static const UBiDiLevel +testLevels10[]={ + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 62, 62, 62, 62, 60 +}; + +static const uint8_t +testVisualMap10[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 +}; + +static const uint8_t +testText11[]={ + S, WS, NSM, RLE, WS, L, L, L, WS, LRO, WS, R, R, R, WS, RLO, WS, L, L, + L, WS, LRE, WS, R, R, R, WS, PDF, WS, L, L, L, WS, PDF, WS, + AL, AL, AL, WS, PDF, WS, L, L, L, WS, PDF, WS, L, L, L, WS, PDF, + ON, PDF, BN, BN, ON, PDF +}; + +static const UBiDiLevel +testLevels11[]={ + 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint8_t +testVisualMap11[]={ + 0, 1, 2, 44, 43, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 31, 30, 29, 28, 27, 26, 20, 21, 24, 23, 22, 25, 19, 18, 17, 16, 15, 14, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 3, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 +}; + +static const uint8_t +testText12[]={ + NSM, WS, L, L, L, L, L, L, L, WS, L, L, L, L, WS, + R, R, R, R, R, WS, L, L, L, L, L, L, L, WS, WS, AL, + AL, AL, AL, WS, EN, EN, ES, EN, EN, CS, S, EN, EN, CS, WS, + EN, EN, WS, AL, AL, AL, AL, AL, B, L, L, L, L, L, L, + L, L, WS, AN, AN, CS, AN, AN, WS +}; + +static const UBiDiLevel +testLevels12[]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0 +}; + +static const uint8_t +testVisualMap12[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 +}; + +static const UBiDiLevel +testLevels13[]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0 +}; + +static const uint8_t +testVisualMap13[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 +}; + +static const UBiDiLevel +testLevels14[]={ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 2, 4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2 +}; + +static const uint8_t +testVisualMap14[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 +}; + +static const UBiDiLevel +testLevels15[]={ + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 5, 5, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 5 +}; + +static const uint8_t +testVisualMap15[]={ + 69, 68, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 55, 54, 53, 52, 51, 50, 49, 42, 43, 44, 45, 46, 47, 48, 41, 40, 39, 38, 37, 36, 35, 33, 34, 32, 30, 31, 29, 28, 26, 27, 25, 24, 22, 23, 21, 20, 19, 18, 17, 16, 15, 7, 8, 9, 10, 11, 12, 13, 14, 6, 1, 2, 3, 4, 5, 0 +}; + +static const UBiDiLevel +testLevels16[]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0 +}; + +static const uint8_t +testVisualMap16[]={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 +}; + +static const uint8_t +testText13[]={ + ON, L, RLO, CS, R, WS, AN, AN, PDF, LRE, R, L, LRO, WS, BN, ON, S, LRE, LRO, B +}; + +static const UBiDiLevel +testLevels17[]={ + 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, 4, 4, 4, 4, 0, 0, 0, 0 +}; + +static const uint8_t +testVisualMap17[]={ + 0, 1, 15, 14, 13, 12, 11, 10, 4, 3, 2, 5, 6, 7, 8, 9, 16, 17, 18, 19 +}; + +static const UBiDiLevel +testLevels18[]={ + 0, 0, 1, 1, 1, 0 +}; + +static const uint8_t +testVisualMap18[]={ + 0, 1, 4, 3, 2, 5 +}; + +static const uint8_t +testText14[]={ + RLO, RLO, AL, AL, WS, EN, ES, ON, WS, S, S, PDF, LRO, WS, AL, ET, RLE, ON, EN, B +}; + +static const UBiDiLevel +testLevels19[]={ + 1 +}; + +static const uint8_t +testVisualMap19[]={ + 0 +}; + +static const uint8_t +testText15[]={ + R, L, CS, L +}; + +static const UBiDiLevel +testLevels20[]={ + 2 +}; + +static const uint8_t +testText16[]={ + L, L, L, WS, L, L, L, WS, L, L, L +}; + +static const UBiDiLevel +testLevels21[]={ + 2, 2, 2, 2, 2, 2, 2, 1 +}; + +static const uint8_t +testVisualMap20[]={ + 1, 2, 3, 4, 5, 6, 7, 0 +}; + +static const uint8_t +testText17[]={ + R, R, R, WS, R, R, R, WS, R, R, R +}; + +static const UBiDiLevel +testLevels22[]={ + 1, 1, 1, 1, 1, 1, 1, 0 +}; + +static const uint8_t +testVisualMap21[]={ + 6, 5, 4, 3, 2, 1, 0, 7 +}; + +static const uint8_t +testTextXX[]={ + L +}; + +static const UBiDiLevel +testLevelsXX[]={ + 2 +}; + +static const uint8_t +testVisualMapXX[]={ + 0 +}; + +const BiDiTestData +tests[]={ + {testText1, ARRAY_LENGTH(testText1), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_LTR, 0, + testLevels1, testVisualMap1}, + {testText2, ARRAY_LENGTH(testText2), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_RTL, 1, + testLevels2, testVisualMap2}, + {testText3, ARRAY_LENGTH(testText3), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_LTR, 0, + testLevels3, testVisualMap3}, + {testText4, ARRAY_LENGTH(testText4), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels4, testVisualMap4}, + {testText5, ARRAY_LENGTH(testText5), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 1, + testLevels5, testVisualMap5}, + {testText6, ARRAY_LENGTH(testText6), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 1, + testLevels6, testVisualMap6}, + {NULL, 0, UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_LTR, 0, + NULL, NULL}, + {testText8, ARRAY_LENGTH(testText8), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_RTL, 1, + testLevels8, testVisualMap8}, + {testText9, ARRAY_LENGTH(testText9), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels9, testVisualMap9}, + {testText10, ARRAY_LENGTH(testText10), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels10, testVisualMap10}, + {testText11, ARRAY_LENGTH(testText11), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels11, testVisualMap11}, + {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels12, testVisualMap12}, + {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_RTL, -1, -1, + UBIDI_MIXED, 0, + testLevels13, testVisualMap13}, + {testText12, ARRAY_LENGTH(testText12), 2, -1, -1, + UBIDI_MIXED, 2, + testLevels14, testVisualMap14}, + {testText12, ARRAY_LENGTH(testText12), 5, -1, -1, + UBIDI_MIXED, 5, + testLevels15, testVisualMap15}, + {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels16, testVisualMap16}, + {testText13, ARRAY_LENGTH(testText13), UBIDI_DEFAULT_LTR, -1, -1, + UBIDI_MIXED, 0, + testLevels17, testVisualMap17}, + {testText13, ARRAY_LENGTH(testText13), UBIDI_DEFAULT_LTR, 0, 6, + UBIDI_MIXED, 0, + testLevels18, testVisualMap18}, + {testText14, ARRAY_LENGTH(testText14), UBIDI_DEFAULT_LTR, 13, 14, + UBIDI_RTL, 1, + testLevels19, testVisualMap19}, + {testText15, ARRAY_LENGTH(testText15), UBIDI_DEFAULT_LTR, 2, 3, + UBIDI_LTR, 2, + testLevels20, testVisualMap19}, + {testText16, ARRAY_LENGTH(testText16), UBIDI_RTL, 0, 8, + UBIDI_MIXED, 1, + testLevels21, testVisualMap20}, + {testText17, ARRAY_LENGTH(testText17), UBIDI_LTR, 0, 8, + UBIDI_MIXED, 0, + testLevels22, testVisualMap21}, + {testTextXX, ARRAY_LENGTH(testTextXX), UBIDI_RTL, -1, -1, + UBIDI_MIXED, 1, testLevelsXX, testVisualMapXX} +}; + +const int +bidiTestCount=ARRAY_LENGTH(tests); diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c new file mode 100644 index 00000000000..517d219df33 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c @@ -0,0 +1,3860 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* file name: cbiditst.cpp +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep27 +* created by: Markus W. Scherer, updated by Matitiahu Allouche +*/ + +#include "cintltst.h" +#include "unicode/utypes.h" +#include "unicode/uchar.h" +#include "unicode/ustring.h" +#include "unicode/ubidi.h" +#include "unicode/ushape.h" +#include "cbiditst.h" +#include "cstring.h" +/* the following include is needed for sprintf */ +#include <stdio.h> + +#define MAXLEN MAX_STRING_LENGTH +#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) + +/* prototypes ---------------------------------------------------------------*/ + +void addComplexTest(TestNode** root); + +static void testCharFromDirProp(void); + +static void testBidi(void); + +static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst); + +static void doMisc(void); + +static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, + int32_t lineStart, UBool countRunsFirst); + +static void _testReordering(UBiDi *pBiDi, int testNumber); + +static void testInverse(void); + +static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction); + +static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, + UBiDiLevel direction, UErrorCode *pErrorCode); + +static void _testWriteReverse(void); + +static void _testManyAddedPoints(void); + +static void _testMisc(void); + +static void doArabicShapingTest(void); + +static void doLamAlefSpecialVLTRArabicShapingTest(void); + +static void doTashkeelSpecialVLTRArabicShapingTest(void); + +static void doLOGICALArabicDeShapingTest(void); + +static void doArabicShapingTestForBug5421(void); + +static void testReorder(void); + +static void testFailureRecovery(void); + +static void testMultipleParagraphs(void); + +/* new BIDI API */ +static void testReorderingMode(void); +static void testReorderRunsOnly(void); +static void testStreaming(void); +static void testClassOverride(void); +static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen, + uint32_t option, UBiDiLevel level, char *result); +static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, + const char *srcChars, const char *destChars, + const UChar *dest, int32_t destLen, int mode, + int option, UBiDiLevel level); +static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars, + const char *destChars, + int32_t destLen, const char *mode, + const char *option, UBiDiLevel level); +static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, + const char *dest, const char *mode, const char* option, + UBiDiLevel level, UBool forward); + +/* helpers ------------------------------------------------------------------ */ + +static const char *levelString="..............................................................."; + +static void initCharFromDirProps(void); + +static UChar * +getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer); + +static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels); + +/* regression tests ---------------------------------------------------------*/ + +void +addComplexTest(TestNode** root) { + addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp"); + addTest(root, testBidi, "complex/bidi/TestBidi"); + addTest(root, testInverse, "complex/bidi/TestInverse"); + addTest(root, testReorder,"complex/bidi/TestReorder"); + addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery"); + addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs"); + addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode"); + addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly"); + addTest(root, testStreaming, "complex/bidi/TestStreaming"); + addTest(root, testClassOverride, "complex/bidi/TestClassOverride"); + + addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest"); + addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef"); + addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel"); + addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping"); + addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421"); +} + +static void +testCharFromDirProp(void) { + /* verify that the exemplar characters have the expected bidi classes */ + int32_t i; + + log_verbose("\nEntering TestCharFromDirProp\n\n"); + initCharFromDirProps(); + + for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) { + if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) { + log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n", + i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i); + } + } + log_verbose("\nExiting TestCharFromDirProp\n\n"); +} + +static void +testBidi(void) { + UBiDi *pBiDi, *pLine=NULL; + UErrorCode errorCode=U_ZERO_ERROR; + + log_verbose("\nEntering TestBidi\n\n"); + + pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode); + if(pBiDi!=NULL) { + pLine=ubidi_open(); + if(pLine!=NULL) { + doTests(pBiDi, pLine, FALSE); + doTests(pBiDi, pLine, TRUE); + } else { + log_err("ubidi_open() returned NULL, out of memory\n"); + } + } else { + log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode)); + } + doMisc(); + + if(pLine!=NULL) { + ubidi_close(pLine); + } + if(pBiDi!=NULL) { + ubidi_close(pBiDi); + } + + log_verbose("\nExiting TestBidi\n\n"); +} + +static void +doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) { + int testNumber; + UChar string[MAXLEN]; + UErrorCode errorCode; + int32_t lineStart; + UBiDiLevel paraLevel; + + for(testNumber=0; testNumber<bidiTestCount; ++testNumber) { + errorCode=U_ZERO_ERROR; + getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string); + paraLevel=tests[testNumber].paraLevel; + ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode); + if(U_SUCCESS(errorCode)) { + log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n", + testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel); + lineStart=tests[testNumber].lineStart; + if(lineStart==-1) { + doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst); + } else { + ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode); + if(U_SUCCESS(errorCode)) { + log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n", + lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine)); + doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst); + } else { + log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n", + testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode)); + } + } + } else { + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + testNumber, paraLevel, myErrorName(errorCode)); + } + } +} + +static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +#define TABLE_SIZE 256 +static UBool tablesInitialized = FALSE; +static UChar pseudoToUChar[TABLE_SIZE]; +static uint8_t UCharToPseudo[TABLE_SIZE]; /* used for Unicode chars < 0x0100 */ +static uint8_t UCharToPseud2[TABLE_SIZE]; /* used for Unicode chars >=0x0100 */ + +static void buildPseudoTables(void) +/* + The rules for pseudo-Bidi are as follows: + - [ == LRE + - ] == RLE + - { == LRO + - } == RLO + - ^ == PDF + - @ == LRM + - & == RLM + - A-F == Arabic Letters 0631-0636 + - G-V == Hebrew letters 05d7-05e6 + - W-Z == Unassigned RTL 08d0-08d3 + - 0-5 == western digits 0030-0035 + - 6-9 == Arabic-Indic digits 0666-0669 + - ` == Combining Grave Accent 0300 (NSM) + - ~ == Delete 007f (BN) + - | == Paragraph Separator 2029 (B) + - _ == Info Separator 1 001f (S) + All other characters represent themselves as Latin-1, with the corresponding + Bidi properties. +*/ +{ + int i; + UChar uchar; + uint8_t c; + /* initialize all tables to unknown */ + for (i=0; i < TABLE_SIZE; i++) { + pseudoToUChar[i] = 0xFFFD; + UCharToPseudo[i] = '?'; + UCharToPseud2[i] = '?'; + } + /* initialize non letters or digits */ + pseudoToUChar[(uint8_t) 0 ] = 0x0000; UCharToPseudo[0x00] = (uint8_t) 0 ; + pseudoToUChar[(uint8_t)' '] = 0x0020; UCharToPseudo[0x20] = (uint8_t)' '; + pseudoToUChar[(uint8_t)'!'] = 0x0021; UCharToPseudo[0x21] = (uint8_t)'!'; + pseudoToUChar[(uint8_t)'"'] = 0x0022; UCharToPseudo[0x22] = (uint8_t)'"'; + pseudoToUChar[(uint8_t)'#'] = 0x0023; UCharToPseudo[0x23] = (uint8_t)'#'; + pseudoToUChar[(uint8_t)'$'] = 0x0024; UCharToPseudo[0x24] = (uint8_t)'$'; + pseudoToUChar[(uint8_t)'%'] = 0x0025; UCharToPseudo[0x25] = (uint8_t)'%'; + pseudoToUChar[(uint8_t)'\'']= 0x0027; UCharToPseudo[0x27] = (uint8_t)'\''; + pseudoToUChar[(uint8_t)'('] = 0x0028; UCharToPseudo[0x28] = (uint8_t)'('; + pseudoToUChar[(uint8_t)')'] = 0x0029; UCharToPseudo[0x29] = (uint8_t)')'; + pseudoToUChar[(uint8_t)'*'] = 0x002A; UCharToPseudo[0x2A] = (uint8_t)'*'; + pseudoToUChar[(uint8_t)'+'] = 0x002B; UCharToPseudo[0x2B] = (uint8_t)'+'; + pseudoToUChar[(uint8_t)','] = 0x002C; UCharToPseudo[0x2C] = (uint8_t)','; + pseudoToUChar[(uint8_t)'-'] = 0x002D; UCharToPseudo[0x2D] = (uint8_t)'-'; + pseudoToUChar[(uint8_t)'.'] = 0x002E; UCharToPseudo[0x2E] = (uint8_t)'.'; + pseudoToUChar[(uint8_t)'/'] = 0x002F; UCharToPseudo[0x2F] = (uint8_t)'/'; + pseudoToUChar[(uint8_t)':'] = 0x003A; UCharToPseudo[0x3A] = (uint8_t)':'; + pseudoToUChar[(uint8_t)';'] = 0x003B; UCharToPseudo[0x3B] = (uint8_t)';'; + pseudoToUChar[(uint8_t)'<'] = 0x003C; UCharToPseudo[0x3C] = (uint8_t)'<'; + pseudoToUChar[(uint8_t)'='] = 0x003D; UCharToPseudo[0x3D] = (uint8_t)'='; + pseudoToUChar[(uint8_t)'>'] = 0x003E; UCharToPseudo[0x3E] = (uint8_t)'>'; + pseudoToUChar[(uint8_t)'?'] = 0x003F; UCharToPseudo[0x3F] = (uint8_t)'?'; + pseudoToUChar[(uint8_t)'\\']= 0x005C; UCharToPseudo[0x5C] = (uint8_t)'\\'; + /* initialize specially used characters */ + pseudoToUChar[(uint8_t)'`'] = 0x0300; UCharToPseud2[0x00] = (uint8_t)'`'; /* NSM */ + pseudoToUChar[(uint8_t)'@'] = 0x200E; UCharToPseud2[0x0E] = (uint8_t)'@'; /* LRM */ + pseudoToUChar[(uint8_t)'&'] = 0x200F; UCharToPseud2[0x0F] = (uint8_t)'&'; /* RLM */ + pseudoToUChar[(uint8_t)'_'] = 0x001F; UCharToPseudo[0x1F] = (uint8_t)'_'; /* S */ + pseudoToUChar[(uint8_t)'|'] = 0x2029; UCharToPseud2[0x29] = (uint8_t)'|'; /* B */ + pseudoToUChar[(uint8_t)'['] = 0x202A; UCharToPseud2[0x2A] = (uint8_t)'['; /* LRE */ + pseudoToUChar[(uint8_t)']'] = 0x202B; UCharToPseud2[0x2B] = (uint8_t)']'; /* RLE */ + pseudoToUChar[(uint8_t)'^'] = 0x202C; UCharToPseud2[0x2C] = (uint8_t)'^'; /* PDF */ + pseudoToUChar[(uint8_t)'{'] = 0x202D; UCharToPseud2[0x2D] = (uint8_t)'{'; /* LRO */ + pseudoToUChar[(uint8_t)'}'] = 0x202E; UCharToPseud2[0x2E] = (uint8_t)'}'; /* RLO */ + pseudoToUChar[(uint8_t)'~'] = 0x007F; UCharToPseudo[0x7F] = (uint8_t)'~'; /* BN */ + /* initialize western digits */ + for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseudo[uchar & 0x00ff] = c; + } + /* initialize Hindi digits */ + for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseud2[uchar & 0x00ff] = c; + } + /* initialize Arabic letters */ + for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseud2[uchar & 0x00ff] = c; + } + /* initialize Hebrew letters */ + for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseud2[uchar & 0x00ff] = c; + } + /* initialize Unassigned code points */ + for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseud2[uchar & 0x00ff] = c; + } + /* initialize Latin lower case letters */ + for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) { + c = (uint8_t)columns[i]; + pseudoToUChar[c] = uchar; + UCharToPseudo[uchar & 0x00ff] = c; + } + tablesInitialized = TRUE; +} + +/*----------------------------------------------------------------------*/ + +static int pseudoToU16(const int length, const char * input, UChar * output) +/* This function converts a pseudo-Bidi string into a UChar string. + It returns the length of the UChar string. +*/ +{ + int i; + if (!tablesInitialized) { + buildPseudoTables(); + } + for (i = 0; i < length; i++) + output[i] = pseudoToUChar[(uint8_t)input[i]]; + return length; +} + +/*----------------------------------------------------------------------*/ + +static int u16ToPseudo(const int length, const UChar * input, char * output) +/* This function converts a UChar string into a pseudo-Bidi string. + It returns the length of the pseudo-Bidi string. +*/ +{ + int i; + UChar uchar; + if (!tablesInitialized) { + buildPseudoTables(); + } + for (i = 0; i < length; i++) + { + uchar = input[i]; + output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] : + UCharToPseud2[uchar & 0x00ff]; + } + output[length] = '\0'; + return length; +} + +static char * formatLevels(UBiDi *bidi, char *buffer) { + UErrorCode ec = U_ZERO_ERROR; + const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec); + int len = ubidi_getLength(bidi); + char c; + int i, k; + + if(U_FAILURE(ec)) { + strcpy(buffer, "BAD LEVELS"); + return buffer; + } + for (i=0; i<len; i++) { + k = gotLevels[i]; + if (k >= sizeof(columns)) + c = '+'; + else + c = columns[k]; + buffer[i] = c; + } + buffer[len] = '\0'; + return buffer; +} +static const char *reorderingModeNames[] = { + "UBIDI_REORDER_DEFAULT", + "UBIDI_REORDER_NUMBERS_SPECIAL", + "UBIDI_REORDER_GROUP_NUMBERS_WITH_R", + "UBIDI_REORDER_RUNS_ONLY", + "UBIDI_REORDER_INVERSE_NUMBERS_AS_L", + "UBIDI_REORDER_INVERSE_LIKE_DIRECT", + "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"}; + +static char *reorderingOptionNames(char *buffer, int options) { + buffer[0] = 0; + if (options & UBIDI_OPTION_INSERT_MARKS) { + strcat(buffer, " UBIDI_OPTION_INSERT_MARKS"); + } + if (options & UBIDI_OPTION_REMOVE_CONTROLS) { + strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS"); + } + if (options & UBIDI_OPTION_STREAMING) { + strcat(buffer, " UBIDI_OPTION_STREAMING"); + } + return buffer; +} + +static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst) +/* src and dst are char arrays encoded as pseudo Bidi */ +{ + /* Since calls to log_err with a \n within the pattern increment the + * error count, new lines are issued via fputs, except when we want the + * increment to happen. + */ + UErrorCode errorCode=U_ZERO_ERROR; + int32_t i, length = ubidi_getProcessedLength(bidi); + const UBiDiLevel *levels; + char levelChars[MAXLEN]; + UBiDiLevel lev; + int32_t runCount; + char buffer[100]; + log_err("========================================"); fputs("\n", stderr); + levels = ubidi_getLevels(bidi, &errorCode); + if (U_FAILURE(errorCode)) { + strcpy(levelChars, "BAD LEVELS"); + } else { + log_err("Processed length: %d", length); fputs("\n", stderr); + for (i = 0; i < length; i++) { + lev = levels[i]; + if (lev < sizeof(columns)) { + levelChars[i] = columns[lev]; + } else { + levelChars[i] = '+'; + } + } + levelChars[length] = 0; + } + log_err("Levels: %s", levelChars); fputs("\n", stderr); + log_err("Source: %s", src); fputs("\n", stderr); + log_err("Result: %s", dst); fputs("\n", stderr); + log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr); + log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr); + i = ubidi_getReorderingMode(bidi); + log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]); + fputs("\n", stderr); + i = ubidi_getReorderingOptions(bidi); + log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i)); + fputs("\n", stderr); + runCount = ubidi_countRuns(bidi, &errorCode); + if (U_FAILURE(errorCode)) { + log_err( "BAD RUNS"); + } else { + log_err("Runs: %d => logicalStart.length/level: ", runCount); + for (i = 0; i < runCount; i++) { + UBiDiDirection dir; + int32_t start, len; + dir = ubidi_getVisualRun(bidi, i, &start, &len); + log_err(" %d.%d/%d", start, len, dir); + } + } + fputs("\n", stderr); +} + +static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2) +{ + /* No test for []{} since they have special meaning for pseudo Bidi */ + static char mates1Chars[] = "<>()"; + static char mates2Chars[] = "><)("; + UBiDiLevel level; + int k, len; + + if (c1 == c2) { + return TRUE; + } + /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i], + so we use the appropriate run's level, which is good for all cases. + */ + ubidi_getLogicalRun(bidi, i, NULL, &level); + if ((level & 1) == 0) { + return FALSE; + } + len = strlen(mates1Chars); + for (k = 0; k < len; k++) { + if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) { + return TRUE; + } + } + return FALSE; +} + +static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars) +/* srcChars and dstChars are char arrays encoded as pseudo Bidi */ +{ + int32_t i, idx, logLimit, visLimit; + UBool testOK, errMap, errDst; + UErrorCode errorCode=U_ZERO_ERROR; + int32_t visMap[MAXLEN]; + int32_t logMap[MAXLEN]; + char accumSrc[MAXLEN]; + char accumDst[MAXLEN]; + ubidi_getVisualMap(bidi, visMap, &errorCode); + ubidi_getLogicalMap(bidi, logMap, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("Error #1 invoking ICU within checkWhatYouCan\n"); + return FALSE; + } + + testOK = TRUE; + errMap = errDst = FALSE; + logLimit = ubidi_getProcessedLength(bidi); + visLimit = ubidi_getResultLength(bidi); + memset(accumSrc, '?', logLimit); + memset(accumDst, '?', visLimit); + + for (i = 0; i < logLimit; i++) { + idx = ubidi_getVisualIndex(bidi, i, &errorCode); + if (idx != logMap[i]) { + errMap = TRUE; + } + if (idx == UBIDI_MAP_NOWHERE) { + continue; + } + if (idx >= visLimit) { + continue; + } + accumDst[idx] = srcChars[i]; + if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) { + errDst = TRUE; + } + } + accumDst[visLimit] = 0; + if (U_FAILURE(errorCode)) { + log_err("Error #2 invoking ICU within checkWhatYouCan\n"); + return FALSE; + } + if (errMap) { + if (testOK) { + printCaseInfo(bidi, srcChars, dstChars); + testOK = FALSE; + } + log_err("Mismatch between getLogicalMap() and getVisualIndex()\n"); + log_err("Map :"); + for (i = 0; i < logLimit; i++) { + log_err(" %d", logMap[i]); + } + fputs("\n", stderr); + log_err("Indexes:"); + for (i = 0; i < logLimit; i++) { + log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode)); + } + fputs("\n", stderr); + } + if (errDst) { + if (testOK) { + printCaseInfo(bidi, srcChars, dstChars); + testOK = FALSE; + } + log_err("Source does not map to Result\n"); + log_err("We got: %s", accumDst); fputs("\n", stderr); + } + + errMap = errDst = FALSE; + for (i = 0; i < visLimit; i++) { + idx = ubidi_getLogicalIndex(bidi, i, &errorCode); + if (idx != visMap[i]) { + errMap = TRUE; + } + if (idx == UBIDI_MAP_NOWHERE) { + continue; + } + if (idx >= logLimit) { + continue; + } + accumSrc[idx] = dstChars[i]; + if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) { + errDst = TRUE; + } + } + accumSrc[logLimit] = 0; + if (U_FAILURE(errorCode)) { + log_err("Error #3 invoking ICU within checkWhatYouCan\n"); + return FALSE; + } + if (errMap) { + if (testOK) { + printCaseInfo(bidi, srcChars, dstChars); + testOK = FALSE; + } + log_err("Mismatch between getVisualMap() and getLogicalIndex()\n"); + log_err("Map :"); + for (i = 0; i < visLimit; i++) { + log_err(" %d", visMap[i]); + } + fputs("\n", stderr); + log_err("Indexes:"); + for (i = 0; i < visLimit; i++) { + log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode)); + } + fputs("\n", stderr); + } + if (errDst) { + if (testOK) { + printCaseInfo(bidi, srcChars, dstChars); + testOK = FALSE; + } + log_err("Result does not map to Source\n"); + log_err("We got: %s", accumSrc); + fputs("\n", stderr); + } + return testOK; +} + +static void +testReorder(void) { + static const char* const logicalOrder[] ={ + "del(KC)add(K.C.&)", + "del(QDVT) add(BVDL)", + "del(PQ)add(R.S.)T)U.&", + "del(LV)add(L.V.) L.V.&", + "day 0 R DPDHRVR dayabbr", + "day 1 H DPHPDHDA dayabbr", + "day 2 L DPBLENDA dayabbr", + "day 3 J DPJQVM dayabbr", + "day 4 I DPIQNF dayabbr", + "day 5 M DPMEG dayabbr", + "helloDPMEG", + "hello WXYZ" + }; + static const char* const visualOrder[]={ + "del(CK)add(&.C.K)", + "del(TVDQ) add(LDVB)", + "del(QP)add(&.U(T(.S.R", + "del(VL)add(&.V.L (.V.L", + "day 0 RVRHDPD R dayabbr", + "day 1 ADHDPHPD H dayabbr", + "day 2 ADNELBPD L dayabbr", + "day 3 MVQJPD J dayabbr", + "day 4 FNQIPD I dayabbr", + "day 5 GEMPD M dayabbr", + "helloGEMPD", + "hello ZYXW" + }; + static const char* const visualOrder1[]={ + ")K.C.&(dda)KC(led", + ")BVDL(dda )QDVT(led", + "R.S.(T(U.&(dda)PQ(led", + "L.V.( L.V.&(dda)LV(led", + "rbbayad R DPDHRVR 0 yad", + "rbbayad H DPHPDHDA 1 yad", + "rbbayad L DPBLENDA 2 yad", + "rbbayad J DPJQVM 3 yad", + "rbbayad I DPIQNF 4 yad", + "rbbayad M DPMEG 5 yad", + "DPMEGolleh", + "WXYZ olleh" + }; + + static const char* const visualOrder2[]={ + "@)@K.C.&@(dda)@KC@(led", + "@)@BVDL@(dda )@QDVT@(led", + "R.S.)T)U.&@(dda)@PQ@(led", + "L.V.) L.V.&@(dda)@LV@(led", + "rbbayad @R DPDHRVR@ 0 yad", + "rbbayad @H DPHPDHDA@ 1 yad", + "rbbayad @L DPBLENDA@ 2 yad", + "rbbayad @J DPJQVM@ 3 yad", + "rbbayad @I DPIQNF@ 4 yad", + "rbbayad @M DPMEG@ 5 yad", + "DPMEGolleh", + "WXYZ@ olleh" + }; + static const char* const visualOrder3[]={ + ")K.C.&(KC)dda(led", + ")BVDL(ddaQDVT) (led", + "R.S.)T)U.&(PQ)dda(led", + "L.V.) L.V.&(LV)dda(led", + "rbbayad DPDHRVR R 0 yad", + "rbbayad DPHPDHDA H 1 yad", + "rbbayad DPBLENDA L 2 yad", + "rbbayad DPJQVM J 3 yad", + "rbbayad DPIQNF I 4 yad", + "rbbayad DPMEG M 5 yad", + "DPMEGolleh", + "WXYZ olleh" + }; + static const char* const visualOrder4[]={ + "del(add(CK(.C.K)", + "del( (TVDQadd(LDVB)", + "del(add(QP(.U(T(.S.R", + "del(add(VL(.V.L (.V.L", + "day 0 R RVRHDPD dayabbr", + "day 1 H ADHDPHPD dayabbr", + "day 2 L ADNELBPD dayabbr", + "day 3 J MVQJPD dayabbr", + "day 4 I FNQIPD dayabbr", + "day 5 M GEMPD dayabbr", + "helloGEMPD", + "hello ZYXW" + }; + char formatChars[MAXLEN]; + UErrorCode ec = U_ZERO_ERROR; + UBiDi* bidi = ubidi_open(); + int i; + + log_verbose("\nEntering TestReorder\n\n"); + + for(i=0;i<LENGTHOF(logicalOrder);i++){ + int32_t srcSize = (int32_t)strlen(logicalOrder[i]); + int32_t destSize = srcSize*2; + UChar src[MAXLEN]; + UChar dest[MAXLEN]; + char chars[MAXLEN]; + log_verbose("Testing L2V #1 for case %d\n", i); + pseudoToU16(srcSize,logicalOrder[i],src); + ec = U_ZERO_ERROR; + ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); + if(U_FAILURE(ec)){ + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + i, UBIDI_DEFAULT_LTR, u_errorName(ec)); + } + /* try pre-flighting */ + destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec); + if(ec!=U_BUFFER_OVERFLOW_ERROR){ + log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); + }else if(destSize!=srcSize){ + log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); + }else{ + ec= U_ZERO_ERROR; + } + destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec); + u16ToPseudo(destSize,dest,chars); + if(destSize!=srcSize){ + log_err("ubidi_writeReordered() destSize and srcSize do not match\n"); + }else if(strcmp(visualOrder[i],chars)!=0){ + log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n" + "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", + logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i); + } + checkWhatYouCan(bidi, logicalOrder[i], chars); + } + + for(i=0;i<LENGTHOF(logicalOrder);i++){ + int32_t srcSize = (int32_t)strlen(logicalOrder[i]); + int32_t destSize = srcSize*2; + UChar src[MAXLEN]; + UChar dest[MAXLEN]; + char chars[MAXLEN]; + log_verbose("Testing L2V #2 for case %d\n", i); + pseudoToU16(srcSize,logicalOrder[i],src); + ec = U_ZERO_ERROR; + ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); + if(U_FAILURE(ec)){ + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + i, UBIDI_DEFAULT_LTR, u_errorName(ec)); + } + /* try pre-flighting */ + destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec); + if(ec!=U_BUFFER_OVERFLOW_ERROR){ + log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); + }else if(destSize!=srcSize){ + log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); + }else{ + ec= U_ZERO_ERROR; + } + destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec); + u16ToPseudo(destSize,dest,chars); + if(destSize!=srcSize){ + log_err("ubidi_writeReordered() destSize and srcSize do not match\n"); + }else if(strcmp(visualOrder1[i],chars)!=0){ + log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n" + "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", + logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i); + } + } + + for(i=0;i<LENGTHOF(logicalOrder);i++){ + int32_t srcSize = (int32_t)strlen(logicalOrder[i]); + int32_t destSize = srcSize*2; + UChar src[MAXLEN]; + UChar dest[MAXLEN]; + char chars[MAXLEN]; + log_verbose("Testing V2L #3 for case %d\n", i); + pseudoToU16(srcSize,logicalOrder[i],src); + ec = U_ZERO_ERROR; + ubidi_setInverse(bidi,TRUE); + ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec); + if(U_FAILURE(ec)){ + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + i, UBIDI_DEFAULT_LTR, u_errorName(ec)); + } + /* try pre-flighting */ + destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec); + if(ec!=U_BUFFER_OVERFLOW_ERROR){ + log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); + }else{ + ec= U_ZERO_ERROR; + } + destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec); + u16ToPseudo(destSize,dest,chars); + if(strcmp(visualOrder2[i],chars)!=0){ + log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n" + "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", + logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i); + } + } + /* Max Explicit level */ + for(i=0;i<LENGTHOF(logicalOrder);i++){ + int32_t srcSize = (int32_t)strlen(logicalOrder[i]); + int32_t destSize = srcSize*2; + UChar src[MAXLEN]; + UChar dest[MAXLEN]; + char chars[MAXLEN]; + UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10}; + log_verbose("Testing V2L #4 for case %d\n", i); + pseudoToU16(srcSize,logicalOrder[i],src); + ec = U_ZERO_ERROR; + ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec); + if(U_FAILURE(ec)){ + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec)); + } + /* try pre-flighting */ + destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec); + if(ec!=U_BUFFER_OVERFLOW_ERROR){ + log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); + }else if(destSize!=srcSize){ + log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize); + }else{ + ec = U_ZERO_ERROR; + } + destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec); + u16ToPseudo(destSize,dest,chars); + if(destSize!=srcSize){ + log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize ); + }else if(strcmp(visualOrder3[i],chars)!=0){ + log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n" + "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", + logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i); + } + } + for(i=0;i<LENGTHOF(logicalOrder);i++){ + int32_t srcSize = (int32_t)strlen(logicalOrder[i]); + int32_t destSize = srcSize*2; + UChar src[MAXLEN]; + UChar dest[MAXLEN]; + char chars[MAXLEN]; + UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10}; + log_verbose("Testing V2L #5 for case %d\n", i); + pseudoToU16(srcSize,logicalOrder[i],src); + ec = U_ZERO_ERROR; + ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec); + if(U_FAILURE(ec)){ + log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n", + i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec)); + } + /* try pre-flighting */ + destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec); + if(ec!=U_BUFFER_OVERFLOW_ERROR){ + log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec)); + }else{ + ec= U_ZERO_ERROR; + } + destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec); + u16ToPseudo(destSize,dest,chars); + if(strcmp(visualOrder4[i],chars)!=0){ + log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n" + "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n", + logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i); + } + } + ubidi_close(bidi); + + log_verbose("\nExiting TestReorder\n\n"); +} + +static void +doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) { + const uint8_t *dirProps=test->text+lineStart; + const UBiDiLevel *levels=test->levels; + const uint8_t *visualMap=test->visualMap; + int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0; + UErrorCode errorCode=U_ZERO_ERROR; + UBiDiLevel level, level2; + + if (countRunsFirst) { + log_verbose("Calling ubidi_countRuns() first.\n"); + + runCount = ubidi_countRuns(pBiDi, &errorCode); + + if(U_FAILURE(errorCode)) { + log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + } else { + log_verbose("Calling ubidi_getLogicalMap() first.\n"); + } + + _testReordering(pBiDi, testNumber); + + for(i=0; i<len; ++i) { + log_verbose("%3d %3d %.*s%-3s @%d\n", + i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString, + dirPropNames[dirProps[i]], + ubidi_getVisualIndex(pBiDi, i, &errorCode)); + } + + log_verbose("\n-----levels:"); + for(i=0; i<len; ++i) { + if(i>0) { + log_verbose(","); + } + log_verbose(" %d", ubidi_getLevelAt(pBiDi, i)); + } + + log_verbose("\n--reordered:"); + for(i=0; i<len; ++i) { + if(i>0) { + log_verbose(","); + } + log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode)); + } + log_verbose("\n"); + + if(test->direction!=ubidi_getDirection(pBiDi)) { + log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi)); + } + + if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) { + log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi)); + } + + for(i=0; i<len; ++i) { + if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) { + log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]); + return; + } + } + + for(i=0; i<len; ++i) { + logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); + return; + } + if(visualMap[i]!=logicalIndex) { + log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex); + return; + } + } + + if (! countRunsFirst) { + runCount=ubidi_countRuns(pBiDi, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + } + + for(logicalIndex=0; logicalIndex<len;) { + level=ubidi_getLevelAt(pBiDi, logicalIndex); + ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2); + if(level!=level2) { + log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): " + "wrong level %d instead of %d\n", + testNumber, logicalIndex, level, level2); + } + if(--runCount<0) { + log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs " + "compared to %d=ubidi_countRuns()\n", + testNumber, ubidi_countRuns(pBiDi, &errorCode)); + return; + } + } + if(runCount!=0) { + log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs " + "compared to %d=ubidi_getRunCount()\n", + testNumber, ubidi_countRuns(pBiDi, &errorCode)); + return; + } + + log_verbose("\n\n"); +} + +static void +_testReordering(UBiDi *pBiDi, int testNumber) { + int32_t + logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN], + visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN]; + UErrorCode errorCode=U_ZERO_ERROR; + const UBiDiLevel *levels; + int32_t i, length=ubidi_getLength(pBiDi), + destLength=ubidi_getResultLength(pBiDi); + int32_t runCount, visualIndex, logicalStart, runLength; + UBool odd; + + if(length<=0) { + return; + } + + /* get the logical and visual maps from the object */ + ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + + ubidi_getVisualMap(pBiDi, visualMap1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + + /* invert them both */ + ubidi_invertMap(logicalMap1, visualMap2, length); + ubidi_invertMap(visualMap1, logicalMap2, destLength); + + /* get them from the levels array, too */ + levels=ubidi_getLevels(pBiDi, &errorCode); + + if(U_FAILURE(errorCode)) { + log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + + ubidi_reorderLogical(levels, length, logicalMap3); + ubidi_reorderVisual(levels, length, visualMap3); + + /* get the visual map from the runs, too */ + runCount=ubidi_countRuns(pBiDi, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode)); + return; + } + log_verbose("\n----%2d runs:", runCount); + visualIndex=0; + for(i=0; i<runCount; ++i) { + odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength); + log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength); + if(UBIDI_LTR==odd) { + do { /* LTR */ + visualMap4[visualIndex++]=logicalStart++; + } while(--runLength>0); + } else { + logicalStart+=runLength; /* logicalLimit */ + do { /* RTL */ + visualMap4[visualIndex++]=--logicalStart; + } while(--runLength>0); + } + } + log_verbose("\n"); + + /* print all the maps */ + log_verbose("logical maps:\n"); + for(i=0; i<length; ++i) { + log_verbose("%4d", logicalMap1[i]); + } + log_verbose("\n"); + for(i=0; i<length; ++i) { + log_verbose("%4d", logicalMap2[i]); + } + log_verbose("\n"); + for(i=0; i<length; ++i) { + log_verbose("%4d", logicalMap3[i]); + } + + log_verbose("\nvisual maps:\n"); + for(i=0; i<destLength; ++i) { + log_verbose("%4d", visualMap1[i]); + } + log_verbose("\n"); + for(i=0; i<destLength; ++i) { + log_verbose("%4d", visualMap2[i]); + } + log_verbose("\n"); + for(i=0; i<length; ++i) { + log_verbose("%4d", visualMap3[i]); + } + log_verbose("\n"); + for(i=0; i<length; ++i) { + log_verbose("%4d", visualMap4[i]); + } + log_verbose("\n"); + + /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */ + for(i=0; i<length; ++i) { + if(logicalMap1[i]!=logicalMap2[i]) { + log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i); + break; + } + if(logicalMap1[i]!=logicalMap3[i]) { + log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i); + break; + } + + if(visualMap1[i]!=visualMap2[i]) { + log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i); + break; + } + if(visualMap1[i]!=visualMap3[i]) { + log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i); + break; + } + if(visualMap1[i]!=visualMap4[i]) { + log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i); + break; + } + + if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) { + log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i); + break; + } + if(U_FAILURE(errorCode)) { + log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); + break; + } + if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) { + log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i); + break; + } + if(U_FAILURE(errorCode)) { + log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode)); + break; + } + } +} + +#define RETURN_IF_BAD_ERRCODE(x) \ + if (U_FAILURE(errorCode)) { \ + log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \ + return; \ + } \ + + +static void doMisc(void) { +/* Miscellaneous tests to exercize less popular code paths */ + UBiDi *bidi, *bidiLine; + UChar src[MAXLEN], dest[MAXLEN]; + int32_t srcLen, destLen, runCount, i; + UBiDiLevel level; + UBiDiDirection dir; + int32_t map[MAXLEN]; + UErrorCode errorCode=U_ZERO_ERROR; + static const int32_t srcMap[6] = {0,1,-1,5,4}; + static const int32_t dstMap[6] = {0,1,-1,-1,4,3}; + + bidi = ubidi_openSized(120, 66, &errorCode); + if (bidi == NULL) { + log_err("Error with openSized(120, 66)\n"); + return; + } + bidiLine = ubidi_open(); + if (bidi == NULL) { + log_err("Error with open()\n"); + return; + } + + destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode); + if (destLen != 0) { + log_err("\nwriteReverse should return zero length, ", + "returned %d instead\n", destLen); + } + RETURN_IF_BAD_ERRCODE("#1#"); + + ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + if (destLen != 0) { + log_err("\nwriteReordered should return zero length, ", + "returned %d instead\n", destLen); + } + RETURN_IF_BAD_ERRCODE("#2#"); + + srcLen = u_unescape("abc ", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + for (i = 3; i < 6; i++) { + level = ubidi_getLevelAt(bidiLine, i); + if (level != UBIDI_RTL) { + log_err("\nTrailing space at index %d should get paragraph level" + "%d, got %d instead\n", i, UBIDI_RTL, level); + } + } + RETURN_IF_BAD_ERRCODE("#3#"); + + srcLen = u_unescape("abc def", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + for (i = 3; i < 6; i++) { + level = ubidi_getLevelAt(bidiLine, i); + if (level != UBIDI_RTL) { + log_err("\nTrailing space at index %d should get paragraph level" + "%d, got %d instead\n", i, UBIDI_RTL, level); + } + } + RETURN_IF_BAD_ERRCODE("#4#"); + + srcLen = u_unescape("abcdefghi ", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + for (i = 3; i < 6; i++) { + level = ubidi_getLevelAt(bidiLine, i); + if (level != 2) { + log_err("\nTrailing char at index %d should get level 2, " + "got %d instead\n", i, level); + } + } + RETURN_IF_BAD_ERRCODE("#5#"); + + ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS); + srcLen = u_unescape("\\u200eabc def", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + destLen = ubidi_getResultLength(bidiLine); + if (destLen != 5) { + log_err("\nWrong result length, should be 5, got %d\n", destLen); + } + RETURN_IF_BAD_ERRCODE("#6#"); + + srcLen = u_unescape("abcdefghi", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + dir = ubidi_getDirection(bidiLine); + if (dir != UBIDI_LTR) { + log_err("\nWrong direction #1, should be %d, got %d\n", + UBIDI_LTR, dir); + } + RETURN_IF_BAD_ERRCODE("#7#"); + + ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode); + runCount = ubidi_countRuns(bidi, &errorCode); + if (runCount != 0) { + log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount); + } + RETURN_IF_BAD_ERRCODE("#8#"); + + srcLen = u_unescape(" ", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + runCount = ubidi_countRuns(bidiLine, &errorCode); + if (runCount != 1) { + log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount); + } + RETURN_IF_BAD_ERRCODE("#9#"); + + srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + dir = ubidi_getDirection(bidi); + if (dir != UBIDI_MIXED) { + log_err("\nWrong direction #2, should be %d, got %d\n", + UBIDI_MIXED, dir); + } + dir = ubidi_getDirection(bidiLine); + if (dir != UBIDI_MIXED) { + log_err("\nWrong direction #3, should be %d, got %d\n", + UBIDI_MIXED, dir); + } + runCount = ubidi_countRuns(bidiLine, &errorCode); + if (runCount != 2) { + log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount); + } + RETURN_IF_BAD_ERRCODE("#10#"); + + ubidi_invertMap(srcMap, map, 5); + if (memcmp(dstMap, map, sizeof(dstMap))) { + log_err("\nUnexpected inverted Map, got "); + for (i = 0; i < 6; i++) { + log_err("%d ", map[i]); + } + log_err("\n"); + } + + /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */ + srcLen = u_unescape("abc\\u200e", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, + UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode); + if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) { + log_err("\nWrong result #1, should be 'abc', got '%s'\n", + aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#11#"); + + /* test inverse Bidi with marks and contextual orientation */ + ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); + ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS); + ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + if (destLen != 0) { + log_err("\nWrong result #2, length should be 0, got %d\n", destLen); + } + RETURN_IF_BAD_ERRCODE("#12#"); + srcLen = u_unescape(" ", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #3, should be ' ', got '%s'\n", + aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#13#"); + srcLen = u_unescape("abc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #4, should be 'abc', got '%s'\n", + aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#14#"); + srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN); + if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #5, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#15#"); + srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN); + if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #6, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#16#"); + srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN); + if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #7, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#17#"); + srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN); + if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #8, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#18#"); + ubidi_orderParagraphsLTR(bidi, TRUE); + srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r" + "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n" + "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r" + "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n" + "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN); + if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #9, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#19#"); + srcLen = u_unescape("\\u05d0 \t", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN); + if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #10, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#20#"); + srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN); + if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #11, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#21#"); + srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN); + if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #12, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#22#"); + srcLen = u_unescape("ab \t", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u200f\t ab", src, MAXLEN); + if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) { + log_err("\nWrong result #13, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + RETURN_IF_BAD_ERRCODE("#23#"); + + /* check exceeding para level */ + ubidi_close(bidi); + bidi = ubidi_open(); + srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode); + level = ubidi_getLevelAt(bidi, 2); + if (level != 61) { + log_err("\nWrong level at index 2\n, should be 61, got %d\n", level); + } + RETURN_IF_BAD_ERRCODE("#24#"); + + /* check 1-char runs with RUNS_ONLY */ + ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY); + srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + runCount = ubidi_countRuns(bidi, &errorCode); + if (runCount != 14) { + log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount); + } + RETURN_IF_BAD_ERRCODE("#25#"); + + ubidi_close(bidi); + ubidi_close(bidiLine); +} + +static void +testFailureRecovery(void) { + UErrorCode errorCode; + UBiDi *bidi, *bidiLine; + UChar src[MAXLEN]; + int32_t srcLen; + UBiDiLevel level; + UBiDiReorderingMode rm; + static UBiDiLevel myLevels[3] = {6,5,4}; + + log_verbose("\nEntering TestFailureRecovery\n\n"); + errorCode = U_FILE_ACCESS_ERROR; + if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) { + log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n"); + } + if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) { + log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n"); + } + errorCode = U_ZERO_ERROR; + if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ubidi_writeReordered did not fail as expected\n"); + } + + bidi = ubidi_open(); + srcLen = u_unescape("abc", src, MAXLEN); + errorCode = U_ZERO_ERROR; + ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nubidi_setPara did not fail when passed too big para level\n"); + } + errorCode = U_ZERO_ERROR; + if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ubidi_writeReverse did not fail as expected\n"); + } + bidiLine = ubidi_open(); + errorCode = U_ZERO_ERROR; + ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nubidi_setLine did not fail when called before valid setPara()\n"); + } + errorCode = U_ZERO_ERROR; + srcLen = u_unescape("abc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode); + level = ubidi_getLevelAt(bidi, 3); + if (level != 0) { + log_err("\nubidi_getLevelAt did not fail when called with bad argument\n"); + } + errorCode = U_ZERO_ERROR; + ubidi_close(bidi); + bidi = ubidi_openSized(-1, 0, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nubidi_openSized did not fail when called with bad argument\n"); + } + ubidi_close(bidi); + bidi = ubidi_openSized(2, 1, &errorCode); + errorCode = U_ZERO_ERROR; + srcLen = u_unescape("abc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nsetPara did not fail when called with text too long\n"); + } + errorCode = U_ZERO_ERROR; + srcLen = u_unescape("=2", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + ubidi_countRuns(bidi, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nsetPara did not fail when called for too many runs\n"); + } + ubidi_close(bidi); + bidi = ubidi_open(); + rm = ubidi_getReorderingMode(bidi); + ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1); + if (rm != ubidi_getReorderingMode(bidi)) { + log_err("\nsetReorderingMode with bad argument #1 should have no effect\n"); + } + ubidi_setReorderingMode(bidi, 9999); + if (rm != ubidi_getReorderingMode(bidi)) { + log_err("\nsetReorderingMode with bad argument #2 should have no effect\n"); + } + + /* Try a surrogate char */ + errorCode = U_ZERO_ERROR; + srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode); + if (ubidi_getDirection(bidi) != UBIDI_MIXED) { + log_err("\ngetDirection for 1st surrogate char should be MIXED\n"); + } + errorCode = U_ZERO_ERROR; + srcLen = u_unescape("abc", src, MAXLEN); + ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("\nsetPara did not fail when called with bad levels\n"); + } + ubidi_close(bidi); + ubidi_close(bidiLine); + + log_verbose("\nExiting TestFailureRecovery\n\n"); +} + +static void +testMultipleParagraphs(void) { + static const char* const text = "__ABC\\u001c" /* Para #0 offset 0 */ + "__\\u05d0DE\\u001c" /* 1 6 */ + "__123\\u001c" /* 2 12 */ + "\\u000d\\u000a" /* 3 18 */ + "FG\\u000d" /* 4 20 */ + "\\u000d" /* 5 23 */ + "HI\\u000d\\u000a" /* 6 24 */ + "\\u000d\\u000a" /* 7 28 */ + "\\u000a" /* 8 30 */ + "\\u000a" /* 9 31 */ + "JK\\u001c"; /* 10 32 */ + static const int32_t paraCount=11; + static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35}; + static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23}; + static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0}, + {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, + {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}}; + static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2"; + static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2}; + static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0}; + UBiDiLevel gotLevel; + const UBiDiLevel* gotLevels; + UBool orderParagraphsLTR; + UChar src[MAXLEN], dest[MAXLEN]; + UErrorCode errorCode=U_ZERO_ERROR; + UBiDi* pBidi=ubidi_open(); + UBiDi* pLine; + int32_t srcSize, count, paraStart, paraLimit, paraIndex, length; + int32_t srcLen, destLen; + int i, j, k; + + log_verbose("\nEntering TestMultipleParagraphs\n\n"); + u_unescape(text, src, MAXLEN); + srcSize=u_strlen(src); + ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n", + UBIDI_LTR, u_errorName(errorCode)); + ubidi_close(pBidi); + return; + } + /* check paragraph count and boundaries */ + if (paraCount!=(count=ubidi_countParagraphs(pBidi))) { + log_err("ubidi_countParagraphs returned %d, should be %d\n", + count, paraCount); + } + for (i=0; i<paraCount; i++) { + ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode); + if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) { + log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n", + i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]); + } + } + errorCode=U_ZERO_ERROR; + /* check with last paragraph not terminated by B */ + src[srcSize-1]='L'; + ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n", + UBIDI_LTR, u_errorName(errorCode)); + ubidi_close(pBidi); + return; + } + if (paraCount!=(count=ubidi_countParagraphs(pBidi))) { + log_err("2nd ubidi_countParagraphs returned %d, should be %d\n", + count, paraCount); + } + i=paraCount-1; + ubidi_getParagraphByIndex(pBidi, i, ¶Start, ¶Limit, NULL, &errorCode); + if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) { + log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n", + i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]); + } + errorCode=U_ZERO_ERROR; + /* check paraLevel for all paragraphs under various paraLevel specs */ + for (k=0; k<6; k++) { + ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode); + for (i=0; i<paraCount; i++) { + paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode); + if (paraIndex!=i) { + log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n", + paraLevels[k], i, paraIndex, i); + } + if (gotLevel!=multiLevels[k][i]) { + log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n", + paraLevels[k], i, gotLevel, multiLevels[k][i]); + } + } + gotLevel=ubidi_getParaLevel(pBidi); + if (gotLevel!=multiLevels[k][0]) { + log_err("For paraLevel=%d getParaLevel=%d, expected %d\n", + paraLevels[k], gotLevel, multiLevels[k][0]); + } + } + errorCode=U_ZERO_ERROR; + /* check that the result of ubidi_getParaLevel changes if the first + * paragraph has a different level + */ + src[0]=0x05d2; /* Hebrew letter Gimel */ + ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode); + gotLevel=ubidi_getParaLevel(pBidi); + if (gotLevel!=UBIDI_RTL) { + log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n", + gotLevel, UBIDI_RTL); + } + errorCode=U_ZERO_ERROR; + /* check that line cannot overlap paragraph boundaries */ + pLine=ubidi_open(); + i=paraBounds[1]; + k=paraBounds[2]+1; + ubidi_setLine(pBidi, i, k, pLine, &errorCode); + if (U_SUCCESS(errorCode)) { + log_err("For line limits %d-%d got success %s\n", + i, k, u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + i=paraBounds[1]; + k=paraBounds[2]; + ubidi_setLine(pBidi, i, k, pLine, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("For line limits %d-%d got error %s\n", + i, k, u_errorName(errorCode)); + errorCode=U_ZERO_ERROR; + } + /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */ + ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); + /* get levels through para Bidi block */ + gotLevels=ubidi_getLevels(pBidi, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("Error on Para getLevels %s\n", u_errorName(errorCode)); + ubidi_close(pLine); + ubidi_close(pBidi); + return; + } + for (i=26; i<32; i++) { + if (gotLevels[i]!=UBIDI_RTL) { + log_err("For char %d(%04x), level=%d, expected=%d\n", + i, src[i], gotLevels[i], UBIDI_RTL); + } + } + /* get levels through para Line block */ + i=paraBounds[1]; + k=paraBounds[2]; + ubidi_setLine(pBidi, i, k, pLine, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("For line limits %d-%d got error %s\n", + i, k, u_errorName(errorCode)); + ubidi_close(pLine); + ubidi_close(pBidi); + return; + } + paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode); + gotLevels=ubidi_getLevels(pLine, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("Error on Line getLevels %s\n", u_errorName(errorCode)); + ubidi_close(pLine); + ubidi_close(pBidi); + return; + } + length=ubidi_getLength(pLine); + if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) { + log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, " + "level of separator=%d expected=%d\n", + paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL); + } + orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi); + if (orderParagraphsLTR) { + log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE); + } + ubidi_orderParagraphsLTR(pBidi, TRUE); + orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi); + if (!orderParagraphsLTR) { + log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE); + } + /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */ + ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); + /* get levels through para Bidi block */ + gotLevels=ubidi_getLevels(pBidi, &errorCode); + for (i=26; i<32; i++) { + if (gotLevels[i]!=0) { + log_err("For char %d(%04x), level=%d, expected=%d\n", + i, src[i], gotLevels[i], 0); + } + } + errorCode=U_ZERO_ERROR; + /* get levels through para Line block */ + i=paraBounds[1]; + k=paraBounds[2]; + ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode); + paraIndex=ubidi_getParagraph(pLine, i, ¶Start, ¶Limit, &gotLevel, &errorCode); + gotLevels=ubidi_getLevels(pLine, &errorCode); + length=ubidi_getLength(pLine); + if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) { + log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, " + "level of separator=%d expected=%d\n", + paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0); + log_verbose("levels="); + for (count=0; count<length; count++) { + log_verbose(" %d", gotLevels[count]); + } + log_verbose("\n"); + } + + /* test that the concatenation of separate invocations of the bidi code + * on each individual paragraph in order matches the levels array that + * results from invoking bidi once over the entire multiparagraph tests + * (with orderParagraphsLTR false, of course) + */ + u_unescape(text, src, MAXLEN); /* restore original content */ + srcSize=u_strlen(src); + ubidi_orderParagraphsLTR(pBidi, FALSE); + ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode); + gotLevels=ubidi_getLevels(pBidi, &errorCode); + for (i=0; i<paraCount; i++) { + /* use pLine for individual paragraphs */ + paraStart = paraBounds[i]; + length = paraBounds[i+1] - paraStart; + ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode); + for (j=0; j<length; j++) { + if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) { + log_err("Checking paragraph concatenation: for paragraph=%d, " + "char=%d(%04x), level=%d, expected=%d\n", + i, j, src[paraStart+j], k, gotLevel); + } + } + } + + /* ensure that leading numerics in a paragraph are not treated as arabic + numerals because of arabic text in a preceding paragraph + */ + u_unescape(text2, src, MAXLEN); + srcSize=u_strlen(src); + ubidi_orderParagraphsLTR(pBidi, TRUE); + ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode); + gotLevels=ubidi_getLevels(pBidi, &errorCode); + for (i=0; i<srcSize; i++) { + if (gotLevels[i]!=levels2[i]) { + log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n", + i, src[i], gotLevels[i], levels2[i]); + } + } + + /* check handling of whitespace before end of paragraph separator when + * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B + */ + u_memset(src, 0x0020, MAXLEN); + srcSize = 5; + ubidi_orderParagraphsLTR(pBidi, TRUE); + for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) { + src[4]=(UChar)i; /* with and without terminating B */ + for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) { + src[0]=(UChar)j; /* leading 'A' or Alef */ + for (gotLevel=4; gotLevel<=5; gotLevel++) { + /* test even and odd paraLevel */ + ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode); + gotLevels=ubidi_getLevels(pBidi, &errorCode); + for (k=1; k<=3; k++) { + if (gotLevels[k]!=gotLevel) { + log_err("Checking trailing spaces: for leading_char=%04x, " + "last_char=%04x, index=%d, level=%d, expected=%d\n", + src[0], src[4], k, gotLevels[k], gotLevel); + } + } + } + } + } + + /* check default orientation when inverse bidi and paragraph starts + * with LTR strong char and ends with RTL strong char, with and without + * a terminating B + */ + ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); + srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN); + ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN); + if (memcmp(src, dest, destLen * sizeof(UChar))) { + log_err("\nInvalid output #0, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN); + ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN); + if (memcmp(src, dest, destLen * sizeof(UChar))) { + log_err("\nInvalid output #1, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + + /* check multiple paragraphs together with explicit levels + */ + ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT); + srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN); + ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode); + destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode); + srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN); + if (memcmp(src, dest, destLen * sizeof(UChar))) { + log_err("\nInvalid output #2, should be '%s', got '%s'\n", + aescstrdup(src, srcLen), aescstrdup(dest, destLen)); + } + count = ubidi_countParagraphs(pBidi); + if (count != 2) { + log_err("\nInvalid number of paras, should be 2, got %d\n", count); + } + + ubidi_close(pLine); + ubidi_close(pBidi); + log_verbose("\nExiting TestMultipleParagraphs\n\n"); +} + + +/* inverse BiDi ------------------------------------------------------------- */ + +static int countRoundtrips=0, countNonRoundtrips=0; + +#define STRING_TEST_CASE(s) { (s), LENGTHOF(s) } + +static void +testInverse(void) { + static const UChar + string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 }, + string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 }, + string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 }, + string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 }, + string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 }; + + static const struct { + const UChar *s; + int32_t length; + } testCases[]={ + STRING_TEST_CASE(string0), + STRING_TEST_CASE(string1), + STRING_TEST_CASE(string2), + STRING_TEST_CASE(string3), + STRING_TEST_CASE(string4) + }; + + UBiDi *pBiDi; + UErrorCode errorCode; + int i; + + log_verbose("\nEntering TestInverse\n\n"); + pBiDi=ubidi_open(); + if(pBiDi==NULL) { + log_err("unable to open a UBiDi object (out of memory)\n"); + return; + } + + log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases)); + for(i=0; i<LENGTHOF(testCases); ++i) { + log_verbose("Testing case %d\n", i); + errorCode=U_ZERO_ERROR; + _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode); + } + + log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases)); + for(i=0; i<LENGTHOF(testCases); ++i) { + log_verbose("Testing case %d\n", i); + errorCode=U_ZERO_ERROR; + _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode); + } + + _testManyInverseBidi(pBiDi, 0); + _testManyInverseBidi(pBiDi, 1); + + ubidi_close(pBiDi); + + log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips); + + _testWriteReverse(); + + _testManyAddedPoints(); + + _testMisc(); + + log_verbose("\nExiting TestInverse\n\n"); +} + +#define COUNT_REPEAT_SEGMENTS 6 + +static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={ + { 0x61, 0x62 }, /* L */ + { 0x5d0, 0x5d1 }, /* R */ + { 0x627, 0x628 }, /* AL */ + { 0x31, 0x32 }, /* EN */ + { 0x661, 0x662 }, /* AN */ + { 0x20, 0x20 } /* WS (N) */ +}; + +static void +_testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) { + UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 }; + int i, j, k; + UErrorCode errorCode; + + log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n", + direction==0 ? 'L' : 'R'); + for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) { + text[0]=repeatSegments[i][0]; + text[1]=repeatSegments[i][1]; + for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) { + text[3]=repeatSegments[j][0]; + text[4]=repeatSegments[j][1]; + for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) { + text[6]=repeatSegments[k][0]; + text[7]=repeatSegments[k][1]; + + errorCode=U_ZERO_ERROR; + log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k); + _testInverseBidi(pBiDi, text, 8, direction, &errorCode); + } + } + } +} + +static void +_testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength, + UBiDiLevel direction, UErrorCode *pErrorCode) { + UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN]; + int32_t ltrLength, logicalLength, visualLength; + + if(direction==0) { + log_verbose("inverse Bidi: testInverse(L)\n"); + + /* convert visual to logical */ + ubidi_setInverse(pBiDi, TRUE); + if (!ubidi_isInverse(pBiDi)) { + log_err("Error while doing ubidi_setInverse(TRUE)\n"); + } + ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode); + if (src != ubidi_getText(pBiDi)) { + log_err("Wrong value returned by ubidi_getText\n"); + } + logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest), + UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode); + log_verbose(" v "); + printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode)); + log_verbose("\n"); + + /* convert back to visual LTR */ + ubidi_setInverse(pBiDi, FALSE); + if (ubidi_isInverse(pBiDi)) { + log_err("Error while doing ubidi_setInverse(FALSE)\n"); + } + ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode); + visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest), + UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode); + } else { + log_verbose("inverse Bidi: testInverse(R)\n"); + + /* reverse visual from RTL to LTR */ + ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode); + log_verbose(" vr"); + printUnicode(src, srcLength, NULL); + log_verbose("\n"); + + /* convert visual RTL to logical */ + ubidi_setInverse(pBiDi, TRUE); + ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode); + logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest), + UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode); + log_verbose(" vl"); + printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode)); + log_verbose("\n"); + + /* convert back to visual RTL */ + ubidi_setInverse(pBiDi, FALSE); + ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode); + visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest), + UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode); + } + log_verbose(" l "); + printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode)); + log_verbose("\n"); + log_verbose(" v "); + printUnicode(visualDest, visualLength, NULL); + log_verbose("\n"); + + /* check and print results */ + if(U_FAILURE(*pErrorCode)) { + log_err("inverse BiDi: *** error %s\n" + " turn on verbose mode to see details\n", u_errorName(*pErrorCode)); + } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) { + ++countRoundtrips; + log_verbose(" + roundtripped\n"); + } else { + ++countNonRoundtrips; + log_verbose(" * did not roundtrip\n"); + log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n" + " turn on verbose mode to see details\n"); + } +} + +static void +_testWriteReverse(void) { + /* U+064e and U+0650 are combining marks (Mn) */ + static const UChar forward[]={ + 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29 + }, reverseKeepCombining[]={ + 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f + }, reverseRemoveControlsKeepCombiningDoMirror[]={ + 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650 + }; + UChar reverse[10]; + UErrorCode errorCode; + int32_t length; + + /* test ubidi_writeReverse() with "interesting" options */ + errorCode=U_ZERO_ERROR; + length=ubidi_writeReverse(forward, LENGTHOF(forward), + reverse, LENGTHOF(reverse), + UBIDI_KEEP_BASE_COMBINING, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n", + length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode)); + } + + memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR); + errorCode=U_ZERO_ERROR; + length=ubidi_writeReverse(forward, LENGTHOF(forward), + reverse, LENGTHOF(reverse), + UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n" + " length=%d (should be %d), error code %s\n", + length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode)); + } +} + +static void _testManyAddedPoints(void) { + UErrorCode errorCode = U_ZERO_ERROR; + UBiDi *bidi = ubidi_open(); + UChar text[90], dest[MAXLEN], expected[120]; + int destLen, i; + for (i = 0; i < LENGTHOF(text); i+=3) { + text[i] = 0x0061; /* 'a' */ + text[i+1] = 0x05d0; + text[i+2] = 0x0033; /* '3' */ + } + ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT); + ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS); + ubidi_setPara(bidi, text, LENGTHOF(text), UBIDI_LTR, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode); + for (i = 0; i < LENGTHOF(expected); i+=4) { + expected[i] = 0x0061; /* 'a' */ + expected[i+1] = 0x05d0; + expected[i+2] = 0x200e; + expected[i+3] = 0x0033; /* '3' */ + } + if (memcmp(dest, expected, destLen * sizeof(UChar))) { + log_err("\nInvalid output with many added points, " + "expected '%s', got '%s'\n", + aescstrdup(expected, LENGTHOF(expected)), + aescstrdup(dest, destLen)); + } + ubidi_close(bidi); +} + +static void _testMisc(void) { + UErrorCode errorCode = U_ZERO_ERROR; + UBiDi *bidi = ubidi_open(); + UChar src[3], dest[MAXLEN], expected[5]; + int destLen; + ubidi_setInverse(bidi, TRUE); + src[0] = src[1] = src[2] = 0x0020; + ubidi_setPara(bidi, src, LENGTHOF(src), UBIDI_RTL, NULL, &errorCode); + destLen = ubidi_writeReordered(bidi, dest, MAXLEN, + UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC, + &errorCode); + u_unescape("\\u200f \\u200f", expected, 5); + if (memcmp(dest, expected, destLen * sizeof(UChar))) { + log_err("\nInvalid output with RLM at both sides, " + "expected '%s', got '%s'\n", + aescstrdup(expected, LENGTHOF(expected)), + aescstrdup(dest, destLen)); + } + ubidi_close(bidi); +} + +/* arabic shaping ----------------------------------------------------------- */ + +static void +doArabicShapingTest(void) { + static const UChar + source[]={ + 0x31, /* en:1 */ + 0x627, /* arabic:alef */ + 0x32, /* en:2 */ + 0x6f3, /* an:3 */ + 0x61, /* latin:a */ + 0x34, /* en:4 */ + 0 + }, en2an[]={ + 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 + }, an2en[]={ + 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0 + }, logical_alen2an_init_lr[]={ + 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0 + }, logical_alen2an_init_al[]={ + 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0 + }, reverse_alen2an_init_lr[]={ + 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 + }, reverse_alen2an_init_al[]={ + 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0 + }; + UChar dest[8]; + UErrorCode errorCode; + int32_t length; + + /* test number shaping */ + + /* european->arabic */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(en2an)\n"); + } + + /* arabic->european */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, -1, + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED, + &errorCode); + if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(an2en)\n"); + } + + /* european->arabic with context, logical order, initial state not AL */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n"); + } + + /* european->arabic with context, logical order, initial state AL */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n"); + } + + /* european->arabic with context, reverse order, initial state not AL */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n"); + } + + /* european->arabic with context, reverse order, initial state AL */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n"); + } + + /* test noop */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + 0, + &errorCode); + if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(noop)\n"); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, 0, + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(U_FAILURE(errorCode) || length!=0) { + log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source)); + } + + /* preflight digit shaping */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + NULL, 0, + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) { + log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n", + length, u_errorName(errorCode), LENGTHOF(source)); + } + + /* test illegal arguments */ + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(NULL, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, -2, + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + NULL, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, -1, + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=u_shapeArabic(source, LENGTHOF(source), + (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */ + U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode)); + } +} + +static void +doLamAlefSpecialVLTRArabicShapingTest(void) { + static const UChar + source[]={ +/*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20, +/*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20, +/*c*/ 0x646,0x627,0x670,0x644,0x627,0x20, +/*d*/ 0x646,0x622,0x653,0x644,0x627,0x20, +/*e*/ 0x646,0x625,0x655,0x644,0x627,0x20, +/*f*/ 0x646,0x622,0x654,0x644,0x627,0x20, +/*g*/ 0xFEFC,0x639 + }, shape_near[]={ + 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20, + 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20, + 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20, + 0xfefc,0xfecb + }, shape_at_end[]={ + 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670, + 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d, + 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20 + }, shape_at_begin[]={ + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76, + 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d, + 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb + }, shape_grow_shrink[]={ + 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5, + 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9, + 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb + }, shape_excepttashkeel_near[]={ + 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20, + 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20, + 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20, + 0xfefc,0xfecb + }, shape_excepttashkeel_at_end[]={ + 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5, + 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9, + 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20, + 0x20,0x20,0x20 + }, shape_excepttashkeel_at_begin[]={ + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76, + 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d, + 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb + }, shape_excepttashkeel_grow_shrink[]={ + 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670, + 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d, + 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb + }; + + UChar dest[38]; + UErrorCode errorCode; + int32_t length; + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_near)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n"); + } + + /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */ + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n"); + } +} + +static void +doTashkeelSpecialVLTRArabicShapingTest(void) { + static const UChar + source[]={ + 0x64A,0x628,0x631,0x639,0x20, + 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20, + 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20, + 0x628,0x670,0x631,0x670,0x639,0x20, + 0x628,0x653,0x631,0x653,0x639,0x20, + 0x628,0x654,0x631,0x654,0x639,0x20, + 0x628,0x655,0x631,0x655,0x639,0x20, + }, shape_near[]={ + 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb, + 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670, + 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654, + 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20 + }, shape_excepttashkeel_near[]={ + 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20, + 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb, + 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20, + 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20 + }; + + UChar dest[43]; + UErrorCode errorCode; + int32_t length; + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| + U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n"); + } +} + +static void +doLOGICALArabicDeShapingTest(void) { + static const UChar + source[]={ + 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020, + 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4, + 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020 + }, unshape_near[]={ + 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627, + 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631, + 0x629,0x20,0x20,0x20,0x20 + }, unshape_at_end[]={ + 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642, + 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627, + 0x644,0x62d,0x631,0x629,0x20 + }, unshape_at_begin[]={ + 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20, + 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631, + 0x629,0x20,0x20,0x20,0x20 + }, unshape_grow_shrink[]={ + 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642, + 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627, + 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20 + }; + + UChar dest[36]; + UErrorCode errorCode; + int32_t length; + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| + U_SHAPE_TEXT_DIRECTION_LOGICAL, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(unshape_near)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END| + U_SHAPE_TEXT_DIRECTION_LOGICAL, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(unshape_at_end)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING| + U_SHAPE_TEXT_DIRECTION_LOGICAL, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(unshape_at_begin)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(source, LENGTHOF(source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK| + U_SHAPE_TEXT_DIRECTION_LOGICAL, + &errorCode); + + if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(unshape_grow_shrink)\n"); + } + +} + +static void +doArabicShapingTestForBug5421(void) { + static const UChar + persian_letters_source[]={ + 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020 + }, persian_letters[]={ + 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020 + }, tashkeel_aggregation_source[]={ + 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020, + 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020 + }, tashkeel_aggregation[]={ + 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, + 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020 + }, untouched_presentation_source[]={ + 0x0020 ,0x0627, 0xfe90,0x0020 + }, untouched_presentation[]={ + 0x0020,0xfe8D, 0xfe90,0x0020 + }, untouched_presentation_r_source[]={ + 0x0020 ,0xfe90, 0x0627, 0x0020 + }, untouched_presentation_r[]={ + 0x0020, 0xfe90,0xfe8D,0x0020 + }; + + UChar dest[38]; + UErrorCode errorCode; + int32_t length; + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(persian_letters_source, LENGTHOF(persian_letters_source), + dest, LENGTHOF(dest), + U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(persian_letters)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(tashkeel_aggregation_source, LENGTHOF(tashkeel_aggregation_source), + dest, LENGTHOF(dest), + U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION| + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(tashkeel_aggregation)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(untouched_presentation_source, LENGTHOF(untouched_presentation_source), + dest, LENGTHOF(dest), + U_SHAPE_PRESERVE_PRESENTATION| + U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(untouched_presentation)\n"); + } + + errorCode=U_ZERO_ERROR; + + length=u_shapeArabic(untouched_presentation_r_source, LENGTHOF(untouched_presentation_r_source), + dest, LENGTHOF(dest), + U_SHAPE_PRESERVE_PRESENTATION| + U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL, + &errorCode); + + if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) { + log_err("failure in u_shapeArabic(untouched_presentation_r)\n"); + } +} + +/* helpers ------------------------------------------------------------------ */ + +static void initCharFromDirProps(void) { + static const UVersionInfo ucd401={ 4, 0, 1, 0 }; + static UVersionInfo ucdVersion={ 0, 0, 0, 0 }; + + /* lazy initialization */ + if(ucdVersion[0]>0) { + return; + } + + u_getUnicodeVersion(ucdVersion); + if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) { + /* Unicode 4.0.1 changes bidi classes for +-/ */ + charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */ + } +} + +/* return a string with characters according to the desired directional properties */ +static UChar * +getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) { + int32_t i; + + initCharFromDirProps(); + + /* this part would have to be modified for UTF-x */ + for(i=0; i<length; ++i) { + buffer[i]=charFromDirProp[dirProps[i]]; + } + buffer[length]=0; + return buffer; +} + +static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) { + int32_t i; + + log_verbose("{ "); + for(i=0; i<length; ++i) { + if(levels!=NULL) { + log_verbose("%4x.%u ", s[i], levels[i]); + } else { + log_verbose("%4x ", s[i]); + } + } + log_verbose(" }"); +} + +/* new BIDI API */ + +/* Reordering Mode BiDi --------------------------------------------------------- */ + +static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL }; + +static UBool +assertSuccessful(const char* message, UErrorCode* rc) { + if (rc != NULL && U_FAILURE(*rc)) { + log_err("%s() failed with error %s.\n", message, myErrorName(*rc)); + return FALSE; + } + return TRUE; +} + +static UBool +assertStringsEqual(const char* expected, const char* actual, const char* src, + const char* mode, const char* option, UBiDi* pBiDi) { + if (uprv_strcmp(expected, actual)) { + char formatChars[MAXLEN]; + log_err("\nActual and expected output mismatch.\n" + "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n", + "Input:", src, + "Actual output:", actual, + "Expected output:", expected, + "Levels:", formatLevels(pBiDi, formatChars), + "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode, + "Paragraph level:", ubidi_getParaLevel(pBiDi), + "Reordering option:", ubidi_getReorderingOptions(pBiDi), option); + return FALSE; + } + return TRUE; +} + +static UBiDi* +getBiDiObject(void) { + UBiDi* pBiDi = ubidi_open(); + if (pBiDi == NULL) { + log_err("Unable to allocate a UBiDi object. Tests are skipped.\n"); + } + return pBiDi; +} + +#define MAKE_ITEMS(val) val, #val + +static const struct { + UBiDiReorderingMode value; + const char* description; +} +modes[] = { + { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) }, + { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) }, + { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) }, + { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) }, + { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) } +}; +static const struct { + uint32_t value; + const char* description; +} +options[] = { + { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) }, + { MAKE_ITEMS(0) } +}; + +#define TC_COUNT LENGTHOF(textIn) +#define MODES_COUNT LENGTHOF(modes) +#define OPTIONS_COUNT LENGTHOF(options) +#define LEVELS_COUNT LENGTHOF(paraLevels) + +static const char* const textIn[] = { +/* (0) 123 */ + "123", +/* (1) .123->4.5 */ + ".123->4.5", +/* (2) 678 */ + "678", +/* (3) .678->8.9 */ + ".678->8.9", +/* (4) JIH1.2,3MLK */ + "JIH1.2,3MLK", +/* (5) FE.>12-> */ + "FE.>12->", +/* (6) JIH.>12->a */ + "JIH.>12->a", +/* (7) CBA.>67->89=a */ + "CBA.>67->89=a", +/* (8) CBA.123->xyz */ + "CBA.123->xyz", +/* (9) .>12->xyz */ + ".>12->xyz", +/* (10) a.>67->xyz */ + "a.>67->xyz", +/* (11) 123JIH */ + "123JIH", +/* (12) 123 JIH */ + "123 JIH" +}; + +static const char* const textOut[] = { +/* TC 0: 123 */ + "123", /* (0) */ +/* TC 1: .123->4.5 */ + ".123->4.5", /* (1) */ + "4.5<-123.", /* (2) */ +/* TC 2: 678 */ + "678", /* (3) */ +/* TC 3: .678->8.9 */ + ".8.9<-678", /* (4) */ + "8.9<-678.", /* (5) */ + ".678->8.9", /* (6) */ +/* TC 4: MLK1.2,3JIH */ + "KLM1.2,3HIJ", /* (7) */ +/* TC 5: FE.>12-> */ + "12<.EF->", /* (8) */ + "<-12<.EF", /* (9) */ + "EF.>@12->", /* (10) */ +/* TC 6: JIH.>12->a */ + "12<.HIJ->a", /* (11) */ + "a<-12<.HIJ", /* (12) */ + "HIJ.>@12->a", /* (13) */ + "a&<-12<.HIJ", /* (14) */ +/* TC 7: CBA.>67->89=a */ + "ABC.>@67->89=a", /* (15) */ + "a=89<-67<.ABC", /* (16) */ + "a&=89<-67<.ABC", /* (17) */ + "89<-67<.ABC=a", /* (18) */ +/* TC 8: CBA.123->xyz */ + "123.ABC->xyz", /* (19) */ + "xyz<-123.ABC", /* (20) */ + "ABC.@123->xyz", /* (21) */ + "xyz&<-123.ABC", /* (22) */ +/* TC 9: .>12->xyz */ + ".>12->xyz", /* (23) */ + "xyz<-12<.", /* (24) */ + "xyz&<-12<.", /* (25) */ +/* TC 10: a.>67->xyz */ + "a.>67->xyz", /* (26) */ + "a.>@67@->xyz", /* (27) */ + "xyz<-67<.a", /* (28) */ +/* TC 11: 123JIH */ + "123HIJ", /* (29) */ + "HIJ123", /* (30) */ +/* TC 12: 123 JIH */ + "123 HIJ", /* (31) */ + "HIJ 123", /* (32) */ +}; + +#define NO UBIDI_MAP_NOWHERE +#define MAX_MAP_LENGTH 20 + +static const int32_t forwardMap[][MAX_MAP_LENGTH] = { +/* TC 0: 123 */ + { 0, 1, 2 }, /* (0) */ +/* TC 1: .123->4.5 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */ + { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */ +/* TC 2: 678 */ + { 0, 1, 2 }, /* (3) */ +/* TC 3: .678->8.9 */ + { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */ + { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */ +/* TC 4: MLK1.2,3JIH */ + { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */ +/* TC 5: FE.>12-> */ + { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */ + { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */ + { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */ +/* TC 6: JIH.>12->a */ + { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */ + { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */ + { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */ + { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */ +/* TC 7: CBA.>67->89=a */ + { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */ + { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */ + { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */ + { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */ +/* TC 8: CBA.123->xyz */ + { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */ + { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */ + { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */ + { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */ +/* TC 9: .>12->xyz */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */ + { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */ + { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */ +/* TC 10: a.>67->xyz */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */ + { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */ + { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */ +/* TC 11: 123JIH */ + { 0, 1, 2, 5, 4, 3 }, /* (29) */ + { 3, 4, 5, 2, 1, 0 }, /* (30) */ +/* TC 12: 123 JIH */ + { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */ + { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */ +}; + +static const int32_t inverseMap[][MAX_MAP_LENGTH] = { +/* TC 0: 123 */ + { 0, 1, 2 }, /* (0) */ +/* TC 1: .123->4.5 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */ + { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */ +/* TC 2: 678 */ + { 0, 1, 2 }, /* (3) */ +/* TC 3: .678->8.9 */ + { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */ + { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */ +/* TC 4: MLK1.2,3JIH */ + { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */ +/* TC 5: FE.>12-> */ + { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */ + { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */ + { 1, 0, 2, 3, NO, 4, 5, 6, 7 }, /* (10) */ +/* TC 6: JIH.>12->a */ + { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */ + { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */ + { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (13) */ + { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */ +/* TC 7: CBA.>67->89=a */ + { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */ + { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */ + { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */ + { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */ +/* TC 8: CBA.123->xyz */ + { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */ + { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */ + { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */ + { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */ +/* TC 9: .>12->xyz */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */ + { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */ + { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 }, /* (25) */ +/* TC 10: a.>67->xyz */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */ + { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (27) */ + { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */ +/* TC 11: 123JIH */ + { 0, 1, 2, 5, 4, 3 }, /* (29) */ + { 5, 4, 3, 0, 1, 2 }, /* (30) */ +/* TC 12: 123 JIH */ + { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */ + { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */ +}; + +static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT] + [LEVELS_COUNT] = { + { /* TC 0: 123 */ + {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 1: .123->4.5 */ + {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 2: 678 */ + {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 3: .678->8.9 */ + {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 4: MLK1.2,3JIH */ + {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 5: FE.>12-> */ + {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 6: JIH.>12->a */ + {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 7: CBA.>67->89=a */ + {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 8: CBA.>124->xyz */ + {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 9: .>12->xyz */ + {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 10: a.>67->xyz */ + {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 11: 124JIH */ + {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + }, + { /* TC 12: 124 JIH */ + {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + } +}; + +static UBool +assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars, + const char *destChars, const UChar *dest, int32_t destLen, + int mode, int option, UBiDiLevel level) { + + static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT] + [LEVELS_COUNT] = { + { /* TC 0: 123 */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 1: .123->4.5 */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 2: 678 */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 3: .678->8.9 */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 4: MLK1.2,3JIH */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 5: FE.>12-> */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 6: JIH.>12->a */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 7: CBA.>67->89=a */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 8: CBA.>123->xyz */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 9: .>12->xyz */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 10: a.>67->xyz */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 11: 123JIH */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + }, + { /* TC 12: 123 JIH */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */ + {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */ + } + }; + + #define SET_ROUND_TRIP_MODE(mode) \ + ubidi_setReorderingMode(pBiDi, mode); \ + desc = #mode; \ + break; + + UErrorCode rc = U_ZERO_ERROR; + UChar dest2[MAXLEN]; + int32_t destLen2; + const char* desc; + char destChars2[MAXLEN]; + char destChars3[MAXLEN]; + + switch (modes[mode].value) { + case UBIDI_REORDER_NUMBERS_SPECIAL: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) + case UBIDI_REORDER_GROUP_NUMBERS_WITH_R: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) + case UBIDI_REORDER_RUNS_ONLY: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY) + case UBIDI_REORDER_INVERSE_NUMBERS_AS_L: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT) + case UBIDI_REORDER_INVERSE_LIKE_DIRECT: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT) + case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL) + default: + SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT) + } + ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS); + + ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + *dest2 = 0; + destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING, + &rc); + assertSuccessful("ubidi_writeReordered", &rc); + + u16ToPseudo(destLen, dest, destChars3); + u16ToPseudo(destLen2, dest2, destChars2); + checkWhatYouCan(pBiDi, destChars3, destChars2); + if (strcmp(srcChars, destChars2)) { + if (roundtrip[tc][mode][option][level]) { + log_err("\nRound trip failed for case=%d mode=%d option=%d.\n" + "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s" + "\n%20s %u\n", tc, mode, option, + "Original text:", srcChars, + "Round-tripped text:", destChars2, + "Intermediate text:", destChars3, + "Reordering mode:", modes[mode].description, + "Reordering option:", options[option].description, + "Paragraph level:", level); + } + else { + log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n" + "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s" + "\n%20s %u\n", tc, mode, option, + "Original text:", srcChars, + "Round-tripped text:", destChars2, + "Intermediate text:", destChars3, + "Reordering mode:", modes[mode].description, + "Reordering option:", options[option].description, + "Paragraph level:", level); + } + return FALSE; + } + if (!checkResultLength(pBiDi, destChars, destChars2, destLen2, + desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) { + return FALSE; + } + if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars, + desc, "UBIDI_OPTION_REMOVE_CONTROLS", + level, FALSE)) { + return FALSE; + } + return TRUE; +} + +static UBool +checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars, + int32_t destLen, const char* mode, + const char* option, UBiDiLevel level) { + int32_t actualLen; + if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0) + actualLen = strlen(destChars); + else + actualLen = ubidi_getResultLength(pBiDi); + if (actualLen != destLen) { + log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n" + "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n", + "Expected:", destLen, "Actual:", actualLen, + "Input:", srcChars, "Output:", destChars, + "Reordering mode:", mode, "Reordering option:", option, + "Paragraph level:", level); + return FALSE; + } + return TRUE; +} + +static void +testReorderRunsOnly(void) { + static const struct { + const char* textIn; + const char* textOut[2][2]; + const char noroundtrip[2]; + } testCases[] = { + {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/ + {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}}, + {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/ + {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/ + {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/ + {"* /%$123=-", "* /%$123=-"}}, {0, 0}}, + {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/ + {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}}, + {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/ + {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}}, + {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/ + {"abc&<-123", "abc<-123"}}, {1, 0}}, + {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/ + {"JKL<-123", "JKL<-@123"}}, {0, 1}}, + {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/ + {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}}, + {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/ + {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}}, + {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/ + {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}}, + {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/ + {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}}, + {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/ + {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}}, + {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/ + {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}}, + {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/ + {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}}, + {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/ + {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}}, + {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/ + {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}}, + {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/ + {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}}, + {"123", {{"123", "123"}, /* just one run */ /*18*/ + {"123", "123"}}, {0, 0}} + }; + UBiDi *pBiDi = getBiDiObject(); + UBiDi *pL2VBiDi = getBiDiObject(); + UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN]; + char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN]; + int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras; + UErrorCode rc = U_ZERO_ERROR; + UBiDiLevel level; + + log_verbose("\nEntering TestReorderRunsOnly\n\n"); + + if(!pL2VBiDi) { + ubidi_close(pBiDi); /* in case this one was allocated */ + return; + } + ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY); + ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS); + + for (option = 0; option < 2; option++) { + ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS + : UBIDI_OPTION_INSERT_MARKS); + for (i = 0, nCases = LENGTHOF(testCases); i < nCases; i++) { + srcLen = strlen(testCases[i].textIn); + pseudoToU16(srcLen, testCases[i].textIn, src); + for(j = 0; j < 2; j++) { + log_verbose("Now doing test for option %d, case %d, level %d\n", + i, option, j); + level = paraLevels[j]; + ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + *dest = 0; + destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered", &rc); + u16ToPseudo(destLen, dest, destChars); + checkWhatYouCan(pBiDi, testCases[i].textIn, destChars); + assertStringsEqual(testCases[i].textOut[option][level], destChars, + testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY", + option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS", + pBiDi); + + if((option==0) && testCases[i].noroundtrip[level]) { + continue; + } + ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc); + assertSuccessful("ubidi_setPara1", &rc); + *visual1 = 0; + vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered1", &rc); + u16ToPseudo(vis1Len, visual1, vis1Chars); + checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars); + ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc); + assertSuccessful("ubidi_setPara2", &rc); + *visual2 = 0; + vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered2", &rc); + u16ToPseudo(vis2Len, visual2, vis2Chars); + checkWhatYouCan(pL2VBiDi, destChars, vis2Chars); + assertStringsEqual(vis1Chars, vis2Chars, + testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)", + option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS", + pBiDi); + } + } + } + + /* test with null or empty text */ + ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc); + assertSuccessful("ubidi_setPara3", &rc); + paras = ubidi_countParagraphs(pBiDi); + if (paras != 0) { + log_err("\nInvalid number of paras (should be 0): %d\n", paras); + } + + ubidi_close(pBiDi); + ubidi_close(pL2VBiDi); + + log_verbose("\nExiting TestReorderRunsOnly\n\n"); +} + +static void +testReorderingMode(void) { + + UChar src[MAXLEN], dest[MAXLEN]; + char destChars[MAXLEN]; + UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL; + UErrorCode rc; + int tc, mode, option, level; + uint32_t optionValue, optionBack; + UBiDiReorderingMode modeValue, modeBack; + int32_t srcLen, destLen, index; + const char *expectedChars; + UBool testOK = TRUE; + + log_verbose("\nEntering TestReorderingMode\n\n"); + + pBiDi = getBiDiObject(); + pBiDi2 = getBiDiObject(); + pBiDi3 = getBiDiObject(); + if(!pBiDi3) { + ubidi_close(pBiDi); /* in case this one was allocated */ + ubidi_close(pBiDi2); /* in case this one was allocated */ + return; + } + + ubidi_setInverse(pBiDi2, TRUE); + + for (tc = 0; tc < TC_COUNT; tc++) { + const char *srcChars = textIn[tc]; + srcLen = strlen(srcChars); + pseudoToU16(srcLen, srcChars, src); + + for (mode = 0; mode < MODES_COUNT; mode++) { + modeValue = modes[mode].value; + ubidi_setReorderingMode(pBiDi, modeValue); + modeBack = ubidi_getReorderingMode(pBiDi); + if (modeValue != modeBack) { + log_err("Error while setting reordering mode to %d, returned %d\n", + modeValue, modeBack); + } + + for (option = 0; option < OPTIONS_COUNT; option++) { + optionValue = options[option].value; + ubidi_setReorderingOptions(pBiDi, optionValue); + optionBack = ubidi_getReorderingOptions(pBiDi); + if (optionValue != optionBack) { + log_err("Error while setting reordering option to %d, returned %d\n", + optionValue, optionBack); + } + + for (level = 0; level < LEVELS_COUNT; level++) { + log_verbose("starting test %d mode=%d option=%d level=%d\n", + tc, modes[mode].value, options[option].value, level); + rc = U_ZERO_ERROR; + ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + + *dest = 0; + destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, + UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered", &rc); + u16ToPseudo(destLen, dest, destChars); + if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) && + (options[option].value == UBIDI_OPTION_INSERT_MARKS))) { + checkWhatYouCan(pBiDi, srcChars, destChars); + } + + if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) { + index = -1; + expectedChars = inverseBasic(pBiDi2, srcChars, srcLen, + options[option].value, paraLevels[level], destChars); + } + else { + index = outIndices[tc][mode][option][level]; + expectedChars = textOut[index]; + } + if (!assertStringsEqual(expectedChars, destChars, srcChars, + modes[mode].description, + options[option].description, + pBiDi)) { + testOK = FALSE; + } + if (options[option].value == UBIDI_OPTION_INSERT_MARKS && + !assertRoundTrip(pBiDi3, tc, index, srcChars, + destChars, dest, destLen, + mode, option, paraLevels[level])) { + testOK = FALSE; + } + else if (!checkResultLength(pBiDi, srcChars, destChars, + destLen, modes[mode].description, + options[option].description, + paraLevels[level])) { + testOK = FALSE; + } + else if (index > -1 && !checkMaps(pBiDi, index, srcChars, + destChars, modes[mode].description, + options[option].description, paraLevels[level], + TRUE)) { + testOK = FALSE; + } + } + } + } + } + if (testOK == TRUE) { + log_verbose("\nReordering mode test OK\n"); + } + ubidi_close(pBiDi3); + ubidi_close(pBiDi2); + ubidi_close(pBiDi); + + log_verbose("\nExiting TestReorderingMode\n\n"); +} + +static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen, + uint32_t option, UBiDiLevel level, char *result) { + UErrorCode rc = U_ZERO_ERROR; + int32_t destLen; + UChar src[MAXLEN], dest2[MAXLEN]; + + if (pBiDi == NULL || src == NULL) { + return NULL; + } + ubidi_setReorderingOptions(pBiDi, option); + pseudoToU16(srcLen, srcChars, src); + ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + + *dest2 = 0; + destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN, + UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered", &rc); + u16ToPseudo(destLen, dest2, result); + if (!(option == UBIDI_OPTION_INSERT_MARKS)) { + checkWhatYouCan(pBiDi, srcChars, result); + } + return result; +} + +#define NULL_CHAR '\0' + +static void +testStreaming(void) { +#define MAXPORTIONS 10 + + static const struct { + const char* textIn; + short int chunk; + short int nPortions[2]; + char portionLens[2][MAXPORTIONS]; + const char* message[2]; + } testData[] = { + { "123\\u000A" + "abc45\\u000D" + "67890\\u000A" + "\\u000D" + "02468\\u000D" + "ghi", + 6, { 6, 6 }, {{ 6, 4, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }}, + {"6, 4, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"} + }, + { "abcd\\u000Afgh\\u000D12345\\u000A456", + 6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }}, + {"6, 3, 6, 3", "5, 4, 6, 3"} + }, + { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D", + 6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }}, + {"6, 3, 6, 3", "5, 4, 6, 3"} + }, + { "abcde\\u000Afghi", + 10, { 1, 2 }, {{ 10 }, { 6, 4 }}, + {"10", "6, 4"} + } + }; + UChar src[MAXLEN]; + UBiDi *pBiDi = NULL; + UChar *pSrc; + UErrorCode rc = U_ZERO_ERROR; + int32_t srcLen, processedLen, chunk, len, nPortions; + int i, j, levelIndex; + UBiDiLevel level; + int nTests = LENGTHOF(testData), nLevels = LENGTHOF(paraLevels); + UBool mismatch, testOK = TRUE; + char processedLenStr[MAXPORTIONS * 5]; + + log_verbose("\nEntering TestStreaming\n\n"); + + pBiDi = getBiDiObject(); + + ubidi_orderParagraphsLTR(pBiDi, TRUE); + + for (levelIndex = 0; levelIndex < nLevels; levelIndex++) { + for (i = 0; i < nTests; i++) { + srcLen = u_unescape(testData[i].textIn, src, MAXLEN); + chunk = testData[i].chunk; + nPortions = testData[i].nPortions[levelIndex]; + level = paraLevels[levelIndex]; + *processedLenStr = NULL_CHAR; + log_verbose("Testing level %d, case %d\n", level, i); + + mismatch = FALSE; + + ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING); + for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) { + + len = chunk < srcLen ? chunk : srcLen; + ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + + processedLen = ubidi_getProcessedLength(pBiDi); + if (processedLen == 0) { + ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT); + j--; + continue; + } + ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING); + + mismatch = (UBool)(j >= nPortions || + processedLen != testData[i].portionLens[levelIndex][j]); + + sprintf(processedLenStr + j * 4, "%4d", processedLen); + srcLen -= processedLen, pSrc += processedLen; + } + + if (mismatch || j != nPortions) { + testOK = FALSE; + log_err("\nProcessed lengths mismatch.\n" + "\tParagraph level: %u\n" + "\tInput string: %s\n" + "\tActually processed portion lengths: { %s }\n" + "\tExpected portion lengths : { %s }\n", + paraLevels[levelIndex], testData[i].textIn, + processedLenStr, testData[i].message[levelIndex]); + } + } + } + ubidi_close(pBiDi); + if (testOK == TRUE) { + log_verbose("\nBiDi streaming test OK\n"); + } + log_verbose("\nExiting TestStreaming\n\n"); +} + +U_CDECL_BEGIN + +static UCharDirection U_CALLCONV +overrideBidiClass(const void *context, UChar32 c) { + +#define DEF U_BIDI_CLASS_DEFAULT + + static const UCharDirection customClasses[] = { + /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 00-07 */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 08-0F */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 10-17 */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 18-1F */ + DEF, DEF, DEF, DEF, DEF, DEF, R, DEF, /* 20-27 */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 28-2F */ + EN, EN, EN, EN, EN, EN, AN, AN, /* 30-37 */ + AN, AN, DEF, DEF, DEF, DEF, DEF, DEF, /* 38-3F */ + L, AL, AL, AL, AL, AL, AL, R, /* 40-47 */ + R, R, R, R, R, R, R, R, /* 48-4F */ + R, R, R, R, R, R, R, R, /* 50-57 */ + R, R, R, LRE, DEF, RLE, PDF, S, /* 58-5F */ + NSM, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 60-67 */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 68-6F */ + DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 70-77 */ + DEF, DEF, DEF, LRO, B, RLO, BN, DEF /* 78-7F */ + }; + static const int nEntries = LENGTHOF(customClasses); + const char *dummy = context; /* just to avoid a compiler warning */ + dummy++; + + return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c]; +} + +U_CDECL_END + +static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context, + UBiDiClassCallback* expectedFn, + const void* expectedContext, + int32_t sizeOfContext) { + if (fn != expectedFn) { + log_err("Class callback pointer is not set properly.\n"); + } + if (context != expectedContext) { + log_err("Class callback context is not set properly.\n"); + } + else if (context != NULL && + memcmp(context, expectedContext, sizeOfContext)) { + log_err("Callback context content doesn't match the expected one.\n"); + } +} + +static void +testClassOverride(void) { + static const char* const textSrc = "JIH.>12->a \\u05D0\\u05D1 6 ABC78"; + static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0"; + + UChar src[MAXLEN], dest[MAXLEN]; + UErrorCode rc = U_ZERO_ERROR; + UBiDi *pBiDi = NULL; + UBiDiClassCallback* oldFn = NULL; + UBiDiClassCallback* newFn = overrideBidiClass; + const void* oldContext = NULL; + int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc); + char* destChars = NULL; + + log_verbose("\nEntering TestClassOverride\n\n"); + + pBiDi = getBiDiObject(); + if(!pBiDi) { + return; + } + + ubidi_getClassCallback(pBiDi, &oldFn, &oldContext); + verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0); + + ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc); + if (!assertSuccessful("ubidi_setClassCallback", &rc)) { + ubidi_close(pBiDi); + return; + } + verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0); + + ubidi_getClassCallback(pBiDi, &oldFn, &oldContext); + verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize); + + ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc); + if (!assertSuccessful("ubidi_setClassCallback", &rc)) { + ubidi_close(pBiDi); + return; + } + verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize); + + srcLen = u_unescape(textSrc, src, MAXLEN); + ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc); + assertSuccessful("ubidi_setPara", &rc); + + destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, + UBIDI_DO_MIRRORING, &rc); + assertSuccessful("ubidi_writeReordered", &rc); + + destChars = aescstrdup(dest, destLen); + if (uprv_strcmp(textResult, destChars)) { + log_err("\nActual and expected output mismatch.\n" + "%20s %s\n%20s %s\n%20s %s\n", + "Input:", textSrc, "Actual output:", destChars, + "Expected output:", textResult); + } + else { + log_verbose("\nClass override test OK\n"); + } + ubidi_close(pBiDi); + log_verbose("\nExiting TestClassOverride\n\n"); +} + +static char * formatMap(const int32_t * map, int len, char * buffer) +{ + int32_t i, k; + char c; + for (i = 0; i < len; i++) { + k = map[i]; + if (k < 0) + c = '-'; + else if (k >= sizeof(columns)) + c = '+'; + else + c = columns[k]; + buffer[i] = c; + } + buffer[len] = '\0'; + return buffer; +} + +static UBool +checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest, + const char *mode, const char* option, UBiDiLevel level, UBool forward) +{ + int32_t actualLogicalMap[MAX_MAP_LENGTH]; + int32_t actualVisualMap[MAX_MAP_LENGTH]; + int32_t getIndexMap[MAX_MAP_LENGTH]; + int32_t i, srcLen, resLen, index; + const int32_t *expectedLogicalMap, *expectedVisualMap; + UErrorCode rc = U_ZERO_ERROR; + UBool testOK = TRUE; + + if (forward) { + expectedLogicalMap = forwardMap[stringIndex]; + expectedVisualMap = inverseMap[stringIndex]; + } + else { + expectedLogicalMap = inverseMap[stringIndex]; + expectedVisualMap = forwardMap[stringIndex]; + } + ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc); + if (!assertSuccessful("ubidi_getLogicalMap", &rc)) { + testOK = FALSE; + } + srcLen = ubidi_getProcessedLength(pBiDi); + if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) { + char expChars[MAX_MAP_LENGTH]; + char actChars[MAX_MAP_LENGTH]; + log_err("\nubidi_getLogicalMap() returns unexpected map for output string " + "index %d\n" + "source: %s\n" + "dest : %s\n" + "Scale : %s\n" + "ExpMap: %s\n" + "Actual: %s\n" + "Paragraph level : %d == %d\n" + "Reordering mode : %s == %d\n" + "Reordering option: %s == %d\n" + "Forward flag : %d\n", + stringIndex, src, dest, columns, + formatMap(expectedLogicalMap, srcLen, expChars), + formatMap(actualLogicalMap, srcLen, actChars), + level, ubidi_getParaLevel(pBiDi), + mode, ubidi_getReorderingMode(pBiDi), + option, ubidi_getReorderingOptions(pBiDi), + forward + ); + testOK = FALSE; + } + resLen = ubidi_getResultLength(pBiDi); + ubidi_getVisualMap(pBiDi, actualVisualMap, &rc); + assertSuccessful("ubidi_getVisualMap", &rc); + if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) { + char expChars[MAX_MAP_LENGTH]; + char actChars[MAX_MAP_LENGTH]; + log_err("\nubidi_getVisualMap() returns unexpected map for output string " + "index %d\n" + "source: %s\n" + "dest : %s\n" + "Scale : %s\n" + "ExpMap: %s\n" + "Actual: %s\n" + "Paragraph level : %d == %d\n" + "Reordering mode : %s == %d\n" + "Reordering option: %s == %d\n" + "Forward flag : %d\n", + stringIndex, src, dest, columns, + formatMap(expectedVisualMap, resLen, expChars), + formatMap(actualVisualMap, resLen, actChars), + level, ubidi_getParaLevel(pBiDi), + mode, ubidi_getReorderingMode(pBiDi), + option, ubidi_getReorderingOptions(pBiDi), + forward + ); + testOK = FALSE; + } + for (i = 0; i < srcLen; i++) { + index = ubidi_getVisualIndex(pBiDi, i, &rc); + assertSuccessful("ubidi_getVisualIndex", &rc); + getIndexMap[i] = index; + } + if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) { + char actChars[MAX_MAP_LENGTH]; + char gotChars[MAX_MAP_LENGTH]; + log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string " + "index %d\n" + "source: %s\n" + "dest : %s\n" + "Scale : %s\n" + "ActMap: %s\n" + "IdxMap: %s\n" + "Paragraph level : %d == %d\n" + "Reordering mode : %s == %d\n" + "Reordering option: %s == %d\n" + "Forward flag : %d\n", + stringIndex, src, dest, columns, + formatMap(actualLogicalMap, srcLen, actChars), + formatMap(getIndexMap, srcLen, gotChars), + level, ubidi_getParaLevel(pBiDi), + mode, ubidi_getReorderingMode(pBiDi), + option, ubidi_getReorderingOptions(pBiDi), + forward + ); + testOK = FALSE; + } + for (i = 0; i < resLen; i++) { + index = ubidi_getLogicalIndex(pBiDi, i, &rc); + assertSuccessful("ubidi_getLogicalIndex", &rc); + getIndexMap[i] = index; + } + if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) { + char actChars[MAX_MAP_LENGTH]; + char gotChars[MAX_MAP_LENGTH]; + log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string " + "index %d\n" + "source: %s\n" + "dest : %s\n" + "Scale : %s\n" + "ActMap: %s\n" + "IdxMap: %s\n" + "Paragraph level : %d == %d\n" + "Reordering mode : %s == %d\n" + "Reordering option: %s == %d\n" + "Forward flag : %d\n", + stringIndex, src, dest, columns, + formatMap(actualVisualMap, resLen, actChars), + formatMap(getIndexMap, resLen, gotChars), + level, ubidi_getParaLevel(pBiDi), + mode, ubidi_getReorderingMode(pBiDi), + option, ubidi_getReorderingOptions(pBiDi), + forward + ); + testOK = FALSE; + } + return testOK; +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h new file mode 100644 index 00000000000..afaffb27d48 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h @@ -0,0 +1,82 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* file name: cbiditst.h +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 1999sep22 +* created by: Markus W. Scherer +*/ + +#ifndef CBIDITST_H +#define CBIDITST_H + +#include "unicode/utypes.h" +#include "unicode/uchar.h" +#include "unicode/ubidi.h" + +#ifdef XP_CPLUSPLUS +extern "C" { +#endif + +#define MAX_STRING_LENGTH 200 + +/* length of an array */ +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) + +/* Comparing the description of the BiDi algorithm with this implementation + is easier with the same names for the BiDi types in the code as there. + See UCharDirection in uchar.h . +*/ +#define L U_LEFT_TO_RIGHT +#define R U_RIGHT_TO_LEFT +#define EN U_EUROPEAN_NUMBER +#define ES U_EUROPEAN_NUMBER_SEPARATOR +#define ET U_EUROPEAN_NUMBER_TERMINATOR +#define AN U_ARABIC_NUMBER +#define CS U_COMMON_NUMBER_SEPARATOR +#define B U_BLOCK_SEPARATOR +#define S U_SEGMENT_SEPARATOR +#define WS U_WHITE_SPACE_NEUTRAL +#define ON U_OTHER_NEUTRAL +#define LRE U_LEFT_TO_RIGHT_EMBEDDING +#define LRO U_LEFT_TO_RIGHT_OVERRIDE +#define AL U_RIGHT_TO_LEFT_ARABIC +#define RLE U_RIGHT_TO_LEFT_EMBEDDING +#define RLO U_RIGHT_TO_LEFT_OVERRIDE +#define PDF U_POP_DIRECTIONAL_FORMAT +#define NSM U_DIR_NON_SPACING_MARK +#define BN U_BOUNDARY_NEUTRAL + +extern const char * const +dirPropNames[U_CHAR_DIRECTION_COUNT]; + +extern UChar +charFromDirProp[U_CHAR_DIRECTION_COUNT]; + +typedef struct { + const uint8_t *text; + int32_t length; + UBiDiLevel paraLevel; + int32_t lineStart, lineLimit; + UBiDiDirection direction; + UBiDiLevel resultLevel; + const UBiDiLevel *levels; + const uint8_t *visualMap; +} BiDiTestData; + +extern const BiDiTestData +tests[]; + +extern const int +bidiTestCount; + +#ifdef XP_CPLUSPLUS +} +#endif + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c new file mode 100644 index 00000000000..4d25865584d --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c @@ -0,0 +1,31 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CBKITTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_BREAK_ITERATION + +#include "cintltst.h" + +void addBrkIterAPITest(TestNode**); + +void addBreakIter(TestNode** root); + +void addBreakIter(TestNode** root) +{ + addBrkIterAPITest(root); +} + +#endif /* #if !UCONFIG_NO_BREAK_ITERATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c new file mode 100644 index 00000000000..bc04ceffbf0 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c @@ -0,0 +1,1337 @@ +/******************************************************************** + * Copyright (c) 1997-2007, International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************** + * + * File CCALTST.C + * + * Modification History: + * Name Description + * Madhu Katragadda Creation + ******************************************************************** + */ + +/* C API AND FUNCTIONALITY TEST FOR CALENDAR (ucol.h)*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include <stdlib.h> + +#include "unicode/uloc.h" +#include "unicode/ucal.h" +#include "unicode/udat.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "ccaltst.h" +#include "cformtst.h" +#include "cstring.h" + +void TestGregorianChange(void); + +void addCalTest(TestNode** root); + +void addCalTest(TestNode** root) +{ + + addTest(root, &TestCalendar, "tsformat/ccaltst/TestCalendar"); + addTest(root, &TestGetSetDateAPI, "tsformat/ccaltst/TestGetSetDateAPI"); + addTest(root, &TestFieldGetSet, "tsformat/ccaltst/TestFieldGetSet"); + addTest(root, &TestAddRollExtensive, "tsformat/ccaltst/TestAddRollExtensive"); + addTest(root, &TestGetLimits, "tsformat/ccaltst/TestGetLimits"); + addTest(root, &TestDOWProgression, "tsformat/ccaltst/TestDOWProgression"); + addTest(root, &TestGMTvsLocal, "tsformat/ccaltst/TestGMTvsLocal"); + addTest(root, &TestGregorianChange, "tsformat/ccaltst/TestGregorianChange"); +} + +/* "GMT" */ +static const UChar fgGMTID [] = { 0x0047, 0x004d, 0x0054, 0x0000 }; + +/* "PST" */ +static const UChar PST[] = {0x50, 0x53, 0x54, 0x00}; /* "PST" */ + +static const UChar EUROPE_PARIS[] = {0x45, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2F, 0x50, 0x61, 0x72, 0x69, 0x73, 0x00}; /* "Europe/Paris" */ + +static void TestCalendar() +{ + UCalendar *caldef = 0, *caldef2 = 0, *calfr = 0, *calit = 0; + UEnumeration* uenum = NULL; + int32_t count, count2, i,j; + UChar *tzID = 0; + UChar *tzdname = 0; + UErrorCode status = U_ZERO_ERROR; + UDate now; + UDateFormat *datdef = 0; + UChar *result = 0; + int32_t resultlength, resultlengthneeded; + char tempMsgBuf[256]; + UChar zone1[32], zone2[32]; + const char *tzver = 0; + +#ifdef U_USE_UCAL_OBSOLETE_2_8 + /*Testing countAvailableTimeZones*/ + int32_t offset=0; + log_verbose("\nTesting ucal_countAvailableTZIDs\n"); + count=ucal_countAvailableTZIDs(offset); + log_verbose("The number of timezone id's present with offset 0 are %d:\n", count); + if(count < 5) /* Don't hard code an exact == test here! */ + log_err("FAIL: error in the ucal_countAvailableTZIDs - got %d expected at least 5 total\n", count); + + /*Testing getAvailableTZIDs*/ + log_verbose("\nTesting ucal_getAvailableTZIDs"); + for(i=0;i<count;i++){ + ucal_getAvailableTZIDs(offset, i, &status); + if(U_FAILURE(status)){ + log_err("FAIL: ucal_getAvailableTZIDs returned %s\n", u_errorName(status)); + } + log_verbose("%s\n", u_austrcpy(tempMsgBuf, ucal_getAvailableTZIDs(offset, i, &status))); + } + /*get Illegal TZID where index >= count*/ + ucal_getAvailableTZIDs(offset, i, &status); + if(status != U_INDEX_OUTOFBOUNDS_ERROR){ + log_err("FAIL:for TZID index >= count Expected INDEX_OUTOFBOUNDS_ERROR Got %s\n", u_errorName(status)); + } + status=U_ZERO_ERROR; +#endif + + /*Test ucal_openTimeZones & ucal_openCountryTimeZones*/ + for (j=0; j<2; ++j) { + const char* api = (j==0) ? "ucal_openTimeZones()" : + "ucal_openCountryTimeZones(US)"; + uenum = (j==0) ? ucal_openTimeZones(&status) : + ucal_openCountryTimeZones("US", &status); + if (U_FAILURE(status)) { + log_err("FAIL: %s failed with %s", api, + u_errorName(status)); + } else { + const char* id; + int32_t len; + count = uenum_count(uenum, &status); + log_verbose("%s returned %d timezone id's:\n", api, count); + if (count < 5) { /* Don't hard code an exact == test here! */ + log_err("FAIL: in %s, got %d, expected at least 5\n", api, count); + } + uenum_reset(uenum, &status); + if (U_FAILURE(status)){ + log_err("FAIL: uenum_reset for %s returned %s\n", + api, u_errorName(status)); + } + for (i=0; i<count; i++) { + id = uenum_next(uenum, &len, &status); + if (U_FAILURE(status)){ + log_err("FAIL: uenum_next for %s returned %s\n", + api, u_errorName(status)); + } else { + log_verbose("%s\n", id); + } + } + /* Next one should be NULL */ + id = uenum_next(uenum, &len, &status); + if (id != NULL) { + log_err("FAIL: uenum_next for %s returned %s, expected NULL\n", + api, id); + } + } + uenum_close(uenum); + } + + /*Test ucal_getDSTSavings*/ + status = U_ZERO_ERROR; + i = ucal_getDSTSavings(fgGMTID, &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getDSTSavings(GMT) => %s\n", + u_errorName(status)); + } else if (i != 0) { + log_err("FAIL: ucal_getDSTSavings(GMT) => %d, expect 0\n", i); + } + i = ucal_getDSTSavings(PST, &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getDSTSavings(PST) => %s\n", + u_errorName(status)); + } else if (i != 1*60*60*1000) { + log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000); + } + + /*Test ucal_set/getDefaultTimeZone*/ + status = U_ZERO_ERROR; + i = ucal_getDefaultTimeZone(zone1, sizeof(zone1)/sizeof(zone1[0]), &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getDefaultTimeZone() => %s\n", + u_errorName(status)); + } else { + ucal_setDefaultTimeZone(EUROPE_PARIS, &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_setDefaultTimeZone(Europe/Paris) => %s\n", + u_errorName(status)); + } else { + i = ucal_getDefaultTimeZone(zone2, sizeof(zone2)/sizeof(zone2[0]), &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getDefaultTimeZone() => %s\n", + u_errorName(status)); + } else { + if (u_strcmp(zone2, EUROPE_PARIS) != 0) { + log_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris\n"); + } + } + } + status = U_ZERO_ERROR; + ucal_setDefaultTimeZone(zone1, &status); + } + + /*Test ucal_getTZDataVersion*/ + status = U_ZERO_ERROR; + tzver = ucal_getTZDataVersion(&status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getTZDataVersion() => %s\n", u_errorName(status)); + } else if (uprv_strlen(tzver) != 5 /*4 digits + 1 letter*/) { + log_err("FAIL: Bad version string was returned by ucal_getTZDataVersion\n"); + } else { + log_verbose("PASS: ucal_getTZDataVersion returned %s\n", tzver); + } + + + /*Testing the ucal_open() function*/ + status = U_ZERO_ERROR; + log_verbose("\nTesting the ucal_open()\n"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: error in ucal_open caldef : %s\n", u_errorName(status)); + } + + caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: error in ucal_open caldef : %s\n", u_errorName(status)); + } + u_strcpy(tzID, fgGMTID); + calfr=ucal_open(tzID, u_strlen(tzID), "fr_FR", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: error in ucal_open calfr : %s\n", u_errorName(status)); + } + calit=ucal_open(tzID, u_strlen(tzID), "it_IT", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)) { + log_err("FAIL: error in ucal_open calit : %s\n", u_errorName(status)); + } + + + /*Testing udat_getAvailable() and udat_countAvailable()*/ + log_verbose("\nTesting getAvailableLocales and countAvailable()\n"); + count=ucal_countAvailable(); + /* use something sensible w/o hardcoding the count */ + if(count > 0) { + log_verbose("PASS: ucal_countAvailable() works fine\n"); + log_verbose("The no: of locales for which calendars are avilable are %d\n", count); + } else { + log_data_err("FAIL: Error in countAvailable()\n"); + } + + for(i=0;i<count;i++) { + log_verbose("%s\n", ucal_getAvailable(i)); + } + + + /*Testing the equality between calendar's*/ + log_verbose("\nTesting ucal_equivalentTo()\n"); + if(caldef && caldef2 && calfr && calit) { + if(ucal_equivalentTo(caldef, caldef2) == FALSE || ucal_equivalentTo(caldef, calfr)== TRUE || + ucal_equivalentTo(caldef, calit)== TRUE) { + log_err("FAIL: Error. equivalentTo test failed\n"); + } else { + log_verbose("PASS: equivalentTo test passed\n"); + } + } + + + /*Testing the current time and date using ucal_getnow()*/ + log_verbose("\nTesting the ucal_getNow function to check if it is fetching tbe current time\n"); + now=ucal_getNow(); + /* open the date format and format the date to check the output */ + datdef=udat_open(UDAT_FULL,UDAT_FULL ,NULL, NULL, 0,NULL,0,&status); + if(U_FAILURE(status)){ + log_err("FAIL: error in creating the dateformat : %s\n", u_errorName(status)); + return; + } + log_verbose("PASS: The current date and time fetched is %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datdef, now)) ); + + + /*Testing the TimeZoneDisplayName */ + log_verbose("\nTesting the fetching of time zone display name\n"); + /*for the US locale */ + resultlength=0; + resultlengthneeded=ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", NULL, resultlength, &status); + + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", result, resultlength, &status); + } + if(U_FAILURE(status)) { + log_err("FAIL: Error in getting the timezone display name : %s\n", u_errorName(status)); + } + else{ + log_verbose("PASS: getting the time zone display name successful : %s, %d needed \n", + u_errorName(status), resultlengthneeded); + } + + +#define expectPDT "Pacific Daylight Time" + + tzdname=(UChar*)malloc(sizeof(UChar) * (sizeof(expectPDT)+1)); + u_uastrcpy(tzdname, expectPDT); + if(u_strcmp(tzdname, result)==0){ + log_verbose("PASS: got the correct time zone display name %s\n", u_austrcpy(tempMsgBuf, result) ); + } + else{ + log_err("FAIL: got the wrong time zone(DST) display name %s, wanted %s\n", austrdup(result) , expectPDT); + } + + ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_DST, "en_US", result, resultlength, &status); + u_uastrcpy(tzdname, "PDT"); + if(u_strcmp(tzdname, result) != 0){ + log_err("FAIL: got the wrong time zone(SHORT_DST) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname)); + } + + ucal_getTimeZoneDisplayName(caldef, UCAL_STANDARD, "en_US", result, resultlength, &status); + u_uastrcpy(tzdname, "Pacific Standard Time"); + if(u_strcmp(tzdname, result) != 0){ + log_err("FAIL: got the wrong time zone(STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname)); + } + + ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_STANDARD, "en_US", result, resultlength, &status); + u_uastrcpy(tzdname, "PST"); + if(u_strcmp(tzdname, result) != 0){ + log_err("FAIL: got the wrong time zone(SHORT_STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname)); + } + + + /*testing the setAttributes and getAttributes of a UCalendar*/ + log_verbose("\nTesting the getAttributes and set Attributes\n"); + count=ucal_getAttribute(calit, UCAL_LENIENT); + count2=ucal_getAttribute(calfr, UCAL_LENIENT); + ucal_setAttribute(calit, UCAL_LENIENT, 0); + ucal_setAttribute(caldef, UCAL_LENIENT, count2); + if( ucal_getAttribute(calit, UCAL_LENIENT) !=0 || + ucal_getAttribute(calfr, UCAL_LENIENT)!=ucal_getAttribute(caldef, UCAL_LENIENT) ) + log_err("FAIL: there is an error in getAttributes or setAttributes\n"); + else + log_verbose("PASS: attribute set and got successfully\n"); + /*set it back to orginal value */ + log_verbose("Setting it back to normal\n"); + ucal_setAttribute(calit, UCAL_LENIENT, count); + if(ucal_getAttribute(calit, UCAL_LENIENT)!=count) + log_err("FAIL: Error in setting the attribute back to normal\n"); + + /*setting the first day of the week to other values */ + count=ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK); + for (i=1; i<=7; ++i) { + ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,i); + if (ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK) != i) + log_err("FAIL: set/getFirstDayOfWeek failed\n"); + } + /*get bogus Attribute*/ + count=ucal_getAttribute(calit, (UCalendarAttribute)99); /* BOGUS_ATTRIBUTE */ + if(count != -1){ + log_err("FAIL: get/bogus attribute should return -1\n"); + } + + /*set it back to normal */ + ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,count); + /*setting minimal days of the week to other values */ + count=ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK); + for (i=1; i<=7; ++i) { + ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,i); + if (ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK) != i) + log_err("FAIL: set/getMinimalDaysInFirstWeek failed\n"); + } + /*set it back to normal */ + ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,count); + + + /*testing if the UCalendar's timezone is currently in day light saving's time*/ + log_verbose("\nTesting if the UCalendar is currently in daylight saving's time\n"); + ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 10, 45, 20, &status); + ucal_inDaylightTime(caldef, &status ); + if(U_FAILURE(status)) { + log_err("Error in ucal_inDaylightTime: %s\n", u_errorName(status)); + } + if(!ucal_inDaylightTime(caldef, &status)) + log_verbose("PASS: It is not in daylight saving's time\n"); + else + log_err("FAIL: It is not in daylight saving's time\n"); + + + + /*closing the UCalendar*/ + ucal_close(caldef); + ucal_close(caldef2); + ucal_close(calfr); + ucal_close(calit); + /*closing the UDateFormat used */ + udat_close(datdef); + free(tzID); + free(result); + free(tzdname); +} + +/*------------------------------------------------------*/ +/*Testing the getMillis, setMillis, setDate and setDateTime functions extensively*/ + +static void TestGetSetDateAPI() +{ + UCalendar *caldef = 0, *caldef2 = 0; + UChar *tzID =0; + UDate d1; + int32_t hour; + int32_t zoneOffset; + UDateFormat *datdef = 0; + UErrorCode status=U_ZERO_ERROR; + UDate d2= 837039928046.0; + UChar temp[30]; + + log_verbose("\nOpening the calendars()\n"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_strcpy(tzID, fgGMTID); + /*open the calendars used */ + caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + /*open the dateformat */ + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /*datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL,fgGMTID,-1, &status);*/ + datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US",fgGMTID,-1,NULL,0, &status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat : %s\n", u_errorName(status)); + return; + } + + + /*Testing getMillis and setMillis */ + log_verbose("\nTesting the date and time fetched in millis for a calendar using getMillis\n"); + d1=ucal_getMillis(caldef, &status); + if(U_FAILURE(status)){ + log_err("Error in getMillis : %s\n", u_errorName(status)); + } + + /*testing setMillis */ + log_verbose("\nTesting the set date and time function using setMillis\n"); + ucal_setMillis(caldef, d2, &status); + if(U_FAILURE(status)){ + log_err("Error in setMillis : %s\n", u_errorName(status)); + } + + /*testing if the calendar date is set properly or not */ + d1=ucal_getMillis(caldef, &status); + if(u_strcmp(myDateFormat(datdef, d1), myDateFormat(datdef, d2))!=0) + log_err("error in setMillis or getMillis\n"); + /*-------------------*/ + + + + ctest_setTimeZone(NULL, &status); + + /*testing ucal_setTimeZone() function*/ + log_verbose("\nTesting if the function ucal_setTimeZone() works fine\n"); + ucal_setMillis(caldef2, d2, &status); + if(U_FAILURE(status)){ + log_err("Error in getMillis : %s\n", u_errorName(status));; + } + hour=ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status); + + u_uastrcpy(tzID, "PST"); + ucal_setTimeZone(caldef2,tzID, 3, &status); + if(U_FAILURE(status)){ + log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status)); + } + else + log_verbose("ucal_setTimeZone worked fine\n"); + if(hour == ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status)) + log_err("FAIL: Error setting the time zone doesn't change the represented time\n"); + else if((hour-8 + 1) != ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status)) /*because it is not in daylight savings time */ + log_err("FAIL: Error setTimeZone doesn't change the represented time correctly with 8 hour offset\n"); + else + log_verbose("PASS: setTimeZone works fine\n"); + + /*testing setTimeZone roundtrip */ + log_verbose("\nTesting setTimeZone() roundtrip\n"); + u_strcpy(tzID, fgGMTID); + ucal_setTimeZone(caldef2, tzID, 3, &status); + if(U_FAILURE(status)){ + log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status)); + } + if(d2==ucal_getMillis(caldef2, &status)) + log_verbose("PASS: setTimeZone roundtrip test passed\n"); + else + log_err("FAIL: setTimeZone roundtrip test failed\n"); + + zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status); + if(U_FAILURE(status)){ + log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status)); + } + else if (zoneOffset != 0) { + log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset); + } + + ucal_setTimeZone(caldef2, NULL, -1, &status); + if(U_FAILURE(status)){ + log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status)); + } + if(ucal_getMillis(caldef2, &status)) + log_verbose("PASS: setTimeZone roundtrip test passed\n"); + else + log_err("FAIL: setTimeZone roundtrip test failed\n"); + + zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status); + if(U_FAILURE(status)){ + log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status)); + } + else if (zoneOffset != -28800000) { + log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset); + } + + ctest_resetTimeZone(); + +/*----------------------------* */ + + + + /*Testing if setDate works fine */ + log_verbose("\nTesting the ucal_setDate() function \n"); + u_uastrcpy(temp, "Dec 17, 1971 11:05:28 PM"); + ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status); + if(U_FAILURE(status)){ + log_err("error in setting the calendar date : %s\n", u_errorName(status)); + } + /*checking if the calendar date is set properly or not */ + d1=ucal_getMillis(caldef, &status); + if(u_strcmp(myDateFormat(datdef, d1), temp)==0) + log_verbose("PASS:setDate works fine\n"); + else + log_err("FAIL:Error in setDate()\n"); + + + /* Testing setDate Extensively with various input values */ + log_verbose("\nTesting ucal_setDate() extensively\n"); + ucal_setDate(caldef, 1999, UCAL_JANUARY, 10, &status); + verify1("1999 10th day of January is :", caldef, datdef, 1999, UCAL_JANUARY, 10); + ucal_setDate(caldef, 1999, UCAL_DECEMBER, 3, &status); + verify1("1999 3rd day of December is :", caldef, datdef, 1999, UCAL_DECEMBER, 3); + ucal_setDate(caldef, 2000, UCAL_MAY, 3, &status); + verify1("2000 3rd day of May is :", caldef, datdef, 2000, UCAL_MAY, 3); + ucal_setDate(caldef, 1999, UCAL_AUGUST, 32, &status); + verify1("1999 32th day of August is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1); + ucal_setDate(caldef, 1999, UCAL_MARCH, 0, &status); + verify1("1999 0th day of March is :", caldef, datdef, 1999, UCAL_FEBRUARY, 28); + ucal_setDate(caldef, 0, UCAL_MARCH, 12, &status); + + /*--------------------*/ + + /*Testing if setDateTime works fine */ + log_verbose("\nTesting the ucal_setDateTime() function \n"); + u_uastrcpy(temp, "May 3, 1972 4:30:42 PM"); + ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status); + if(U_FAILURE(status)){ + log_err("error in setting the calendar date : %s\n", u_errorName(status)); + } + /*checking if the calendar date is set properly or not */ + d1=ucal_getMillis(caldef, &status); + if(u_strcmp(myDateFormat(datdef, d1), temp)==0) + log_verbose("PASS: setDateTime works fine\n"); + else + log_err("FAIL: Error in setDateTime\n"); + + + + /*Testing setDateTime extensively with various input values*/ + log_verbose("\nTesting ucal_setDateTime() function extensively\n"); + ucal_setDateTime(caldef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, &status); + verify2("1999 10th day of October at 6:45:30 is :", caldef, datdef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, 0 ); + ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 15, 10, 55, &status); + verify2("1999 3rd day of March at 15:10:55 is :", caldef, datdef, 1999, UCAL_MARCH, 3, 3, 10, 55, 1); + ucal_setDateTime(caldef, 1999, UCAL_MAY, 3, 25, 30, 45, &status); + verify2("1999 3rd day of May at 25:30:45 is :", caldef, datdef, 1999, UCAL_MAY, 4, 1, 30, 45, 0); + ucal_setDateTime(caldef, 1999, UCAL_AUGUST, 32, 22, 65, 40, &status); + verify2("1999 32th day of August at 22:65:40 is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1, 11, 5, 40,1); + ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, 0, 0, 0,&status); + verify2("1999 12th day of March at 0:0:0 is :", caldef, datdef, 1999, UCAL_MARCH, 12, 0, 0, 0, 0); + ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, -10, -10,0, &status); + verify2("1999 12th day of March is at -10:-10:0 :", caldef, datdef, 1999, UCAL_MARCH, 11, 1, 50, 0, 1); + + + + /*close caldef and datdef*/ + ucal_close(caldef); + ucal_close(caldef2); + udat_close(datdef); + free(tzID); + +} + +/*----------------------------------------------------------- */ +/** + * Confirm the functioning of the calendar field related functions. + */ +static void TestFieldGetSet() +{ + UCalendar *cal = 0; + UChar *tzID = 0; + UDateFormat *datdef = 0; + UDate d1; + UErrorCode status=U_ZERO_ERROR; + log_verbose("\nFetching pointer to UCalendar using the ucal_open()\n"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_strcpy(tzID, fgGMTID); + /*open the calendar used */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if (U_FAILURE(status)) { + log_err("ucal_open failed: %s\n", u_errorName(status)); + return; + } + datdef=udat_open(UDAT_SHORT,UDAT_SHORT ,NULL,fgGMTID,-1,NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat : %s\n", u_errorName(status)); + } + + /*Testing ucal_get()*/ + log_verbose("\nTesting the ucal_get() function of Calendar\n"); + ucal_setDateTime(cal, 1999, UCAL_MARCH, 12, 5, 25, 30, &status); + if(U_FAILURE(status)){ + log_err("error in the setDateTime() : %s\n", u_errorName(status)); + } + if(ucal_get(cal, UCAL_YEAR, &status)!=1999 || ucal_get(cal, UCAL_MONTH, &status)!=2 || + ucal_get(cal, UCAL_DATE, &status)!=12 || ucal_get(cal, UCAL_HOUR, &status)!=5) + log_err("error in ucal_get()\n"); + else if(ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status)!=2 || ucal_get(cal, UCAL_DAY_OF_WEEK, &status)!=6 + || ucal_get(cal, UCAL_WEEK_OF_MONTH, &status)!=2 || ucal_get(cal, UCAL_WEEK_OF_YEAR, &status)!= 11) + log_err("FAIL: error in ucal_get()\n"); + else + log_verbose("PASS: ucal_get() works fine\n"); + + /*Testing the ucal_set() , ucal_clear() functions of calendar*/ + log_verbose("\nTesting the set, and clear field functions of calendar\n"); + ucal_setAttribute(cal, UCAL_LENIENT, 0); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_DATE, 3); + verify1("1997 third day of June = ", cal, datdef, 1997, UCAL_JUNE, 3); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 1); + verify1("1997 first Tuesday in June = ", cal, datdef, 1997, UCAL_JUNE, 3); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, - 1); + verify1("1997 last Tuesday in June = ", cal, datdef,1997, UCAL_JUNE, 24); + /*give undesirable input */ + status = U_ZERO_ERROR; + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 0); + d1=ucal_getMillis(cal,&status); + if (status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("FAIL: No IllegalArgumentError for :"); + log_err("1997 zero-th Tuesday in June \n"); + } + else + log_verbose("PASS: IllegalArgumentError as expected\n"); + + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_WEEK_OF_MONTH, 1); + verify1("1997 Tuesday in week 1 of June = ", cal,datdef, 1997, UCAL_JUNE, 3); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_WEEK_OF_MONTH, 5); + verify1("1997 Tuesday in week 5 of June = ", cal,datdef, 1997, UCAL_JULY, 1); + status = U_ZERO_ERROR; + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_MONTH, UCAL_JUNE); + ucal_set(cal, UCAL_WEEK_OF_MONTH, 0); + verify1("1997 Tuesday in week 0 of June = ", cal, datdef , 1997, UCAL_MAY, 27); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR_WOY, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_WEEK_OF_YEAR, 1); + verify1("1997 Tuesday in week 1 of year = ", cal, datdef,1996, UCAL_DECEMBER, 31); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1997); + ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY); + ucal_set(cal, UCAL_WEEK_OF_YEAR, 10); + verify1("1997 Tuesday in week 10 of year = ", cal,datdef, 1997, UCAL_MARCH, 4); + ucal_clear(cal); + ucal_set(cal, UCAL_YEAR, 1999); + ucal_set(cal, UCAL_DAY_OF_YEAR, 1); + verify1("1999 1st day of the year =", cal, datdef, 1999, UCAL_JANUARY, 1); + ucal_set(cal, UCAL_MONTH, -3); + d1=ucal_getMillis(cal,&status); + if (status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("FAIL: No IllegalArgumentError for :\"1999 -3th month \" "); + } + else + log_verbose("PASS: IllegalArgumentError as expected\n"); + + ucal_setAttribute(cal, UCAL_LENIENT, 1); + + ucal_set(cal, UCAL_MONTH, -3); + verify1("1999 -3th month should be", cal, datdef, 1998, UCAL_OCTOBER, 1); + + + /*testing isSet and clearField()*/ + if(!ucal_isSet(cal, UCAL_WEEK_OF_YEAR)) + log_err("FAIL: error in isSet\n"); + else + log_verbose("PASS: isSet working fine\n"); + ucal_clearField(cal, UCAL_WEEK_OF_YEAR); + if(ucal_isSet(cal, UCAL_WEEK_OF_YEAR)) + log_err("FAIL: there is an error in clearField or isSet\n"); + else + log_verbose("PASS :clearField working fine\n"); + + /*-------------------------------*/ + + ucal_close(cal); + udat_close(datdef); + free(tzID); + +} + + + +/* ------------------------------------- */ +/** + * Execute adding and rolling in Calendar extensively, + */ +static void TestAddRollExtensive() +{ + UCalendar *cal = 0; + int32_t i,limit; + UChar* tzID = 0; + UCalendarDateFields e; + int32_t y,m,d,hr,min,sec,ms; + int32_t maxlimit = 40; + UErrorCode status = U_ZERO_ERROR; + y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0; + + log_verbose("Testing add and roll extensively\n"); + + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + /*open the calendar used */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + if (U_FAILURE(status)) { + log_err("ucal_open() failed : %s\n", u_errorName(status)); + return; + } + + ucal_set(cal, UCAL_YEAR, y); + ucal_set(cal, UCAL_MONTH, m); + ucal_set(cal, UCAL_DATE, d); + + /* Confirm that adding to various fields works.*/ + log_verbose("\nTesting to confirm that adding to various fields works with ucal_add()\n"); + checkDate(cal, y, m, d); + ucal_add(cal,UCAL_YEAR, 1, &status); + if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status)); return; } + y++; + checkDate(cal, y, m, d); + ucal_add(cal,UCAL_MONTH, 12, &status); + if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; } + y+=1; + checkDate(cal, y, m, d); + ucal_add(cal,UCAL_DATE, 1, &status); + if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; } + d++; + checkDate(cal, y, m, d); + ucal_add(cal,UCAL_DATE, 2, &status); + if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; } + d += 2; + checkDate(cal, y, m, d); + ucal_add(cal,UCAL_DATE, 28, &status); + if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; } + ++m; + checkDate(cal, y, m, d); + ucal_add(cal, (UCalendarDateFields)-1, 10, &status); + if(status==U_ILLEGAL_ARGUMENT_ERROR) + log_verbose("Pass: Illegal argument error as expected\n"); + else{ + log_err("Fail: No, illegal argument error as expected. Got....: %s\n", u_errorName(status)); + } + status=U_ZERO_ERROR; + + + /*confirm that applying roll to various fields works fine*/ + log_verbose("\nTesting to confirm that ucal_roll() works\n"); + ucal_roll(cal, UCAL_DATE, -1, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + d -=1; + checkDate(cal, y, m, d); + ucal_roll(cal, UCAL_MONTH, -2, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + m -=2; + checkDate(cal, y, m, d); + ucal_roll(cal, UCAL_DATE, 1, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + d +=1; + checkDate(cal, y, m, d); + ucal_roll(cal, UCAL_MONTH, -12, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + checkDate(cal, y, m, d); + ucal_roll(cal, UCAL_YEAR, -1, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + y -=1; + checkDate(cal, y, m, d); + ucal_roll(cal, UCAL_DATE, 29, &status); + if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; } + d = 2; + checkDate(cal, y, m, d); + ucal_roll(cal, (UCalendarDateFields)-1, 10, &status); + if(status==U_ILLEGAL_ARGUMENT_ERROR) + log_verbose("Pass: illegal arguement error as expected\n"); + else{ + log_err("Fail: no illegal argument error got..: %s\n", u_errorName(status)); + return; + } + status=U_ZERO_ERROR; + ucal_clear(cal); + ucal_setDateTime(cal, 1999, UCAL_FEBRUARY, 28, 10, 30, 45, &status); + if(U_FAILURE(status)){ + log_err("error is setting the datetime: %s\n", u_errorName(status)); + } + ucal_add(cal, UCAL_MONTH, 1, &status); + checkDate(cal, 1999, UCAL_MARCH, 28); + ucal_add(cal, UCAL_MILLISECOND, 1000, &status); + checkDateTime(cal, 1999, UCAL_MARCH, 28, 10, 30, 46, 0, UCAL_MILLISECOND); + + ucal_close(cal); +/*--------------- */ + status=U_ZERO_ERROR; + /* Testing add and roll extensively */ + log_verbose("\nTesting the ucal_add() and ucal_roll() functions extensively\n"); + y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0; + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if (U_FAILURE(status)) { + log_err("ucal_open failed: %s\n", u_errorName(status)); + return; + } + ucal_set(cal, UCAL_YEAR, y); + ucal_set(cal, UCAL_MONTH, m); + ucal_set(cal, UCAL_DATE, d); + ucal_set(cal, UCAL_HOUR, hr); + ucal_set(cal, UCAL_MINUTE, min); + ucal_set(cal, UCAL_SECOND,sec); + ucal_set(cal, UCAL_MILLISECOND, ms); + status=U_ZERO_ERROR; + + log_verbose("\nTesting UCalendar add...\n"); + for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) { + limit = maxlimit; + status = U_ZERO_ERROR; + for (i = 0; i < limit; i++) { + ucal_add(cal, e, 1, &status); + if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; } + } + for (i = 0; i < limit; i++) { + ucal_add(cal, e, -1, &status); + if (U_FAILURE(status)) { + log_err("ucal_add -1 failed: %s\n", u_errorName(status)); + return; + } + } + checkDateTime(cal, y, m, d, hr, min, sec, ms, e); + } + log_verbose("\nTesting calendar ucal_roll()...\n"); + for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) { + limit = maxlimit; + status = U_ZERO_ERROR; + for (i = 0; i < limit; i++) { + ucal_roll(cal, e, 1, &status); + if (U_FAILURE(status)) { + limit = i; + status = U_ZERO_ERROR; + } + } + for (i = 0; i < limit; i++) { + ucal_roll(cal, e, -1, &status); + if (U_FAILURE(status)) { + log_err("ucal_roll -1 failed: %s\n", u_errorName(status)); + return; + } + } + checkDateTime(cal, y, m, d, hr, min, sec, ms, e); + } + + ucal_close(cal); + free(tzID); +} + +/*------------------------------------------------------ */ +/*Testing the Limits for various Fields of Calendar*/ +static void TestGetLimits() +{ + UCalendar *cal = 0; + int32_t min, max, gr_min, le_max, ac_min, ac_max, val; + UChar* tzID = 0; + UErrorCode status = U_ZERO_ERROR; + + + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + /*open the calendar used */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);; + if (U_FAILURE(status)) { + log_err("ucal_open() for gregorian calendar failed in TestGetLimits: %s\n", u_errorName(status)); + return; + } + + log_verbose("\nTesting the getLimits function for various fields\n"); + + + + ucal_setDate(cal, 1999, UCAL_MARCH, 5, &status); /* Set the date to be March 5, 1999 */ + val = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MINIMUM, &status); + max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MAXIMUM, &status); + if ( (min != UCAL_SUNDAY || max != UCAL_SATURDAY ) && (min > val && val > max) && (val != UCAL_FRIDAY)){ + log_err("FAIL: Min/max bad\n"); + log_err("FAIL: Day of week %d out of range\n", val); + log_err("FAIL: FAIL: Day of week should be SUNDAY Got %d\n", val); + } + else + log_verbose("getLimits successful\n"); + + val = ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status); + min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MINIMUM, &status); + max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MAXIMUM, &status); + if ( (min != 0 || max != 5 ) && (min > val && val > max) && (val != 1)){ + log_err("FAIL: Min/max bad\n"); + log_err("FAIL: Day of week in month %d out of range\n", val); + log_err("FAIL: FAIL: Day of week in month should be SUNDAY Got %d\n", val); + + } + else + log_verbose("getLimits successful\n"); + + min=ucal_getLimit(cal, UCAL_MONTH, UCAL_MINIMUM, &status); + max=ucal_getLimit(cal, UCAL_MONTH, UCAL_MAXIMUM, &status); + gr_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_GREATEST_MINIMUM, &status); + le_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_LEAST_MAXIMUM, &status); + ac_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MINIMUM, &status); + ac_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MAXIMUM, &status); + if(U_FAILURE(status)){ + log_err("Error in getLimits: %s\n", u_errorName(status)); + } + if(min!=0 || max!=11 || gr_min!=0 || le_max!=11 || ac_min!=0 || ac_max!=11) + log_err("There is and error in getLimits in fetching the values\n"); + else + log_verbose("getLimits successful\n"); + + ucal_setDateTime(cal, 1999, UCAL_MARCH, 5, 4, 10, 35, &status); + val=ucal_get(cal, UCAL_HOUR_OF_DAY, &status); + min=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MINIMUM, &status); + max=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MAXIMUM, &status); + gr_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_GREATEST_MINIMUM, &status); + le_max=ucal_getLimit(cal, UCAL_MINUTE, UCAL_LEAST_MAXIMUM, &status); + ac_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_ACTUAL_MINIMUM, &status); + ac_max=ucal_getLimit(cal, UCAL_SECOND, UCAL_ACTUAL_MAXIMUM, &status); + if( (min!=0 || max!= 11 || gr_min!=0 || le_max!=60 || ac_min!=0 || ac_max!=60) && + (min>val && val>max) && val!=4){ + + log_err("FAIL: Min/max bad\n"); + log_err("FAIL: Hour of Day %d out of range\n", val); + log_err("FAIL: HOUR_OF_DAY should be 4 Got %d\n", val); + } + else + log_verbose("getLimits successful\n"); + + + /*get BOGUS_LIMIT type*/ + val=ucal_getLimit(cal, UCAL_SECOND, (UCalendarLimitType)99, &status); + if(val != -1){ + log_err("FAIL: ucal_getLimit() with BOGUS type should return -1\n"); + } + status=U_ZERO_ERROR; + + + ucal_close(cal); + free(tzID); +} + + + +/* ------------------------------------- */ + +/** + * Test that the days of the week progress properly when add is called repeatedly + * for increments of 24 days. + */ +static void TestDOWProgression() +{ + int32_t initialDOW, DOW, newDOW, expectedDOW; + UCalendar *cal = 0; + UDateFormat *datfor = 0; + UDate date1; + int32_t delta=24; + UErrorCode status = U_ZERO_ERROR; + UChar* tzID = 0; + char tempMsgBuf[256]; + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_strcpy(tzID, fgGMTID); + /*open the calendar used */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);; + if (U_FAILURE(status)) { + log_err("ucal_open failed: %s\n", u_errorName(status)); + return; + } + + datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status); + if(U_FAILURE(status)){ + log_err("error in creating the dateformat : %s\n", u_errorName(status)); + } + + + ucal_setDate(cal, 1999, UCAL_JANUARY, 1, &status); + + log_verbose("\nTesting the DOW progression\n"); + + initialDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status) ); return; } + newDOW = initialDOW; + do { + DOW = newDOW; + log_verbose("DOW = %d...\n", DOW); + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} + log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1))); + + ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status); + if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); return; } + + newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); return; } + expectedDOW = 1 + (DOW + delta - 1) % 7; + date1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;} + if (newDOW != expectedDOW) { + log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW, + u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); + return; + } + } + while (newDOW != initialDOW); + + ucal_close(cal); + udat_close(datfor); + free(tzID); + +} + +/* ------------------------------------- */ + +/** + * Confirm that the offset between local time and GMT behaves as expected. + */ +static void TestGMTvsLocal() +{ + log_verbose("\nTesting the offset between the GMT and local time\n"); + testZones(1999, 1, 1, 12, 0, 0); + testZones(1999, 4, 16, 18, 30, 0); + testZones(1998, 12, 17, 19, 0, 0); +} + +/* ------------------------------------- */ + +static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc) +{ + int32_t offset,utc, expected; + UCalendar *gmtcal = 0, *cal = 0; + UDate date1; + double temp; + UDateFormat *datfor = 0; + UErrorCode status = U_ZERO_ERROR; + UChar* tzID = 0; + char tempMsgBuf[256]; + + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_strcpy(tzID, fgGMTID); + gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);; + if (U_FAILURE(status)) { + log_err("ucal_open failed: %s\n", u_errorName(status)); + return; + } + u_uastrcpy(tzID, "PST"); + cal = ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status); + if (U_FAILURE(status)) { + log_err("ucal_open failed: %s\n", u_errorName(status)); + return; + } + + datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status); + if(U_FAILURE(status)){ + log_err("error in creating the dateformat : %s\n", u_errorName(status)); + } + + ucal_setDateTime(gmtcal, yr, mo - 1, dt, hr, mn, sc, &status); + if (U_FAILURE(status)) { + log_err("ucal_setDateTime failed: %s\n", u_errorName(status)); + return; + } + ucal_set(gmtcal, UCAL_MILLISECOND, 0); + date1 = ucal_getMillis(gmtcal, &status); + if (U_FAILURE(status)) { + log_err("ucal_getMillis failed: %s\n", u_errorName(status)); + return; + } + log_verbose("date = %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) ); + + + ucal_setMillis(cal, date1, &status); + if (U_FAILURE(status)) { + log_err("ucal_setMillis() failed: %s\n", u_errorName(status)); + return; + } + + offset = ucal_get(cal, UCAL_ZONE_OFFSET, &status); + offset += ucal_get(cal, UCAL_DST_OFFSET, &status); + + if (U_FAILURE(status)) { + log_err("ucal_get() failed: %s\n", u_errorName(status)); + return; + } + temp=(double)((double)offset / 1000.0 / 60.0 / 60.0); + /*printf("offset for %s %f hr\n", austrdup(myDateFormat(datfor, date1)), temp);*/ + + utc = ((ucal_get(cal, UCAL_HOUR_OF_DAY, &status) * 60 + + ucal_get(cal, UCAL_MINUTE, &status)) * 60 + + ucal_get(cal, UCAL_SECOND, &status)) * 1000 + + ucal_get(cal, UCAL_MILLISECOND, &status) - offset; + if (U_FAILURE(status)) { + log_err("ucal_get() failed: %s\n", u_errorName(status)); + return; + } + + expected = ((hr * 60 + mn) * 60 + sc) * 1000; + if (utc != expected) { + temp=(double)(utc - expected)/ 1000 / 60 / 60.0; + log_err("FAIL: Discrepancy of %d millis = %fhr\n", utc-expected, temp ); + } + else + log_verbose("PASS: the offset between local and GMT is correct\n"); + ucal_close(gmtcal); + ucal_close(cal); + udat_close(datfor); + free(tzID); +} + +/* ------------------------------------- */ + + + + +/* INTERNAL FUNCTIONS USED */ +/*------------------------------------------------------------------------------------------- */ + +/* ------------------------------------- */ +static void checkDateTime(UCalendar* c, + int32_t y, int32_t m, int32_t d, + int32_t hr, int32_t min, int32_t sec, + int32_t ms, UCalendarDateFields field) + +{ + UErrorCode status = U_ZERO_ERROR; + if (ucal_get(c, UCAL_YEAR, &status) != y || + ucal_get(c, UCAL_MONTH, &status) != m || + ucal_get(c, UCAL_DATE, &status) != d || + ucal_get(c, UCAL_HOUR, &status) != hr || + ucal_get(c, UCAL_MINUTE, &status) != min || + ucal_get(c, UCAL_SECOND, &status) != sec || + ucal_get(c, UCAL_MILLISECOND, &status) != ms) { + log_err("U_FAILURE for field %d, Expected y/m/d h:m:s:ms of %d/%d/%d %d:%d:%d:%d got %d/%d/%d %d:%d:%d:%d\n", + (int32_t)field, y, m + 1, d, hr, min, sec, ms, + ucal_get(c, UCAL_YEAR, &status), + ucal_get(c, UCAL_MONTH, &status) + 1, + ucal_get(c, UCAL_DATE, &status), + ucal_get(c, UCAL_HOUR, &status), + ucal_get(c, UCAL_MINUTE, &status) + 1, + ucal_get(c, UCAL_SECOND, &status), + ucal_get(c, UCAL_MILLISECOND, &status) ); + + if (U_FAILURE(status)){ + log_err("ucal_get failed: %s\n", u_errorName(status)); + return; + } + + } + else + log_verbose("Confirmed: %d/%d/%d %d:%d:%d:%d\n", y, m + 1, d, hr, min, sec, ms); + +} + +/* ------------------------------------- */ +static void checkDate(UCalendar* c, int32_t y, int32_t m, int32_t d) +{ + UErrorCode status = U_ZERO_ERROR; + if (ucal_get(c,UCAL_YEAR, &status) != y || + ucal_get(c, UCAL_MONTH, &status) != m || + ucal_get(c, UCAL_DATE, &status) != d) { + + log_err("FAILURE: Expected y/m/d of %d/%d/%d got %d/%d/%d\n", y, m + 1, d, + ucal_get(c, UCAL_YEAR, &status), + ucal_get(c, UCAL_MONTH, &status) + 1, + ucal_get(c, UCAL_DATE, &status) ); + + if (U_FAILURE(status)) { + log_err("ucal_get failed: %s\n", u_errorName(status)); + return; + } + } + else + log_verbose("Confirmed: %d/%d/%d\n", y, m + 1, d); + + +} + +/* ------------------------------------- */ + +/* ------------------------------------- */ + +static void verify1(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day) +{ + UDate d1; + UErrorCode status = U_ZERO_ERROR; + if (ucal_get(c, UCAL_YEAR, &status) == year && + ucal_get(c, UCAL_MONTH, &status) == month && + ucal_get(c, UCAL_DATE, &status) == day) { + if (U_FAILURE(status)) { + log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status)); + return; + } + log_verbose("PASS: %s\n", msg); + d1=ucal_getMillis(c, &status); + if (U_FAILURE(status)) { + log_err("ucal_getMillis failed: %s\n", u_errorName(status)); + return; + } + /*log_verbose(austrdup(myDateFormat(dat, d1)) );*/ + } + else { + log_err("FAIL: %s\n", msg); + d1=ucal_getMillis(c, &status); + if (U_FAILURE(status)) { + log_err("ucal_getMillis failed: %s\n", u_errorName(status) ); + return; + } + log_err("Got %s Expected %d/%d/%d \n", austrdup(myDateFormat(dat, d1)), year, month + 1, day ); + return; + } + + +} + +/* ------------------------------------ */ +static void verify2(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day, + int32_t hour, int32_t min, int32_t sec, int32_t am_pm) +{ + UDate d1; + UErrorCode status = U_ZERO_ERROR; + char tempMsgBuf[256]; + + if (ucal_get(c, UCAL_YEAR, &status) == year && + ucal_get(c, UCAL_MONTH, &status) == month && + ucal_get(c, UCAL_DATE, &status) == day && + ucal_get(c, UCAL_HOUR, &status) == hour && + ucal_get(c, UCAL_MINUTE, &status) == min && + ucal_get(c, UCAL_SECOND, &status) == sec && + ucal_get(c, UCAL_AM_PM, &status) == am_pm ){ + if (U_FAILURE(status)) { + log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status)); + return; + } + log_verbose("PASS: %s\n", msg); + d1=ucal_getMillis(c, &status); + if (U_FAILURE(status)) { + log_err("ucal_getMillis failed: %s\n", u_errorName(status)); + return; + } + log_verbose("%s\n" , u_austrcpy(tempMsgBuf, myDateFormat(dat, d1)) ); + } + else { + log_err("FAIL: %s\n", msg); + d1=ucal_getMillis(c, &status); + if (U_FAILURE(status)) { + log_err("ucal_getMillis failed: %s\n", u_errorName(status)); + return; + } + log_err("Got %s Expected %d/%d/%d/ %d:%d:%d %s\n", austrdup(myDateFormat(dat, d1)), + year, month + 1, day, hour, min, sec, (am_pm==0) ? "AM": "PM"); + + return; + } + + +} + +void TestGregorianChange() { + static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */ + const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */ + UCalendar *cal; + UDate date; + UErrorCode errorCode = U_ZERO_ERROR; + + /* Test ucal_setGregorianChange() on a Gregorian calendar. */ + errorCode = U_ZERO_ERROR; + cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucal_open(UTC) failed: %s\n", u_errorName(errorCode)); + return; + } + ucal_setGregorianChange(cal, -365 * (dayMillis * (UDate)1), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucal_setGregorianChange(1969) failed: %s\n", u_errorName(errorCode)); + } else { + date = ucal_getGregorianChange(cal, &errorCode); + if(U_FAILURE(errorCode) || date != -365 * (dayMillis * (UDate)1)) { + log_err("ucal_getGregorianChange() failed: %s, date = %f\n", u_errorName(errorCode), date); + } + } + ucal_close(cal); + + /* Test ucal_setGregorianChange() on a non-Gregorian calendar where it should fail. */ + errorCode = U_ZERO_ERROR; + cal = ucal_open(utc, -1, "th@calendar=buddhist", UCAL_TRADITIONAL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucal_open(UTC, non-Gregorian) failed: %s\n", u_errorName(errorCode)); + return; + } + ucal_setGregorianChange(cal, -730 * (dayMillis * (UDate)1), &errorCode); + if(errorCode != U_UNSUPPORTED_ERROR) { + log_err("ucal_setGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n", + u_errorName(errorCode)); + } + errorCode = U_ZERO_ERROR; + date = ucal_getGregorianChange(cal, &errorCode); + if(errorCode != U_UNSUPPORTED_ERROR) { + log_err("ucal_getGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n", + u_errorName(errorCode)); + } + ucal_close(cal); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h new file mode 100644 index 00000000000..e4ec3fdafe0 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h @@ -0,0 +1,80 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CAPITEST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +*********************************************************************************/ +/* C API TEST FOR CALENDAR */ +#ifndef _CCALTST +#define _CCALTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + + + /** + * The function used to test the Calendar API + **/ + static void TestCalendar(void); + /** + * The function used to test getMillis, setMillis, setDate and setDateTime functions extensively + **/ + static void TestGetSetDateAPI(void); + /** + * This function is used to test and confirm the functioning of + * the calendar get and set functions of calendar fields. + **/ + static void TestFieldGetSet(void); + /** + * Execute and test adding and rolling extensively. + **/ + static void TestAddRollExtensive(void); + /** + *Testing the Limits for various Fields of Calendar + **/ + static void TestGetLimits(void); + /** + * Test that the days of the week progress properly when add is called repeatedly + * for increments of 24 days. + **/ + static void TestDOWProgression(void); + /** + * Confirm that the offset between local time and GMT behaves as expected. + **/ + static void TestGMTvsLocal(void); + /** + * test subroutine used by TestGMTvsLocal() + */ + static void testZones(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); + +/*Internal functions used*/ + /** + * test subroutines used by TestAddRollExtensive() + **/ + static void checkDate(UCalendar* c, int32_t y, int32_t m, int32_t d); + + static void checkDateTime(UCalendar* c, int32_t y, int32_t m, int32_t d, + int32_t hr, int32_t min, int32_t sec, int32_t ms, + UCalendarDateFields field); + + /** + * test subroutines used by TestGetSetDateAPI and TestFieldGetSet + **/ + static void verify1(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day); + + static void verify2(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day, + int32_t hour, int32_t min, int32_t sec, int32_t am_pm); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c new file mode 100644 index 00000000000..4864ccd6260 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c @@ -0,0 +1,3575 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/***************************************************************************** +* +* File CU_CAPITST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +****************************************************************************** +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "unicode/uloc.h" +#include "unicode/ucnv.h" +#include "unicode/ucnv_err.h" +#include "unicode/putil.h" +#include "unicode/uset.h" +#include "unicode/ustring.h" +#include "ucnv_bld.h" /* for sizeof(UConverter) */ +#include "cmemory.h" /* for UAlignedMemory */ +#include "cintltst.h" +#include "ccapitst.h" + +/* for not including "cstring.h" -begin*/ +#ifdef U_WINDOWS +# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2) +#elif defined(POSIX) +# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2) +#else +# define ctest_stricmp(str1, str2) T_CString_stricmp(str1, str2) +#endif + +static int U_EXPORT2 +T_CString_stricmp(const char *str1, const char *str2) { + if(str1==NULL) { + if(str2==NULL) { + return 0; + } else { + return -1; + } + } else if(str2==NULL) { + return 1; + } else { + /* compare non-NULL strings lexically with lowercase */ + int rc; + unsigned char c1, c2; + for(;;) { + c1=(unsigned char)*str1; + c2=(unsigned char)*str2; + if(c1==0) { + if(c2==0) { + return 0; + } else { + return -1; + } + } else if(c2==0) { + return 1; + } else { + /* compare non-zero characters with lowercase */ + rc=(int)(unsigned char)tolower(c1)-(int)(unsigned char)tolower(c2); + if(rc!=0) { + return rc; + } + } + ++str1; + ++str2; + } + } +} +/* for not including "cstring.h" -end*/ + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +#define NUM_CODEPAGE 1 +#define MAX_FILE_LEN 1024*20 +#define UCS_FILE_NAME_SIZE 512 + +/*returns an action other than the one provided*/ +static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA); +static UConverterToUCallback otherCharAction(UConverterToUCallback MIA); + +static UConverter * +cnv_open(const char *name, UErrorCode *pErrorCode) { + if(name!=NULL && name[0]=='*') { + return ucnv_openPackage(loadTestData(pErrorCode), name+1, pErrorCode); + } else { + return ucnv_open(name, pErrorCode); + } +} + + +static void ListNames(void); +static void TestFlushCache(void); +static void TestDuplicateAlias(void); +static void TestCCSID(void); +static void TestJ932(void); +static void TestJ1968(void); +static void TestLMBCSMaxChar(void); + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestConvertSafeCloneCallback(void); +#endif + +static void TestEBCDICSwapLFNL(void); +static void TestConvertEx(void); +static void TestConvertExFromUTF8(void); +static void TestConvertAlgorithmic(void); + void TestDefaultConverterError(void); /* defined in cctest.c */ +static void TestToUCountPending(void); +static void TestFromUCountPending(void); +static void TestDefaultName(void); +static void TestCompareNames(void); +static void TestSubstString(void); +static void InvalidArguments(void); + +void addTestConvert(TestNode** root); + +void addTestConvert(TestNode** root) +{ + addTest(root, &ListNames, "tsconv/ccapitst/ListNames"); + addTest(root, &TestConvert, "tsconv/ccapitst/TestConvert"); + addTest(root, &TestFlushCache, "tsconv/ccapitst/TestFlushCache"); + addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias"); + addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias"); + addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone"); +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback"); +#endif + addTest(root, &TestCCSID, "tsconv/ccapitst/TestCCSID"); + addTest(root, &TestJ932, "tsconv/ccapitst/TestJ932"); + addTest(root, &TestJ1968, "tsconv/ccapitst/TestJ1968"); + addTest(root, &TestLMBCSMaxChar, "tsconv/ccapitst/TestLMBCSMaxChar"); + addTest(root, &TestEBCDICSwapLFNL, "tsconv/ccapitst/TestEBCDICSwapLFNL"); + addTest(root, &TestConvertEx, "tsconv/ccapitst/TestConvertEx"); + addTest(root, &TestConvertExFromUTF8, "tsconv/ccapitst/TestConvertExFromUTF8"); + addTest(root, &TestConvertAlgorithmic, "tsconv/ccapitst/TestConvertAlgorithmic"); + addTest(root, &TestDefaultConverterError, "tsconv/ccapitst/TestDefaultConverterError"); + addTest(root, &TestToUCountPending, "tsconv/ccapitst/TestToUCountPending"); + addTest(root, &TestFromUCountPending, "tsconv/ccapitst/TestFromUCountPending"); + addTest(root, &TestDefaultName, "tsconv/ccapitst/TestDefaultName"); + addTest(root, &TestCompareNames, "tsconv/ccapitst/TestCompareNames"); + addTest(root, &TestSubstString, "tsconv/ccapitst/TestSubstString"); + addTest(root, &InvalidArguments, "tsconv/ccapitst/InvalidArguments"); +} + +static void ListNames(void) { + UErrorCode err = U_ZERO_ERROR; + int32_t testLong1 = 0; + const char* available_conv; + UEnumeration *allNamesEnum = NULL; + int32_t allNamesCount = 0; + uint16_t count; + + log_verbose("Testing ucnv_openAllNames()..."); + allNamesEnum = ucnv_openAllNames(&err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err)); + } + else { + const char *string = NULL; + int32_t len = 0; + int32_t count1 = 0; + int32_t count2 = 0; + allNamesCount = uenum_count(allNamesEnum, &err); + while ((string = uenum_next(allNamesEnum, &len, &err))) { + count1++; + log_verbose("read \"%s\", length %i\n", string, len); + } + if (U_FAILURE(err)) { + log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err)); + err = U_ZERO_ERROR; + } + uenum_reset(allNamesEnum, &err); + while ((string = uenum_next(allNamesEnum, &len, &err))) { + count2++; + ucnv_close(ucnv_open(string, &err)); + log_verbose("read \"%s\", length %i (%s)\n", string, len, U_SUCCESS(err) ? "available" : "unavailable"); + err = U_ZERO_ERROR; + } + if (count1 != count2) { + log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n"); + } + } + uenum_close(allNamesEnum); + err = U_ZERO_ERROR; + + /*Tests ucnv_getAvailableName(), getAvialableCount()*/ + + log_verbose("Testing ucnv_countAvailable()..."); + + testLong1=ucnv_countAvailable(); + log_info("Number of available codepages: %d/%d\n", testLong1, allNamesCount); + + log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */ + + available_conv = ucnv_getAvailableName(testLong1); + /*test ucnv_getAvailableName with err condition*/ + log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 "); + available_conv = ucnv_getAvailableName(-1); + if(available_conv != NULL){ + log_err("ucnv_getAvailableName() with index < 0) should return NULL\n"); + } + + /* Test ucnv_countAliases() etc. */ + count = ucnv_countAliases("utf-8", &err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err)); + } else if(count <= 0) { + log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count); + } else { + /* try to get the aliases individually */ + const char *alias; + alias = ucnv_getAlias("utf-8", 0, &err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err)); + } else if(strcmp("UTF-8", alias) != 0) { + log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias); + } else { + uint16_t aliasNum; + for(aliasNum = 0; aliasNum < count; ++aliasNum) { + alias = ucnv_getAlias("utf-8", aliasNum, &err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err)); + } else if(strlen(alias) > 20) { + /* sanity check */ + log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum, alias); + } else { + log_verbose("alias %d for utf-8: %s\n", aliasNum, alias); + } + } + if(U_SUCCESS(err)) { + /* try to fill an array with all aliases */ + const char **aliases; + aliases=(const char **)malloc(count * sizeof(const char *)); + if(aliases != 0) { + ucnv_getAliases("utf-8", aliases, &err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err)); + } else { + for(aliasNum = 0; aliasNum < count; ++aliasNum) { + /* compare the pointers with the ones returned individually */ + alias = ucnv_getAlias("utf-8", aliasNum, &err); + if(U_FAILURE(err)) { + log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err)); + } else if(aliases[aliasNum] != alias) { + log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum, aliasNum); + } + } + } + free((char **)aliases); + } + } + } + } +} + + +static void TestConvert() +{ +#if !UCONFIG_NO_LEGACY_CONVERSION + char myptr[4]; + char save[4]; + int32_t testLong1 = 0; + uint16_t rest = 0; + int32_t len = 0; + int32_t x = 0; + FILE* ucs_file_in = NULL; + UChar BOM = 0x0000; + UChar myUChar = 0x0000; + char* mytarget; /* [MAX_FILE_LEN] */ + char* mytarget_1; + char* mytarget_use; + UChar* consumedUni = NULL; + char* consumed = NULL; + char* output_cp_buffer; /* [MAX_FILE_LEN] */ + UChar* ucs_file_buffer; /* [MAX_FILE_LEN] */ + UChar* ucs_file_buffer_use; + UChar* my_ucs_file_buffer; /* [MAX_FILE_LEN] */ + UChar* my_ucs_file_buffer_1; + int8_t ii = 0; + int32_t j = 0; + uint16_t codepage_index = 0; + int32_t cp = 0; + UErrorCode err = U_ZERO_ERROR; + char ucs_file_name[UCS_FILE_NAME_SIZE]; + UConverterFromUCallback MIA1, MIA1_2; + UConverterToUCallback MIA2, MIA2_2; + const void *MIA1Context, *MIA1Context2, *MIA2Context, *MIA2Context2; + UConverter* someConverters[5]; + UConverter* myConverter = 0; + UChar* displayname = 0; + + const char* locale; + + UChar* uchar1 = 0; + UChar* uchar2 = 0; + UChar* uchar3 = 0; + int32_t targetcapacity2; + int32_t targetcapacity; + int32_t targetsize; + int32_t disnamelen; + + const UChar* tmp_ucs_buf; + const UChar* tmp_consumedUni=NULL; + const char* tmp_mytarget_use; + const char* tmp_consumed; + + /****************************************************************** + Checking Unicode -> ksc + ******************************************************************/ + + const char* CodePagesToTest[NUM_CODEPAGE] = + { + "ibm-949_P110-1999" + + + }; + const uint16_t CodePageNumberToTest[NUM_CODEPAGE] = + { + 949 + }; + + + const int8_t CodePagesMinChars[NUM_CODEPAGE] = + { + 1 + + }; + + const int8_t CodePagesMaxChars[NUM_CODEPAGE] = + { + 2 + + }; + + const uint16_t CodePagesSubstitutionChars[NUM_CODEPAGE] = + { + 0xAFFE + }; + + const char* CodePagesTestFiles[NUM_CODEPAGE] = + { + "uni-text.bin" + }; + + + const UConverterPlatform CodePagesPlatform[NUM_CODEPAGE] = + { + UCNV_IBM + + }; + + const char* CodePagesLocale[NUM_CODEPAGE] = + { + "ko_KR" + }; + + UConverterFromUCallback oldFromUAction = NULL; + UConverterToUCallback oldToUAction = NULL; + const void* oldFromUContext = NULL; + const void* oldToUContext = NULL; + + /* Allocate memory */ + mytarget = (char*) malloc(MAX_FILE_LEN * sizeof(mytarget[0])); + output_cp_buffer = (char*) malloc(MAX_FILE_LEN * sizeof(output_cp_buffer[0])); + ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(ucs_file_buffer[0])); + my_ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(my_ucs_file_buffer[0])); + + ucs_file_buffer_use = ucs_file_buffer; + mytarget_1=mytarget; + mytarget_use = mytarget; + my_ucs_file_buffer_1=my_ucs_file_buffer; + + /* flush the converter cache to get a consistent state before the flushing is tested */ + ucnv_flushCache(); + + /*Testing ucnv_openU()*/ + { + UChar converterName[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/ + UChar firstSortedName[]={ 0x0021, 0x0000}; /* ! */ + UChar lastSortedName[]={ 0x007E, 0x0000}; /* ~ */ + const char *illegalNameChars={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"}; + UChar illegalName[100]; + UConverter *converter=NULL; + err=U_ZERO_ERROR; + converter=ucnv_openU(converterName, &err); + if(U_FAILURE(err)){ + log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err)); + } + ucnv_close(converter); + err=U_ZERO_ERROR; + converter=ucnv_openU(NULL, &err); + if(U_FAILURE(err)){ + log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err)); + } + ucnv_close(converter); + /*testing with error value*/ + err=U_ILLEGAL_ARGUMENT_ERROR; + converter=ucnv_openU(converterName, &err); + if(!(converter == NULL)){ + log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n"); + } + ucnv_close(converter); + err=U_ZERO_ERROR; + u_uastrcpy(illegalName, ""); + u_uastrcpy(illegalName, illegalNameChars); + ucnv_openU(illegalName, &err); + if(!(err==U_ILLEGAL_ARGUMENT_ERROR)){ + log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n"); + } + + err=U_ZERO_ERROR; + ucnv_openU(firstSortedName, &err); + if(err!=U_FILE_ACCESS_ERROR){ + log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n"); + } + + err=U_ZERO_ERROR; + ucnv_openU(lastSortedName, &err); + if(err!=U_FILE_ACCESS_ERROR){ + log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n"); + } + + err=U_ZERO_ERROR; + } + log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n"); + { + UConverter *cnv=NULL; + err=U_ZERO_ERROR; + cnv=ucnv_open("ibm-949,Madhu", &err); + if(U_FAILURE(err)){ + log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err)); + } + ucnv_close(cnv); + + } + /*Testing ucnv_convert()*/ + { + int32_t targetLimit=0, sourceLimit=0, i=0, targetCapacity=0; + const uint8_t source[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00}; + const uint8_t expectedTarget[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00}; + char *target=0; + sourceLimit=sizeof(source)/sizeof(source[0]); + err=U_ZERO_ERROR; + targetLimit=0; + + targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", NULL, targetLimit , (const char*)source, sourceLimit, &err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err=U_ZERO_ERROR; + targetLimit=targetCapacity+1; + target=(char*)malloc(sizeof(char) * targetLimit); + targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err); + } + if(U_FAILURE(err)){ + log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err)); + } + else { + for(i=0; i<targetCapacity; i++){ + if(target[i] != expectedTarget[i]){ + log_err("FAIL: ucnv_convert(ibm-1363->ibm-1364) failed.at index \n i=%d, Expected: %lx Got: %lx\n", i, (UChar)expectedTarget[i], (uint8_t)target[i]); + } + } + + i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source+1, -1, &err); + if(U_FAILURE(err) || i!=7){ + log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n", + u_errorName(err), i); + } + + /*Test error conditions*/ + err=U_ZERO_ERROR; + i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, 0, &err); + if(i !=0){ + log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n"); + } + + err=U_ILLEGAL_ARGUMENT_ERROR; + sourceLimit=sizeof(source)/sizeof(source[0]); + i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err); + if(i !=0 ){ + log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n"); + } + + err=U_ZERO_ERROR; + sourceLimit=sizeof(source)/sizeof(source[0]); + targetLimit=0; + i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err); + if(!(U_FAILURE(err) && err==U_BUFFER_OVERFLOW_ERROR)){ + log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n"); + } + err=U_ZERO_ERROR; + free(target); + } + } + + /*Testing ucnv_openCCSID and ucnv_open with error conditions*/ + log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n"); + err=U_ILLEGAL_ARGUMENT_ERROR; + if(ucnv_open(NULL, &err) != NULL){ + log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n"); + } + if(ucnv_openCCSID(1051, UCNV_IBM, &err) != NULL){ + log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n"); + } + err=U_ZERO_ERROR; + + /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */ + log_verbose("\n---Testing ucnv_open default...\n"); + someConverters[0] = ucnv_open(NULL,&err); + someConverters[1] = ucnv_open(NULL,&err); + someConverters[2] = ucnv_open("utf8", &err); + someConverters[3] = ucnv_openCCSID(949,UCNV_IBM,&err); + ucnv_close(ucnv_openCCSID(1051, UCNV_IBM, &err)); /* test for j350; ucnv_close(NULL) is safe */ + if (U_FAILURE(err)){ log_data_err("FAILURE! %s\n", myErrorName(err));} + + /* Testing ucnv_getName()*/ + /*default code page */ + ucnv_getName(someConverters[0], &err); + if(U_FAILURE(err)) { + log_data_err("getName[0] failed\n"); + } else { + log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters[0], &err)); + } + ucnv_getName(someConverters[1], &err); + if(U_FAILURE(err)) { + log_data_err("getName[1] failed\n"); + } else { + log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err)); + } + + ucnv_close(someConverters[0]); + ucnv_close(someConverters[1]); + ucnv_close(someConverters[2]); + ucnv_close(someConverters[3]); + + + for (codepage_index=0; codepage_index < NUM_CODEPAGE; ++codepage_index) + { + int32_t i = 0; + + err = U_ZERO_ERROR; +#ifdef U_TOPSRCDIR + strcpy(ucs_file_name, U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING); +#else + strcpy(ucs_file_name, loadTestData(&err)); + + if(U_FAILURE(err)){ + log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err)); + return; + } + + { + char* index = strrchr(ucs_file_name,(char)U_FILE_SEP_CHAR); + + if((unsigned int)(index-ucs_file_name) != (strlen(ucs_file_name)-1)){ + *(index+1)=0; + } + } + + strcat(ucs_file_name,".."U_FILE_SEP_STRING); +#endif + strcat(ucs_file_name, CodePagesTestFiles[codepage_index]); + + ucs_file_in = fopen(ucs_file_name,"rb"); + if (!ucs_file_in) + { + log_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name); + return; + } + + /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/ + + /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */ + /* ucnv_flushCache(); */ + myConverter =ucnv_open( "ibm-949", &err); + if (!myConverter || U_FAILURE(err)) + { + log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err)); + + return; + } + + /*testing for ucnv_getName() */ + log_verbose("Testing ucnv_getName()...\n"); + ucnv_getName(myConverter, &err); + if(U_FAILURE(err)) + log_err("Error in getName\n"); + else + { + log_verbose("getName o.k. %s\n", ucnv_getName(myConverter, &err)); + } + if (ctest_stricmp(ucnv_getName(myConverter, &err), CodePagesToTest[codepage_index])) + log_err("getName failed\n"); + else + log_verbose("getName ok\n"); + /*Test getName with error condition*/ + { + const char* name=0; + err=U_ILLEGAL_ARGUMENT_ERROR; + log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR"); + name=ucnv_getName(myConverter, &err); + if(name != NULL){ + log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail"); + } + err=U_ZERO_ERROR; + } + + + /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/ + + log_verbose("Testing ucnv_getMaxCharSize()...\n"); + if (ucnv_getMaxCharSize(myConverter)==CodePagesMaxChars[codepage_index]) + log_verbose("Max byte per character OK\n"); + else + log_err("Max byte per character failed\n"); + + log_verbose("\n---Testing ucnv_getMinCharSize()...\n"); + if (ucnv_getMinCharSize(myConverter)==CodePagesMinChars[codepage_index]) + log_verbose("Min byte per character OK\n"); + else + log_err("Min byte per character failed\n"); + + + /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/ + log_verbose("\n---Testing ucnv_getSubstChars...\n"); + ii=4; + ucnv_getSubstChars(myConverter, myptr, &ii, &err); + if (ii <= 0) { + log_err("ucnv_getSubstChars returned a negative number %d\n", ii); + } + + for(x=0;x<ii;x++) + rest = (uint16_t)(((unsigned char)rest << 8) + (unsigned char)myptr[x]); + if (rest==CodePagesSubstitutionChars[codepage_index]) + log_verbose("Substitution character ok\n"); + else + log_err("Substitution character failed.\n"); + + log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n"); + ucnv_setSubstChars(myConverter, myptr, ii, &err); + if (U_FAILURE(err)) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + ucnv_getSubstChars(myConverter,save, &ii, &err); + if (U_FAILURE(err)) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + + if (strncmp(save, myptr, ii)) + log_err("Saved substitution character failed\n"); + else + log_verbose("Saved substitution character ok\n"); + + /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/ + log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n"); + ii=1; + ucnv_getSubstChars(myConverter, myptr, &ii, &err); + if(err != U_INDEX_OUTOFBOUNDS_ERROR){ + log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err)); + } + err=U_ZERO_ERROR; + ii=4; + ucnv_getSubstChars(myConverter, myptr, &ii, &err); + log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n"); + ucnv_setSubstChars(myConverter, myptr, 0, &err); + if(err != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err)); + } + log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n"); + strcpy(myptr, "abc"); + ucnv_setSubstChars(myConverter, myptr, ii, &err); + err=U_ZERO_ERROR; + ucnv_getSubstChars(myConverter, save, &ii, &err); + if(strncmp(save, myptr, ii) == 0){ + log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n"); + } + log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n"); + err=U_ZERO_ERROR; + strcpy(myptr, "abc"); + ucnv_setSubstChars(myConverter, myptr, ii, &err); + err=U_ILLEGAL_ARGUMENT_ERROR; + ucnv_getSubstChars(myConverter, save, &ii, &err); + if(strncmp(save, myptr, ii) == 0){ + log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n"); + } + err=U_ZERO_ERROR; + /*------*/ + +#ifdef U_ENABLE_GENERIC_ISO_2022 + /*resetState ucnv_reset()*/ + log_verbose("\n---Testing ucnv_reset()..\n"); + ucnv_reset(myConverter); + { + UChar32 c; + const uint8_t in[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80}; + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UConverter *cnv=ucnv_open("ISO_2022", &err); + if(U_FAILURE(err)) { + log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err)); + } + c=ucnv_getNextUChar(cnv, &source, limit, &err); + if((U_FAILURE(err) || c != (UChar32)0x0031)) { + log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err)); + } + ucnv_reset(cnv); + ucnv_close(cnv); + + } +#endif + + /*getDisplayName*/ + log_verbose("\n---Testing ucnv_getDisplayName()...\n"); + locale=CodePagesLocale[codepage_index]; + len=0; + displayname=NULL; + disnamelen = ucnv_getDisplayName(myConverter, locale, displayname, len, &err); + if(err==U_BUFFER_OVERFLOW_ERROR) { + err=U_ZERO_ERROR; + displayname=(UChar*)malloc((disnamelen+1) * sizeof(UChar)); + ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err); + if(U_FAILURE(err)) { + log_err("getDisplayName failed. The error is %s\n", myErrorName(err)); + } + else { + log_verbose(" getDisplayName o.k.\n"); + } + free(displayname); + displayname=NULL; + } + else { + log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err)); + } + /*test ucnv_getDiaplayName with error condition*/ + err= U_ILLEGAL_ARGUMENT_ERROR; + len=ucnv_getDisplayName(myConverter,locale,NULL,0, &err); + if( len !=0 ){ + log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n"); + } + /*test ucnv_getDiaplayName with error condition*/ + err=U_ZERO_ERROR; + len=ucnv_getDisplayName(NULL,locale,NULL,0, &err); + if( len !=0 || U_SUCCESS(err)){ + log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n"); + } + err=U_ZERO_ERROR; + + /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/ + ucnv_getFromUCallBack(myConverter, &MIA1, &MIA1Context); + + log_verbose("\n---Testing ucnv_setFromUCallBack...\n"); + ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err); + if (U_FAILURE(err) || oldFromUAction != MIA1 || oldFromUContext != MIA1Context) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + + ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2); + if (MIA1_2 != otherUnicodeAction(MIA1) || MIA1Context2 != &BOM) + log_err("get From UCallBack failed\n"); + else + log_verbose("get From UCallBack ok\n"); + + log_verbose("\n---Testing getFromUCallBack Roundtrip...\n"); + ucnv_setFromUCallBack(myConverter,MIA1, MIA1Context, &oldFromUAction, &oldFromUContext, &err); + if (U_FAILURE(err) || oldFromUAction != otherUnicodeAction(MIA1) || oldFromUContext != &BOM) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + + ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2); + if (MIA1_2 != MIA1 || MIA1Context2 != MIA1Context) + log_err("get From UCallBack action failed\n"); + else + log_verbose("get From UCallBack action ok\n"); + + /*testing ucnv_setToUCallBack with error conditions*/ + err=U_ILLEGAL_ARGUMENT_ERROR; + log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n"); + ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err); + ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2); + if(MIA1_2 == otherUnicodeAction(MIA1) || MIA1Context2 == &BOM){ + log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n"); + } + err=U_ZERO_ERROR; + + + /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/ + ucnv_getToUCallBack(myConverter, &MIA2, &MIA2Context); + + log_verbose("\n---Testing setTo UCallBack...\n"); + ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), &BOM, &oldToUAction, &oldToUContext, &err); + if (U_FAILURE(err) || oldToUAction != MIA2 || oldToUContext != MIA2Context) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + + ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2); + if (MIA2_2 != otherCharAction(MIA2) || MIA2Context2 != &BOM) + log_err("To UCallBack failed\n"); + else + log_verbose("To UCallBack ok\n"); + + log_verbose("\n---Testing setTo UCallBack Roundtrip...\n"); + ucnv_setToUCallBack(myConverter,MIA2, MIA2Context, &oldToUAction, &oldToUContext, &err); + if (U_FAILURE(err) || oldToUAction != otherCharAction(MIA2) || oldToUContext != &BOM) + { log_err("FAILURE! %s\n", myErrorName(err)); } + + ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2); + if (MIA2_2 != MIA2 || MIA2Context2 != MIA2Context) + log_err("To UCallBack failed\n"); + else + log_verbose("To UCallBack ok\n"); + + /*testing ucnv_setToUCallBack with error conditions*/ + err=U_ILLEGAL_ARGUMENT_ERROR; + log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n"); + ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), NULL, &oldToUAction, &oldToUContext, &err); + ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2); + if (MIA2_2 == otherCharAction(MIA2) || MIA2Context2 == &BOM){ + log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n"); + } + err=U_ZERO_ERROR; + + + /*getcodepageid testing ucnv_getCCSID() */ + log_verbose("\n----Testing getCCSID....\n"); + cp = ucnv_getCCSID(myConverter,&err); + if (U_FAILURE(err)) + { + log_err("FAILURE!..... %s\n", myErrorName(err)); + } + if (cp != CodePageNumberToTest[codepage_index]) + log_err("Codepage number test failed\n"); + else + log_verbose("Codepage number test OK\n"); + + /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/ + err=U_ILLEGAL_ARGUMENT_ERROR; + if( ucnv_getCCSID(myConverter,&err) != -1){ + log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n"); + } + err=U_ZERO_ERROR; + + /*getCodepagePlatform testing ucnv_getPlatform()*/ + log_verbose("\n---Testing getCodepagePlatform ..\n"); + if (CodePagesPlatform[codepage_index]!=ucnv_getPlatform(myConverter, &err)) + log_err("Platform codepage test failed\n"); + else + log_verbose("Platform codepage test ok\n"); + + if (U_FAILURE(err)) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/ + err= U_ILLEGAL_ARGUMENT_ERROR; + if(ucnv_getPlatform(myConverter, &err) != UCNV_UNKNOWN){ + log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n"); + } + err=U_ZERO_ERROR; + + + /*Reads the BOM*/ + fread(&BOM, sizeof(UChar), 1, ucs_file_in); + if (BOM!=0xFEFF && BOM!=0xFFFE) + { + log_err("File Missing BOM...Bailing!\n"); + return; + } + + + /*Reads in the file*/ + while(!feof(ucs_file_in)&&(i+=fread(ucs_file_buffer+i, sizeof(UChar), 1, ucs_file_in))) + { + myUChar = ucs_file_buffer[i-1]; + + ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN*/ + } + + myUChar = ucs_file_buffer[i-1]; + ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN Corner Case*/ + + + /*testing ucnv_fromUChars() and ucnv_toUChars() */ + /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/ + + uchar1=(UChar*)malloc(sizeof(UChar) * (i+1)); + u_uastrcpy(uchar1,""); + u_strncpy(uchar1,ucs_file_buffer,i); + uchar1[i] = 0; + + uchar3=(UChar*)malloc(sizeof(UChar)*(i+1)); + u_uastrcpy(uchar3,""); + u_strncpy(uchar3,ucs_file_buffer,i); + uchar3[i] = 0; + + /*Calls the Conversion Routine */ + testLong1 = MAX_FILE_LEN; + log_verbose("\n---Testing ucnv_fromUChars()\n"); + targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err); + if (U_FAILURE(err)) + { + log_err("\nFAILURE...%s\n", myErrorName(err)); + } + else + log_verbose(" ucnv_fromUChars() o.k.\n"); + + /*test the conversion routine */ + log_verbose("\n---Testing ucnv_toUChars()\n"); + /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */ + targetcapacity2=0; + targetsize = ucnv_toUChars(myConverter, + NULL, + targetcapacity2, + output_cp_buffer, + strlen(output_cp_buffer), + &err); + /*if there is an buffer overflow then trap the values and pass them and make the actual call*/ + + if(err==U_BUFFER_OVERFLOW_ERROR) + { + err=U_ZERO_ERROR; + uchar2=(UChar*)malloc((targetsize+1) * sizeof(UChar)); + targetsize = ucnv_toUChars(myConverter, + uchar2, + targetsize+1, + output_cp_buffer, + strlen(output_cp_buffer), + &err); + + if(U_FAILURE(err)) + log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err)); + else + log_verbose(" ucnv_toUChars() o.k.\n"); + + if(u_strcmp(uchar1,uchar2)!=0) + log_err("equality test failed with conversion routine\n"); + } + else + { + log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n"); + } + /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/ + err=U_ILLEGAL_ARGUMENT_ERROR; + log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n"); + targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err); + if (targetcapacity !=0) { + log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n"); + } + err=U_ZERO_ERROR; + log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n"); + targetcapacity = ucnv_fromUChars(NULL, output_cp_buffer, testLong1, uchar1, -1, &err); + if (targetcapacity !=0 || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n"); + } + err=U_ZERO_ERROR; + log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n"); + targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, 0, &err); + if (targetcapacity !=0) { + log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n"); + } + log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n"); + targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, 0, uchar1, -1, &err); + if (err != U_BUFFER_OVERFLOW_ERROR) { + log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n"); + } + /*toUChars with error conditions*/ + targetsize = ucnv_toUChars(myConverter, uchar2, targetsize, output_cp_buffer, strlen(output_cp_buffer), &err); + if(targetsize != 0){ + log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n"); + } + err=U_ZERO_ERROR; + targetsize = ucnv_toUChars(myConverter, uchar2, -1, output_cp_buffer, strlen(output_cp_buffer), &err); + if(targetsize != 0 || err != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n"); + } + err=U_ZERO_ERROR; + targetsize = ucnv_toUChars(myConverter, uchar2, 0, output_cp_buffer, 0, &err); + if (targetsize !=0) { + log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n"); + } + targetcapacity2=0; + targetsize = ucnv_toUChars(myConverter, NULL, targetcapacity2, output_cp_buffer, strlen(output_cp_buffer), &err); + if (err != U_STRING_NOT_TERMINATED_WARNING) { + log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n", + u_errorName(err)); + } + err=U_ZERO_ERROR; + /*-----*/ + + + /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */ + /*Clean up re-usable vars*/ + j=0; + log_verbose("Testing ucnv_fromUnicode().....\n"); + tmp_ucs_buf=ucs_file_buffer_use; + ucnv_fromUnicode(myConverter, &mytarget_1, + mytarget + MAX_FILE_LEN, + &tmp_ucs_buf, + ucs_file_buffer_use+i, + NULL, + TRUE, + &err); + consumedUni = (UChar*)tmp_consumedUni; + + if (U_FAILURE(err)) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + else + log_verbose("ucnv_fromUnicode() o.k.\n"); + + /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */ + log_verbose("Testing ucnv_toUnicode().....\n"); + tmp_mytarget_use=mytarget_use; + tmp_consumed = consumed; + ucnv_toUnicode(myConverter, &my_ucs_file_buffer_1, + my_ucs_file_buffer + MAX_FILE_LEN, + &tmp_mytarget_use, + mytarget_use + (mytarget_1 - mytarget), + NULL, + FALSE, + &err); + consumed = (char*)tmp_consumed; + if (U_FAILURE(err)) + { + log_err("FAILURE! %s\n", myErrorName(err)); + } + else + log_verbose("ucnv_toUnicode() o.k.\n"); + + + log_verbose("\n---Testing RoundTrip ...\n"); + + + u_strncpy(uchar3, my_ucs_file_buffer,i); + uchar3[i] = 0; + + if(u_strcmp(uchar1,uchar3)==0) + log_verbose("Equality test o.k.\n"); + else + log_err("Equality test failed\n"); + + /*sanity compare */ + if(uchar2 == NULL) + { + log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__); + } + else + { + if(u_strcmp(uchar2, uchar3)==0) + log_verbose("Equality test o.k.\n"); + else + log_err("Equality test failed\n"); + } + + fclose(ucs_file_in); + ucnv_close(myConverter); + if (uchar1 != 0) free(uchar1); + if (uchar2 != 0) free(uchar2); + if (uchar3 != 0) free(uchar3); + } + + free((void*)mytarget); + free((void*)output_cp_buffer); + free((void*)ucs_file_buffer); + free((void*)my_ucs_file_buffer); +#endif +} + +static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA) +{ + return (MIA==(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP)?(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_SUBSTITUTE:(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP; +} + + +static UConverterToUCallback otherCharAction(UConverterToUCallback MIA) +{ + return (MIA==(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP)?(UConverterToUCallback)UCNV_TO_U_CALLBACK_SUBSTITUTE:(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP; +} + +static void TestFlushCache(void) { +#if !UCONFIG_NO_LEGACY_CONVERSION + UErrorCode err = U_ZERO_ERROR; + UConverter* someConverters[5]; + int flushCount = 0; + + /* flush the converter cache to get a consistent state before the flushing is tested */ + ucnv_flushCache(); + + /*Testing ucnv_open()*/ + /* Note: These converters have been chosen because they do NOT + encode the Latin characters (U+0041, ...), and therefore are + highly unlikely to be chosen as system default codepages */ + + someConverters[0] = ucnv_open("ibm-1047", &err); + if (U_FAILURE(err)) { + log_data_err("FAILURE! %s\n", myErrorName(err)); + } + + someConverters[1] = ucnv_open("ibm-1047", &err); + if (U_FAILURE(err)) { + log_data_err("FAILURE! %s\n", myErrorName(err)); + } + + someConverters[2] = ucnv_open("ibm-1047", &err); + if (U_FAILURE(err)) { + log_data_err("FAILURE! %s\n", myErrorName(err)); + } + + someConverters[3] = ucnv_open("gb18030", &err); + if (U_FAILURE(err)) { + log_data_err("FAILURE! %s\n", myErrorName(err)); + } + + someConverters[4] = ucnv_open("ibm-954", &err); + if (U_FAILURE(err)) { + log_data_err("FAILURE! %s\n", myErrorName(err)); + } + + + /* Testing ucnv_flushCache() */ + log_verbose("\n---Testing ucnv_flushCache...\n"); + if ((flushCount=ucnv_flushCache())==0) + log_verbose("Flush cache ok\n"); + else + log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount); + + /*testing ucnv_close() and ucnv_flushCache() */ + ucnv_close(someConverters[0]); + ucnv_close(someConverters[1]); + + if ((flushCount=ucnv_flushCache())==0) + log_verbose("Flush cache ok\n"); + else + log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount); + + ucnv_close(someConverters[2]); + ucnv_close(someConverters[3]); + + if ((flushCount=ucnv_flushCache())==2) + log_verbose("Flush cache ok\n"); /*because first, second and third are same */ + else + log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n", + __LINE__, + flushCount); + + ucnv_close(someConverters[4]); + if ( (flushCount=ucnv_flushCache())==1) + log_verbose("Flush cache ok\n"); + else + log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount); +#endif +} + +/** + * Test the converter alias API, specifically the fuzzy matching of + * alias names and the alias table integrity. Make sure each + * converter has at least one alias (itself), and that its listed + * aliases map back to itself. Check some hard-coded UTF-8 and + * ISO_2022 aliases to make sure they work. + */ +static void TestAlias() { + int32_t i, ncnv; + UErrorCode status = U_ZERO_ERROR; + + /* Predetermined aliases that we expect to map back to ISO_2022 + * and UTF-8. UPDATE THIS DATA AS NECESSARY. */ + const char* ISO_2022_NAMES[] = + {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2", + "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"}; + int32_t ISO_2022_NAMES_LENGTH = + sizeof(ISO_2022_NAMES) / sizeof(ISO_2022_NAMES[0]); + const char *UTF8_NAMES[] = + { "UTF-8", "utf-8", "utf8", "ibm-1208", + "utf_8", "ibm1208", "cp1208" }; + int32_t UTF8_NAMES_LENGTH = + sizeof(UTF8_NAMES) / sizeof(UTF8_NAMES[0]); + + struct { + const char *name; + const char *alias; + } CONVERTERS_NAMES[] = { + { "UTF-32BE", "UTF32_BigEndian" }, + { "UTF-32LE", "UTF32_LittleEndian" }, + { "UTF-32", "ISO-10646-UCS-4" }, + { "UTF32_PlatformEndian", "UTF32_PlatformEndian" }, + { "UTF-32", "ucs-4" } + }; + int32_t CONVERTERS_NAMES_LENGTH = sizeof(CONVERTERS_NAMES) / sizeof(*CONVERTERS_NAMES); + + /* When there are bugs in gencnval or in ucnv_io, converters can + appear to have no aliases. */ + ncnv = ucnv_countAvailable(); + log_verbose("%d converters\n", ncnv); + for (i=0; i<ncnv; ++i) { + const char *name = ucnv_getAvailableName(i); + const char *alias0; + uint16_t na = ucnv_countAliases(name, &status); + uint16_t j; + UConverter *cnv; + + if (na == 0) { + log_err("FAIL: Converter \"%s\" (i=%d)" + " has no aliases; expect at least one\n", + name, i); + continue; + } + cnv = ucnv_open(name, &status); + if (U_FAILURE(status)) { + log_data_err("FAIL: Converter \"%s\" (i=%d)" + " can't be opened.\n", + name, i); + } + else { + if (strcmp(ucnv_getName(cnv, &status), name) != 0 + && (strstr(name, "PlatformEndian") == 0 && strstr(name, "OppositeEndian") == 0)) { + log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. " + "The should be the same\n", + name, ucnv_getName(cnv, &status)); + } + } + ucnv_close(cnv); + + status = U_ZERO_ERROR; + alias0 = ucnv_getAlias(name, 0, &status); + for (j=1; j<na; ++j) { + const char *alias; + /* Make sure each alias maps back to the the same list of + aliases. Assume that if alias 0 is the same, the whole + list is the same (this should always be true). */ + const char *mapBack; + + status = U_ZERO_ERROR; + alias = ucnv_getAlias(name, j, &status); + if (status == U_AMBIGUOUS_ALIAS_WARNING) { + log_err("FAIL: Converter \"%s\"is ambiguous\n", name); + } + + if (alias == NULL) { + log_err("FAIL: Converter \"%s\" -> " + "alias[%d]=NULL\n", + name, j); + continue; + } + + mapBack = ucnv_getAlias(alias, 0, &status); + + if (mapBack == NULL) { + log_err("FAIL: Converter \"%s\" -> " + "alias[%d]=\"%s\" -> " + "alias[0]=NULL, exp. \"%s\"\n", + name, j, alias, alias0); + continue; + } + + if (0 != strcmp(alias0, mapBack)) { + int32_t idx; + UBool foundAlias = FALSE; + if (status == U_AMBIGUOUS_ALIAS_WARNING) { + /* Make sure that we only get this mismapping when there is + an ambiguous alias, and the other converter has this alias too. */ + for (idx = 0; idx < ucnv_countAliases(mapBack, &status); idx++) { + if (strcmp(ucnv_getAlias(mapBack, (uint16_t)idx, &status), alias) == 0) { + foundAlias = TRUE; + break; + } + } + } + /* else not ambiguous, and this is a real problem. foundAlias = FALSE */ + + if (!foundAlias) { + log_err("FAIL: Converter \"%s\" -> " + "alias[%d]=\"%s\" -> " + "alias[0]=\"%s\", exp. \"%s\"\n", + name, j, alias, mapBack, alias0); + } + } + } + } + + + /* Check a list of predetermined aliases that we expect to map + * back to ISO_2022 and UTF-8. */ + for (i=1; i<ISO_2022_NAMES_LENGTH; ++i) { + const char* mapBack = ucnv_getAlias(ISO_2022_NAMES[i], 0, &status); + if(!mapBack) { + log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES[i]); + continue; + } + if (0 != strcmp(mapBack, ISO_2022_NAMES[0])) { + log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n", + ISO_2022_NAMES[i], mapBack); + } + } + + + for (i=1; i<UTF8_NAMES_LENGTH; ++i) { + const char* mapBack = ucnv_getAlias(UTF8_NAMES[i], 0, &status); + if(!mapBack) { + log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES[i]); + continue; + } + if (mapBack && 0 != strcmp(mapBack, UTF8_NAMES[0])) { + log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n", + UTF8_NAMES[i], mapBack); + } + } + + /* + * Check a list of predetermined aliases that we expect to map + * back to predermined converter names. + */ + + for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) { + const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status); + if(!mapBack) { + log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i].name); + continue; + } + if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) { + log_err("FAIL: \"%s\" -> \"%s\", expect %s\n", + CONVERTERS_NAMES[i].alias, mapBack, CONVERTERS_NAMES[i].name); + } + } + +} + +static void TestDuplicateAlias(void) { + const char *alias; + UErrorCode status = U_ZERO_ERROR; + + status = U_ZERO_ERROR; + alias = ucnv_getStandardName("Shift_JIS", "IBM", &status); + if (alias == NULL || strcmp(alias, "ibm-943") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) { + log_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias); + } + status = U_ZERO_ERROR; + alias = ucnv_getStandardName("ibm-943", "IANA", &status); + if (alias == NULL || strcmp(alias, "Shift_JIS") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) { + log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias); + } + status = U_ZERO_ERROR; + alias = ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status); + if (alias != NULL || status == U_AMBIGUOUS_ALIAS_WARNING) { + log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias); + } +} + + +/* Test safe clone callback */ + +static uint32_t TSCC_nextSerial() +{ + static uint32_t n = 1; + + return (n++); +} + +typedef struct +{ + uint32_t magic; /* 0xC0FFEE to identify that the object is OK */ + uint32_t serial; /* minted from nextSerial, above */ + UBool wasClosed; /* close happened on the object */ +} TSCCContext; + +static TSCCContext *TSCC_clone(TSCCContext *ctx) +{ + TSCCContext *newCtx = (TSCCContext *)malloc(sizeof(TSCCContext)); + + newCtx->serial = TSCC_nextSerial(); + newCtx->wasClosed = 0; + newCtx->magic = 0xC0FFEE; + + log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial); + + return newCtx; +} + +static void TSCC_fromU(const void *context, + UConverterFromUnicodeArgs *fromUArgs, + const UChar* codeUnits, + int32_t length, + UChar32 codePoint, + UConverterCallbackReason reason, + UErrorCode * err) +{ + TSCCContext *ctx = (TSCCContext*)context; + UConverterFromUCallback junkFrom; + + log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, fromUArgs->converter); + + if(ctx->magic != 0xC0FFEE) { + log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic); + return; + } + + if(reason == UCNV_CLONE) { + UErrorCode subErr = U_ZERO_ERROR; + TSCCContext *newCtx; + TSCCContext *junkCtx; + TSCCContext **pjunkCtx = &junkCtx; + + /* "recreate" it */ + log_verbose("TSCC_fromU: cloning..\n"); + newCtx = TSCC_clone(ctx); + + if(newCtx == NULL) { + log_err("TSCC_fromU: internal clone failed on %p\n", ctx); + } + + /* now, SET it */ + ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)pjunkCtx); + ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr); + + if(U_FAILURE(subErr)) { + *err = subErr; + } + } + + if(reason == UCNV_CLOSE) { + log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx, ctx->serial); + ctx->wasClosed = TRUE; + } +} + + +static void TSCC_toU(const void *context, + UConverterToUnicodeArgs *toUArgs, + const char* codeUnits, + int32_t length, + UConverterCallbackReason reason, + UErrorCode * err) +{ + TSCCContext *ctx = (TSCCContext*)context; + UConverterToUCallback junkFrom; + + log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, toUArgs->converter); + + if(ctx->magic != 0xC0FFEE) { + log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic); + return; + } + + if(reason == UCNV_CLONE) { + UErrorCode subErr = U_ZERO_ERROR; + TSCCContext *newCtx; + TSCCContext *junkCtx; + TSCCContext **pjunkCtx = &junkCtx; + + /* "recreate" it */ + log_verbose("TSCC_toU: cloning..\n"); + newCtx = TSCC_clone(ctx); + + if(newCtx == NULL) { + log_err("TSCC_toU: internal clone failed on %p\n", ctx); + } + + /* now, SET it */ + ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)pjunkCtx); + ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr); + + if(U_FAILURE(subErr)) { + *err = subErr; + } + } + + if(reason == UCNV_CLOSE) { + log_verbose("TSCC_toU: Context %p:%d closing\n", ctx, ctx->serial); + ctx->wasClosed = TRUE; + } +} + +static void TSCC_init(TSCCContext *q) +{ + q->magic = 0xC0FFEE; + q->serial = TSCC_nextSerial(); + q->wasClosed = 0; +} + +static void TSCC_print_log(TSCCContext *q, const char *name) +{ + if(q==NULL) { + log_verbose("TSCContext: %s is NULL!!\n", name); + } else { + if(q->magic != 0xC0FFEE) { + log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n", + q,q->serial, q->magic); + } + log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n", + q, q->serial, name, q->magic, q->wasClosed?"CLOSED":"open"); + } +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestConvertSafeCloneCallback() +{ + UErrorCode err = U_ZERO_ERROR; + TSCCContext from1, to1; + TSCCContext *from2, *from3, *to2, *to3; + TSCCContext **pfrom2 = &from2, **pfrom3 = &from3, **pto2 = &to2, **pto3 = &to3; + char hunk[8192]; + int32_t hunkSize = 8192; + UConverterFromUCallback junkFrom; + UConverterToUCallback junkTo; + UConverter *conv1, *conv2 = NULL; + + conv1 = ucnv_open("iso-8859-3", &err); + + if(U_FAILURE(err)) { + log_data_err("Err opening iso-8859-3, %s", u_errorName(err)); + return; + } + + log_verbose("Opened conv1=%p\n", conv1); + + TSCC_init(&from1); + TSCC_init(&to1); + + TSCC_print_log(&from1, "from1"); + TSCC_print_log(&to1, "to1"); + + ucnv_setFromUCallBack(conv1, TSCC_fromU, &from1, NULL, NULL, &err); + log_verbose("Set from1 on conv1\n"); + TSCC_print_log(&from1, "from1"); + + ucnv_setToUCallBack(conv1, TSCC_toU, &to1, NULL, NULL, &err); + log_verbose("Set to1 on conv1\n"); + TSCC_print_log(&to1, "to1"); + + conv2 = ucnv_safeClone(conv1, hunk, &hunkSize, &err); + if(U_FAILURE(err)) { + log_err("safeClone failed: %s\n", u_errorName(err)); + return; + } + log_verbose("Cloned to conv2=%p.\n", conv2); + +/********** from *********************/ + ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)pfrom2); + ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)pfrom3); + + TSCC_print_log(from2, "from2"); + TSCC_print_log(from3, "from3(==from1)"); + + if(from2 == NULL) { + log_err("FAIL! from2 is null \n"); + return; + } + + if(from3 == NULL) { + log_err("FAIL! from3 is null \n"); + return; + } + + if(from3 != (&from1) ) { + log_err("FAIL! conv1's FROM context changed!\n"); + } + + if(from2 == (&from1) ) { + log_err("FAIL! conv1's FROM context is the same as conv2's!\n"); + } + + if(from1.wasClosed) { + log_err("FAIL! from1 is closed \n"); + } + + if(from2->wasClosed) { + log_err("FAIL! from2 was closed\n"); + } + +/********** to *********************/ + ucnv_getToUCallBack(conv2, &junkTo, (const void**)pto2); + ucnv_getToUCallBack(conv1, &junkTo, (const void**)pto3); + + TSCC_print_log(to2, "to2"); + TSCC_print_log(to3, "to3(==to1)"); + + if(to2 == NULL) { + log_err("FAIL! to2 is null \n"); + return; + } + + if(to3 == NULL) { + log_err("FAIL! to3 is null \n"); + return; + } + + if(to3 != (&to1) ) { + log_err("FAIL! conv1's TO context changed!\n"); + } + + if(to2 == (&to1) ) { + log_err("FAIL! conv1's TO context is the same as conv2's!\n"); + } + + if(to1.wasClosed) { + log_err("FAIL! to1 is closed \n"); + } + + if(to2->wasClosed) { + log_err("FAIL! to2 was closed\n"); + } + +/*************************************/ + + ucnv_close(conv1); + log_verbose("ucnv_closed (conv1)\n"); + TSCC_print_log(&from1, "from1"); + TSCC_print_log(from2, "from2"); + TSCC_print_log(&to1, "to1"); + TSCC_print_log(to2, "to2"); + + if(from1.wasClosed == FALSE) { + log_err("FAIL! from1 is NOT closed \n"); + } + + if(from2->wasClosed) { + log_err("FAIL! from2 was closed\n"); + } + + if(to1.wasClosed == FALSE) { + log_err("FAIL! to1 is NOT closed \n"); + } + + if(to2->wasClosed) { + log_err("FAIL! to2 was closed\n"); + } + + ucnv_close(conv2); + log_verbose("ucnv_closed (conv2)\n"); + + TSCC_print_log(&from1, "from1"); + TSCC_print_log(from2, "from2"); + + if(from1.wasClosed == FALSE) { + log_err("FAIL! from1 is NOT closed \n"); + } + + if(from2->wasClosed == FALSE) { + log_err("FAIL! from2 was NOT closed\n"); + } + + TSCC_print_log(&to1, "to1"); + TSCC_print_log(to2, "to2"); + + if(to1.wasClosed == FALSE) { + log_err("FAIL! to1 is NOT closed \n"); + } + + if(to2->wasClosed == FALSE) { + log_err("FAIL! to2 was NOT closed\n"); + } + + if(to2 != (&to1)) { + free(to2); /* to1 is stack based */ + } + if(from2 != (&from1)) { + free(from2); /* from1 is stack based */ + } +} +#endif + +static UBool +containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) { + while(length>0) { + if(*p!=b) { + return TRUE; + } + ++p; + --length; + } + return FALSE; +} + +static void TestConvertSafeClone() +{ + /* one 'regular' & all the 'private stateful' converters */ + static const char *const names[] = { +#if !UCONFIG_NO_LEGACY_CONVERSION + "ibm-1047", + "ISO_2022,locale=zh,version=1", +#endif + "SCSU", +#if !UCONFIG_NO_LEGACY_CONVERSION + "HZ", + "lmbcs", + "ISCII,version=0", + "ISO_2022,locale=kr,version=1", + "ISO_2022,locale=jp,version=2", +#endif + "BOCU-1", + "UTF-7", +#if !UCONFIG_NO_LEGACY_CONVERSION + "IMAP-mailbox-name", + "ibm-1047-s390" +#else + "IMAP=mailbox-name" +#endif + }; + + /* store the actual sizes of each converter */ + int32_t actualSizes[LENGTHOF(names)]; + + static const int32_t bufferSizes[] = { + U_CNV_SAFECLONE_BUFFERSIZE, + (int32_t)(3*sizeof(UConverter))/2, /* 1.5*sizeof(UConverter) */ + (int32_t)sizeof(UConverter)/2 /* 0.5*sizeof(UConverter) */ + }; + + char charBuffer[21]; /* Leave at an odd number for alignment testing */ + uint8_t buffer[3] [U_CNV_SAFECLONE_BUFFERSIZE]; + int32_t bufferSize, maxBufferSize; + const char *maxName; + UConverter * cnv, *cnv2; + UErrorCode err; + + char *pCharBuffer; + const char *pConstCharBuffer; + const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer); + UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */ + UChar uniCharBuffer[20]; + char charSourceBuffer[] = { 0x1b, 0x24, 0x42 }; + const char *pCharSource = charSourceBuffer; + const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer); + UChar *pUCharTarget = uniCharBuffer; + UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer)/sizeof(*uniCharBuffer); + const UChar * pUniBuffer; + const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer); + int32_t index, j; + + err = U_ZERO_ERROR; + cnv = ucnv_open(names[0], &err); + if(U_SUCCESS(err)) { + /* Check the various error & informational states: */ + + /* Null status - just returns NULL */ + bufferSize = U_CNV_SAFECLONE_BUFFERSIZE; + if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, 0)) + { + log_err("FAIL: Cloned converter failed to deal correctly with null status\n"); + } + /* error status - should return 0 & keep error the same */ + err = U_MEMORY_ALLOCATION_ERROR; + if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR) + { + log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n"); + } + err = U_ZERO_ERROR; + + /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/ + if (0 != ucnv_safeClone(cnv, buffer[0], 0, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n"); + } + err = U_ZERO_ERROR; + + /* buffer size pointer is 0 - fill in pbufferSize with a size */ + bufferSize = 0; + if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0) + { + log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n"); + } + /* Verify our define is large enough */ + if (U_CNV_SAFECLONE_BUFFERSIZE < bufferSize) + { + log_err("FAIL: Pre-calculated buffer size is too small\n"); + } + /* Verify we can use this run-time calculated size */ + if (0 == (cnv2 = ucnv_safeClone(cnv, buffer[0], &bufferSize, &err)) || U_FAILURE(err)) + { + log_err("FAIL: Converter can't be cloned with run-time size\n"); + } + if (cnv2) { + ucnv_close(cnv2); + } + + /* size one byte too small - should allocate & let us know */ + --bufferSize; + if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n"); + } + if (cnv2) { + ucnv_close(cnv2); + } + + err = U_ZERO_ERROR; + bufferSize = U_CNV_SAFECLONE_BUFFERSIZE; + + /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */ + if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING) + { + log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n"); + } + if (cnv2) { + ucnv_close(cnv2); + } + + err = U_ZERO_ERROR; + + /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */ + if (0 != ucnv_safeClone(0, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n"); + } + + ucnv_close(cnv); + } + + maxBufferSize = 0; + maxName = ""; + + /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/ + + for(j = 0; j < LENGTHOF(bufferSizes); ++j) { + for (index = 0; index < LENGTHOF(names); index++) + { + err = U_ZERO_ERROR; + cnv = ucnv_open(names[index], &err); + if(U_FAILURE(err)) { + log_data_err("ucnv_open(\"%s\") failed - %s\n", names[index], u_errorName(err)); + continue; + } + + if(j == 0) { + /* preflight to get maxBufferSize */ + actualSizes[index] = 0; + ucnv_safeClone(cnv, NULL, &actualSizes[index], &err); + if(actualSizes[index] > maxBufferSize) { + maxBufferSize = actualSizes[index]; + maxName = names[index]; + } + } + + memset(buffer, 0xaa, sizeof(buffer)); + + bufferSize = bufferSizes[j]; + cnv2 = ucnv_safeClone(cnv, buffer[1], &bufferSize, &err); + + /* close the original immediately to make sure that the clone works by itself */ + ucnv_close(cnv); + + if( actualSizes[index] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) && + err == U_SAFECLONE_ALLOCATED_WARNING + ) { + log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[index]); + } + + /* check if the clone function overwrote any bytes that it is not supposed to touch */ + if(bufferSize <= bufferSizes[j]) { + /* used the stack buffer */ + if( containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer[0]), 0xaa) || + containsAnyOtherByte(buffer[1]+bufferSize, (int32_t)(sizeof(buffer)-(sizeof(buffer[0])+bufferSize)), 0xaa) + ) { + log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n", + names[index], bufferSize, bufferSizes[j]); + } + } else { + /* heap-allocated the clone */ + if(containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer), 0xaa)) { + log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n", + names[index], bufferSize, bufferSizes[j]); + } + } + + pCharBuffer = charBuffer; + pUniBuffer = uniBuffer; + + ucnv_fromUnicode(cnv2, + &pCharBuffer, + charBufferLimit, + &pUniBuffer, + uniBufferLimit, + NULL, + TRUE, + &err); + if(U_FAILURE(err)){ + log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err)); + } + ucnv_toUnicode(cnv2, + &pUCharTarget, + pUCharTargetLimit, + &pCharSource, + pCharSourceLimit, + NULL, + TRUE, + &err + ); + + if(U_FAILURE(err)){ + log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err)); + } + + pConstCharBuffer = charBuffer; + if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err)) + { + log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err)); + } + ucnv_close(cnv2); + } + } + + log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n", + sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE); + if(maxBufferSize > U_CNV_SAFECLONE_BUFFERSIZE) { + log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n", + maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE); + } +} + +static void TestCCSID() { +#if !UCONFIG_NO_LEGACY_CONVERSION + UConverter *cnv; + UErrorCode errorCode; + int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 }; + int32_t i, ccsid; + + for(i=0; i<(int32_t)(sizeof(ccsids)/sizeof(int32_t)); ++i) { + ccsid=ccsids[i]; + + errorCode=U_ZERO_ERROR; + cnv=ucnv_openCCSID(ccsid, UCNV_IBM, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid, u_errorName(errorCode)); + continue; + } + + if(ccsid!=ucnv_getCCSID(cnv, &errorCode)) { + log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid, ucnv_getCCSID(cnv, &errorCode)); + } + + /* skip gb18030(ccsid 1392) */ + if(ccsid != 1392 && UCNV_IBM!=ucnv_getPlatform(cnv, &errorCode)) { + log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid, ucnv_getPlatform(cnv, &errorCode)); + } + + ucnv_close(cnv); + } +#endif +} + +/* jitterbug 932: ucnv_convert() bugs --------------------------------------- */ + +/* CHUNK_SIZE defined in common\ucnv.c: */ +#define CHUNK_SIZE 1024 + +static void bug1(void); +static void bug2(void); +static void bug3(void); + +static void +TestJ932(void) +{ + bug1(); /* Unicode intermediate buffer straddle bug */ + bug2(); /* pre-flighting size incorrect caused by simple overflow */ + bug3(); /* pre-flighting size incorrect caused by expansion overflow */ +} + +/* + * jitterbug 932: test chunking boundary conditions in + + int32_t ucnv_convert(const char *toConverterName, + const char *fromConverterName, + char *target, + int32_t targetSize, + const char *source, + int32_t sourceSize, + UErrorCode * err) + + * See discussions on the icu mailing list in + * 2001-April with the subject "converter 'flush' question". + * + * Bug report and test code provided by Edward J. Batutis. + */ +static void bug1() +{ +#if !UCONFIG_NO_LEGACY_CONVERSION + char char_in[CHUNK_SIZE+32]; + char char_out[CHUNK_SIZE*2]; + + /* GB 18030 equivalent of U+10000 is 90308130 */ + static const char test_seq[]={ (char)0x90u, 0x30, (char)0x81u, 0x30 }; + + UErrorCode err = U_ZERO_ERROR; + int32_t i, test_seq_len = sizeof(test_seq); + + /* + * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward + * until the straddle bug appears. I didn't want to hard-code everything so this test could + * be expanded - however this is the only type of straddle bug I can think of at the moment - + * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no + * other Unicode sequences cause a bug since combining sequences are not supported by the + * converters. + */ + + for (i = test_seq_len; i >= 0; i--) { + /* put character sequence into input buffer */ + memset(char_in, 0x61, sizeof(char_in)); /* GB 18030 'a' */ + memcpy(char_in + (CHUNK_SIZE - i), test_seq, test_seq_len); + + /* do the conversion */ + ucnv_convert("us-ascii", /* out */ + "gb18030", /* in */ + char_out, + sizeof(char_out), + char_in, + sizeof(char_in), + &err); + + /* bug1: */ + if (err == U_TRUNCATED_CHAR_FOUND) { + /* this happens when surrogate pair straddles the intermediate buffer in + * T_UConverter_fromCodepageToCodepage */ + log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n"); + } + } +#endif +} + +/* bug2: pre-flighting loop bug: simple overflow causes bug */ +static void bug2() +{ + /* US-ASCII "1234567890" */ + static const char source[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 }; + static const char sourceUTF8[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 }; + static const char sourceUTF32[]={ 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x33, + 0x00, 0x00, 0x00, 0x34, + 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x36, + 0x00, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, (char)0xf0, 0x00}; + static char target[5]; + + UErrorCode err = U_ZERO_ERROR; + int32_t size; + + /* do the conversion */ + size = ucnv_convert("iso-8859-1", /* out */ + "us-ascii", /* in */ + target, + sizeof(target), + source, + sizeof(source), + &err); + + if ( size != 10 ) { + /* bug2: size is 5, should be 10 */ + log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size); + } + + err = U_ZERO_ERROR; + /* do the conversion */ + size = ucnv_convert("UTF-32BE", /* out */ + "UTF-8", /* in */ + target, + sizeof(target), + sourceUTF8, + sizeof(sourceUTF8), + &err); + + if ( size != 32 ) { + /* bug2: size is 5, should be 32 */ + log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size); + } + + err = U_ZERO_ERROR; + /* do the conversion */ + size = ucnv_convert("UTF-8", /* out */ + "UTF-32BE", /* in */ + target, + sizeof(target), + sourceUTF32, + sizeof(sourceUTF32), + &err); + + if ( size != 12 ) { + /* bug2: size is 5, should be 12 */ + log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size); + } +} + +/* + * bug3: when the characters expand going from source to target codepage + * you get bug3 in addition to bug2 + */ +static void bug3() +{ +#if !UCONFIG_NO_LEGACY_CONVERSION + char char_in[CHUNK_SIZE*4]; + char target[5]; + UErrorCode err = U_ZERO_ERROR; + int32_t size; + + /* + * first get the buggy size from bug2 then + * compare it to buggy size with an expansion + */ + memset(char_in, 0x61, sizeof(char_in)); /* US-ASCII 'a' */ + + /* do the conversion */ + size = ucnv_convert("lmbcs", /* out */ + "us-ascii", /* in */ + target, + sizeof(target), + char_in, + sizeof(char_in), + &err); + + if ( size != sizeof(char_in) ) { + /* + * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer + * in the converter?), should be CHUNK_SIZE*4 + * + * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize... + */ + log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in), size); + } + + /* + * now do the conversion with expansion + * ascii 0x08 expands to 0x0F 0x28 in lmbcs + */ + memset(char_in, 8, sizeof(char_in)); + err = U_ZERO_ERROR; + + /* do the conversion */ + size = ucnv_convert("lmbcs", /* out */ + "us-ascii", /* in */ + target, + sizeof(target), + char_in, + sizeof(char_in), + &err); + + /* expect 2X expansion */ + if ( size != sizeof(char_in) * 2 ) { + /* + * bug3: + * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05: + */ + log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size); + } +#endif +} + +static void +convertExStreaming(UConverter *srcCnv, UConverter *targetCnv, + const char *src, int32_t srcLength, + const char *expectTarget, int32_t expectTargetLength, + int32_t chunkSize, + const char *testName, + UErrorCode expectCode) { + UChar pivotBuffer[CHUNK_SIZE]; + UChar *pivotSource, *pivotTarget; + const UChar *pivotLimit; + + char targetBuffer[CHUNK_SIZE]; + char *target; + const char *srcLimit, *finalSrcLimit, *targetLimit; + + int32_t targetLength; + + UBool flush; + + UErrorCode errorCode; + + /* setup */ + if(chunkSize>CHUNK_SIZE) { + chunkSize=CHUNK_SIZE; + } + + pivotSource=pivotTarget=pivotBuffer; + pivotLimit=pivotBuffer+chunkSize; + + finalSrcLimit=src+srcLength; + target=targetBuffer; + targetLimit=targetBuffer+chunkSize; + + ucnv_resetToUnicode(srcCnv); + ucnv_resetFromUnicode(targetCnv); + + errorCode=U_ZERO_ERROR; + flush=FALSE; + + /* convert, streaming-style (both converters and pivot keep state) */ + for(;;) { + /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */ + if(src+chunkSize<=finalSrcLimit) { + srcLimit=src+chunkSize; + } else { + srcLimit=finalSrcLimit; + } + ucnv_convertEx(targetCnv, srcCnv, + &target, targetLimit, + &src, srcLimit, + pivotBuffer, &pivotSource, &pivotTarget, pivotLimit, + FALSE, flush, &errorCode); + targetLength=(int32_t)(target-targetBuffer); + if(target>targetLimit) { + log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n", + testName, chunkSize, target, targetLimit); + break; /* TODO: major problem! */ + } + if(errorCode==U_BUFFER_OVERFLOW_ERROR) { + /* continue converting another chunk */ + errorCode=U_ZERO_ERROR; + if(targetLength+chunkSize<=sizeof(targetBuffer)) { + targetLimit=target+chunkSize; + } else { + targetLimit=targetBuffer+sizeof(targetBuffer); + } + } else if(U_FAILURE(errorCode)) { + /* failure */ + break; + } else if(flush) { + /* all done */ + break; + } else if(src==finalSrcLimit && pivotSource==pivotTarget) { + /* all consumed, now flush without input (separate from conversion for testing) */ + flush=TRUE; + } + } + + if(!(errorCode==expectCode || (expectCode==U_ZERO_ERROR && errorCode==U_STRING_NOT_TERMINATED_WARNING))) { + log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n", + testName, chunkSize, u_errorName(errorCode), u_errorName(expectCode)); + } else if(targetLength!=expectTargetLength) { + log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n", + testName, chunkSize, targetLength, expectTargetLength); + } else if(memcmp(targetBuffer, expectTarget, targetLength)!=0) { + log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n", + testName, chunkSize); + } +} + +static void +convertExMultiStreaming(UConverter *srcCnv, UConverter *targetCnv, + const char *src, int32_t srcLength, + const char *expectTarget, int32_t expectTargetLength, + const char *testName, + UErrorCode expectCode) { + convertExStreaming(srcCnv, targetCnv, + src, srcLength, + expectTarget, expectTargetLength, + 1, testName, expectCode); + convertExStreaming(srcCnv, targetCnv, + src, srcLength, + expectTarget, expectTargetLength, + 3, testName, expectCode); + convertExStreaming(srcCnv, targetCnv, + src, srcLength, + expectTarget, expectTargetLength, + 7, testName, expectCode); +} + +static void TestConvertEx() { +#if !UCONFIG_NO_LEGACY_CONVERSION + static const uint8_t + utf8[]={ + /* 4e00 30a1 ff61 0410 */ + 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90 + }, + shiftJIS[]={ + 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40 + }, + errorTarget[]={ + /* + * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS: + * SUB, SUB, 0x40, SUB, SUB, 0x40 + */ + 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40 + }; + + char srcBuffer[100], targetBuffer[100]; + + const char *src; + char *target; + + UChar pivotBuffer[100]; + UChar *pivotSource, *pivotTarget; + + UConverter *cnv1, *cnv2; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + cnv1=ucnv_open("UTF-8", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode)); + return; + } + + cnv2=ucnv_open("Shift-JIS", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode)); + ucnv_close(cnv1); + return; + } + + /* test ucnv_convertEx() with streaming conversion style */ + convertExMultiStreaming(cnv1, cnv2, + (const char *)utf8, sizeof(utf8), (const char *)shiftJIS, sizeof(shiftJIS), + "UTF-8 -> Shift-JIS", U_ZERO_ERROR); + + convertExMultiStreaming(cnv2, cnv1, + (const char *)shiftJIS, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), + "Shift-JIS -> UTF-8", U_ZERO_ERROR); + + /* U_ZERO_ERROR because by default the SUB callbacks are set */ + convertExMultiStreaming(cnv1, cnv2, + (const char *)shiftJIS, sizeof(shiftJIS), (const char *)errorTarget, sizeof(errorTarget), + "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR); + + /* test some simple conversions */ + + /* NUL-terminated source and target */ + errorCode=U_STRING_NOT_TERMINATED_WARNING; + memcpy(srcBuffer, utf8, sizeof(utf8)); + srcBuffer[sizeof(utf8)]=0; + src=srcBuffer; + target=targetBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode); + if( errorCode!=U_ZERO_ERROR || + target-targetBuffer!=sizeof(shiftJIS) || + *target!=0 || + memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0 + ) { + log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n", + u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS)); + } + + /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */ + errorCode=U_AMBIGUOUS_ALIAS_WARNING; + memset(targetBuffer, 0xff, sizeof(targetBuffer)); + src=srcBuffer; + target=targetBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(shiftJIS), &src, NULL, + NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode); + if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || + target-targetBuffer!=sizeof(shiftJIS) || + *target!=(char)0xff || + memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0 + ) { + log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n", + u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS)); + } + + /* bad arguments */ + errorCode=U_MESSAGE_PARSE_ERROR; + src=srcBuffer; + target=targetBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode); + if(errorCode!=U_MESSAGE_PARSE_ERROR) { + log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode)); + } + + /* pivotLimit==pivotStart */ + errorCode=U_ZERO_ERROR; + pivotSource=pivotTarget=pivotBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer, TRUE, TRUE, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode)); + } + + /* *pivotSource==NULL */ + errorCode=U_ZERO_ERROR; + pivotSource=NULL; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode)); + } + + /* *source==NULL */ + errorCode=U_ZERO_ERROR; + src=NULL; + pivotSource=pivotBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode)); + } + + /* streaming conversion without a pivot buffer */ + errorCode=U_ZERO_ERROR; + src=srcBuffer; + pivotSource=pivotBuffer; + ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL, + NULL, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, FALSE, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode)); + } + + ucnv_close(cnv1); + ucnv_close(cnv2); +#endif +} + +/* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */ +static const char *const badUTF8[]={ + /* trail byte */ + "\x80", + + /* truncated multi-byte sequences */ + "\xd0", + "\xe0", + "\xe1", + "\xed", + "\xee", + "\xf0", + "\xf1", + "\xf4", + "\xf8", + "\xfc", + + "\xe0\x80", + "\xe0\xa0", + "\xe1\x80", + "\xed\x80", + "\xed\xa0", + "\xee\x80", + "\xf0\x80", + "\xf0\x90", + "\xf1\x80", + "\xf4\x80", + "\xf4\x90", + "\xf8\x80", + "\xfc\x80", + + "\xf0\x80\x80", + "\xf0\x90\x80", + "\xf1\x80\x80", + "\xf4\x80\x80", + "\xf4\x90\x80", + "\xf8\x80\x80", + "\xfc\x80\x80", + + "\xf8\x80\x80\x80", + "\xfc\x80\x80\x80", + + "\xfc\x80\x80\x80\x80", + + /* complete sequences but non-shortest forms or out of range etc. */ + "\xc0\x80", + "\xe0\x80\x80", + "\xed\xa0\x80", + "\xf0\x80\x80\x80", + "\xf4\x90\x80\x80", + "\xf8\x80\x80\x80\x80", + "\xfc\x80\x80\x80\x80\x80", + "\xfe", + "\xff" +}; + +/* get some character that can be converted and convert it */ +static UBool getTestChar(UConverter *cnv, const char *converterName, + char charUTF8[4], int32_t *pCharUTF8Length, + char char0[8], int32_t *pChar0Length, + char char1[8], int32_t *pChar1Length) { + UChar utf16[U16_MAX_LENGTH]; + int32_t utf16Length; + + const UChar *utf16Source; + char *target; + + USet *set; + UChar32 c; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + set=uset_open(1, 0); + ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode); + c=uset_charAt(set, uset_size(set)/2); + uset_close(set); + + utf16Length=0; + U16_APPEND_UNSAFE(utf16, utf16Length, c); + *pCharUTF8Length=0; + U8_APPEND_UNSAFE(charUTF8, *pCharUTF8Length, c); + + utf16Source=utf16; + target=char0; + ucnv_fromUnicode(cnv, + &target, char0+sizeof(char0), + &utf16Source, utf16+utf16Length, + NULL, FALSE, &errorCode); + *pChar0Length=(int32_t)(target-char0); + + utf16Source=utf16; + target=char1; + ucnv_fromUnicode(cnv, + &target, char1+sizeof(char1), + &utf16Source, utf16+utf16Length, + NULL, FALSE, &errorCode); + *pChar1Length=(int32_t)(target-char1); + + if(U_FAILURE(errorCode)) { + log_err("unable to get test character for %s - %s\n", converterName, u_errorName(errorCode)); + return FALSE; + } + return TRUE; +} + +static void testFromTruncatedUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName, + char charUTF8[4], int32_t charUTF8Length, + char char0[8], int32_t char0Length, + char char1[8], int32_t char1Length) { + char utf8[16]; + int32_t utf8Length; + + char output[16]; + int32_t outputLength; + + char invalidChars[8]; + int8_t invalidLength; + + const char *source; + char *target; + + UChar pivotBuffer[8]; + UChar *pivotSource, *pivotTarget; + + UErrorCode errorCode; + int32_t i; + + /* test truncated sequences */ + errorCode=U_ZERO_ERROR; + ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + + memcpy(utf8, charUTF8, charUTF8Length); + + for(i=0; i<LENGTHOF(badUTF8); ++i) { + /* truncated sequence? */ + int32_t length=strlen(badUTF8[i]); + if(length>=(1+U8_COUNT_TRAIL_BYTES(badUTF8[i][0]))) { + continue; + } + + /* assemble a string with the test character and the truncated sequence */ + memcpy(utf8+charUTF8Length, badUTF8[i], length); + utf8Length=charUTF8Length+length; + + /* convert and check the invalidChars */ + source=utf8; + target=output; + pivotSource=pivotTarget=pivotBuffer; + errorCode=U_ZERO_ERROR; + ucnv_convertEx(cnv, utf8Cnv, + &target, output+sizeof(output), + &source, utf8+utf8Length, + pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+LENGTHOF(pivotBuffer), + TRUE, TRUE, /* reset & flush */ + &errorCode); + outputLength=(int32_t)(target-output); + if(errorCode!=U_TRUNCATED_CHAR_FOUND || pivotSource!=pivotBuffer) { + log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode), converterName, (long)i); + continue; + } + + errorCode=U_ZERO_ERROR; + invalidLength=(int8_t)sizeof(invalidChars); + ucnv_getInvalidChars(utf8Cnv, invalidChars, &invalidLength, &errorCode); + if(invalidLength!=length || 0!=memcmp(invalidChars, badUTF8[i], length)) { + log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName, (long)i); + } + } +} + +static void testFromBadUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName, + char charUTF8[4], int32_t charUTF8Length, + char char0[8], int32_t char0Length, + char char1[8], int32_t char1Length) { + char utf8[600], expect[600]; + int32_t utf8Length, expectLength; + + char testName[32]; + + UErrorCode errorCode; + int32_t i; + + errorCode=U_ZERO_ERROR; + ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, NULL, &errorCode); + + /* + * assemble an input string with the test character between each + * bad sequence, + * and an expected string with repeated test character output + */ + memcpy(utf8, charUTF8, charUTF8Length); + utf8Length=charUTF8Length; + + memcpy(expect, char0, char0Length); + expectLength=char0Length; + + for(i=0; i<LENGTHOF(badUTF8); ++i) { + int32_t length=strlen(badUTF8[i]); + memcpy(utf8+utf8Length, badUTF8[i], length); + utf8Length+=length; + + memcpy(utf8+utf8Length, charUTF8, charUTF8Length); + utf8Length+=charUTF8Length; + + memcpy(expect+expectLength, char1, char1Length); + expectLength+=char1Length; + } + + /* expect that each bad UTF-8 sequence is detected and skipped */ + strcpy(testName, "from bad UTF-8 to "); + strcat(testName, converterName); + + convertExMultiStreaming(utf8Cnv, cnv, + utf8, utf8Length, + expect, expectLength, + testName, + U_ZERO_ERROR); +} + +/* Test illegal UTF-8 input. */ +static void TestConvertExFromUTF8() { + static const char *const converterNames[]={ +#if !UCONFIG_NO_LEGACY_CONVERSION + "windows-1252", + "shift-jis", +#endif + "us-ascii", + "iso-8859-1", + "utf-8" + }; + + UConverter *utf8Cnv, *cnv; + UErrorCode errorCode; + int32_t i; + + /* fromUnicode versions of some character, from initial state and later */ + char charUTF8[4], char0[8], char1[8]; + int32_t charUTF8Length, char0Length, char1Length; + + errorCode=U_ZERO_ERROR; + utf8Cnv=ucnv_open("UTF-8", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode)); + return; + } + + for(i=0; i<LENGTHOF(converterNames); ++i) { + errorCode=U_ZERO_ERROR; + cnv=ucnv_open(converterNames[i], &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to open %s converter - %s\n", converterNames[i], u_errorName(errorCode)); + continue; + } + if(!getTestChar(cnv, converterNames[i], charUTF8, &charUTF8Length, char0, &char0Length, char1, &char1Length)) { + continue; + } + testFromTruncatedUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length); + testFromBadUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length); + ucnv_close(cnv); + } + ucnv_close(utf8Cnv); +} + +static void +TestConvertAlgorithmic() { +#if !UCONFIG_NO_LEGACY_CONVERSION + static const uint8_t + utf8[]={ + /* 4e00 30a1 ff61 0410 */ + 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90 + }, + shiftJIS[]={ + 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40 + }, + /*errorTarget[]={*/ + /* + * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS: + * SUB, SUB, 0x40, SUB, SUB, 0x40 + */ + /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/ + /*},*/ + utf16[]={ + 0xfe, 0xff /* BOM only, no text */ + }, + utf32[]={ + 0xff, 0xfe, 0, 0 /* BOM only, no text */ + }; + + char target[100], utf8NUL[100], shiftJISNUL[100]; + + UConverter *cnv; + UErrorCode errorCode; + + int32_t length; + + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("Shift-JIS", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode)); + ucnv_close(cnv); + return; + } + + memcpy(utf8NUL, utf8, sizeof(utf8)); + utf8NUL[sizeof(utf8)]=0; + memcpy(shiftJISNUL, shiftJIS, sizeof(shiftJIS)); + shiftJISNUL[sizeof(shiftJIS)]=0; + + /* + * The to/from algorithmic convenience functions share a common implementation, + * so we need not test all permutations of them. + */ + + /* length in, not terminated out */ + errorCode=U_ZERO_ERROR; + length=ucnv_fromAlgorithmic(cnv, UCNV_UTF8, target, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), &errorCode); + if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || + length!=sizeof(shiftJIS) || + memcmp(target, shiftJIS, length)!=0 + ) { + log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n", + u_errorName(errorCode), length, sizeof(shiftJIS)); + } + + /* terminated in and out */ + memset(target, 0x55, sizeof(target)); + errorCode=U_STRING_NOT_TERMINATED_WARNING; + length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, -1, &errorCode); + if( errorCode!=U_ZERO_ERROR || + length!=sizeof(utf8) || + memcmp(target, utf8, length)!=0 + ) { + log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n", + u_errorName(errorCode), length, sizeof(shiftJIS)); + } + + /* empty string, some target buffer */ + errorCode=U_STRING_NOT_TERMINATED_WARNING; + length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, 0, &errorCode); + if( errorCode!=U_ZERO_ERROR || + length!=0 + ) { + log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n", + u_errorName(errorCode), length); + } + + /* pseudo-empty string, no target buffer */ + errorCode=U_ZERO_ERROR; + length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode); + if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || + length!=0 + ) { + log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n", + u_errorName(errorCode), length); + } + + errorCode=U_ZERO_ERROR; + length=ucnv_fromAlgorithmic(cnv, UCNV_UTF32, target, 0, (const char *)utf32, 4, &errorCode); + if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || + length!=0 + ) { + log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n", + u_errorName(errorCode), length); + } + + /* bad arguments */ + errorCode=U_MESSAGE_PARSE_ERROR; + length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode); + if(errorCode!=U_MESSAGE_PARSE_ERROR) { + log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode)); + } + + /* source==NULL */ + errorCode=U_ZERO_ERROR; + length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, NULL, 2, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode)); + } + + /* illegal alg. type */ + errorCode=U_ZERO_ERROR; + length=ucnv_fromAlgorithmic(cnv, (UConverterType)99, target, 0, (const char *)utf16, 2, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode)); + } +ucnv_close(cnv); +#endif +} + +static void TestLMBCSMaxChar(void) { + static const struct { + int8_t maxSize; + const char *name; + } converter[] = { + /* some non-LMBCS converters - perfect test setup here */ + { 1, "US-ASCII"}, + { 1, "ISO-8859-1"}, + + { 2, "UTF-16"}, + { 2, "UTF-16BE"}, + { 3, "UTF-8"}, + { 3, "CESU-8"}, + { 3, "SCSU"}, + { 4, "UTF-32"}, + { 4, "UTF-7"}, + { 4, "IMAP-mailbox-name"}, + { 4, "BOCU-1"}, + + { 1, "windows-1256"}, + { 2, "Shift-JIS"}, + { 2, "ibm-16684"}, + { 3, "ibm-930"}, + { 3, "ibm-1390"}, + { 4, "*test3"}, + { 16,"*test4"}, + + { 4, "ISCII"}, + { 4, "HZ"}, + + { 3, "ISO-2022"}, + { 3, "ISO-2022-KR"}, + { 6, "ISO-2022-JP"}, + { 8, "ISO-2022-CN"}, + + /* LMBCS */ + { 3, "LMBCS-1"}, + { 3, "LMBCS-2"}, + { 3, "LMBCS-3"}, + { 3, "LMBCS-4"}, + { 3, "LMBCS-5"}, + { 3, "LMBCS-6"}, + { 3, "LMBCS-8"}, + { 3, "LMBCS-11"}, + { 3, "LMBCS-16"}, + { 3, "LMBCS-17"}, + { 3, "LMBCS-18"}, + { 3, "LMBCS-19"} + }; + int32_t idx; + + for (idx = 0; idx < LENGTHOF(converter); idx++) { + UErrorCode status = U_ZERO_ERROR; + UConverter *cnv = cnv_open(converter[idx].name, &status); + if (U_FAILURE(status)) { + continue; + } + if (converter[idx].maxSize != ucnv_getMaxCharSize(cnv)) { + log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n", + converter[idx].name, converter[idx].maxSize, ucnv_getMaxCharSize(cnv)); + } + ucnv_close(cnv); + } + + /* mostly test that the macro compiles */ + if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) { + log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n"); + } +} + + +static void TestJ1968(void) { + UErrorCode err = U_ZERO_ERROR; + UConverter *cnv; + char myConvName[] = "My really really really really really really really really really really really" + " really really really really really really really really really really really" + " really really really really really really really really long converter name"; + UChar myConvNameU[sizeof(myConvName)]; + + u_charsToUChars(myConvName, myConvNameU, sizeof(myConvName)); + + err = U_ZERO_ERROR; + myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH+1] = 0; + cnv = ucnv_openU(myConvNameU, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0; + cnv = ucnv_openU(myConvNameU, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0; + cnv = ucnv_openU(myConvNameU, &err); + if (cnv || err != U_FILE_ACCESS_ERROR) { + log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err)); + } + + + + + err = U_ZERO_ERROR; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = ','; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ','; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_FILE_ACCESS_ERROR) { + log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ','; + strncpy(myConvName + UCNV_MAX_CONVERTER_NAME_LENGTH, "locale=", 7); + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + /* The comma isn't really a part of the converter name. */ + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_FILE_ACCESS_ERROR) { + log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ' '; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err)); + } + + err = U_ZERO_ERROR; + myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0; + cnv = ucnv_open(myConvName, &err); + if (cnv || err != U_FILE_ACCESS_ERROR) { + log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err)); + } + +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void +testSwap(const char *name, UBool swap) { + /* + * Test Unicode text. + * Contains characters that are the highest for some of the + * tested conversions, to make sure that the ucnvmbcs.c code that modifies the + * tables copies the entire tables. + */ + static const UChar text[]={ + 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a + }; + + UChar uNormal[32], uSwapped[32]; + char normal[32], swapped[32]; + const UChar *pcu; + UChar *pu; + char *pc; + int32_t i, normalLength, swappedLength; + UChar u; + char c; + + const char *swappedName; + UConverter *cnv, *swapCnv; + UErrorCode errorCode; + + /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */ + + /* open both the normal and the LF/NL-swapping converters */ + strcpy(swapped, name); + strcat(swapped, UCNV_SWAP_LFNL_OPTION_STRING); + + errorCode=U_ZERO_ERROR; + swapCnv=ucnv_open(swapped, &errorCode); + cnv=ucnv_open(name, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name, swapped, u_errorName(errorCode)); + goto cleanup; + } + + /* the name must contain the swap option if and only if we expect the converter to swap */ + swappedName=ucnv_getName(swapCnv, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name, u_errorName(errorCode)); + goto cleanup; + } + + pc=strstr(swappedName, UCNV_SWAP_LFNL_OPTION_STRING); + if(swap != (pc!=NULL)) { + log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name, swappedName, swap); + goto cleanup; + } + + /* convert to EBCDIC */ + pcu=text; + pc=normal; + ucnv_fromUnicode(cnv, &pc, normal+LENGTHOF(normal), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode); + normalLength=(int32_t)(pc-normal); + + pcu=text; + pc=swapped; + ucnv_fromUnicode(swapCnv, &pc, swapped+LENGTHOF(swapped), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode); + swappedLength=(int32_t)(pc-swapped); + + if(U_FAILURE(errorCode)) { + log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name, u_errorName(errorCode)); + goto cleanup; + } + + /* compare EBCDIC output */ + if(normalLength!=swappedLength) { + log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name, normalLength, swappedLength); + goto cleanup; + } + for(i=0; i<normalLength; ++i) { + /* swap EBCDIC LF/NL for comparison */ + c=normal[i]; + if(swap) { + if(c==0x15) { + c=0x25; + } else if(c==0x25) { + c=0x15; + } + } + + if(c!=swapped[i]) { + log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name, i, (uint8_t)swapped[i]); + goto cleanup; + } + } + + /* convert back to Unicode (may not roundtrip) */ + pc=normal; + pu=uNormal; + ucnv_toUnicode(cnv, &pu, uNormal+LENGTHOF(uNormal), (const char **)&pc, normal+normalLength, NULL, TRUE, &errorCode); + normalLength=(int32_t)(pu-uNormal); + + pc=normal; + pu=uSwapped; + ucnv_toUnicode(swapCnv, &pu, uSwapped+LENGTHOF(uSwapped), (const char **)&pc, normal+swappedLength, NULL, TRUE, &errorCode); + swappedLength=(int32_t)(pu-uSwapped); + + if(U_FAILURE(errorCode)) { + log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name, u_errorName(errorCode)); + goto cleanup; + } + + /* compare EBCDIC output */ + if(normalLength!=swappedLength) { + log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name, normalLength, swappedLength); + goto cleanup; + } + for(i=0; i<normalLength; ++i) { + /* swap EBCDIC LF/NL for comparison */ + u=uNormal[i]; + if(swap) { + if(u==0xa) { + u=0x85; + } else if(u==0x85) { + u=0xa; + } + } + + if(u!=uSwapped[i]) { + log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name, i, uSwapped[i]); + goto cleanup; + } + } + + /* clean up */ +cleanup: + ucnv_close(cnv); + ucnv_close(swapCnv); +} + +static void +TestEBCDICSwapLFNL() { + static const struct { + const char *name; + UBool swap; + } tests[]={ + { "ibm-37", TRUE }, + { "ibm-1047", TRUE }, + { "ibm-1140", TRUE }, + { "ibm-930", TRUE }, + { "iso-8859-3", FALSE } + }; + + int i; + + for(i=0; i<LENGTHOF(tests); ++i) { + testSwap(tests[i].name, tests[i].swap); + } +} +#else +static void +TestEBCDICSwapLFNL() { + /* test nothing... */ +} +#endif + +static const UVersionInfo ICU_34 = {3,4,0,0}; + +static void TestFromUCountPending(){ +#if !UCONFIG_NO_LEGACY_CONVERSION + UErrorCode status = U_ZERO_ERROR; +/* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */ + static const struct { + UChar input[6]; + int32_t len; + int32_t exp; + }fromUnicodeTests[] = { + /*m:n conversion*/ + {{0xdbc4},1,1}, + {{ 0xdbc4, 0xde34, 0xd84d},3,1}, + {{ 0xdbc4, 0xde34, 0xd900},3,3}, + }; + int i; + UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status); + if(U_FAILURE(status)){ + log_err("Could not create converter for test3. Error: %s\n", u_errorName(status)); + return; + } + for(i=0; i<LENGTHOF(fromUnicodeTests); ++i) { + char tgt[10]; + char* target = tgt; + char* targetLimit = target + 10; + const UChar* source = fromUnicodeTests[i].input; + const UChar* sourceLimit = source + fromUnicodeTests[i].len; + int32_t len = 0; + ucnv_reset(cnv); + ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_fromUCountPending(cnv, &status); + if(U_FAILURE(status)){ + log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + continue; + } + if(len != fromUnicodeTests[i].exp){ + log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n"); + } + } + status = U_ZERO_ERROR; + { + /* + * The converter has to read the tail before it knows that + * only head alone matches. + * At the end, the output for head will overflow the target, + * middle will be pending, and tail will not have been consumed. + */ + /* + \U00101234 -> x (<U101234> \x07 |0) + \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0) + \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0) + \U00060007 -> unassigned + */ + static const UChar head[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */ + static const UChar middle[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */ + static const UChar tail[] = {0xDC07,0x0000};/* second half of \U00060007 */ + char tgt[10]; + char* target = tgt; + char* targetLimit = target + 2; /* expect overflow from converting \U00101234\U00050005 */ + const UChar* source = head; + const UChar* sourceLimit = source + u_strlen(head); + int32_t len = 0; + ucnv_reset(cnv); + ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_fromUCountPending(cnv, &status); + if(U_FAILURE(status)){ + log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } + if(len!=4){ + log_err("ucnv_fromUInputHeld did not return correct length for head\n"); + } + source = middle; + sourceLimit = source + u_strlen(middle); + ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_fromUCountPending(cnv, &status); + if(U_FAILURE(status)){ + log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } + if(len!=5){ + log_err("ucnv_fromUInputHeld did not return correct length for middle\n"); + } + source = tail; + sourceLimit = source + u_strlen(tail); + ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + if(status != U_BUFFER_OVERFLOW_ERROR){ + log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + len = ucnv_fromUCountPending(cnv, &status); + /* middle[1] is pending, tail has not been consumed */ + if(U_FAILURE(status)){ + log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status)); + } + if(len!=1){ + log_err("ucnv_fromUInputHeld did not return correct length for tail\n"); + } + } + ucnv_close(cnv); +#endif +} + +static void +TestToUCountPending(){ +#if !UCONFIG_NO_LEGACY_CONVERSION + UErrorCode status = U_ZERO_ERROR; + static const struct { + char input[6]; + int32_t len; + int32_t exp; + }toUnicodeTests[] = { + /*m:n conversion*/ + {{0x05, 0x01, 0x02},3,3}, + {{0x01, 0x02},2,2}, + {{0x07, 0x00, 0x01, 0x02},4,4}, + }; + + int i; + UConverterToUCallback *oldToUAction= NULL; + UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status); + if(U_FAILURE(status)){ + log_err("Could not create converter for test3. Error: %s\n", u_errorName(status)); + return; + } + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status); + for(i=0; i<LENGTHOF(toUnicodeTests); ++i) { + UChar tgt[10]; + UChar* target = tgt; + UChar* targetLimit = target + 20; + const char* source = toUnicodeTests[i].input; + const char* sourceLimit = source + toUnicodeTests[i].len; + int32_t len = 0; + ucnv_reset(cnv); + ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_toUCountPending(cnv,&status); + if(U_FAILURE(status)){ + log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + continue; + } + if(len != toUnicodeTests[i].exp){ + log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n"); + } + } + status = U_ZERO_ERROR; + ucnv_close(cnv); + + { + /* + * The converter has to read the tail before it knows that + * only head alone matches. + * At the end, the output for head will overflow the target, + * mid will be pending, and tail will not have been consumed. + */ + char head[] = { 0x01, 0x02, 0x03, 0x0a , 0x00}; + char mid[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 }; + char tail[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 }; + /* + 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0) + 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0) + 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3) + 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar") + */ + UChar tgt[10]; + UChar* target = tgt; + UChar* targetLimit = target + 1; /* expect overflow from converting */ + const char* source = head; + const char* sourceLimit = source + strlen(head); + int32_t len = 0; + cnv = ucnv_openPackage(loadTestData(&status), "test4", &status); + if(U_FAILURE(status)){ + log_err("Could not create converter for test3. Error: %s\n", u_errorName(status)); + return; + } + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status); + ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_toUCountPending(cnv,&status); + if(U_FAILURE(status)){ + log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status)); + } + if(len != 4){ + log_err("Did not get the expected len for head.\n"); + } + source=mid; + sourceLimit = source+strlen(mid); + ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + len = ucnv_toUCountPending(cnv,&status); + if(U_FAILURE(status)){ + log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status)); + } + if(len != 8){ + log_err("Did not get the expected len for mid.\n"); + } + + source=tail; + sourceLimit = source+strlen(tail); + targetLimit = target; + ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status); + if(status != U_BUFFER_OVERFLOW_ERROR){ + log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + len = ucnv_toUCountPending(cnv,&status); + /* mid[4] is pending, tail has not been consumed */ + if(U_FAILURE(status)){ + log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status)); + } + if(len != 4){ + log_err("Did not get the expected len for tail.\n"); + } + ucnv_close(cnv); + } +#endif +} + +static void TestOneDefaultNameChange(const char *name) { + UErrorCode status = U_ZERO_ERROR; + UConverter *cnv; + ucnv_setDefaultName(name); + if(strcmp(ucnv_getDefaultName(), name)==0) + log_verbose("setDefaultName of %s works.\n", name); + else + log_err("setDefaultName of %s failed\n", name); + cnv=ucnv_open(NULL, &status); + if (U_FAILURE(status) || cnv == NULL) { + log_err("opening the default converter of %s failed\n", name); + return; + } + if(strcmp(ucnv_getName(cnv, &status), name)==0) + log_verbose("ucnv_getName of %s works.\n", name); + else + log_err("ucnv_getName of %s failed\n", name); + ucnv_close(cnv); +} + +static void TestDefaultName(void) { + /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/ + static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1]; + strcpy(defaultName, ucnv_getDefaultName()); + + log_verbose("getDefaultName returned %s\n", defaultName); + + /*change the default name by setting it */ + TestOneDefaultNameChange("UTF-8"); +#if !UCONFIG_NO_LEGACY_CONVERSION + TestOneDefaultNameChange("ISCII,version=1"); + TestOneDefaultNameChange("ISCII,version=2"); +#endif + TestOneDefaultNameChange("ISO-8859-1"); + + /*set the default name back*/ + ucnv_setDefaultName(defaultName); +} + +/* Test that ucnv_compareNames() matches names according to spec. ----------- */ + +static U_INLINE int +sign(int n) { + if(n==0) { + return 0; + } else if(n<0) { + return -1; + } else /* n>0 */ { + return 1; + } +} + +static void +compareNames(const char **names) { + const char *relation, *name1, *name2; + int rel, result; + + relation=*names++; + if(*relation=='=') { + rel = 0; + } else if(*relation=='<') { + rel = -1; + } else { + rel = 1; + } + + name1=*names++; + if(name1==NULL) { + return; + } + while((name2=*names++)!=NULL) { + result=ucnv_compareNames(name1, name2); + if(sign(result)!=rel) { + log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1, name2, result, rel); + } + name1=name2; + } +} + +static void +TestCompareNames() { + static const char *equalUTF8[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL }; + static const char *equalIBM[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL }; + static const char *lessMac[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL }; + static const char *lessUTF080[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL }; + + compareNames(equalUTF8); + compareNames(equalIBM); + compareNames(lessMac); + compareNames(lessUTF080); +} + +static void +TestSubstString() { + static const UChar surrogate[1]={ 0xd900 }; + char buffer[16]; + + static const UChar sub[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 }; + static const char subChars[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 }; + UConverter *cnv; + UErrorCode errorCode; + int32_t length; + int8_t len8; + + /* UTF-16/32: test that the BOM is output before the sub character */ + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("UTF-16", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode)); + return; + } + length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode); + ucnv_close(cnv); + if(U_FAILURE(errorCode) || + length!=4 || + NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode) + ) { + log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n"); + } + + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("UTF-32", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode)); + return; + } + length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode); + ucnv_close(cnv); + if(U_FAILURE(errorCode) || + length!=8 || + NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode) + ) { + log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n"); + } + + /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */ + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("ISO-8859-1", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode)); + return; + } + ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode)); + } else { + len8 = sizeof(buffer); + ucnv_getSubstChars(cnv, buffer, &len8, &errorCode); + /* Stateless converter, we expect the string converted to charset bytes. */ + if(U_FAILURE(errorCode) || len8!=sizeof(subChars) || 0!=uprv_memcmp(buffer, subChars, len8)) { + log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode)); + } + } + ucnv_close(cnv); + +#if !UCONFIG_NO_LEGACY_CONVERSION + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("HZ", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode)); + return; + } + ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode)); + } else { + len8 = sizeof(buffer); + ucnv_getSubstChars(cnv, buffer, &len8, &errorCode); + /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */ + if(U_FAILURE(errorCode) || len8!=0) { + log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode)); + } + } + ucnv_close(cnv); +#endif + /* + * Further testing of ucnv_setSubstString() is done via intltest convert. + * We do not test edge cases of illegal arguments and similar because the + * function implementation uses all of its parameters in calls to other + * functions with UErrorCode parameters. + */ +} + +static void +InvalidArguments() { + UConverter *cnv; + UErrorCode errorCode; + char charBuffer[2] = {1, 1}; + char ucharAsCharBuffer[2] = {2, 2}; + char *charsPtr = charBuffer; + UChar *ucharsPtr = (UChar *)ucharAsCharBuffer; + UChar *ucharsBadPtr = (UChar *)(ucharAsCharBuffer + 1); + + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("UTF-8", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_open() failed - %s\n", u_errorName(errorCode)); + return; + } + + errorCode=U_ZERO_ERROR; + /* This one should fail because an incomplete UChar is being passed in */ + ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsPtr, ucharsBadPtr, NULL, TRUE, &errorCode); + if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + /* This one should fail because ucharsBadPtr is > than ucharsPtr */ + ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsBadPtr, ucharsPtr, NULL, TRUE, &errorCode); + if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + /* This one should fail because an incomplete UChar is being passed in */ + ucnv_toUnicode(cnv, &ucharsPtr, ucharsBadPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode); + if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + /* This one should fail because ucharsBadPtr is > than ucharsPtr */ + ucnv_toUnicode(cnv, &ucharsBadPtr, ucharsPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode); + if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode)); + } + + if (charBuffer[0] != 1 || charBuffer[1] != 1 + || ucharAsCharBuffer[0] != 2 || ucharAsCharBuffer[1] != 2) + { + log_err("Data was incorrectly written to buffers\n"); + } + + ucnv_close(cnv); +} + + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h new file mode 100644 index 00000000000..a15dfc67d88 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h @@ -0,0 +1,25 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CAPITEST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*/ +#ifndef _CU_CAPITSTST +#define _CU_CAPITSTST +/* C API TEST FOR CODESET CONVERSION COMPONENT */ +#include "cintltst.h" +#include "unicode/utypes.h" + +static void TestConvert(void); +static void TestAlias(void); +static void TestConvertSafeClone(void); + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c new file mode 100644 index 00000000000..c2e4fd93bc0 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c @@ -0,0 +1,157 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CCOLLTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +#include <stdio.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" +#include "ccolltst.h" +#include "unicode/ucol.h" +#include "unicode/ustring.h" +#include "cmemory.h" + +void addCollTest(TestNode** root); + +void addCollTest(TestNode** root) +{ + addCollAPITest(root); + addCurrencyCollTest(root); + addNormTest(root); + addGermanCollTest(root); + addSpanishCollTest(root); + addFrenchCollTest(root); + addKannaCollTest(root); + addTurkishCollTest(root); + addEnglishCollTest(root); + addFinnishCollTest(root); + + /* WEIVTODO: return tests here */ + addRuleBasedCollTest(root); + addCollIterTest(root); + addAllCollTest(root); + addMiscCollTest(root); + + addSearchTest(root); +} + + + +/*Internal functions used*/ +static char* dumpSk(uint8_t *sourceKey, char *sk) { + uint32_t kLen = (uint32_t)strlen((const char *)sourceKey); + uint32_t i = 0; + + *sk = 0; + + for(i = 0; i<kLen; i++) { + sprintf(sk+2*i, "%02X", sourceKey[i]); + } + return sk; +} + +void reportCResult( const UChar source[], const UChar target[], + uint8_t *sourceKey, uint8_t *targetKey, + UCollationResult compareResult, + UCollationResult keyResult, + UCollationResult incResult, + UCollationResult expectedResult ) +{ + UChar *sResult, *sExpect; + sResult=(UChar*)malloc(sizeof(UChar) * 10); + sExpect=(UChar*)malloc(sizeof(UChar) * 10); + if (expectedResult < -1 || expectedResult > 1) + { + log_err("***** invalid call to reportCResult ****\n"); + return; + } + + if (compareResult != expectedResult) + { + + appendCompareResult(compareResult, sResult); + appendCompareResult(expectedResult, sExpect); + log_err("Compare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1), + austrdup(sResult), austrdup(sExpect) ); + } + + if (incResult != expectedResult) + { + + appendCompareResult(incResult, sResult); + appendCompareResult(expectedResult, sExpect); + log_err("incCompare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1), + austrdup(sResult), austrdup(sExpect) ); + } + + if (keyResult != expectedResult) + { + + appendCompareResult(keyResult, sResult); + appendCompareResult(expectedResult, sExpect); + + log_err("KeyCompare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1), + austrdup(sResult), austrdup(sExpect) ); + + + } + + if (keyResult != compareResult) + { + + appendCompareResult(keyResult, sResult); + appendCompareResult(compareResult, sExpect); + + log_err("difference between sortkey and compare result for (%s , %s) Keys: %s compare %s\n", aescstrdup(source,-1), aescstrdup(target,-1), + austrdup(sResult), austrdup(sExpect) ); + + + } + + if(keyResult != expectedResult || keyResult != compareResult) + { + char sk[10000]; + log_verbose("SortKey1: %s\n", dumpSk(sourceKey, sk)); + log_verbose("SortKey2: %s\n", dumpSk(targetKey, sk)); + } + + free(sExpect); + free(sResult); +} + +UChar* appendCompareResult(UCollationResult result, UChar* target) +{ + if (result == UCOL_LESS) + { + u_uastrcpy(target, "LESS"); + } + else if (result == UCOL_EQUAL) + { + u_uastrcpy(target, "EQUAL"); + } + else if (result == UCOL_GREATER) + { + u_uastrcpy(target, "GREATER"); + } + else + { + u_uastrcpy(target, "huh???"); + } + + return target; +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h new file mode 100644 index 00000000000..d3e7f51da3b --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h @@ -0,0 +1,56 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2005, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CCOLLTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +#ifndef _CCOLLTST +#define _CCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" +#include "unicode/ucol.h" + +/* Internal Functions used*/ + +void reportCResult( const UChar source[], const UChar target[], + uint8_t *sourceKey, uint8_t *targetKey, + UCollationResult compareResult, + UCollationResult keyResult, + UCollationResult incResult, + UCollationResult expectedResult ); + +UChar* appendCompareResult(UCollationResult result, UChar* target); + +void addCollAPITest(TestNode**); +void addCurrencyCollTest(TestNode**); +void addNormTest(TestNode**); +void addDanishCollTest(TestNode**); +void addGermanCollTest(TestNode**); +void addSpanishCollTest(TestNode**); +void addFrenchCollTest(TestNode**); +void addKannaCollTest(TestNode**); +void addTurkishCollTest(TestNode**); +void addEnglishCollTest(TestNode**); +void addFinnishCollTest(TestNode**); + +void addRuleBasedCollTest(TestNode**); +void addCollIterTest(TestNode**); +void addAllCollTest(TestNode**); +void addMiscCollTest(TestNode**); +void addSearchTest(TestNode**); + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c new file mode 100644 index 00000000000..c4d431b72a9 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c @@ -0,0 +1,39 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CCONVTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +#include "cintltst.h" + +void addTestConvert(TestNode**); +void addTestNewConvert(TestNode**); +void addTestConvertErrorCallBack(TestNode** root); +void addTestEuroRegression(TestNode** root); +void addTestConverterFallBack(TestNode** root); +void addExtraTests(TestNode** root); + +/* bocu1tst.c */ +U_CFUNC void +addBOCU1Tests(TestNode** root); + +void addConvert(TestNode** root); + +void addConvert(TestNode** root) +{ + addTestConvert(root); + addTestNewConvert(root); + addBOCU1Tests(root); + addTestConvertErrorCallBack(root); + addTestEuroRegression(root); + addTestConverterFallBack(root); + addExtraTests(root); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c new file mode 100644 index 00000000000..c7085a12b6a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c @@ -0,0 +1,36 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2004, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ + +#include "unicode/ucnv.h" +#include "unicode/ucnv_err.h" + +#include "cintltst.h" +#include "ustr_cnv.h" +void TestDefaultConverterError(void); /* keep gcc happy */ + + +/* This makes sure that a converter isn't leaked when an error is passed to + u_getDefaultConverter */ +void TestDefaultConverterError(void) { + UErrorCode err = U_ZERO_ERROR; + + /* Remove the default converter */ + ucnv_close(u_getDefaultConverter(&err)); + + if (U_FAILURE(err)) { + log_err("Didn't expect a failure yet %s\n", myErrorName(err)); + return; + } + + /* Set to any radom error state */ + err = U_FILE_ACCESS_ERROR; + if (u_getDefaultConverter(&err) != NULL) { + log_err("Didn't expect to get a converter on a failure\n"); + } +} + + + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c new file mode 100644 index 00000000000..a768be7c8e3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c @@ -0,0 +1,167 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2005, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CCURRTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +********************************************************************************* +*/ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if (!UCONFIG_NO_COLLATION) /* This is not a formatting test. This is a collation test. */ + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccurrtst.h" +#include "ccolltst.h" +#include "unicode/ustring.h" +#include "cmemory.h" + +#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0]) + +void addCurrencyCollTest(TestNode** root) +{ + + addTest(root, &currTest, "tscoll/ccurrtst/currTest"); + +} + + +void currTest() +{ + /* All the currency symbols, in UCA order*/ + static const UChar currency[][2] = + { + { 0x00A4, 0x0000}, /*00A4; L; [14 36, 03, 03] # [082B.0020.0002] # CURRENCY SIGN*/ + { 0x00A2, 0x0000}, /*00A2; L; [14 38, 03, 03] # [082C.0020.0002] # CENT SIGN*/ + { 0xFFE0, 0x0000}, /*FFE0; L; [14 38, 03, 05] # [082C.0020.0003] # FULLWIDTH CENT SIGN*/ + { 0x0024, 0x0000}, /*0024; L; [14 3A, 03, 03] # [082D.0020.0002] # DOLLAR SIGN*/ + { 0xFF04, 0x0000}, /*FF04; L; [14 3A, 03, 05] # [082D.0020.0003] # FULLWIDTH DOLLAR SIGN*/ + { 0xFE69, 0x0000}, /*FE69; L; [14 3A, 03, 1D] # [082D.0020.000F] # SMALL DOLLAR SIGN*/ + { 0x00A3, 0x0000}, /*00A3; L; [14 3C, 03, 03] # [082E.0020.0002] # POUND SIGN*/ + { 0xFFE1, 0x0000}, /*FFE1; L; [14 3C, 03, 05] # [082E.0020.0003] # FULLWIDTH POUND SIGN*/ + { 0x00A5, 0x0000}, /*00A5; L; [14 3E, 03, 03] # [082F.0020.0002] # YEN SIGN*/ + { 0xFFE5, 0x0000}, /*FFE5; L; [14 3E, 03, 05] # [082F.0020.0003] # FULLWIDTH YEN SIGN*/ + { 0x09F2, 0x0000}, /*09F2; L; [14 40, 03, 03] # [0830.0020.0002] # BENGALI RUPEE MARK*/ + { 0x09F3, 0x0000}, /*09F3; L; [14 42, 03, 03] # [0831.0020.0002] # BENGALI RUPEE SIGN*/ + { 0x0E3F, 0x0000}, /*0E3F; L; [14 44, 03, 03] # [0832.0020.0002] # THAI CURRENCY SYMBOL BAHT*/ + { 0x17DB, 0x0000}, /*17DB; L; [14 46, 03, 03] # [0833.0020.0002] # KHMER CURRENCY SYMBOL RIEL*/ + { 0x20A0, 0x0000}, /*20A0; L; [14 48, 03, 03] # [0834.0020.0002] # EURO-CURRENCY SIGN*/ + { 0x20A1, 0x0000}, /*20A1; L; [14 4A, 03, 03] # [0835.0020.0002] # COLON SIGN*/ + { 0x20A2, 0x0000}, /*20A2; L; [14 4C, 03, 03] # [0836.0020.0002] # CRUZEIRO SIGN*/ + { 0x20A3, 0x0000}, /*20A3; L; [14 4E, 03, 03] # [0837.0020.0002] # FRENCH FRANC SIGN*/ + { 0x20A4, 0x0000}, /*20A4; L; [14 50, 03, 03] # [0838.0020.0002] # LIRA SIGN*/ + { 0x20A5, 0x0000}, /*20A5; L; [14 52, 03, 03] # [0839.0020.0002] # MILL SIGN*/ + { 0x20A6, 0x0000}, /*20A6; L; [14 54, 03, 03] # [083A.0020.0002] # NAIRA SIGN*/ + { 0x20A7, 0x0000}, /*20A7; L; [14 56, 03, 03] # [083B.0020.0002] # PESETA SIGN*/ + { 0x20A9, 0x0000}, /*20A9; L; [14 58, 03, 03] # [083C.0020.0002] # WON SIGN*/ + { 0xFFE6, 0x0000}, /*FFE6; L; [14 58, 03, 05] # [083C.0020.0003] # FULLWIDTH WON SIGN*/ + { 0x20AA, 0x0000}, /*20AA; L; [14 5A, 03, 03] # [083D.0020.0002] # NEW SHEQEL SIGN*/ + { 0x20AB, 0x0000}, /*20AB; L; [14 5C, 03, 03] # [083E.0020.0002] # DONG SIGN*/ + { 0x20AC, 0x0000}, /*20AC; L; [14 5E, 03, 03] # [083F.0020.0002] # EURO SIGN*/ + { 0x20AD, 0x0000}, /*20AD; L; [14 60, 03, 03] # [0840.0020.0002] # KIP SIGN*/ + { 0x20AE, 0x0000}, /*20AE; L; [14 62, 03, 03] # [0841.0020.0002] # TUGRIK SIGN*/ + { 0x20AF, 0x0000}, /*20AF; L; [14 64, 03, 03] # [0842.0020.0002] # DRACHMA SIGN*/ + }; + +#if 0 + /* All the currency symbols, in collation order*/ + static const UChar currency[][2] = + { + { 0x00a4, 0x0000}, /* generic currency*/ + { 0x0e3f, 0x0000}, /* baht*/ + { 0x00a2, 0x0000}, /* cent*/ + { 0x20a1, 0x0000}, /* colon*/ + { 0x20a2, 0x0000}, /* cruzeiro*/ + { 0x0024, 0x0000}, /* dollar */ + { 0x20ab, 0x0000}, /* dong */ + { 0x20ac, 0x0000}, /* euro */ + { 0x20a3, 0x0000}, /* franc */ + { 0x20a4, 0x0000}, /* lira */ + { 0x20a5, 0x0000}, /* mill */ + { 0x20a6, 0x0000}, /* naira */ + { 0x20a7, 0x0000}, /* peseta */ + { 0x00a3, 0x0000}, /* pound */ + { 0x20a8, 0x0000}, /* rupee */ + { 0x20aa, 0x0000}, /* shekel*/ + { 0x20a9, 0x0000}, /* won*/ + { 0x00a5, 0x0000} /* yen*/ + }; +#endif + + UChar source[2], target[2]; + int32_t i, j, sortklen; + int res; + UCollator *c; + uint8_t *sortKey1, *sortKey2; + UErrorCode status = U_ZERO_ERROR; + UCollationResult compareResult, keyResult; + UCollationResult expectedResult = UCOL_EQUAL; + log_verbose("Testing currency of all locales\n"); + c = ucol_open("en_US", &status); + if (U_FAILURE(status)) + { + log_err("collator open failed! :%s\n", myErrorName(status)); + return; + } + + /*Compare each currency symbol against all the + currency symbols, including itself*/ + for (i = 0; i < ARRAY_LENGTH(currency); i += 1) + { + for (j = 0; j < ARRAY_LENGTH(currency); j += 1) + { + u_strcpy(source, currency[i]); + u_strcpy(target, currency[j]); + + if (i < j) + { + expectedResult = UCOL_LESS; + } + else if ( i == j) + { + expectedResult = UCOL_EQUAL; + } + else + { + expectedResult = UCOL_GREATER; + } + + compareResult = ucol_strcoll(c, source, u_strlen(source), target, u_strlen(target)); + + status = U_ZERO_ERROR; + + sortklen=ucol_getSortKey(c, source, u_strlen(source), NULL, 0); + sortKey1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + ucol_getSortKey(c, source, u_strlen(source), sortKey1, sortklen+1); + + sortklen=ucol_getSortKey(c, target, u_strlen(target), NULL, 0); + sortKey2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1)); + ucol_getSortKey(c, target, u_strlen(target), sortKey2, sortklen+1); + + res = uprv_memcmp(sortKey1, sortKey2, sortklen); + if (res < 0) keyResult = (UCollationResult)-1; + else if (res > 0) keyResult = (UCollationResult)1; + else keyResult = (UCollationResult)0; + + reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResult, expectedResult ); + + free(sortKey1); + free(sortKey2); + + } + } + ucol_close(c); +} + +#endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h new file mode 100644 index 00000000000..bec5e99815e --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h @@ -0,0 +1,35 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CCURRTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*/ +/** + * Collation currency tests. + * (It's important to stay current!) + */ + +#ifndef _CCURRCOLLTST +#define _CCURRCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 + /* Perform Collation Currency Test */ + void currTest(void); + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c new file mode 100644 index 00000000000..0bdd4906dd3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c @@ -0,0 +1,958 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDATTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ + +/* C API TEST FOR DATE FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uloc.h" +#include "unicode/udat.h" +#include "unicode/ucal.h" +#include "unicode/unum.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cdattst.h" +#include "cformtst.h" +#include "cmemory.h" + +#include <math.h> + +static void TestExtremeDates(void); +static void TestAllLocales(void); + +#define LEN(a) (sizeof(a)/sizeof(a[0])) + +void addDateForTest(TestNode** root); + +#define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x) + +void addDateForTest(TestNode** root) +{ + TESTCASE(TestDateFormat); + TESTCASE(TestSymbols); + TESTCASE(TestDateFormatCalendar); + TESTCASE(TestExtremeDates); + TESTCASE(TestAllLocales); +} +/* Testing the DateFormat API */ +static void TestDateFormat() +{ + UDateFormat *def, *fr, *it, *de, *def1, *fr_pat; + UDateFormat *any; + UDateFormat *copy; + UErrorCode status = U_ZERO_ERROR; + UChar* result = NULL; + const UCalendar *cal; + const UNumberFormat *numformat1, *numformat2; + UChar temp[50]; + int32_t numlocales; + UDate d1; + int i; + int32_t resultlength; + int32_t resultlengthneeded; + int32_t parsepos; + UDate d = 837039928046.0; + double num = -10456.37; + /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z"; + const char t[]="2/3/76 2:50 AM";*/ + /*Testing udat_open() to open a dateformat */ + + ctest_setTimeZone(NULL, &status); + + log_verbose("\nTesting udat_open() with various parameters\n"); + fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using full time style with french locale\n %s\n", + myErrorName(status) ); + return; + } + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */ + def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n", + myErrorName(status) ); + return; + } + it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n", + myErrorName(status) ); + return; + } + de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n", + myErrorName(status)); + return; + } + /*creating a default dateformat */ + def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n", + myErrorName(status) ); + return; + } + + + /*Testing udat_getAvailable() and udat_countAvailable()*/ + log_verbose("\nTesting getAvailableLocales and countAvailable()\n"); + numlocales=udat_countAvailable(); + /* use something sensible w/o hardcoding the count */ + if(numlocales < 0) + log_data_err("FAIL: error in countAvailable\n"); + log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales); + + for(i=0;i<numlocales;i++) { + UErrorCode subStatus = U_ZERO_ERROR; + log_verbose("Testing open of %s\n", udat_getAvailable(i)); + any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus); + if(U_FAILURE(subStatus)) { + log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus)); + } + udat_close(any); + } + + /*Testing udat_clone()*/ + log_verbose("\nTesting the udat_clone() function of date format\n"); + copy=udat_clone(def, &status); + if(U_FAILURE(status)){ + log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) ); + } + /*if(def != copy) + log_err("Error in udat_clone");*/ /*how should i check for equality???? */ + + /*Testing udat_format()*/ + log_verbose("\nTesting the udat_format() function of date format\n"); + u_uastrcpy(temp, "7/10/96 4:05 PM"); + /*format using def */ + resultlength=0; + resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + if(result != NULL) { + free(result); + result = NULL; + } + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_format(def, d, result, resultlength, NULL, &status); + } + if(U_FAILURE(status) || !result) + { + log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) ); + return; + } + else + log_verbose("PASS: formatting successful\n"); + if(u_strcmp(result, temp)==0) + log_verbose("PASS: Date Format for US locale successful uisng udat_format()\n"); + else + log_err("FAIL: Date Format for US locale failed using udat_format()\n"); + /*format using fr */ + + u_unescape("10 juil. 1996 16:05:28 \\u00C9tats-Unis (Los Angeles)", temp, 50); + if(result != NULL) { + free(result); + result = NULL; + } + result=myDateFormat(fr, d); + if(u_strcmp(result, temp)==0) + log_verbose("PASS: Date Format for french locale successful using udat_format()\n"); + else + log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" ); + + /*format using it */ + u_uastrcpy(temp, "10/lug/1996 16:05:28"); + + { + UChar *fmtted; + char g[100]; + char x[100]; + + fmtted = myDateFormat(it,d); + u_austrcpy(g, fmtted); + u_austrcpy(x, temp); + if(u_strcmp(fmtted, temp)==0) { + log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g); + } else { + log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g); + } + } + + /*Testing parsing using udat_parse()*/ + log_verbose("\nTesting parsing using udat_parse()\n"); + u_uastrcpy(temp,"2/3/76 2:50 AM"); + parsepos=0; + status=U_ZERO_ERROR; + + d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) ); + } + else + log_verbose("PASS: parsing succesful\n"); + /*format it back and check for equality */ + + + if(u_strcmp(myDateFormat(def, d1),temp)!=0) + log_err("FAIL: error in parsing\n"); + + /*Testing parsing using udat_parse()*/ + log_verbose("\nTesting parsing using udat_parse()\n"); + u_uastrcpy(temp,"2/Don't parse this part"); + status=U_ZERO_ERROR; + + d1=udat_parse(def, temp, u_strlen(temp), NULL, &status); + if(status != U_PARSE_ERROR) + { + log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n"); + } + else + log_verbose("PASS: parsing succesful\n"); + + + + /*Testing udat_openPattern() */ + status=U_ZERO_ERROR; + log_verbose("\nTesting the udat_openPattern with a specified pattern\n"); + /*for french locale */ + fr_pat=udat_open(UDAT_IGNORE, UDAT_IGNORE,"fr_FR",NULL,0,temp, u_strlen(temp), &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n", + myErrorName(status) ); + } + else + log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n"); + + + /*Testing applyPattern and toPattern */ + log_verbose("\nTesting applyPattern and toPattern()\n"); + udat_applyPattern(def1, FALSE, temp, u_strlen(temp)); + log_verbose("Extracting the pattern\n"); + + resultlength=0; + resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded + 1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_toPattern(def1, FALSE, result, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n", + myErrorName(status) ); + } + if(u_strcmp(result, temp)!=0) + log_err("FAIL: Error in extracting the pattern\n"); + else + log_verbose("PASS: applyPattern and toPattern work fine\n"); + + if(result != NULL) { + free(result); + result = NULL; + } + + + /*Testing getter and setter functions*/ + /*isLenient and setLenient()*/ + log_verbose("\nTesting the isLenient and setLenient properties\n"); + udat_setLenient(fr, udat_isLenient(it)); + if(udat_isLenient(fr) != udat_isLenient(it)) + log_err("ERROR: setLenient() failed\n"); + else + log_verbose("PASS: setLenient() successful\n"); + + + /*Test get2DigitYearStart set2DigitYearStart */ + log_verbose("\nTesting the get and set 2DigitYearStart properties\n"); + d1= udat_get2DigitYearStart(fr_pat,&status); + if(U_FAILURE(status)) { + log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) ); + } + status = U_ZERO_ERROR; + udat_set2DigitYearStart(def1 ,d1, &status); + if(U_FAILURE(status)) { + log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) ); + } + if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status)) + log_err("FAIL: error in set2DigitYearStart\n"); + else + log_verbose("PASS: set2DigitYearStart successful\n"); + /*try setting it to another value */ + udat_set2DigitYearStart(de, 2000.0, &status); + if(U_FAILURE(status)){ + log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) ); + } + if(udat_get2DigitYearStart(de, &status) != 2000) + log_err("FAIL: error in set2DigitYearStart\n"); + else + log_verbose("PASS: set2DigitYearStart successful\n"); + + + + /*Test getNumberFormat() and setNumberFormat() */ + log_verbose("\nTesting the get and set NumberFormat properties of date format\n"); + numformat1=udat_getNumberFormat(fr_pat); + udat_setNumberFormat(def1, numformat1); + numformat2=udat_getNumberFormat(def1); + if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0) + log_err("FAIL: error in setNumberFormat or getNumberFormat()\n"); + else + log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n"); + + /*try setting the number format to another format */ + numformat1=udat_getNumberFormat(def); + udat_setNumberFormat(def1, numformat1); + numformat2=udat_getNumberFormat(def1); + if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0) + log_err("FAIL: error in setNumberFormat or getNumberFormat()\n"); + else + log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n"); + + + + /*Test getCalendar and setCalendar*/ + log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n"); + cal=udat_getCalendar(fr_pat); + + + udat_setCalendar(def1, cal); + if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1))) + log_err("FAIL: Error in setting and getting the calendar\n"); + else + log_verbose("PASS: getting and setting calendar successful\n"); + + if(result!=NULL) { + free(result); + } + + /*Closing the UDateForamt */ + udat_close(def); + udat_close(fr); + udat_close(it); + udat_close(de); + udat_close(def1); + udat_close(fr_pat); + udat_close(copy); + + ctest_resetTimeZone(); +} + +/*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/ +static void TestSymbols() +{ + UDateFormat *def, *fr; + UErrorCode status = U_ZERO_ERROR; + UChar *value=NULL; + UChar *result = NULL; + int32_t resultlength; + int32_t resultlengthout; + UChar *pattern; + + + /*creating a dateformat with french locale */ + log_verbose("\ncreating a date format with french locale\n"); + fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat using full time style with french locale\n %s\n", + myErrorName(status) ); + return; + } + /*creating a default dateformat */ + log_verbose("\ncreating a date format with default locale\n"); + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */ + def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat using short date and time style\n %s\n", + myErrorName(status) ); + return; + } + + + /*Testing countSymbols, getSymbols and setSymbols*/ + log_verbose("\nTesting countSymbols\n"); + /*since the month names has the last string empty and week names are 1 based 1.e first string in the weeknames array is empty */ + if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 || + udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 || + udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 || + udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 || + udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1) + { + log_err("FAIL: error in udat_countSymbols\n"); + } + else + log_verbose("PASS: udat_countSymbols() successful\n"); + + /*testing getSymbols*/ + log_verbose("\nTesting getSymbols\n"); + pattern=(UChar*)malloc(sizeof(UChar) * 10); + u_uastrcpy(pattern, "jeudi"); + resultlength=0; + resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + if(result != NULL) { + free(result); + result = NULL; + } + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status); + + } + if(U_FAILURE(status)) + { + log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) ); + } + else + log_verbose("PASS: getSymbols succesful\n"); + + if(u_strcmp(result, pattern)==0) + log_verbose("PASS: getSymbols retrieved the right value\n"); + else + log_data_err("FAIL: getSymbols retrieved the wrong value\n"); + + /*run series of tests to test getsymbols regressively*/ + log_verbose("\nTesting getSymbols() regressively\n"); + VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche"); + VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday"); + VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam."); + VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat"); + VerifygetSymbols(def, UDAT_MONTHS, 11, "December"); + VerifygetSymbols(def, UDAT_MONTHS, 0, "January"); + VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C."); + VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM"); + VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM"); + VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv."); + VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec"); + VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre"); + VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter"); + VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2"); + VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3"); + VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqV"); + + + if(result != NULL) { + free(result); + result = NULL; + } +free(pattern); + + log_verbose("\nTesting setSymbols\n"); + /*applying the pattern so that setSymbolss works */ + resultlength=0; + resultlengthout=udat_toPattern(fr, FALSE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthout + 1; + pattern=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_toPattern(fr, FALSE, pattern, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n", + myErrorName(status) ); + } + + udat_applyPattern(def, FALSE, pattern, u_strlen(pattern)); + resultlength=0; + resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthout + 1; + if(result != NULL) { + free(result); + result = NULL; + } + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_toPattern(fr, FALSE,result, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n", + myErrorName(status) ); + } + if(u_strcmp(result, pattern)==0) + log_verbose("Pattern applied properly\n"); + else + log_err("pattern could not be applied properly\n"); + +free(pattern); + /*testing set symbols */ + resultlength=0; + resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + if(result != NULL) { + free(result); + result = NULL; + } + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status); + + } + if(U_FAILURE(status)) + log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) ); + resultlength=resultlengthout+1; + + udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) ); + } + else + log_verbose("PASS: SetSymbols successful\n"); + + resultlength=0; + resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + value=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status); + } + if(U_FAILURE(status)) + log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n"); + + if(u_strcmp(result, value)!=0) + log_data_err("FAIL: Error in settting and getting symbols\n"); + else + log_verbose("PASS: setSymbols successful\n"); + + + /*run series of tests to test setSymbols regressively*/ + log_verbose("\nTesting setSymbols regressively\n"); + VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist"); + VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini"); + VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek"); + VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek"); + VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M"); + VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek"); + VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams"); + VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V"); + VerifysetSymbols(fr, UDAT_MONTHS, 11, "december"); + VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan"); + VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R"); + VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember"); + VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug"); + VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M"); + VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart"); + VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2"); + VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar."); + VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ"); + + + /*run series of tests to test get and setSymbols regressively*/ + log_verbose("\nTesting get and set symbols regressively\n"); + VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1); + VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7); + VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1); + VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7); + VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0); + VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0); + VerifygetsetSymbols(fr, def, UDAT_ERAS,1); + VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0); + VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1); + + + /*closing*/ + + udat_close(fr); + udat_close(def); + if(result != NULL) { + free(result); + result = NULL; + } + free(value); + +} + +/** + * Test DateFormat(Calendar) API + */ +static void TestDateFormatCalendar() { + UDateFormat *date=0, *time=0, *full=0; + UCalendar *cal=0; + UChar buf[256]; + char cbuf[256]; + int32_t pos; + UDate when; + UErrorCode ec = U_ZERO_ERROR; + + ctest_setTimeZone(NULL, &ec); + + /* Create a formatter for date fields. */ + date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s\n", + u_errorName(ec)); + goto FAIL; + } + + /* Create a formatter for time fields. */ + time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n", + u_errorName(ec)); + goto FAIL; + } + + /* Create a full format for output */ + full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n", + u_errorName(ec)); + goto FAIL; + } + + /* Create a calendar */ + cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: ucal_open(en_US) failed with %s\n", + u_errorName(ec)); + goto FAIL; + } + + /* Parse the date */ + ucal_clear(cal); + u_uastrcpy(buf, "4/5/2001"); + pos = 0; + udat_parseCalendar(date, cal, buf, -1, &pos, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n", + pos, u_errorName(ec)); + goto FAIL; + } + + /* Parse the time */ + u_uastrcpy(buf, "5:45 PM"); + pos = 0; + udat_parseCalendar(time, cal, buf, -1, &pos, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n", + pos, u_errorName(ec)); + goto FAIL; + } + + /* Check result */ + when = ucal_getMillis(cal, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec)); + goto FAIL; + } + udat_format(full, when, buf, sizeof(buf), NULL, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec)); + goto FAIL; + } + u_austrcpy(cbuf, buf); + /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */ + if (when == 986517900000.0) { + log_verbose("Ok: Parsed result: %s\n", cbuf); + } else { + log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf); + } + + FAIL: + udat_close(date); + udat_close(time); + udat_close(full); + ucal_close(cal); + + ctest_resetTimeZone(); +} + +/*INTERNAL FUNCTIONS USED*/ +static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected) +{ + UChar *pattern=NULL; + UErrorCode status = U_ZERO_ERROR; + UChar *result=NULL; + int32_t resultlength, resultlengthout; + + + pattern=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1)); + u_uastrcpy(pattern, expected); + resultlength=0; + resultlengthout=udat_getSymbols(datfor, type, index , NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(datfor, type, index, result, resultlength, &status); + + } + if(U_FAILURE(status)) + { + log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) ); + return; + } + if(u_strcmp(result, pattern)==0) + log_verbose("PASS: getSymbols retrieved the right value\n"); + else{ + log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", austrdup(pattern), + austrdup(result) ); + } + free(result); + free(pattern); +} + +static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected) +{ + UChar *result=NULL; + UChar *value=NULL; + int32_t resultlength, resultlengthout; + UErrorCode status = U_ZERO_ERROR; + + value=(UChar*)malloc(sizeof(UChar) * (strlen(expected) + 1)); + u_uastrcpy(value, expected); + udat_setSymbols(datfor, type, index, value, u_strlen(value), &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) ); + return; + } + + resultlength=0; + resultlengthout=udat_getSymbols(datfor, type, index, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(datfor, type, index, result, resultlength, &status); + } + if(U_FAILURE(status)){ + log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n", + myErrorName(status) ); + return; + } + + if(u_strcmp(result, value)!=0){ + log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(value), + austrdup(result) ); + } + else + log_verbose("PASS: setSymbols successful\n"); + + free(value); + free(result); +} + + +static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t index) +{ + UChar *result=NULL; + UChar *value=NULL; + int32_t resultlength, resultlengthout; + UErrorCode status = U_ZERO_ERROR; + + resultlength=0; + resultlengthout=udat_getSymbols(from, type, index , NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(from, type, index, result, resultlength, &status); + } + if(U_FAILURE(status)){ + log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) ); + return; + } + + resultlength=resultlengthout+1; + udat_setSymbols(to, type, index, result, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) ); + return; + } + + resultlength=0; + resultlengthout=udat_getSymbols(to, type, index, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + resultlength=resultlengthout+1; + value=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_getSymbols(to, type, index, value, resultlength, &status); + } + if(U_FAILURE(status)){ + log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n", + myErrorName(status) ); + return; + } + + if(u_strcmp(result, value)!=0){ + log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result), + austrdup(value) ); + } + else + log_verbose("PASS: setSymbols successful\n"); + + free(value); + free(result); +} + + +static UChar* myNumformat(const UNumberFormat* numfor, double d) +{ + UChar *result2=NULL; + int32_t resultlength, resultlengthneeded; + UErrorCode status = U_ZERO_ERROR; + + resultlength=0; + resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */ + result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/ + unum_formatDouble(numfor, d, result2, resultlength, NULL, &status); + } + if(U_FAILURE(status)) + { + log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) ); + return 0; + } + + return result2; +} + +/** + * The search depth for TestExtremeDates. The total number of + * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1. + */ +#define EXTREME_DATES_DEPTH 8 + +/** + * Support for TestExtremeDates (below). + * + * Test a single date to see whether udat_format handles it properly. + */ +static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date, + UChar* buf, int32_t buflen, char* cbuf, + UErrorCode* ec) { + int32_t len = udat_format(fmt, date, buf, buflen, 0, ec); + if (!assertSuccess("udat_format", ec)) return FALSE; + u_austrncpy(cbuf, buf, buflen); + if (len < 4) { + log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf); + } else { + log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf); + } + return TRUE; +} + +/** + * Support for TestExtremeDates (below). + * + * Recursively test between 'small' and 'large', up to the depth + * limit specified by EXTREME_DATES_DEPTH. + */ +static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large, + UChar* buf, int32_t buflen, char* cbuf, + int32_t count, + UErrorCode* ec) { + /* Logarithmic midpoint; see below */ + UDate mid = (UDate) exp((log(small) + log(large)) / 2); + if (count == EXTREME_DATES_DEPTH) { + return TRUE; + } + return + _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) && + _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) && + _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec); +} + +/** + * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659 + * + * For certain large dates, udat_format crashes on MacOS. This test + * attempts to reproduce this problem by doing a recursive logarithmic* + * binary search of a predefined interval (from 'small' to 'large'). + * + * The limit of the search is given by EXTREME_DATES_DEPTH, above. + * + * *The search has to be logarithmic, not linear. A linear search of the + * range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and + * 0.75*10^30, etc. A logarithmic search will find 10^15, then 10^7.5 + * and 10^22.5, etc. + */ +static void TestExtremeDates() { + UDateFormat *fmt; + UErrorCode ec; + UChar buf[256]; + char cbuf[256]; + const double small = 1000; /* 1 sec */ + const double large = 1e+30; /* well beyond usable UDate range */ + + /* There is no need to test larger values from 1e+30 to 1e+300; + the failures occur around 1e+27, and never above 1e+30. */ + + ec = U_ZERO_ERROR; + fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US", + 0, 0, 0, 0, &ec); + if (!assertSuccess("udat_open", &ec)) return; + + _aux2ExtremeDates(fmt, small, large, buf, LEN(buf), cbuf, 0, &ec); + + udat_close(fmt); +} + +static void TestAllLocales(void) { + int32_t idx, dateIdx, timeIdx, localeCount; + static const UDateFormatStyle style[] = { + UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT + }; + localeCount = uloc_countAvailable(); + for (idx = 0; idx < localeCount; idx++) { + for (dateIdx = 0; dateIdx < (int32_t)(sizeof(style)/sizeof(style[0])); dateIdx++) { + for (timeIdx = 0; timeIdx < (int32_t)(sizeof(style)/sizeof(style[0])); timeIdx++) { + UErrorCode status = U_ZERO_ERROR; + udat_close(udat_open(style[dateIdx], style[timeIdx], + uloc_getAvailable(idx), NULL, 0, NULL, 0, &status)); + if (U_FAILURE(status)) { + log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n", + uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx); + } + } + } + } +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h new file mode 100644 index 00000000000..861a1087645 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h @@ -0,0 +1,54 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDATTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* C API TEST FOR DATE FORMAT */ +#ifndef _CDATFRMTST +#define _CDATFRMTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + + /** + * The function used to test the Date format API + **/ + static void TestDateFormat(void); + + /** + * The function used to test API udat_getSymbols(), udat_setSymbols() and udat_countSymbols() + **/ + static void TestSymbols(void); + + /** + * Test DateFormat(Calendar) API + */ + static void TestDateFormatCalendar(void); + + /** + * test subroutines used by TestSymbols + **/ + static void VerifygetSymbols(UDateFormat*, UDateFormatSymbolType, int32_t, const char*); + static void VerifysetSymbols(UDateFormat*, UDateFormatSymbolType, int32_t, const char*); + static void VerifygetsetSymbols(UDateFormat*, UDateFormat*, UDateFormatSymbolType, int32_t); + + /** + * test subroutine used by the testing functions + **/ + static UChar* myNumformat(const UNumberFormat* numfor, double d); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c new file mode 100644 index 00000000000..6d53b74e602 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c @@ -0,0 +1,139 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDETST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * CollationGermanTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "cdetst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = +{ + {0x0047/*'G'*/, 0x0072/*'r'*/, 0x00F6, 0x00DF, 0x0065/*'e'*/, 0x0000}, + {0x0061/*'a'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, + {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000}, + {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000}, + {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000}, + {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, + {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here */ + {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/ + {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x00DF, 0x0065/*'e'*/, 0x0000}, + {0x0065/*'e'*/, 0x0066/*'f'*/, 0x0067/*'g'*/, 0x0000}, + {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/ + {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x00DF, 0x0065/*'e'*/, 0x0000} +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = +{ + {0x0047/*'G'*/, 0x0072/*'r'*/, 0x006f/*'o'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0069/*'i'*/, 0x0073/*'s'*/, 0x0074/*'t'*/, 0x0000}, + {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, + {0x0054/*'T'*/, 0x006f/*'o'*/, 0x006e/*'n'*/, 0x0000}, + {0x0054/*'T'*/, 0x006f/*'o'*/, 0x0064/*'d'*/, 0x0000}, + {0x0054/*'T'*/, 0x006f/*'o'*/, 0x0066/*'f'*/, 0x0075/*'u'*/, 0x0000}, + {0x0041/*'A'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/ + {0x0061/*'a'*/, 0x0065/*'e'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/ + {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0065/*'e'*/, 0x0000}, + {0x0065/*'e'*/, 0x0066/*'f'*/, 0x0067/*'g'*/, 0x0000}, + {0x0061/*'a'*/, 0x0065/*'e'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/ + {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0065/*'e'*/, 0x0000} +}; + +const static UCollationResult results[][2] = +{ + /* Primary*/ /* Tertiary*/ + { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/ + { UCOL_EQUAL, UCOL_LESS }, + { UCOL_GREATER, UCOL_GREATER }, + { UCOL_GREATER, UCOL_GREATER }, + { UCOL_GREATER, UCOL_GREATER }, + { UCOL_EQUAL, UCOL_LESS }, + { UCOL_EQUAL, UCOL_EQUAL }, /*should be UCOL_GREATER for primary*/ + { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/ + { UCOL_EQUAL, UCOL_GREATER }, + { UCOL_EQUAL, UCOL_EQUAL }, + { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/ + { UCOL_EQUAL, UCOL_GREATER } +}; + + + + +void addGermanCollTest(TestNode** root) +{ + + + addTest(root, &TestTertiary, "tscoll/cdetst/TestTertiary"); + addTest(root, &TestPrimary, "tscoll/cdetst/TestPrimary"); + + + +} + +static void TestTertiary( ) +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("de_DE", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing German Collation with Tertiary strength\n"); + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 12 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i][1]); + } + ucol_close(myCollation); +} + +static void TestPrimary() +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("de_DE", &status); + if(U_FAILURE(status)){ + log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status)); + return; + } + log_verbose("Testing German Collation with primary strength\n"); + ucol_setStrength(myCollation, UCOL_PRIMARY); + for (i = 0; i < 12 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i][0]); + } + ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h new file mode 100644 index 00000000000..36696a5c2ec --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h @@ -0,0 +1,42 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDETST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationGERMANTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CGERCOLLTST +#define _CGERCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + + +#define MAX_TOKEN_LEN 16 + + /* performs test with strength PRIMARY */ +static void TestPrimary(void); + + /* perform test with strength TERTIARY */ +static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c new file mode 100644 index 00000000000..d19b7eedac4 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c @@ -0,0 +1,350 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDTDPTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* INDEPTH TEST FOR DATE FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uloc.h" +#include "unicode/udat.h" +#include "unicode/ucal.h" +#include "unicode/unum.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cdtdptst.h" +#include "cformtst.h" + +#include "cmemory.h" + +void addDtFrDepTest(TestNode** root); + +void addDtFrDepTest(TestNode** root) +{ + addTest(root, &TestTwoDigitYearDSTParse, "tsformat/cdtdptst/TestTwoDigitYearDSTParse"); + addTest(root, &TestPartialParse994, "tsformat/cdtdptst/TestPartialParse994"); + addTest(root, &TestRunTogetherPattern985, "tsformat/cdtdptst/TestRunTogetherPattern985"); + addTest(root, &TestCzechMonths459, "tsformat/cdtdptst/TestCzechMonths459"); + addTest(root, &TestQuotePattern161, "tsformat/cdtdptst/TestQuotePattern161"); + +} + +/** + * Test the parsing of 2-digit years. + */ +void TestTwoDigitYearDSTParse() +{ + UDateFormat *fullFmt, *fmt; + UErrorCode status = U_ZERO_ERROR; + UChar *pattern; + UDate d; + UChar *s; + int32_t pos; + + ctest_setTimeZone(NULL, &status); + + pattern=(UChar*)malloc(sizeof(UChar) * (strlen("EEE MMM dd HH:mm:ss.SSS zzz yyyy G")+1 )); + u_uastrcpy(pattern, "EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); + fullFmt= udat_open(UDAT_IGNORE, UDAT_IGNORE,"en_US",NULL,0,pattern, u_strlen(pattern),&status); + if(U_FAILURE(status)) { + log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n", + myErrorName(status) ); + } + else {log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");} + + u_uastrcpy(pattern, "dd-MMM-yy h:mm:ss 'o''clock' a z"); + fmt= udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); + + + s=(UChar*)malloc(sizeof(UChar) * (strlen("03-Apr-04 2:20:47 o'clock AM PST")+1) ); + u_uastrcpy(s, "03-Apr-04 2:20:47 o'clock AM PST"); + pos=0; + d = udat_parse(fmt, s, u_strlen(s), &pos, &status); + if (U_FAILURE(status)) { + log_err("FAIL: Could not parse \"%s\"\n", austrdup(s)); + } else { + UCalendar *cal = ucal_open(NULL, 0, uloc_getDefault(), UCAL_TRADITIONAL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: Could not open calendar"); + } else { + int32_t h; + ucal_setMillis(cal, d, &status); + h = ucal_get(cal, UCAL_HOUR_OF_DAY, &status); + if (U_FAILURE(status)) { + log_err("FAIL: Some calendar operations failed"); + } else if (h != 2) { + log_err("FAIL: Parse of \"%s\" returned HOUR_OF_DAY %d\n", + austrdup(s), h); + } + ucal_close(cal); + } + } + + udat_close(fullFmt); + udat_close(fmt); + free(pattern); + free(s); + + ctest_resetTimeZone(); +} + + +/** + * Verify that strings which contain incomplete specifications are parsed + * correctly. In some instances, this means not being parsed at all, and + * returning an appropriate error. + */ +void TestPartialParse994() +{ + int32_t pos; + UDateFormat *f; + UErrorCode status = U_ZERO_ERROR; + UChar *s; + UChar *fmtChars; + UDate d, null; + null=0; + + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* f = udat_open(UDAT_DEFAULT, UDAT_SHORT, NULL, NULL, 0, &status); */ + f = udat_open(UDAT_DEFAULT, UDAT_SHORT, "en_US", NULL, 0, NULL, 0,&status); + if(U_FAILURE(status)){ + log_err("FAIL: ErrorCode received during test: %s\n", myErrorName(status)); + return; + } + s=(UChar*)malloc(sizeof(UChar) * (strlen("01/01/1997 10:11:42 AM")+1) ); + u_uastrcpy(s, "01/01/1997 10:11:42 AM"); + pos=0; + d = udat_parse(f, s, u_strlen(s), &pos, &status); + if(U_FAILURE(status)) { + log_data_err("FAIL: could not parse - exitting"); + return; + } + fmtChars = myDateFormat(f, d); + if(fmtChars) { + log_verbose("%s\n", fmtChars); + } else { + log_data_err("FAIL: could not format \n"); + return; + } + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:11:42", d); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 ", null); + tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01", null); + udat_close(f); + free(s); +} + + + +void tryPat994(UDateFormat* format, const char* pattern, const char* s, UDate expected) +{ + UChar *f; + UChar *str, *pat; + UDate date; + UDate null=0; + int32_t pos; + UErrorCode status = U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (strlen(s) + 1) ); + u_uastrcpy(str, s); + pat=(UChar*)malloc(sizeof(UChar) * (strlen(pattern) + 1) ); + u_uastrcpy(pat, pattern); + log_verbose("Pattern : %s ; String : %s\n", austrdup(pat), austrdup(str)); + udat_applyPattern(format, FALSE, pat, u_strlen(pat)); + pos=0; + date = udat_parse(format, str, u_strlen(str), &pos, &status); + if(U_FAILURE(status) || date == null) { + log_verbose("ParseException: : %s\n", myErrorName(status) ); + if (expected != null) + log_err("FAIL: Expected: %s\n", austrdup(myDateFormat(format, expected)) ); + } + else { + f=myDateFormat(format, date); + log_verbose(" parse( %s ) -> %s\n", austrdup(str), austrdup(f)); + if (expected == null || date != expected) + log_err("FAIL: Expected null for \"%s\"\n", s); + if (u_strcmp(f, str) !=0) + log_err("FAIL: Expected : %s\n", austrdup(str) ); + } + + free(str); + free(pat); +} + + +/** + * Verify the behavior of patterns in which digits for different fields run together + * without intervening separators. + */ +void TestRunTogetherPattern985() +{ + int32_t pos; + UChar *pattern=NULL, *now=NULL, *then=NULL; + UDateFormat *format; + UDate date1, date2; + UErrorCode status = U_ZERO_ERROR; + pattern=(UChar*)malloc(sizeof(UChar) * (strlen("yyyyMMddHHmmssSSS")+1) ); + u_uastrcpy(pattern, "yyyyMMddHHmmssSSS"); + format = udat_open(UDAT_IGNORE, UDAT_IGNORE, NULL, NULL, 0,pattern, u_strlen(pattern), &status); + if(U_FAILURE(status)){ + log_err("FAIL: Error in date format construction with pattern: %s\n", myErrorName(status)); + return; + } + date1 = ucal_getNow(); + now=myDateFormat(format, date1); + log_verbose("%s\n", austrdup(now) ); + pos = 0; + date2 = udat_parse(format, now, u_strlen(now), &pos, &status); + if (date2 == 0) log_verbose("Parse stopped at : %d\n", pos); + else then=myDateFormat(format, date2); + log_verbose("%s\n", austrdup(then) ); + if (!(date2 == date1)) log_err("FAIL\n"); + + udat_close(format); + free(pattern); + +} + +/** + * Verify the handling of Czech June and July, which have the unique attribute that + * one is a proper prefix substring of the other. + */ +void TestCzechMonths459() +{ + int32_t lneed, pos; + UChar *pattern=NULL, *tzID=NULL; + UChar *juneStr, *julyStr; + UDateFormat *fmt; + UCalendar *cal; + UDate june, july, d; + UErrorCode status = U_ZERO_ERROR; + UChar *date; + + ctest_setTimeZone(NULL, &status); + fmt = udat_open(UDAT_FULL, UDAT_FULL, "cs", NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)){ + log_err("Error in constructing the date format\n"); + ctest_resetTimeZone(); + return; + } + lneed=0; + lneed=udat_toPattern(fmt, TRUE, NULL, lneed, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + pattern=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + udat_toPattern(fmt, TRUE, pattern, lneed+1, &status); + } + if(U_FAILURE(status)){ log_err("Error in extracting the pattern\n"); } + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "GMT"); + cal=ucal_open(tzID, u_strlen(tzID), "cs", UCAL_GREGORIAN, &status); + if(U_FAILURE(status)){ log_err("error in ucal_open caldef : %s\n", myErrorName(status)); } + + ucal_setDate(cal, 1997, UCAL_JUNE, 15, &status); + june=ucal_getMillis(cal, &status); + ucal_setDate(cal, 1997, UCAL_JULY, 15, &status); + july=ucal_getMillis(cal, &status); + + juneStr = myDateFormat(fmt, june); + julyStr = myDateFormat(fmt, july); + pos=0; + if(juneStr == NULL) { + log_data_err("Can't load juneStr. Quitting.\n"); + return; + } + d = udat_parse(fmt, juneStr, u_strlen(juneStr), &pos, &status); + date = myDateFormat(fmt, d); + + if(U_SUCCESS(status)){ + UChar* out1 = myDateFormat(fmt, june); + UChar* out2 = myDateFormat(fmt, d); + if(u_strcmp(out1, out2) !=0) + log_err("Error in handling the czech month june\n"); + else + log_verbose("Pass: Date = %s (czech month June)\n", aescstrdup(date, -1)); + }else{ + log_err("udat_parse failed. Error. %s\n",u_errorName(status)); + } + pos=0; + d = udat_parse(fmt, julyStr, u_strlen(julyStr), &pos, &status); + date = myDateFormat(fmt, d); + if(u_strcmp(myDateFormat(fmt, july), myDateFormat(fmt, d) ) !=0) + log_err("Error in handling the czech month july\n"); + else + log_verbose("Pass: Date = %s (czech month July)\n", aescstrdup(date, -1)); + + ctest_resetTimeZone(); + udat_close(fmt); + ucal_close(cal); + free(pattern); + free(tzID); +} + +/** + * Test the handling of single quotes in patterns. + */ +void TestQuotePattern161() +{ + UDateFormat *format; + UCalendar *cal; + UDate currentTime_1; + UChar *pattern, *tzID, *exp; + UChar *dateString; + UErrorCode status = U_ZERO_ERROR; + const char* expStr = "04/13/1999 at 10:42:28 AM "; + + ctest_setTimeZone(NULL, &status); + + pattern=(UChar*)malloc(sizeof(UChar) * (strlen("MM/dd/yyyy 'at' hh:mm:ss a zzz")+1) ); + u_uastrcpy(pattern, "MM/dd/yyyy 'at' hh:mm:ss a zzz"); + + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* format= udat_openPattern(pattern, u_strlen(pattern), NULL, &status); */ + format= udat_open(UDAT_IGNORE, UDAT_IGNORE,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); + if(U_FAILURE(status)){ + log_err("error in udat_open: %s\n", myErrorName(status)); + return; + } + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */ + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); } + + ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status); + currentTime_1 = ucal_getMillis(cal, &status); + + dateString = myDateFormat(format, currentTime_1); + exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) ); + u_uastrcpy(exp, expStr); + + log_verbose("%s\n", austrdup(dateString) ); + if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0) + log_err("Error in formatting a pattern with single quotes\n"); + + udat_close(format); + ucal_close(cal); + free(exp); + free(tzID); + free(pattern); + + ctest_resetTimeZone(); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h new file mode 100644 index 00000000000..11fd9e5faaa --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h @@ -0,0 +1,57 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDTDPTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* INDEPTH TEST FOR DATE FORMAT */ +#ifndef _CDTFRRGSTST +#define _CDTFRRGSTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + +/** + * Test the parsing of 2-digit years. + */ +void TestTwoDigitYearDSTParse(void); +/** + * Verify that strings which contain incomplete specifications are parsed + * correctly. In some instances, this means not being parsed at all, and + * returning an appropriate error. + */ +void TestPartialParse994(void); +/** + * Verify the behavior of patterns in which digits for different fields run together + * without intervening separators. + */ +void TestRunTogetherPattern985(void); + +/** + * Verify the handling of Czech June and July, which have the unique attribute that + * one is a proper prefix substring of the other. + */ +void TestCzechMonths459(void); + +/** + * Test the handling of single quotes in patterns. + */ +void TestQuotePattern161(void); + +/*Internal functions used*/ +void tryPat994(UDateFormat* format, const char* pat, const char* s, UDate expected); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c new file mode 100644 index 00000000000..3ef0f780af0 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c @@ -0,0 +1,536 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDTRGTST.C +* +* Madhu Katragadda Ported for C API +* Modification History: +* Date Name Description +* 07/15/99 helena Ported to HPUX 10/11 CC. +********************************************************************************* +*/ +/* REGRESSION TEST FOR DATE FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uloc.h" +#include "unicode/udat.h" +#include "unicode/ucal.h" +#include "unicode/unum.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cdtrgtst.h" +#include "cmemory.h" + +void addDateForRgrTest(TestNode** root); + +void addDateForRgrTest(TestNode** root) +{ + addTest(root, &Test4029195, "tsformat/cdtrgtst/Test4029195"); + addTest(root, &Test4056591, "tsformat/cdtrgtst/Test4056591"); + addTest(root, &Test4059917, "tsformat/cdtrgtst/Test4059917"); + addTest(root, &Test4060212, "tsformat/cdtrgtst/Test4060212"); + addTest(root, &Test4061287, "tsformat/cdtrgtst/Test4061287"); + addTest(root, &Test4073003, "tsformat/cdtrgtst/Test4073003"); + addTest(root, &Test4162071, "tsformat/cdtrgtst/Test4162071"); + addTest(root, &Test714, "tsformat/cdtrgtst/Test714"); +} + +/** + * @bug 4029195 + */ +void Test4029195() +{ + int32_t resultlength, resultlengthneeded; + UChar *fmdt, *todayS, *rt; + UChar *pat=NULL; + UChar *temp; + UDate today, d1; + UDateFormat *df; + int32_t parsepos; + UErrorCode status = U_ZERO_ERROR; + + log_verbose("Testing date format and parse function in regression test\n"); + today = ucal_getNow(); + + df = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using default date and time style : %s\n", myErrorName(status)); + return; + } + resultlength=0; + resultlengthneeded=udat_toPattern(df, TRUE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded + 1; + pat=(UChar*)malloc(sizeof(UChar) * resultlength); + udat_toPattern(df, TRUE, pat, resultlength, &status); + } + + log_verbose("pattern: %s\n", austrdup(pat)); + + + fmdt = myFormatit(df, today); + if(fmdt) { + log_verbose("today: %s\n", austrdup(fmdt)); + } else { + log_data_err("ERROR: couldn't format, exitting test"); + return; + } + + temp=(UChar*)malloc(sizeof(UChar) * 10); + u_uastrcpy(temp, "M yyyy dd"); + udat_applyPattern(df, TRUE, temp, u_strlen(temp)); + + todayS =myFormatit(df, today); + log_verbose("After teh pattern is applied\n today: %s\n", austrdup(todayS) ); + parsepos=0; + d1=udat_parse(df, todayS, u_strlen(todayS), &parsepos, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: Error in parsing using udat_parse(.....): %s\n", myErrorName(status)); + } + + rt =myFormatit(df, d1); + log_verbose("today: %s\n", austrdup(rt) ); + + log_verbose("round trip: %s\n", austrdup(rt) ); + + if(u_strcmp(rt, todayS)!=0) { + log_err("Fail: Want %s Got %s\n", austrdup(todayS), austrdup(rt) ); + } + else + log_verbose("Pass: parse and format working fine\n"); + udat_close(df); + free(temp); + if(pat != NULL) { + free(pat); + } +} + + +/** + * @bug 4056591 + * Verify the function of the [s|g]et2DigitYearStart() API. + */ +void Test4056591() +{ + int i; + UCalendar *cal; + UDateFormat *def; + UDate start,exp,got; + UChar s[10]; + UChar *gotdate, *expdate; + UChar pat[10]; + UDate d[4]; + UErrorCode status = U_ZERO_ERROR; + const char* strings[] = { + "091225", + "091224", + "611226", + "991227" + }; + + log_verbose("Testing s[get] 2 digit year start regressively\n"); + cal=ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &status); + if(U_FAILURE(status)){ + log_err("error in ucal_open caldef : %s\n", myErrorName(status)); + } + ucal_setDateTime(cal, 1809, UCAL_DECEMBER, 25, 17, 40, 30, &status); + d[0]=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ + log_err("Error: failure in get millis: %s\n", myErrorName(status)); + } + ucal_setDateTime(cal, 1909, UCAL_DECEMBER, 24, 17, 40, 30, &status); + d[1]=ucal_getMillis(cal, &status); + ucal_setDateTime(cal, 1861, UCAL_DECEMBER, 26, 17, 40, 30, &status); + d[2]=ucal_getMillis(cal, &status); + ucal_setDateTime(cal, 1999, UCAL_DECEMBER, 27, 17, 40, 30, &status); + d[3]=ucal_getMillis(cal, &status); + + + u_uastrcpy(pat, "yyMMdd"); + def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL, NULL, 0, pat, u_strlen(pat), &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using u_openPattern(): %s\n", myErrorName(status)); + return; + } + start = 1800; + udat_set2DigitYearStart(def, start, &status); + if(U_FAILURE(status)) + log_err("ERROR: in setTwoDigitStartDate: %s\n", myErrorName(status)); + if( (udat_get2DigitYearStart(def, &status) != start)) + log_err("ERROR: get2DigitYearStart broken\n"); + + + for(i = 0; i < 4; ++i) { + u_uastrcpy(s, strings[i]); + exp = d[i]; + got = udat_parse(def, s, u_strlen(s), 0, &status); + gotdate=myFormatit(def, got); + expdate=myFormatit(def, exp); + + if (gotdate == NULL || expdate == NULL) { + log_err("myFormatit failed!\n"); + } + else if(u_strcmp(gotdate, expdate) !=0){ + log_err("set2DigitYearStart broken for %s \n got: %s, expected: %s\n", austrdup(s), + austrdup(gotdate), austrdup(expdate) ); + } + } + + udat_close(def); + ucal_close(cal); +} + + +/** + * SimpleDateFormat does not properly parse date strings without delimiters + * @bug 4059917 + */ +void Test4059917() +{ + UDateFormat* def; + UChar *myDate; + UErrorCode status = U_ZERO_ERROR; + UChar *pattern; + UChar tzID[4]; + + log_verbose("Testing apply pattern and to pattern regressively\n"); + u_uastrcpy(tzID, "PST"); + pattern=(UChar*)malloc(sizeof(UChar) * 11); + u_uastrcpy(pattern, "yyyy/MM/dd"); + log_verbose("%s\n", austrdup(pattern) ); + def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,tzID,-1,pattern, u_strlen(pattern),&status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using openPattern: %s\n", myErrorName(status)); + return; + } + myDate=(UChar*)malloc(sizeof(UChar) * 11); + u_uastrcpy(myDate, "1970/01/12"); + + aux917( def, myDate ); + udat_close(def); + + u_uastrcpy(pattern, "yyyyMMdd"); + def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,tzID,-1,pattern, u_strlen(pattern),&status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using openPattern: %s\n", myErrorName(status)); + return; + } + u_uastrcpy(myDate, "19700112"); + aux917( def, myDate ); + udat_close(def); + free(pattern); + free(myDate); + +} + +void aux917( UDateFormat *fmt, UChar* str) +{ + int32_t resultlength, resultlengthneeded; + UErrorCode status = U_ZERO_ERROR; + UChar* formatted=NULL; + UChar *pat=NULL; + UDate d1=1000000000.0; + + resultlength=0; + resultlengthneeded=udat_toPattern(fmt, TRUE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded + 1; + pat=(UChar*)malloc(sizeof(UChar) * (resultlength)); + udat_toPattern(fmt, TRUE, pat, resultlength, &status); + } + if(U_FAILURE(status)){ + log_err("failure in retrieving the pattern: %s\n", myErrorName(status)); + } + log_verbose("pattern: %s\n", austrdup(pat) ); + + status = U_ZERO_ERROR; + formatted = myFormatit(fmt, d1); + if( u_strcmp(formatted,str)!=0) { + log_err("Fail: Want %s Got: %s\n", austrdup(str), austrdup(formatted) ); + } + free(pat); +} + +/** + * @bug 4060212 + */ +void Test4060212() +{ + int32_t pos; + UCalendar *cal; + UDateFormat *formatter, *fmt; + UErrorCode status = U_ZERO_ERROR; + UDate myDate; + UChar *myString; + UChar dateString[30], pattern[20], tzID[4]; + u_uastrcpy(dateString, "1995-040.05:01:29 -8"); + u_uastrcpy(pattern, "yyyy-DDD.hh:mm:ss z"); + + log_verbose( "dateString= %s Using yyyy-DDD.hh:mm:ss\n", austrdup(dateString) ); + status = U_ZERO_ERROR; + u_uastrcpy(tzID, "PST"); + + formatter = udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US",tzID,-1,pattern, u_strlen(pattern), &status); + pos=0; + myDate = udat_parse(formatter, dateString, u_strlen(dateString), &pos, &status); + + + fmt = udat_open(UDAT_FULL,UDAT_LONG ,NULL, tzID, -1, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using default date and time style: %s\n", + myErrorName(status) ); + return; + } + myString = myFormatit(fmt, myDate); + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status); + if(U_FAILURE(status)){ + log_err("FAIL: error in ucal_open caldef : %s\n", myErrorName(status)); + } + ucal_setMillis(cal, myDate, &status); + if ((ucal_get(cal, UCAL_DAY_OF_YEAR, &status) != 40)){ + log_err("Fail: Got %d Expected 40\n", ucal_get(cal, UCAL_DAY_OF_YEAR, &status)); + } + + udat_close(formatter); + ucal_close(cal); + udat_close(fmt); + +} + +/** + * @bug 4061287 + */ +void Test4061287() +{ + UBool ok; + int32_t pos; + UDateFormat *df; + UErrorCode status = U_ZERO_ERROR; + UDate myDate; + UChar pattern[21], dateString[11]; + + u_uastrcpy(dateString, "35/13/1971"); + u_uastrcpy(pattern, "dd/mm/yyyy"); + status = U_ZERO_ERROR; + log_verbose("Testing parsing by changing the attribute lenient\n"); + df = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,NULL,0,pattern, u_strlen(pattern),&status); + if(U_FAILURE(status)){ + log_err("ERROR: failure in open pattern of test4061287: %s\n", myErrorName(status)); + return; + } + + pos=0; + + udat_setLenient(df, FALSE); + ok=udat_isLenient(df); + if(ok==TRUE) + log_err("setLenient nor working\n"); + ok = FALSE; + myDate = udat_parse(df, dateString, u_strlen(dateString), &pos, &status); + if(U_FAILURE(status)) + ok = TRUE; + if(ok!=TRUE) + log_err("Fail: Lenient not working: does lenient parsing in spite of setting Leninent as FALSE "); + + udat_close(df); + +} + + + +/* The java.text.DateFormat.parse(String) method expects for the + US locale a string formatted according to mm/dd/yy and parses it + correctly. + + When given a string mm/dd/yyyy it only parses up to the first + two y's, typically resulting in a date in the year 1919. + + Please extend the parsing method(s) to handle strings with + four-digit year values (probably also applicable to various + other locales. */ +/** + * @bug 4073003 + */ +void Test4073003() +{ + int32_t pos,i; + UDate d,dd; + UChar *datestr; + UChar temp[15]; + UErrorCode status = U_ZERO_ERROR; + UDateFormat *fmt; + UChar *result, *result2; + const char* tests [] = { + "12/25/61", + "12/25/1961", + "4/3/1999", + "4/3/99" + }; + + fmt= udat_open(UDAT_SHORT,UDAT_SHORT ,NULL, NULL, 0, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using short date and time style: %s\n", + myErrorName(status)); + return; + } + u_uastrcpy(temp, "m/D/yy"); + udat_applyPattern(fmt, FALSE, temp, u_strlen(temp)); + + for(i= 0; i < 4; i+=2) { + status=U_ZERO_ERROR; + datestr=(UChar*)malloc(sizeof(UChar) * (strlen(tests[i])+1)); + u_uastrcpy(datestr, tests[i]); + + pos=0; + d = udat_parse(fmt, datestr, u_strlen(datestr), &pos, &status); + if(U_FAILURE(status)){ + log_err("ERROR : in test 4073003: %s\n", myErrorName(status)); + } + + free(datestr); + datestr=(UChar*)malloc(sizeof(UChar) * (strlen(tests[i+1])+1)); + u_uastrcpy(datestr, tests[i+1]); + + pos=0; + status=U_ZERO_ERROR; + dd = udat_parse(fmt, datestr, u_strlen(datestr), &pos, &status); + if(U_FAILURE(status)){ + log_err("ERROR : in test 4073003: %s\n", myErrorName(status)); + } + free(datestr); + + result =myFormatit(fmt, d); + result2 =myFormatit(fmt, dd); + if(!result || !result2) { + log_data_err("Fail: could not format - exitting test\n"); + return; + } + if (u_strcmp(result, result2)!=0){ + log_err("Fail: %s != %s\n", austrdup(result), austrdup(result2) ); + } + else{ + log_verbose("Ok: %s == %s\n", austrdup(result), austrdup(result2) ); + } + + } + udat_close(fmt); +} + +/** + * @bug 4162071 + **/ +void Test4162071() +{ + int32_t pos; + UDate x; + UErrorCode status = U_ZERO_ERROR; + UDateFormat *df; + UChar datestr[30]; + UChar format[50]; + u_uastrcpy(datestr, "Thu, 30-Jul-1999 11:51:14 GMT"); + u_uastrcpy(format, "EEE', 'dd-MMM-yyyy HH:mm:ss z"); /* RFC 822/1123 */ + status = U_ZERO_ERROR; + /* Can't hardcode the result to assume the default locale is "en_US". */ + df = udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US",NULL,0,format, u_strlen(format),&status); + if(U_FAILURE(status)){ + log_data_err("ERROR: couldn't create date format: %s\n", myErrorName(status)); + return; + } + pos=0; + x = udat_parse(df, datestr, u_strlen(datestr), &pos, &status); + if(U_FAILURE(status)){ + log_data_err("ERROR : parse format %s fails : %s\n", austrdup(format), myErrorName(status)); + } + else{ + log_verbose("Parse format \"%s \" ok.\n", austrdup(format) ); + } + /*log_verbose("date= %s\n", austrdup(myFormatit(df, x)) );*/ + udat_close(df); +} + +void Test714(void) +{ + UDate d=978103543000.0; + UChar temp[20]; + UErrorCode status = U_ZERO_ERROR; + UDateFormat *fmt; + UChar *result; + const char* expect = "7:25:43 AM"; + + ctest_setTimeZone(NULL, &status); + + fmt= udat_open(UDAT_MEDIUM,UDAT_NONE ,"en_US_CA", NULL, -1, NULL, 0, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error in creating the dateformat using medium time style and NO date style: %s\n", + myErrorName(status)); + return; + } + result =myFormatit(fmt, d); + if(!result) { + log_data_err("Fail: could not format - exitting test\n"); + return; + } + u_uastrcpy(temp, expect); + if (u_strcmp(result, temp)!=0){ + log_err("Fail: %s != %s\n", austrdup(result), expect); + } + else{ + log_verbose("Ok: %s == %s\n", austrdup(result), expect ); + } + + udat_close(fmt); + + ctest_resetTimeZone(); +} + +/*INTERNAL FUNCTION USED */ + +UChar* myFormatit(UDateFormat* datdef, UDate d1) +{ + UChar *result1=NULL; + int32_t resultlength, resultlengthneeded; + UErrorCode status = U_ZERO_ERROR; + + resultlength=0; + resultlengthneeded=udat_format(datdef, d1, NULL, resultlength, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + /*result1=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /*this leaks*/ + result1=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/ + udat_format(datdef, d1, result1, resultlength, NULL, &status); + } + if(U_FAILURE(status)) + { + log_err("FAIL: Error in formatting using udat_format(.....): %s\n", myErrorName(status)); + return 0; + } + + + return result1; + +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +/*eof*/ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h new file mode 100644 index 00000000000..18df92e5ed2 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h @@ -0,0 +1,50 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CDTRGTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*/ +/* REGRESSION TEST FOR DATE FORMAT */ +#ifndef _CDTFRRGSTST +#define _CDTFRRGSTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + + /** + * DateFormat Regresstion tests + **/ + + void Test4029195(void); + void Test4056591(void); + void Test4059917(void); + void Test4060212(void); + void Test4061287(void); + void Test4073003(void); + void Test4162071(void); + void Test714(void); + + /** + * test subroutine + **/ + void aux917(UDateFormat *fmt, UChar* str ); + + /** + * test subroutine used by the testing functions + **/ + UChar* myFormatit(UDateFormat* datdef, UDate d1); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c new file mode 100644 index 00000000000..650143fb1bc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c @@ -0,0 +1,123 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CESTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * CollationSpanishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "cestst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {0x0062/*'a'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000}, + {0x0045/*'E'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x006f/*'o'*/, 0x0074/*'t'*/, 0x0000}, + {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000}, + {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000}, + {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0063/*'c'*/, 0x0000}, + {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000}, +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {0x0062/*'a'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000}, + {0x0045/*'E'*/, 0x006d/*'m'*/, 0x0069/*'i'*/, 0x006f/*'o'*/, 0x0074/*'t'*/, 0x0000}, + {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'O'*/, 0x0000}, + {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0062/*'a'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000}, + {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000}, + {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'O'*/, 0x0000}, +}; + +const static UCollationResult results[] = { + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS, + /* test primary > 5*/ + UCOL_LESS, + UCOL_EQUAL, + UCOL_LESS, + UCOL_EQUAL +}; + + +void addSpanishCollTest(TestNode** root) +{ + + + addTest(root, &TestPrimary, "tscoll/cestst/TestPrimary"); + addTest(root, &TestTertiary, "tscoll/cestst/TestTertiary"); + +} + + +static void TestTertiary( ) +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("es_ES", &status); + if(U_FAILURE(status)){ + log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status)); + return; + } + log_verbose("Testing Spanish Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 5 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +static void TestPrimary() +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("es_ES", &status); + if(U_FAILURE(status)){ + log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status)); + return; + } + log_verbose("Testing Spanish Collation with Primary strength\n"); + ucol_setStrength(myCollation, UCOL_PRIMARY); + for (i = 5; i < 9; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h new file mode 100644 index 00000000000..e15f32d4875 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h @@ -0,0 +1,44 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CESTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationSpanishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CESCOLLTST +#define _CESCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + + +#define MAX_TOKEN_LEN 16 + + + /* perform test with strength SECONDARY */ + static void TestPrimary(void); + + /* perform test with strength TERTIARY */ + static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c new file mode 100644 index 00000000000..3ab68dfde1a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c @@ -0,0 +1,112 @@ +/******************************************************************** + * Copyright (c) 1997-2007, International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************** + * + * File CFINTST.C + * + * Modification History: + * Name Description + * Madhu Katragadda Ported for C API + ******************************************************************** + */ + +/** + * CollationFinnishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "cfintst.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000}, + {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000}, + {0x0061/*'a'*/, 0x00FC, 0x0062/*'b'*/, 0x0065/*'e'*/, 0x0063/*'c'*/, 0x006b/*'k'*/, 0x0000}, + {0x004c/*'L'*/, 0x00E5, 0x0076/*'v'*/, 0x0069/*'i'*/, 0x0000}, + {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000} +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000}, + {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0079/*'y'*/, 0x0000}, + {0x0061/*'a'*/, 0x0078/*'x'*/, 0x0062/*'b'*/, 0x0065/*'e'*/, 0x0063/*'c'*/, 0x006b/*'k'*/, 0x0000}, + {0x004c/*'L'*/, 0x00E4, 0x0077/*'w'*/, 0x0065/*'e'*/, 0x0000}, + {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000} +}; + +const static UCollationResult results[] = { + UCOL_GREATER, + UCOL_LESS, + UCOL_GREATER, + UCOL_LESS, + /* test primary > 4*/ + UCOL_EQUAL +}; + + + +void addFinnishCollTest(TestNode** root) +{ + + + addTest(root, &TestPrimary, "tscoll/cficoll/TestPrimary"); + addTest(root, &TestTertiary, "tscoll/cficoll/TestTertiary"); + + + +} + + +static void TestTertiary( ) +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("fi_FI@collation=standard", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + } + log_verbose("Testing Finnish Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 4 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +static void TestPrimary() +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("fi_FI@collation=standard", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + } + log_verbose("Testing Finnish Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_PRIMARY); + for (i = 4; i < 5; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h new file mode 100644 index 00000000000..4edd517611e --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h @@ -0,0 +1,43 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CFINTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationFinnishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CFINCOLLTST +#define _CFINCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + + +#define MAX_TOKEN_LEN 16 + + + /* perform test with strength SECONDARY*/ +static void TestPrimary(void); + + /* perform test with strength TERTIARY */ + static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c new file mode 100644 index 00000000000..cbbcf1ff54a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c @@ -0,0 +1,78 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation + * and others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CFORMTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ + +/* FormatTest is a medium top level test for everything in the C FORMAT API */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" +#include "cformtst.h" + +void addCalTest(TestNode**); +void addDateForTest(TestNode**); +void addDateTimePatternGeneratorTest(TestNode** root); +void addNumForTest(TestNode**); +void addMsgForTest(TestNode**); +void addDateForRgrTest(TestNode**); +void addNumFrDepTest(TestNode**); +void addDtFrDepTest(TestNode**); +void addUtmsTest(TestNode**); +void addCurrencyTest(TestNode**); + +void addFormatTest(TestNode** root); + +void addFormatTest(TestNode** root) +{ + addCalTest(root); + addDateForTest(root); + addDateTimePatternGeneratorTest(root); + addNumForTest(root); + addNumFrDepTest(root); + addMsgForTest(root); + addDateForRgrTest(root); + addDtFrDepTest(root); + addUtmsTest(root); + addCurrencyTest(root); +} +/*Internal functions used*/ + +UChar* myDateFormat(UDateFormat* dat, UDate d1) +{ + UChar *result1=NULL; + int32_t resultlength, resultlengthneeded; + UErrorCode status = U_ZERO_ERROR; + + + resultlength=0; + resultlengthneeded=udat_format(dat, d1, NULL, resultlength, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result1=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); + udat_format(dat, d1, result1, resultlength, NULL, &status); + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using udat_format(.....): %s\n", myErrorName(status)); + return 0; + } + return result1; + +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h new file mode 100644 index 00000000000..e5c0e44ccea --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h @@ -0,0 +1,33 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CFORMTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* FormatTest is a medium top level test for everything in the C FORMAT API */ + +#ifndef _CFORMATTST +#define _CFORMATTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" +#include "unicode/udat.h" + + +/* Internal fucntion used by all the test format files */ +UChar* myDateFormat(UDateFormat *dat, UDate d); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c new file mode 100644 index 00000000000..63a01284f85 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c @@ -0,0 +1,335 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CFRTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * CollationFrenchTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "cfrtst.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = +{ + {0x0061/*'a'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, + {0x0043/*'C'*/, 0x004f/*'O'*/, 0x0054/*'T'*/, 0x0045/*'E'*/, 0x0000}, + {0x0063/*'c'*/, 0x006f/*'o'*/, 0x002d/*'-'*/, 0x006f/*'o'*/, 0x0070/*'p'*/, 0x0000}, + {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0000}, + {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000}, + {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000}, + {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000}, + {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000}, + {0x01f1, 0x0000}, + {0xfb00, 0x0000}, + {0x01fa, 0x0000}, + {0x0101, 0x0000} +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = +{ + {0x0041/*'A'*/, 0x0042/*'B'*/, 0x0043/*'C'*/, 0x0000}, + {0x0063/*'c'*/, 0x00f4, 0x0074/*'t'*/, 0x0065/*'e'*/, 0x0000}, + {0x0043/*'C'*/, 0x004f/*'O'*/, 0x004f/*'O'*/, 0x0050/*'P'*/, 0x0000}, + {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x00E9, 0x0000}, + {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x00E9, 0x0000}, + {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0000}, + {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000}, + {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x004f/*'O'*/, 0x0000}, + {0x01ee, 0x0000}, + {0x25ca, 0x0000}, + {0x00e0, 0x0000}, + {0x01df, 0x0000} +}; + +const static UCollationResult results[] = +{ + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, /*UCOL_GREATER,*/ + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_LESS, + UCOL_GREATER, + UCOL_LESS, /*UCOL_GREATER,*/ + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS +}; + +/* 0x0300 is grave, 0x0301 is acute*/ +/* the order of elements in this array must be different than the order in CollationEnglishTest*/ +const static UChar testAcute[][MAX_TOKEN_LEN] = +{ +/*00*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0000}, +/*01*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0000}, +/*02*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0000}, +/*03*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0000}, +/*04*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0000}, +/*05*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0301, 0x0000}, +/*06*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0000}, +/*07*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0000}, +/*08*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0000}, +/*09*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0000}, +/*0a*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000}, +/*0b*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000}, +/*0c*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000}, +/*0d*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000}, +/*0e*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000}, +/*0f*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0300, 0x0000}, +/*10*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0000}, +/*11*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0000}, +/*12*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0000}, +/*13*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0000}, +/*14*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000}, +/*15*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000}, +/*16*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000}, +/*17*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000}, +/*18*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000} +}; + +const static UChar testBugs[][MAX_TOKEN_LEN] = +{ + {0x0061/*'a'*/, 0x000}, + {0x0041/*'A'*/, 0x000}, + {0x0065/*'e'*/, 0x000}, + {0x0045/*'E'*/, 0x000}, + {0x00e9, 0x000}, + {0x00e8, 0x000}, + {0x00ea, 0x000}, + {0x00eb, 0x000}, + {0x0065/*'e'*/, 0x0061/*'a'*/, 0x000}, + {0x0078/*'x'*/, 0x000} +}; + + +static void TestGetSortKey(void); + + +void addFrenchCollTest(TestNode** root) +{ + addTest(root, &TestSecondary, "tscoll/cfrtst/TestSecondary"); + addTest(root, &TestTertiary, "tscoll/cfrtst/TestTertiary"); + addTest(root, &TestExtra, "tscoll/cfrtst/TestExtra"); + addTest(root, &TestGetSortKey, "tscoll/cfrtst/TestGetSortKey"); +} + + +static void TestTertiary( ) +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("fr_FR", &status); + if(U_FAILURE(status) || !myCollation){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + + ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing French Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_QUATERNARY); + for (i = 0; i < 12 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +static void TestSecondary() +{ + int32_t i,j, testAcuteSize; + UCollationResult expected=UCOL_EQUAL; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("fr_FR", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_SECONDARY, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing French Collation with Secondary strength\n"); + /*test acute and grave ordering (compare to french collation)*/ + testAcuteSize = sizeof(testAcute) / sizeof(testAcute[0]); + for (i = 0; i < testAcuteSize; i++) + { + for (j = 0; j < testAcuteSize; j++) + { + if (i < j) expected = UCOL_LESS; + if (i == j) expected = UCOL_EQUAL; + if (i > j) expected = UCOL_GREATER; + doTest(myCollation, testAcute[i], testAcute[j], expected ); + } + } + ucol_close(myCollation); +} + +static void TestExtra() +{ + int32_t i, j; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("fr_FR", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing French Collation extra with secondary strength\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 9 ; i++) + { + for (j = i + 1; j < 10; j += 1) + { + doTest(myCollation, testBugs[i], testBugs[j], UCOL_LESS); + } + } + ucol_close(myCollation); +} + +static void TestGetSortKey() { + /* This is meant to test a buffer reallocation crash while using + French secondary sorting with a large buffer. + The fact that Japanese characters are used is irrelevant. */ + static const UChar pucUTF16[] = { + 0x3049,0x30b9,0x3088,0xfffd,0xfffd,0x308f,0xfffd,0x3042, + 0xfffd,0xfffd,0x305e,0xfffd,0x30b6,0x30bb,0x305b,0x30b1, + 0x3050,0x30af,0x304e,0x30bd,0xfffd,0x30c6,0xfffd,0xfffd, + 0x30e1,0xfffd,0xfffd,0x30d9,0xfffd,0x3092,0x3075,0x304a, + 0x3074,0x3070,0x30f5,0x30c4,0x306e,0x30df,0x3053,0xfffd, + 0x30a6,0x30b6,0x30e0,0xfffd,0x30bc,0x30ef,0x3087,0x30cc, + 0x305f,0x30de,0xfffd,0x3090,0x3063,0x30dc,0x30b6,0x30b9, + 0x30d2,0x3072,0x3061,0xfffd,0xfffd,0xfffd,0x307b,0x3092, + 0x30a5,0x30a9,0x30b1,0x30e7,0xfffd,0xfffd,0xfffd,0xfffd, + 0xfffd,0x305e,0xfffd,0x30c7,0x30ae,0x305b,0x308b,0x30c0, + 0x30f5,0xfffd,0xfffd,0xfffd,0x307d,0x304e,0xfffd,0xfffd, + 0x30c0,0x30c8,0x306f,0x307a,0x30dd,0x30e4,0x3084,0xfffd, + 0x308c,0x30f1,0xfffd,0x30c6,0xfffd,0x307a,0xfffd,0x3052, + 0x3056,0x305d,0x30b7,0xfffd,0x305b,0x30b0,0x30b9,0xfffd, + 0x30b2,0x306d,0x3044,0xfffd,0x3073,0xfffd,0x30be,0x30cf, + 0x3080,0xfffd,0x30a8,0x30f5,0x30a5,0x30c7,0x307c,0xfffd, + 0x30d1,0x305f,0x30b2,0xfffd,0x3053,0x30ca,0xfffd,0x30dd, + 0x3058,0x30c0,0x305d,0x30e1,0xfffd,0x30bb,0x305f,0x30d1, + 0x30f2,0x3058,0x3086,0x30ce,0x30db,0x30cb,0x30e9,0xfffd, + 0x308c,0xfffd,0xfffd,0x30af,0x30c4,0x3076,0x304c,0x30f5, + 0x30e8,0x308c,0xfffd,0x30e2,0x3073,0x30a3,0x304e,0x30ea, + 0xfffd,0x304f,0xfffd,0x306c,0x3044,0xfffd,0xfffd,0x30c9, + 0xfffd,0x30f5,0xfffd,0xfffd,0xfffd,0x30eb,0x30a8,0xfffd, + 0x306d,0x307d,0x30d8,0x3069,0xfffd,0xfffd,0x3086,0x30a9, + 0xfffd,0x3076,0x30e9,0x30cc,0x3074,0x30e0,0xfffd,0xfffd, + 0xfffd,0x30f0,0x3086,0x30ac,0x3076,0x3068,0x30c7,0xfffd, + 0x30b7,0x30d2,0x3048,0x308e,0x30e8,0x30d9,0x30ce,0x30d0, + 0x308b,0x30ee,0x30e6,0x3079,0x30f3,0x30af,0xfffd,0x3079, + 0xfffd,0xfffd,0x30ca,0x30bf,0xfffd,0x30b5,0xfffd,0xfffd, + 0x3093,0xfffd,0x30ba,0xfffd,0x3076,0x3047,0x304a,0xfffd, + 0xfffd,0x3086,0xfffd,0x3081,0xfffd,0x30f6,0x3066,0xfffd, + 0xfffd,0x30b6,0x30ef,0x30e2,0x30bf,0xfffd,0x3053,0x304a, + 0xfffd,0xfffd,0x304a,0x30e8,0xfffd,0x30e2,0xfffd,0xfffd, + 0x305c,0x3081,0x30c6,0xfffd,0x3091,0x3046,0x306a,0x3059, + 0xfffd,0xfffd,0x30dd,0x30d1,0x308a,0x30ee,0xfffd,0xfffd, + 0x308a,0x3042,0x30da,0xfffd,0x3064,0x30ef,0x305c,0x306b, + 0xfffd,0x30ca,0x3085,0x3067,0x30ea,0x30c2,0x30c8,0xfffd, + 0x30f5,0xfffd,0xfffd,0xfffd,0x30ca,0xfffd,0x3050,0x30f1, + 0x3050,0x3053,0x3072,0xfffd,0xfffd,0xfffd,0x3074,0xfffd, + 0x304b,0x30dd,0x306d,0xfffd,0x3049,0x30a1,0x30cc,0x30de, + 0x30ae,0x307b,0x308a,0xfffd,0x3065,0xfffd,0xfffd,0x30c0, + 0xfffd,0x3048,0x30dc,0x304f,0x3085,0x3059,0x304b,0x30d3, + 0x30eb,0x30a4,0x3073,0xfffd,0x30ba,0x308f,0x30a7,0x30c3, + 0x3074,0x30cf,0x306c,0x3053,0x30c0,0xfffd,0x3066,0xfffd, + 0x308f,0xfffd,0x30b5,0xfffd,0x3092,0x30c4,0xfffd,0x30d6, + 0x3056,0x30ad,0x30d2,0x30ba,0xfffd,0x30e6,0x304c,0x3088, + 0x30b6,0x3048,0x3077,0x30d1,0xfffd,0x3050,0xfffd,0x3042, + 0xfffd,0xfffd,0x308f,0xfffd,0x30c1,0xfffd,0x3074,0x3061, + 0x3056,0x30e5,0xfffd,0xfffd,0x3057,0xfffd,0xfffd,0xfffd, + 0xfffd,0x30bd,0x30b3,0x30ee,0xfffd,0x30f2,0x3084,0x3050, + 0xfffd,0x30e7,0xfffd,0xfffd,0x3060,0x3049,0x30f2,0x30ad, + 0x30bf,0x30f1,0x30a2,0xfffd,0x30af,0xfffd,0x3060,0x30a1, + 0x30e9,0x30c3,0xfffd,0x3072,0x3093,0x3070,0xfffd,0x308f, + 0x3060,0xfffd,0x3067,0x306f,0x3082,0x308b,0x3051,0xfffd, + 0x3058,0xfffd,0xfffd,0x30a8,0x3051,0x3054,0x30ad,0x30f0, + 0x3053,0xfffd,0x30e1,0x30d7,0x308d,0x307f,0x30be,0x30b0, + 0xfffd,0x30db,0xfffd,0x30d1,0xfffd,0x3054,0x30a5,0xfffd, + 0x306a,0xfffd,0x305c,0xfffd,0x3052,0x3088,0xfffd,0x306e, + 0xfffd,0x30a9,0x30a1,0x30b4,0x3083,0x30bd,0xfffd,0xfffd, + 0x306a,0x3070,0x30cd,0xfffd,0x3072,0x30ed,0x30c6,0x30be, + 0x30c4,0x305e,0x30b3,0x30e1,0x308a,0xfffd,0x305b,0xfffd, + 0x3042,0x3088,0xfffd,0x304c,0xfffd,0x3089,0x3071,0xfffd, + 0xfffd,0x30c6,0x3062,0x3079,0xfffd,0x304b,0x304a,0xfffd, + 0x30ad,0x3045,0x3045,0x3087,0xfffd,0x306a,0x308b,0x0000, + 0x30bd,0x3065,0x30b8,0x3086,0x30d3,0x3076,0xfffd,0xfffd, + 0x308f,0x3053,0x307c,0x3053,0x3084,0x30ae,0x30c4,0x3045, + 0x30a8,0x30d0,0x30e1,0x308c,0x30e6,0x30b7,0xfffd,0xfffd, + 0xfffd,0x3046,0x305f,0xfffd,0x3086,0x30ab,0xfffd,0xfffd, + 0x30c8,0xfffd,0x30a1,0x3052,0x3059,0xfffd,0x30a4,0xfffd, + 0xfffd,0x308c,0x3085,0x30ab,0x30b5,0x3091,0x30bf,0x30e3, + 0xfffd,0xfffd,0x3087,0xfffd,0x30f6,0x3051,0x30bd,0x3092, + 0x3063,0xfffd,0x30a9,0x3063,0x306e,0xfffd,0xfffd,0xfffd, + 0x306c,0xfffd,0x307e,0x30ad,0x3077,0x30c2,0x30e9,0x30d5, + 0xfffd,0xfffd,0x30c6,0x305c,0xfffd,0xfffd,0x3089,0xfffd, + 0x3048,0x30cb,0x308c,0xfffd,0xfffd,0x3044,0xfffd,0x3080, + 0x3063,0x3079,0xfffd,0x308a,0x30cb,0x3042,0x3057,0xfffd, + 0x307c,0x30c1,0x30a8,0x30cf,0xfffd,0x3083,0xfffd,0xfffd, + 0x306c,0xfffd,0x305e,0x3092,0xfffd,0x30dc,0x30b0,0x3081, + 0x30e3,0x30f0,0x304e,0x30cc,0x308e,0x30c4,0x30ad + }; + + UErrorCode status = U_ZERO_ERROR; + UCollator *pCollator; + int32_t lenActualSortKey; + uint8_t pucSortKey[4096]; + static const int32_t LENSORTKEY = (int32_t)sizeof(pucSortKey); + + ucol_prepareShortStringOpen("LFR_AN_CX_EX_FO_HX_NX_S3", 0, NULL, &status); + + pCollator = ucol_openFromShortString("LFR_AN_CX_EX_FO_HX_NX_S3", 0, NULL, &status); + + if (U_FAILURE(status)) { + log_err("error opening collator\n"); + return; + } + + lenActualSortKey = ucol_getSortKey(pCollator, + (const UChar *)pucUTF16, + sizeof(pucUTF16) / sizeof(pucUTF16[0]), + pucSortKey, + LENSORTKEY); + + if (lenActualSortKey > LENSORTKEY) { + log_err("sort key too big for original buffer. Got: %d Expected: %d\n", lenActualSortKey, LENSORTKEY); + return; + } + /* If the test didn't crash, then the test succeeded. */ + ucol_close(pCollator); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h new file mode 100644 index 00000000000..1fe136a3f88 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h @@ -0,0 +1,44 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CFRTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationFrenchTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CFRCOLLTST +#define _CFRCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 + + /* performs Extra tests*/ + static void TestExtra(void); + + /* perform test with strength SECONDARY*/ + static void TestSecondary(void); + + /*perform test with strength TERTIARY*/ +static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c new file mode 100644 index 00000000000..a493450ee6c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c @@ -0,0 +1,310 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CG7COLL.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * G7CollationTest is a third level test class. This test performs the examples + * mentioned on the IBM Java international demos web site. + * Sample Rules: & Z < p , P + * Effect : Making P sort after Z. + * + * Sample Rules: & c < ch , cH, Ch, CH + * Effect : As well as adding sequences of characters that act as a single character (this is + * known as contraction), you can also add characters that act like a sequence of + * characters (this is known as expansion). + * + * Sample Rules: & Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&' + * Effect : Expansion and contraction can actually be combined. + * + * Sample Rules: & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' + * Effect : sorted sequence as the following, + * aardvark + * a-rdvark + * abbot + * coop + * co-p + * cop + */ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "cg7coll.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "unicode/ustring.h" + + +const char* locales[8] = { + "en_US", + "en_GB", + "en_CA", + "fr_FR", + "fr_CA", + "de_DE", + "it_IT", + "ja_JP" +}; + + + +const static UChar testCases[][MAX_TOKEN_LEN] = { + { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/, + 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073 /*'s'*/, 0x0000}, /* 9 */ + { 0x0050 /*'P'*/, 0x0061 /*'a'*/, 0x0074/*'t'*/, 0x0000}, /* 1 */ + { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x00E9, 0x0000}, /* 2 */ + { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0000}, /* 3 */ + { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000}, /* 4 */ + { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000}, /* 5 */ + { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0064 /*'d'*/, 0x0000}, /* 6 */ + { 0x0054 /*'T'*/, 0x00F6, 0x006e /*'n'*/, 0x0065 /*'e'*/, 0x0000}, /* 7 */ + { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0066 /*'f'*/, 0x0075 /*'u'*/, 0x0000}, /* 8 */ + { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/, + 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000}, /* 12 */ + { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x006e /*'n'*/, 0x0000}, /* 10 */ + { 0x0050 /*'P'*/, 0x0041 /*'A'*/, 0x0054 /*'T'*/, 0x0000}, /* 11 */ + { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/, + 0x002d /*'-'*/, 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000}, /* 13 */ + { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/, + 0x002d /*'-'*/, 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073/*'s'*/, 0x0000}, /* 0 */ + {0x0070 /*'p'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x0000}, /* 14 */ + /* Additional tests */ + { 0x0063 /*'c'*/, 0x007a /*'z'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0000 }, /* 15 */ + { 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0075 /*'u'*/, 0x0072 /*'r'*/, 0x006f /*'o'*/, 0x0000 }, /* 16 */ + { 0x0063 /*'c'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x000 }, /* 17 */ + { 0x0064 /*'d'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x006e /*'n'*/, 0x0000 }, /* 18 */ + { 0x003f /*'?'*/, 0x0000 }, /* 19 */ + { 0x0071 /*'q'*/, 0x0075 /*'u'*/, 0x0069 /*'i'*/, 0x0063 /*'c'*/, 0x006b /*'k'*/, 0x0000 }, /* 20 */ + { 0x0023 /*'#'*/, 0x0000 }, /* 21 */ + { 0x0026 /*'&'*/, 0x0000 }, /* 22 */ + { 0x0061 /*'a'*/, 0x002d /*'-'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/, + 0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000}, /* 24 */ + { 0x0061 /*'a'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/, + 0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000}, /* 23 */ + { 0x0061 /*'a'*/, 0x0062 /*'b'*/, 0x0062 /*'b'*/, 0x006f /*'o'*/, 0x0074 /*'t'*/, 0x0000}, /* 25 */ + { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x002d /*'-'*/, 0x0070 /*'p'*/, 0x0000}, /* 27 */ + { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x0070 /*'p'*/, 0x0000}, /* 28 */ + { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x006f /*'o'*/, 0x0070 /*'p'*/, 0x0000}, /* 26 */ + { 0x007a /*'z'*/, 0x0065 /*'e'*/, 0x0062 /*'b'*/, 0x0072 /*'r'*/, 0x0061 /*'a'*/, 0x0000} /* 29 */ +}; + +const static int32_t results[TESTLOCALES][TOTALTESTSET] = { + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_US */ + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_GB */ + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_CA */ + { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_FR */ + { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_CA */ + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* de_DE */ + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* it_IT */ + { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* ja_JP */ + /* new table collation with rules "& Z < p, P" loop to FIXEDTESTSET */ + { 12, 13, 9, 0, 6, 8, 10, 7, 14, 1, 11, 2, 3, 4, 5, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, + /* new table collation with rules "& C < ch , cH, Ch, CH " loop to TOTALTESTSET */ + { 19, 22, 21, 23, 24, 25, 12, 13, 9, 0, 17, 26, 28, 27, 15, 16, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 }, + /* new table collation with rules "& Question-mark ; ? & Hash-mark ; # & Ampersand ; '&' " loop to TOTALTESTSET */ + { 23, 24, 25, 22, 12, 13, 9, 0, 17, 16, 26, 28, 27, 15, 18, 21, 14, 1, 11, 2, 3, 4, 5, 19, 20, 6, 8, 10, 7, 29 }, + /* analogous to Japanese rules " & aa ; a- & ee ; e- & ii ; i- & oo ; o- & uu ; u- " */ /* loop to TOTALTESTSET */ + { 19, 22, 21, 24, 23, 25, 12, 13, 9, 0, 17, 16, 28, 26, 27, 15, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 } +}; + +void addRuleBasedCollTest(TestNode** root) +{ + addTest(root, &TestG7Locales, "tscoll/cg7coll/TestG7Locales"); + addTest(root, &TestDemo1, "tscoll/cg7coll/TestDemo1"); + addTest(root, &TestDemo2, "tscoll/cg7coll/TestDemo2"); + addTest(root, &TestDemo3, "tscoll/cg7coll/TestDemo3"); + addTest(root, &TestDemo4, "tscoll/cg7coll/TestDemo4"); + + +} + +static void TestG7Locales() +{ + UCollator *myCollation, *tblColl1; + UErrorCode status = U_ZERO_ERROR; + const UChar *defRules; + int32_t i, rlen, j, n; + log_verbose("Testing ucol_openRules for all the locales\n"); + for (i = 0; i < 8; i++) + { + status = U_ZERO_ERROR; + myCollation = ucol_open(locales[i], &status); + ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_QUATERNARY, &status); + ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + + if (U_FAILURE(status)) + { + log_err("Error in creating collator in %s: %s\n", locales[i], myErrorName(status)); + continue; + } + + defRules = ucol_getRules(myCollation, &rlen); + status = U_ZERO_ERROR; + tblColl1 = ucol_openRules(defRules, rlen, UCOL_OFF, + UCOL_DEFAULT_STRENGTH,NULL, &status); + if (U_FAILURE(status)) + { + + log_err("Error in creating collator in %s: %s\n", locales[i], myErrorName(status)); + continue; + } + + + log_verbose("Locale %s\n", locales[i]); + log_verbose(" tests start...\n"); + + j = 0; + n = 0; + for (j = 0; j < FIXEDTESTSET; j++) + { + for (n = j+1; n < FIXEDTESTSET; n++) + { + doTest(tblColl1, testCases[results[i][j]], testCases[results[i][n]], UCOL_LESS); + } + } + + ucol_close(myCollation); + ucol_close(tblColl1); + } +} + +static void TestDemo1() +{ + UCollator *myCollation; + int32_t j, n; + const char *rules = "& Z < p, P"; + int32_t len=(int32_t)strlen(rules); + UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1)); + UErrorCode status = U_ZERO_ERROR; + u_uastrcpy(temp, rules); + + log_verbose("Demo Test 1 : Create a new table collation with rules \" & Z < p, P \" \n"); + + myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + + if (U_FAILURE(status)) + { + log_err( "Demo Test 1 Rule collation object creation failed. : %s\n", myErrorName(status)); + return; + } + + for (j = 0; j < FIXEDTESTSET; j++) + { + for (n = j+1; n < FIXEDTESTSET; n++) + { + doTest(myCollation, testCases[results[8][j]], testCases[results[8][n]], UCOL_LESS); + } + } + + ucol_close(myCollation); + free(temp); +} + +static void TestDemo2() +{ + UCollator *myCollation; + int32_t j, n; + const char *rules = "& C < ch , cH, Ch, CH"; + int32_t len=(int32_t)strlen(rules); + UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1)); + UErrorCode status = U_ZERO_ERROR; + u_uastrcpy(temp, rules); + + log_verbose("Demo Test 2 : Create a new table collation with rules \"& C < ch , cH, Ch, CH\""); + + myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + + if (U_FAILURE(status)) + { + log_err( "Demo Test 2 Rule collation object creation failed.: %s\n", myErrorName(status)); + return; + } + for (j = 0; j < TOTALTESTSET; j++) + { + for (n = j+1; n < TOTALTESTSET; n++) + { + doTest(myCollation, testCases[results[9][j]], testCases[results[9][n]], UCOL_LESS); + } + } + ucol_close(myCollation); + free(temp); +} + +static void TestDemo3() +{ + UCollator *myCollation; + int32_t j, n; + const char *rules = "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'"; + int32_t len=(int32_t)strlen(rules); + UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1)); + UErrorCode status = U_ZERO_ERROR; + u_uastrcpy(temp, rules); + + log_verbose("Demo Test 3 : Create a new table collation with rules \"& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'\" \n"); + + myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + + if (U_FAILURE(status)) + { + log_err( "Demo Test 3 Rule collation object creation failed.: %s\n", myErrorName(status)); + return; + } + + for (j = 0; j < TOTALTESTSET; j++) + { + for (n = j+1; n < TOTALTESTSET; n++) + { + doTest(myCollation, testCases[results[10][j]], testCases[results[10][n]], UCOL_LESS); + } + } + ucol_close(myCollation); + free(temp); +} + +static void TestDemo4() +{ + UCollator *myCollation; + int32_t j, n; + const char *rules = " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' "; + int32_t len=(int32_t)strlen(rules); + UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1)); + UErrorCode status = U_ZERO_ERROR; + u_uastrcpy(temp, rules); + + log_verbose("Demo Test 4 : Create a new table collation with rules \" & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' \"\n"); + + myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + + if (U_FAILURE(status)) + { + log_err( "Demo Test 4 Rule collation object creation failed.: %s\n", myErrorName(status)); + return; + } + for (j = 0; j < TOTALTESTSET; j++) + { + for (n = j+1; n < TOTALTESTSET; n++) + { + doTest(myCollation, testCases[results[11][j]], testCases[results[11][n]], UCOL_LESS); + } + } + ucol_close(myCollation); + free(temp); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h new file mode 100644 index 00000000000..d45461cdb12 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h @@ -0,0 +1,71 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CG7COLL.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * G7CollationTest is a third level test class. This test performs the examples + * mentioned on the IBM Java international demos web site. + * Sample Rules: & Z < p , P + * Effect : Making P sort after Z. + * + * Sample Rules: & c < ch , cH, Ch, CH + * Effect : As well as adding sequences of characters that act as a single character (this is + * known as contraction), you can also add characters that act like a sequence of + * characters (this is known as expansion). + * + * Sample Rules: & Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&' + * Effect : Expansion and contraction can actually be combined. + * + * Sample Rules: & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' + * Effect : sorted sequence as the following, + * aardvark + * a-rdvark + * abbot + * coop + * co-p + * cop + */ + +#ifndef _CG7COLLTST +#define _CG7COLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 +#define TESTLOCALES 12 +#define FIXEDTESTSET 15 +#define TOTALTESTSET 30 + + /* perform test for G7 locales */ + static void TestG7Locales(void); + + /* perform test with added rules " & Z < p, P" */ + static void TestDemo1(void); + + /* perorm test with added rules "& C < ch , cH, Ch, CH" */ + static void TestDemo2(void); + + /* perform test with added rules */ + /* "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'" */ + static void TestDemo3(void); + + /* perform test with added rules */ + /* " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' " */ + static void TestDemo4(void); + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c new file mode 100644 index 00000000000..c70ae2bca5d --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c @@ -0,0 +1,384 @@ +/* +******************************************************************************* +* Copyright (C) 2000-2005, International Business Machines +* Corporation and others. All Rights Reserved. +******************************************************************************* +* Date Name Description +* 03/22/00 aliu Creation. +* 07/13/00 Madhu Added more tests +******************************************************************************* +*/ + +#include "cintltst.h" +#include "uhash.h" +#include "unicode/ctest.h" +#include "unicode/ustring.h" +#include "cstring.h" + +/********************************************************************** + * Prototypes + *********************************************************************/ + +static void TestBasic(void); +static void TestOtherAPI(void); +static void hashIChars(void); + +static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key); + +static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2); + +static void _put(UHashtable* hash, + const char* key, + int32_t value, + int32_t expectedOldValue); + +static void _get(UHashtable* hash, + const char* key, + int32_t expectedValue); + +static void _remove(UHashtable* hash, + const char* key, + int32_t expectedValue); + +void addHashtableTest(TestNode** root); + +/********************************************************************** + * UHashTok wrapper functions + *********************************************************************/ + +static UBool +_compareChars(void* a, void* b) { + UHashTok s, t; + s.pointer = a; + t.pointer = b; + return uhash_compareChars(s, t); +} + +static UBool +_compareIChars(void* a, void* b) { + UHashTok s, t; + s.pointer = a; + t.pointer = b; + return uhash_compareIChars(s, t); +} + +static UBool +_compareUChars(void* a, void* b) { + UHashTok s, t; + s.pointer = a; + t.pointer = b; + return uhash_compareUChars(s, t); +} + +static UBool +_compareLong(int32_t a, int32_t b) { + UHashTok s, t; + s.integer = a; + t.integer = b; + return uhash_compareLong(s, t); +} + +/********************************************************************** + * FW Registration + *********************************************************************/ + +void addHashtableTest(TestNode** root) { + + addTest(root, &TestBasic, "tsutil/chashtst/TestBasic"); + addTest(root, &TestOtherAPI, "tsutil/chashtst/TestOtherAPI"); + addTest(root, &hashIChars, "tsutil/chashtst/hashIChars"); + +} + +/********************************************************************** + * Test Functions + *********************************************************************/ + +static void TestBasic(void) { + static const char one[4] = {0x6F, 0x6E, 0x65, 0}; /* "one" */ + static const char one2[4] = {0x6F, 0x6E, 0x65, 0}; /* Get around compiler optimizations */ + static const char two[4] = {0x74, 0x77, 0x6F, 0}; /* "two" */ + static const char three[6] = {0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* "three" */ + static const char omega[6] = {0x6F, 0x6D, 0x65, 0x67, 0x61, 0}; /* "omega" */ + UErrorCode status = U_ZERO_ERROR; + UHashtable *hash; + + hash = uhash_open(hashChars, isEqualChars, NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n", + u_errorName(status), hash); + return; + } + if (hash == NULL) { + log_err("FAIL: uhash_open returned NULL\n"); + return; + } + log_verbose("Ok: uhash_open returned 0x%08X\n", hash); + + _put(hash, one, 1, 0); + _put(hash, omega, 24, 0); + _put(hash, two, 2, 0); + _put(hash, three, 3, 0); + _put(hash, one, -1, 1); + _put(hash, two, -2, 2); + _put(hash, omega, 48, 24); + _put(hash, one, 100, -1); + _get(hash, three, 3); + _remove(hash, two, -2); + _get(hash, two, 0); + _get(hash, one, 100); + _put(hash, two, 200, 0); + _get(hash, omega, 48); + _get(hash, two, 200); + + if(_compareChars((void*)one, (void*)three) == TRUE || + _compareChars((void*)one, (void*)one2) != TRUE || + _compareChars((void*)one, (void*)one) != TRUE || + _compareChars((void*)one, NULL) == TRUE ) { + log_err("FAIL: compareChars failed\n"); + } + if(_compareIChars((void*)one, (void*)three) == TRUE || + _compareIChars((void*)one, (void*)one) != TRUE || + _compareIChars((void*)one, (void*)one2) != TRUE || + _compareIChars((void*)one, NULL) == TRUE ) { + log_err("FAIL: compareIChars failed\n"); + } + + uhash_close(hash); + +} + +static void TestOtherAPI(void){ + + UErrorCode status = U_ZERO_ERROR; + UHashtable *hash; + + /* Use the correct type when cast to void * */ + static const UChar one[4] = {0x006F, 0x006E, 0x0065, 0}; /* L"one" */ + static const UChar one2[4] = {0x006F, 0x006E, 0x0065, 0}; /* Get around compiler optimizations */ + static const UChar two[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */ + static const UChar two2[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */ + static const UChar three[6] = {0x0074, 0x0068, 0x0072, 0x0065, 0x0065, 0}; /* L"three" */ + static const UChar four[6] = {0x0066, 0x006F, 0x0075, 0x0072, 0}; /* L"four" */ + static const UChar five[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */ + static const UChar five2[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */ + + hash = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n", + u_errorName(status), hash); + return; + } + if (hash == NULL) { + log_err("FAIL: uhash_open returned NULL\n"); + return; + } + log_verbose("Ok: uhash_open returned 0x%08X\n", hash); + + uhash_puti(hash, (void*)one, 1, &status); + if(uhash_count(hash) != 1){ + log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash)); + } + if(uhash_find(hash, (void*)two) != NULL){ + log_err("FAIL: uhash_find failed\n"); + } + uhash_puti(hash, (void*)two, 2, &status); + uhash_puti(hash, (void*)three, 3, &status); + uhash_puti(hash, (void*)four, 4, &status); + uhash_puti(hash, (void*)five, 5, &status); + + if(uhash_count(hash) != 5){ + log_err("FAIL: uhas_count() failed. Expected: 5, Got: %d\n", uhash_count(hash)); + } + + if(uhash_geti(hash, (void*)two2) != 2){ + log_err("FAIL: uhash_geti failed\n"); + } + + if(uhash_find(hash, (void*)two2) == NULL){ + log_err("FAIL: uhash_find of \"two\" failed\n"); + } + + if(uhash_removei(hash, (void*)five2) != 5){ + log_err("FAIL: uhash_remove() failed\n"); + } + if(uhash_count(hash) != 4){ + log_err("FAIL: uhas_count() failed. Expected: 4, Got: %d\n", uhash_count(hash)); + } + + uhash_put(hash, (void*)one, NULL, &status); + if(uhash_count(hash) != 3){ + log_err("FAIL: uhash_put() with value=NULL didn't remove the key value pair\n"); + } + status=U_ILLEGAL_ARGUMENT_ERROR; + uhash_puti(hash, (void*)one, 1, &status); + if(uhash_count(hash) != 3){ + log_err("FAIL: uhash_put() with value!=NULL should fail when status != U_ZERO_ERROR \n"); + } + + status=U_ZERO_ERROR; + uhash_puti(hash, (void*)one, 1, &status); + if(uhash_count(hash) != 4){ + log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n"); + } + + if(_compareUChars((void*)one, (void*)two) == TRUE || + _compareUChars((void*)one, (void*)one) != TRUE || + _compareUChars((void*)one, (void*)one2) != TRUE || + _compareUChars((void*)one, NULL) == TRUE ) { + log_err("FAIL: compareUChars failed\n"); + } + + uhash_removeAll(hash); + if(uhash_count(hash) != 0){ + log_err("FAIL: uhas_count() failed. Expected: 0, Got: %d\n", uhash_count(hash)); + } + + uhash_setKeyComparator(hash, uhash_compareLong); + uhash_setKeyHasher(hash, uhash_hashLong); + uhash_iputi(hash, 1001, 1, &status); + uhash_iputi(hash, 1002, 2, &status); + uhash_iputi(hash, 1003, 3, &status); + if(_compareLong(1001, 1002) == TRUE || + _compareLong(1001, 1001) != TRUE || + _compareLong(1001, 0) == TRUE ) { + log_err("FAIL: compareLong failed\n"); + } + /*set the resize policy to just GROW and SHRINK*/ + /*how to test this??*/ + uhash_setResizePolicy(hash, U_GROW_AND_SHRINK); + uhash_iputi(hash, 1004, 4, &status); + uhash_iputi(hash, 1005, 5, &status); + uhash_iputi(hash, 1006, 6, &status); + if(uhash_count(hash) != 6){ + log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash)); + } + if(uhash_iremovei(hash, 1004) != 4){ + log_err("FAIL: uhash_remove failed\n"); + } + if(uhash_iremovei(hash, 1004) != 0){ + log_err("FAIL: uhash_remove failed\n"); + } + + uhash_removeAll(hash); + uhash_iput(hash, 2004, (void*)one, &status); + uhash_iput(hash, 2005, (void*)two, &status); + if(uhash_count(hash) != 2){ + log_err("FAIL: uhash_count() failed. Expected: 2, Got: %d\n", uhash_count(hash)); + } + if(uhash_iremove(hash, 2004) != (void*)one){ + log_err("FAIL: uhash_remove failed\n"); + } + if(uhash_iremove(hash, 2004) != NULL){ + log_err("FAIL: uhash_remove failed\n"); + } + if(uhash_count(hash) != 1){ + log_err("FAIL: uhash_count() failed. Expected: 1, Got: %d\n", uhash_count(hash)); + } + + uhash_close(hash); + +} + +static void hashIChars(void) { + static const char which[] = "which"; + static const char WHICH2[] = "WHICH"; + static const char where[] = "where"; + UErrorCode status = U_ZERO_ERROR; + UHashtable *hash; + + hash = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n", + u_errorName(status), hash); + return; + } + if (hash == NULL) { + log_err("FAIL: uhash_open returned NULL\n"); + return; + } + log_verbose("Ok: uhash_open returned 0x%08X\n", hash); + + _put(hash, which, 1, 0); + _put(hash, WHICH2, 2, 1); + _put(hash, where, 3, 0); + if(uhash_count(hash) != 2){ + log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash)); + } + _remove(hash, which, 2); + + uhash_close(hash); +} + + +/********************************************************************** + * uhash Callbacks + *********************************************************************/ + +/** + * This hash function is designed to collide a lot to test key equality + * resolution. It only uses the first char. + */ +static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key) { + return *(const char*) key.pointer; +} + +static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2) { + return (UBool)((key1.pointer != NULL) && + (key2.pointer != NULL) && + (uprv_strcmp((const char*)key1.pointer, (const char*)key2.pointer) == 0)); +} + +/********************************************************************** + * Wrapper Functions + *********************************************************************/ + +static void _put(UHashtable* hash, + const char* key, + int32_t value, + int32_t expectedOldValue) { + UErrorCode status = U_ZERO_ERROR; + int32_t oldValue = + uhash_puti(hash, (void*) key, value, &status); + if (U_FAILURE(status)) { + log_err("FAIL: uhash_put(%s) failed with %s and returned %ld\n", + key, u_errorName(status), oldValue); + } else if (oldValue != expectedOldValue) { + log_err("FAIL: uhash_put(%s) returned old value %ld; expected %ld\n", + key, oldValue, expectedOldValue); + } else { + log_verbose("Ok: uhash_put(%s, %d) returned old value %ld\n", + key, value, oldValue); + } +} + +static void _get(UHashtable* hash, + const char* key, + int32_t expectedValue) { + UErrorCode status = U_ZERO_ERROR; + int32_t value = uhash_geti(hash, key); + if (U_FAILURE(status)) { + log_err("FAIL: uhash_get(%s) failed with %s and returned %ld\n", + key, u_errorName(status), value); + } else if (value != expectedValue) { + log_err("FAIL: uhash_get(%s) returned %ld; expected %ld\n", + key, value, expectedValue); + } else { + log_verbose("Ok: uhash_get(%s) returned value %ld\n", + key, value); + } +} + +static void _remove(UHashtable* hash, + const char* key, + int32_t expectedValue) { + int32_t value = uhash_removei(hash, key); + if (value != expectedValue) { + log_err("FAIL: uhash_remove(%s) returned %ld; expected %ld\n", + key, value, expectedValue); + } else { + log_verbose("Ok: uhash_remove(%s) returned old value %ld\n", + key, value); + } +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c new file mode 100644 index 00000000000..03efad93248 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c @@ -0,0 +1,725 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CINTLTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ + +/*The main root for C API tests*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "unicode/utypes.h" +#include "unicode/putil.h" +#include "cstring.h" +#include "cintltst.h" +#include "umutex.h" +#include "uassert.h" +#include "cmemory.h" +#include "unicode/uchar.h" +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "unicode/ures.h" +#include "unicode/uclean.h" +#include "unicode/ucal.h" +#include "uoptions.h" +#include "putilimp.h" /* for uprv_getUTCtime() */ + +#ifdef XP_MAC_CONSOLE +# include <console.h> +#endif + +#define CTST_LEAK_CHECK 1 +#ifdef CTST_LEAK_CHECK +U_CFUNC void ctst_freeAll(void); +#endif + +static char* _testDataPath=NULL; + +/* + * Forward Declarations + */ +void ctest_setICU_DATA(void); + + + +#if UCONFIG_NO_LEGACY_CONVERSION +# define TRY_CNV_1 "iso-8859-1" +# define TRY_CNV_2 "ibm-1208" +#else +# define TRY_CNV_1 "iso-8859-7" +# define TRY_CNV_2 "sjis" +#endif + + +/* + * Tracing functions. + */ +static int traceFnNestingDepth = 0; +U_CDECL_BEGIN +static void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) { + char buf[500]; + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber)); + buf[sizeof(buf)-1]=0; + fputs(buf, stdout); + traceFnNestingDepth++; +} + +static void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) { + char buf[500]; + + if (traceFnNestingDepth>0) { + traceFnNestingDepth--; + } + utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber)); + buf[sizeof(buf)-1]=0; + fputs(buf, stdout); + utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); + buf[sizeof(buf)-1]=0; + fputs(buf, stdout); + putc('\n', stdout); +} + +static void U_CALLCONV TraceData(const void *context, int32_t fnNumber, + int32_t level, const char *fmt, va_list args) { + char buf[500]; + utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args); + buf[sizeof(buf)-1]=0; + fputs(buf, stdout); + putc('\n', stdout); +} +U_CDECL_END + + + +int main(int argc, const char* const argv[]) +{ + int nerrors = 0; + int warnOnMissingData = 0; + int i, j; + UBool defaultDataFound; + TestNode *root; + const char *warnOrErr = "Failure"; + const char** argv2; + UDate startTime, endTime; + int32_t diffTime; + + /* initial check for the default converter */ + UErrorCode errorCode = U_ZERO_ERROR; + UResourceBundle *rb; + UConverter *cnv; + + U_MAIN_INIT_ARGS(argc, argv); + + startTime = uprv_getUTCtime(); + + argv2 = (const char**) malloc(sizeof(char*) * argc); + if (argv2 == NULL) { + printf("*** Error: Out of memory (too many cmd line args?)\n"); + return 1; + } + argv2[0] = argv[0]; + + + /* Checkargs */ + /* TODO: Test framework arg handling needs to be decoupled from test execution + * so that the args being processed here don't need special handling, + * separate from the other test args. + */ + ICU_TRACE = UTRACE_OFF; + for(i=1,j=1;i<argc;i++) { + argv2[j++] = argv[i]; + if(!strcmp(argv[i],"-w")) { + warnOnMissingData = 1; + warnOrErr = "Warning"; + } + else if (strcmp( argv[i], "-t_error") == 0) { + ICU_TRACE = UTRACE_ERROR; + } + else if (strcmp( argv[i], "-t_warn") == 0) { + ICU_TRACE = UTRACE_WARNING; + } + else if (strcmp( argv[i], "-t_oc") == 0) { + ICU_TRACE = UTRACE_OPEN_CLOSE; + } + else if (strcmp( argv[i], "-t_info") == 0) { + ICU_TRACE = UTRACE_INFO; + } + else if (strcmp( argv[i], "-t_verbose") == 0) { + ICU_TRACE = UTRACE_VERBOSE; + } + } + argc = j; + + + utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData); + utrace_setLevel(ICU_TRACE); + + + while (REPEAT_TESTS > 0) { /* Loop runs once per complete execution of the tests + * used for -r (repeat) test option. */ + + /* Check whether ICU will initialize without forcing the build data directory into + * the ICU_DATA path. Success here means either the data dll contains data, or that + * this test program was run with ICU_DATA set externally. Failure of this check + * is normal when ICU data is not packaged into a shared library. + * + * Whether or not this test succeeds, we want to cleanup and reinitialize + * with a data path so that data loading from individual files can be tested. + */ + defaultDataFound = TRUE; + u_init(&errorCode); + if (U_FAILURE(errorCode)) { + fprintf(stderr, + "#### Note: ICU Init without build-specific setDataDirectory() failed. %s\n", u_errorName(errorCode)); + defaultDataFound = FALSE; + } + u_cleanup(); + errorCode = U_ZERO_ERROR; + utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData); + utrace_setLevel(ICU_TRACE); + + /* Initialize ICU */ + if (!defaultDataFound) { + ctest_setICU_DATA(); /* u_setDataDirectory() must happen Before u_init() */ + } + u_init(&errorCode); + if (U_FAILURE(errorCode)) { + fprintf(stderr, + "#### ERROR! %s: u_init() failed with status = \"%s\".\n" + "*** Check the ICU_DATA environment variable and \n" + "*** check that the data files are present.\n", argv[0], u_errorName(errorCode)); + if(warnOnMissingData == 0) { + fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + u_cleanup(); + return 1; + } + } + + + + /* try more data */ + cnv = ucnv_open(TRY_CNV_2, &errorCode); + if(cnv != 0) { + /* ok */ + ucnv_close(cnv); + } else { + fprintf(stderr, + "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n" + "*** Check the ICU_DATA environment variable and \n" + "*** check that the data files are present.\n", warnOrErr); + if(warnOnMissingData == 0) { + fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + u_cleanup(); + return 1; + } + } + + rb = ures_open(NULL, "en", &errorCode); + if(U_SUCCESS(errorCode)) { + /* ok */ + ures_close(rb); + } else { + fprintf(stderr, + "*** %s! The \"en\" locale resource bundle cannot be opened.\n" + "*** Check the ICU_DATA environment variable and \n" + "*** check that the data files are present.\n", warnOrErr); + if(warnOnMissingData == 0) { + fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n"); + u_cleanup(); + return 1; + } + } + + errorCode = U_ZERO_ERROR; + rb = ures_open(NULL, NULL, &errorCode); + if(U_SUCCESS(errorCode)) { + /* ok */ + if (errorCode == U_USING_DEFAULT_WARNING || errorCode == U_USING_FALLBACK_WARNING) { + fprintf(stderr, + "#### Note: The default locale %s is not available\n", uloc_getDefault()); + } + ures_close(rb); + } else { + fprintf(stderr, + "*** %s! Can not open a resource bundle for the default locale %s\n", warnOrErr, uloc_getDefault()); + if(warnOnMissingData == 0) { + fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n" + "*** purposely removed, to continue test anyway.\n"); + u_cleanup(); + return 1; + } + } + fprintf(stdout, "Default locale for this run is %s\n", uloc_getDefault()); + + /* Build a tree of all tests. + * Subsequently will be used to find / iterate the tests to run */ + root = NULL; + addAllTests(&root); + + /* Tests acutally run HERE. TODO: separate command line option parsing & setting from test execution!! */ + nerrors = processArgs(root, argc, argv2); + + if (--REPEAT_TESTS > 0) { + printf("Repeating tests %d more time(s)\n", REPEAT_TESTS); + } + cleanUpTestTree(root); + +#ifdef CTST_LEAK_CHECK + ctst_freeAll(); + /* To check for leaks */ + u_cleanup(); /* nuke the hashtable.. so that any still-open cnvs are leaked */ +#endif + + } /* End of loop that repeats the entire test, if requested. (Normally doesn't loop) */ + + free((void*)argv2); + + endTime = uprv_getUTCtime(); + diffTime = (int32_t)(endTime - startTime); + printf("Elapsed Time: %02d:%02d:%02d.%03d\n", + (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR), + (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE), + (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND), + (int)(diffTime%U_MILLIS_PER_SECOND)); + + return nerrors ? 1 : 0; +} + +/* +static void ctest_appendToDataDirectory(const char *toAppend) +{ + const char *oldPath =""; + char newBuf [1024]; + char *newPath = newBuf; + int32_t oldLen; + int32_t newLen; + + if((toAppend == NULL) || (*toAppend == 0)) { + return; + } + + oldPath = u_getDataDirectory(); + if( (oldPath==NULL) || (*oldPath == 0)) { + u_setDataDirectory(toAppend); + } else { + oldLen = strlen(oldPath); + newLen = strlen(toAppend)+1+oldLen; + + if(newLen > 1022) + { + newPath = (char *)ctst_malloc(newLen); + } + + strcpy(newPath, oldPath); + strcpy(newPath+oldLen, U_PATH_SEP_STRING); + strcpy(newPath+oldLen+1, toAppend); + + u_setDataDirectory(newPath); + + if(newPath != newBuf) + { + free(newPath); + } + } +} +*/ + +/* returns the path to icu/source/data */ +const char * ctest_dataSrcDir() +{ + static const char *dataSrcDir = NULL; + + if(dataSrcDir) { + return dataSrcDir; + } + + /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst + // to point to the top of the build hierarchy, which may or + // may not be the same as the source directory, depending on + // the configure options used. At any rate, + // set the data path to the built data from this directory. + // The value is complete with quotes, so it can be used + // as-is as a string constant. + */ +#if defined (U_TOPSRCDIR) + { + dataSrcDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; + } +#else + + /* On Windows, the file name obtained from __FILE__ includes a full path. + * This file is "wherever\icu\source\test\cintltst\cintltst.c" + * Change to "wherever\icu\source\data" + */ + { + static char p[sizeof(__FILE__) + 20]; + char *pBackSlash; + int i; + + strcpy(p, __FILE__); + /* We want to back over three '\' chars. */ + /* Only Windows should end up here, so looking for '\' is safe. */ + for (i=1; i<=3; i++) { + pBackSlash = strrchr(p, U_FILE_SEP_CHAR); + if (pBackSlash != NULL) { + *pBackSlash = 0; /* Truncate the string at the '\' */ + } + } + + if (pBackSlash != NULL) { + /* We found and truncated three names from the path. + * Now append "source\data" and set the environment + */ + strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING ); + dataSrcDir = p; + } + else { + /* __FILE__ on MSVC7 does not contain the directory */ + FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); + if (file) { + fclose(file); + dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; + } + else { + dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING; + } + } + } +#endif + + return dataSrcDir; + +} + +/* returns the path to icu/source/data/out */ +const char *ctest_dataOutDir() +{ + static const char *dataOutDir = NULL; + + if(dataOutDir) { + return dataOutDir; + } + + /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst + // to point to the top of the build hierarchy, which may or + // may not be the same as the source directory, depending on + // the configure options used. At any rate, + // set the data path to the built data from this directory. + // The value is complete with quotes, so it can be used + // as-is as a string constant. + */ +#if defined (U_TOPBUILDDIR) + { + dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; + } +#else + + /* On Windows, the file name obtained from __FILE__ includes a full path. + * This file is "wherever\icu\source\test\cintltst\cintltst.c" + * Change to "wherever\icu\source\data" + */ + { + static char p[sizeof(__FILE__) + 20]; + char *pBackSlash; + int i; + + strcpy(p, __FILE__); + /* We want to back over three '\' chars. */ + /* Only Windows should end up here, so looking for '\' is safe. */ + for (i=1; i<=3; i++) { + pBackSlash = strrchr(p, U_FILE_SEP_CHAR); + if (pBackSlash != NULL) { + *pBackSlash = 0; /* Truncate the string at the '\' */ + } + } + + if (pBackSlash != NULL) { + /* We found and truncated three names from the path. + * Now append "source\data" and set the environment + */ + strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING); + dataOutDir = p; + } + else { + /* __FILE__ on MSVC7 does not contain the directory */ + FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r"); + if (file) { + fclose(file); + dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; + } + else { + dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING; + } + } + } +#endif + + return dataOutDir; +} + +/* ctest_setICU_DATA - if the ICU_DATA environment variable is not already + * set, try to deduce the directory in which ICU was built, + * and set ICU_DATA to "icu/source/data" in that location. + * The intent is to allow the tests to have a good chance + * of running without requiring that the user manually set + * ICU_DATA. Common data isn't a problem, since it is + * picked up via a static (build time) reference, but the + * tests dynamically load some data. + */ +void ctest_setICU_DATA() { + + /* No location for the data dir was identifiable. + * Add other fallbacks for the test data location here if the need arises + */ + if (getenv("ICU_DATA") == NULL) { + /* If ICU_DATA isn't set, set it to the usual location */ + u_setDataDirectory(ctest_dataOutDir()); + } +} + +UChar* CharsToUChars(const char* str) { + /* Might be faster to just use uprv_strlen() as the preflight len - liu */ + int32_t len = u_unescape(str, 0, 0); /* preflight */ + /* Do NOT use malloc() - we are supposed to be acting like user code! */ + UChar *buf = (UChar*) malloc(sizeof(UChar) * (len + 1)); + u_unescape(str, buf, len + 1); + return buf; +} + +char *austrdup(const UChar* unichars) +{ + int length; + char *newString; + + length = u_strlen ( unichars ); + /*newString = (char*)malloc ( sizeof( char ) * 4 * ( length + 1 ) );*/ /* this leaks for now */ + newString = (char*)ctst_malloc ( sizeof( char ) * 4 * ( length + 1 ) ); /* this shouldn't */ + + if ( newString == NULL ) + return NULL; + + u_austrcpy ( newString, unichars ); + + return newString; +} + +char *aescstrdup(const UChar* unichars,int32_t length){ + char *newString,*targetLimit,*target; + UConverterFromUCallback cb; + const void *p; + UErrorCode errorCode = U_ZERO_ERROR; +#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY +# ifdef OS390 + static const char convName[] = "ibm-1047"; +# else + static const char convName[] = "ibm-37"; +# endif +#else + static const char convName[] = "US-ASCII"; +#endif + UConverter* conv = ucnv_open(convName, &errorCode); + if(length==-1){ + length = u_strlen( unichars); + } + newString = (char*)ctst_malloc ( sizeof(char) * 8 * (length +1)); + target = newString; + targetLimit = newString+sizeof(char) * 8 * (length +1); + ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_JAVA, &cb, &p, &errorCode); + ucnv_fromUnicode(conv,&target,targetLimit, &unichars, (UChar*)(unichars+length),NULL,TRUE,&errorCode); + ucnv_close(conv); + *target = '\0'; + return newString; +} + +const char* loadTestData(UErrorCode* err){ + if( _testDataPath == NULL){ + const char* directory=NULL; + UResourceBundle* test =NULL; + char* tdpath=NULL; + const char* tdrelativepath; +#if defined (U_TOPBUILDDIR) + tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; + directory = U_TOPBUILDDIR; +#else + tdrelativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING; + directory= ctest_dataOutDir(); +#endif + + tdpath = (char*) ctst_malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 10)); + + + /* u_getDataDirectory shoul return \source\data ... set the + * directory to ..\source\data\..\test\testdata\out\testdata + * + * Fallback: When Memory mapped file is built + * ..\source\data\out\..\..\test\testdata\out\testdata + */ + strcpy(tdpath, directory); + strcat(tdpath, tdrelativepath); + strcat(tdpath,"testdata"); + + + test=ures_open(tdpath, "testtypes", err); + + /* Fall back did not succeed either so return */ + if(U_FAILURE(*err)){ + *err = U_FILE_ACCESS_ERROR; + log_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(*err)); + return ""; + } + ures_close(test); + _testDataPath = tdpath; + return _testDataPath; + } + return _testDataPath; +} + +#define CTEST_MAX_TIMEZONE_SIZE 256 +static UChar gOriginalTimeZone[CTEST_MAX_TIMEZONE_SIZE] = {0}; + +/** + * Call this once to get a consistent timezone. Use ctest_resetTimeZone to set it back to the original value. + * @param optionalTimeZone Set this to a requested timezone. + * Set to NULL to use the standard test timezone (Pacific Time) + */ +U_CFUNC void ctest_setTimeZone(const char *optionalTimeZone, UErrorCode *status) { +#if !UCONFIG_NO_FORMATTING + UChar zoneID[CTEST_MAX_TIMEZONE_SIZE]; + + if (optionalTimeZone == NULL) { + optionalTimeZone = "America/Los_Angeles"; + } + if (gOriginalTimeZone[0]) { + log_err("*** Error: time zone saved twice. New value will be %s\n", + optionalTimeZone); + } + ucal_getDefaultTimeZone(gOriginalTimeZone, CTEST_MAX_TIMEZONE_SIZE, status); + if (U_FAILURE(*status)) { + log_err("*** Error: Failed to save default time zone: %s\n", + u_errorName(*status)); + *status = U_ZERO_ERROR; + } + + u_uastrncpy(zoneID, optionalTimeZone, CTEST_MAX_TIMEZONE_SIZE-1); + zoneID[CTEST_MAX_TIMEZONE_SIZE-1] = 0; + ucal_setDefaultTimeZone(zoneID, status); + if (U_FAILURE(*status)) { + log_err("*** Error: Failed to set default time zone to \"%s\": %s\n", + optionalTimeZone, u_errorName(*status)); + } +#endif +} + +/** + * Call this once get back the original timezone + */ +U_CFUNC void ctest_resetTimeZone(void) { +#if !UCONFIG_NO_FORMATTING + UErrorCode status = U_ZERO_ERROR; + + ucal_setDefaultTimeZone(gOriginalTimeZone, &status); + if (U_FAILURE(status)) { + log_err("*** Error: Failed to reset default time zone: %s\n", + u_errorName(status)); + } + /* Set to an empty state */ + gOriginalTimeZone[0] = 0; +#endif +} + +#define CTST_MAX_ALLOC 8192 +/* Array used as a queue */ +static void * ctst_allocated_stuff[CTST_MAX_ALLOC] = {0}; +static int ctst_allocated = 0; +static UBool ctst_free = FALSE; + +void *ctst_malloc(size_t size) { + if(ctst_allocated >= CTST_MAX_ALLOC - 1) { + ctst_allocated = 0; + ctst_free = TRUE; + } + if(ctst_allocated_stuff[ctst_allocated]) { + free(ctst_allocated_stuff[ctst_allocated]); + } + return ctst_allocated_stuff[ctst_allocated++] = malloc(size); +} + +#ifdef CTST_LEAK_CHECK +void ctst_freeAll() { + int i; + if(ctst_free == 0) { + for(i=0; i<ctst_allocated; i++) { + free(ctst_allocated_stuff[i]); + ctst_allocated_stuff[i] = NULL; + } + } else { + for(i=0; i<CTST_MAX_ALLOC; i++) { + free(ctst_allocated_stuff[i]); + ctst_allocated_stuff[i] = NULL; + } + } + ctst_allocated = 0; + _testDataPath=NULL; +} + +#define VERBOSE_ASSERTIONS + +U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec) { + U_ASSERT(ec!=NULL); + if (U_FAILURE(*ec)) { + log_err("FAIL: %s (%s)\n", msg, u_errorName(*ec)); + return FALSE; + } + return TRUE; +} + +/* if 'condition' is a UBool, the compiler complains bitterly about + expressions like 'a > 0' which it evaluates as int */ +U_CFUNC UBool assertTrue(const char* msg, int /*not UBool*/ condition) { + if (!condition) { + log_err("FAIL: assertTrue() failed: %s\n", msg); + } +#ifdef VERBOSE_ASSERTIONS + else { + log_verbose("Ok: %s\n", msg); + } +#endif + return (UBool)condition; +} + +U_CFUNC UBool assertEquals(const char* message, const char* expected, + const char* actual) { + if (uprv_strcmp(expected, actual) != 0) { + log_err("FAIL: %s; got \"%s\"; expected \"%s\"\n", + message, actual, expected); + return FALSE; + } +#ifdef VERBOSE_ASSERTIONS + else { + log_verbose("Ok: %s; got \"%s\"\n", message, actual); + } +#endif + return TRUE; +} +/*-------------------------------------------------------------------- + * Time bomb - allows temporary behavior that expires at a given + * release + *-------------------------------------------------------------------- + */ + +U_CFUNC UBool isICUVersionAtLeast(const UVersionInfo x) { + UVersionInfo v; + u_getVersion(v); + return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0); +} +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h new file mode 100644 index 00000000000..e750424b895 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h @@ -0,0 +1,108 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2005, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CINTLTST.H +* +* Madhu Katragadda Creation +* Modification History: +* Date Name Description +* 07/13/99 helena HPUX 11 CC port. +********************************************************************************* + +The main root for C API tests +*/ + +#ifndef _CINTLTST +#define _CINTLTST + +#include "unicode/utypes.h" +#include "unicode/putil.h" +#include "unicode/ctest.h" +#include <stdlib.h> + +#ifndef U_USE_DEPRECATED_API +#define U_USE_DEPRECATED_API 1 +#endif + +U_CFUNC void addAllTests(TestNode** root); + +/** + * Return the path to the icu/source/data/out directory + */ +U_CFUNC const char* ctest_dataOutDir(void); + +/** + * Return the path to the icu/source/data/ directory + * for out of source builds too returns the source directory + */ +U_CFUNC const char* ctest_dataSrcDir(void); + +U_CFUNC UChar* CharsToUChars(const char* chars); + +/** + * Convert a const UChar* into a char* + * Caller owns storage, but in practice this function + * LEAKS so be aware of that. + * @param unichars UChars (null terminated) to be converted + * @return new char* to the unichars in host format + */ + +U_CFUNC char *austrdup(const UChar* unichars); +U_CFUNC char *aescstrdup(const UChar* unichars, int32_t length); +U_CFUNC void *ctst_malloc(size_t size); +U_CFUNC void ctst_freeAll(void); + +U_CFUNC const char* loadTestData(UErrorCode* err); + +/** + * function used to specify the error + * converts the errorcode to an error descriptive string(const char*) + * @param status the error code + */ +#define myErrorName(errorCode) u_errorName(errorCode) + + +/** + * Call this once to get a consistent timezone. Use ctest_resetTimeZone to set it back to the original value. + * @param optionalTimeZone Set this to a requested timezone. + * Set to NULL to use the standard test timezone (Pacific Time) + */ +U_CFUNC void ctest_setTimeZone(const char *optionalTimeZone, UErrorCode *status); +/** + * Call this once get back the original timezone + */ +U_CFUNC void ctest_resetTimeZone(void); + +/** + * Assert that the given UErrorCode succeeds, and return TRUE if it does. + */ +U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec); + +/** + * Assert that the UBool is TRUE, and return TRUE if it does. + * + * NOTE: Use 'int condition' rather than 'UBool condition' so the + * compiler doesn't complain about integral conversion of expressions + * like 'p != 0'. + */ +U_CFUNC UBool assertTrue(const char* msg, int condition); + +/** + * Assert that the actualString equals the expectedString, and return + * TRUE if it does. + */ +U_CFUNC UBool assertEquals(const char* msg, const char* expectedString, + const char* actualString); + +/** + * Time bomb - allows temporary behavior that expires at a given + * release + * + */ +U_CFUNC UBool isICUVersionAtLeast(const UVersionInfo x); + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj new file mode 100644 index 00000000000..65c4c1b935c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj @@ -0,0 +1,721 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="cintltst" + ProjectGUID="{3D1246AE-1B32-479B-BECA-AEFA97BE2321}" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory=".\Debug" + IntermediateDirectory=".\Debug" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Debug/cintltst.tlb" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil" + PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + BufferSecurityCheck="true" + DisableLanguageExtensions="true" + TreatWChar_tAsBuiltInType="true" + PrecompiledHeaderFile=".\Debug/cintltst.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + BrowseInformation="1" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="4" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile=".\Debug/cintltst.exe" + LinkIncremental="2" + SuppressStartupBanner="true" + GenerateDebugInformation="true" + ProgramDatabaseFile=".\Debug/cintltst.pdb" + SubSystem="1" + FixedBaseAddress="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + UseFAT32Workaround="true" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory=".\Release" + IntermediateDirectory=".\Release" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TypeLibraryName=".\Release/cintltst.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil" + PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE" + StringPooling="true" + RuntimeLibrary="0" + BufferSecurityCheck="true" + EnableFunctionLevelLinking="true" + DisableLanguageExtensions="true" + TreatWChar_tAsBuiltInType="true" + PrecompiledHeaderFile=".\Release/cintltst.pch" + AssemblerListingLocation=".\Release/" + ObjectFile=".\Release/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="true" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile=".\Release/cintltst.exe" + LinkIncremental="1" + SuppressStartupBanner="true" + GenerateDebugInformation="true" + ProgramDatabaseFile=".\Release/cintltst.pdb" + SubSystem="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="bidi" + > + <File + RelativePath=".\cbididat.c" + > + </File> + <File + RelativePath=".\cbiditst.c" + > + </File> + <File + RelativePath=".\cbiditst.h" + > + </File> + </Filter> + <Filter + Name="break iteration" + > + <File + RelativePath=".\cbiapts.c" + > + </File> + <File + RelativePath=".\cbiapts.h" + > + </File> + <File + RelativePath=".\cbkittst.c" + > + </File> + </Filter> + <Filter + Name="collation" + > + <File + RelativePath=".\callcoll.c" + > + </File> + <File + RelativePath=".\callcoll.h" + > + </File> + <File + RelativePath=".\capitst.c" + > + </File> + <File + RelativePath=".\capitst.h" + > + </File> + <File + RelativePath=".\ccolltst.c" + > + </File> + <File + RelativePath=".\ccolltst.h" + > + </File> + <File + RelativePath=".\ccurrtst.c" + > + </File> + <File + RelativePath=".\ccurrtst.h" + > + </File> + <File + RelativePath=".\cdetst.c" + > + </File> + <File + RelativePath=".\cdetst.h" + > + </File> + <File + RelativePath=".\cestst.c" + > + </File> + <File + RelativePath=".\cestst.h" + > + </File> + <File + RelativePath=".\cfintst.c" + > + </File> + <File + RelativePath=".\cfintst.h" + > + </File> + <File + RelativePath=".\cfrtst.c" + > + </File> + <File + RelativePath=".\cfrtst.h" + > + </File> + <File + RelativePath=".\cg7coll.c" + > + </File> + <File + RelativePath=".\cg7coll.h" + > + </File> + <File + RelativePath=".\citertst.c" + > + </File> + <File + RelativePath=".\citertst.h" + > + </File> + <File + RelativePath=".\cjaptst.c" + > + </File> + <File + RelativePath=".\cjaptst.h" + > + </File> + <File + RelativePath=".\cmsccoll.c" + > + </File> + <File + RelativePath=".\colutil.c" + > + </File> + <File + RelativePath=".\cturtst.c" + > + </File> + <File + RelativePath=".\cturtst.h" + > + </File> + <File + RelativePath=".\encoll.c" + > + </File> + <File + RelativePath=".\encoll.h" + > + </File> + <File + RelativePath=".\usrchdat.c" + > + </File> + <File + RelativePath=".\usrchtst.c" + > + </File> + </Filter> + <Filter + Name="collections" + > + <File + RelativePath=".\chashtst.c" + > + </File> + <File + RelativePath=".\sorttest.c" + > + </File> + <File + RelativePath=".\trietest.c" + > + </File> + <File + RelativePath=".\uenumtst.c" + > + </File> + </Filter> + <Filter + Name="conversion" + > + <File + RelativePath=".\bocu1tst.c" + > + </File> + <File + RelativePath=".\ccapitst.c" + > + </File> + <File + RelativePath=".\ccapitst.h" + > + </File> + <File + RelativePath=".\cconvtst.c" + > + </File> + <File + RelativePath=".\cctest.c" + > + </File> + <File + RelativePath=".\eurocreg.c" + > + </File> + <File + RelativePath=".\nccbtst.c" + > + </File> + <File + RelativePath=".\nccbtst.h" + > + </File> + <File + RelativePath=".\ncnvfbts.c" + > + </File> + <File + RelativePath=".\ncnvfbts.h" + > + </File> + <File + RelativePath=".\ncnvtst.c" + > + </File> + <File + RelativePath=".\nucnvtst.c" + > + </File> + <File + RelativePath=".\nucnvtst.h" + > + </File> + <File + RelativePath=".\stdnmtst.c" + > + </File> + <File + RelativePath=".\ucsdetst.c" + > + </File> + </Filter> + <Filter + Name="data & memory" + > + <File + RelativePath=".\udatatst.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + DisableLanguageExtensions="false" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + DisableLanguageExtensions="false" + /> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="formatting" + > + <File + RelativePath=".\ccaltst.c" + > + </File> + <File + RelativePath=".\ccaltst.h" + > + </File> + <File + RelativePath=".\cdattst.c" + > + </File> + <File + RelativePath=".\cdattst.h" + > + </File> + <File + RelativePath=".\cdtdptst.c" + > + </File> + <File + RelativePath=".\cdtdptst.h" + > + </File> + <File + RelativePath=".\cdtrgtst.c" + > + </File> + <File + RelativePath=".\cdtrgtst.h" + > + </File> + <File + RelativePath=".\cformtst.c" + > + </File> + <File + RelativePath=".\cformtst.h" + > + </File> + <File + RelativePath=".\cmsgtst.c" + > + </File> + <File + RelativePath=".\cmsgtst.h" + > + </File> + <File + RelativePath=".\cnmdptst.c" + > + </File> + <File + RelativePath=".\cnmdptst.h" + > + </File> + <File + RelativePath=".\cnumtst.c" + > + </File> + <File + RelativePath=".\cnumtst.h" + > + </File> + <File + RelativePath=".\currtest.c" + > + </File> + <File + RelativePath=".\udatpg_test.c" + > + </File> + <File + RelativePath=".\utmstest.c" + > + </File> + </Filter> + <Filter + Name="locales & resources" + > + <File + RelativePath=".\cldrtest.c" + > + </File> + <File + RelativePath=".\cloctst.c" + > + </File> + <File + RelativePath=".\cloctst.h" + > + </File> + <File + RelativePath=".\cposxtst.c" + > + </File> + <File + RelativePath=".\crestst.c" + > + </File> + <File + RelativePath=".\crestst.h" + > + </File> + <File + RelativePath=".\creststn.c" + > + </File> + <File + RelativePath=".\creststn.h" + > + </File> + </Filter> + <Filter + Name="misc" + > + <File + RelativePath=".\calltest.c" + > + </File> + <File + RelativePath=".\cintltst.c" + > + </File> + <File + RelativePath=".\cintltst.h" + > + </File> + <File + RelativePath=".\cutiltst.c" + > + </File> + <File + RelativePath=".\hpmufn.c" + > + </File> + <File + RelativePath=".\putiltst.c" + > + </File> + <File + RelativePath=".\tracetst.c" + > + </File> + </Filter> + <Filter + Name="normalization" + > + <File + RelativePath=".\cnormtst.c" + > + </File> + <File + RelativePath=".\cnormtst.h" + > + </File> + </Filter> + <Filter + Name="properties & sets" + > + <File + RelativePath=".\cucdapi.c" + > + </File> + <File + RelativePath=".\cucdapi.h" + > + </File> + <File + RelativePath=".\cucdtst.c" + > + </File> + <File + RelativePath=".\usettest.c" + > + </File> + </Filter> + <Filter + Name="strings" + > + <File + RelativePath=".\cstrcase.c" + > + </File> + <File + RelativePath=".\cstrtest.c" + > + </File> + <File + RelativePath=".\custrtrn.c" + > + </File> + <File + RelativePath=".\custrtst.c" + > + </File> + <File + RelativePath=".\utexttst.c" + > + </File> + <File + RelativePath=".\utf16tst.c" + > + </File> + <File + RelativePath=".\utf8tst.c" + > + </File> + </Filter> + <Filter + Name="transforms" + > + <File + RelativePath=".\utransts.c" + > + </File> + </Filter> + <Filter + Name="regex" + > + <File + RelativePath=".\reapits.c" + > + </File> + </Filter> + <Filter + Name="sprep & idna" + > + <File + RelativePath="idnatest.c" + > + </File> + <File + RelativePath="nfsprep.c" + > + </File> + <File + RelativePath="nfsprep.h" + > + </File> + <File + RelativePath="spreptst.c" + > + </File> + <File + RelativePath="sprpdata.c" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c new file mode 100644 index 00000000000..dc24f4acea5 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c @@ -0,0 +1,1923 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2004, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CITERTST.C +* +* Modification History: +* Date Name Description +* Madhu Katragadda Ported for C API +* 02/19/01 synwee Modified test case for new collation iterator +*********************************************************************************/ +/* + * Collation Iterator tests. + * (Let me reiterate my position...) + */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "unicode/uchar.h" +#include "unicode/ustring.h" +#include "unicode/putil.h" +#include "callcoll.h" +#include "cmemory.h" +#include "cintltst.h" +#include "citertst.h" +#include "ccolltst.h" +#include "filestrm.h" +#include "cstring.h" +#include "ucol_imp.h" +#include "ucol_tok.h" +#include <stdio.h> + +extern uint8_t ucol_uprv_getCaseBits(const UChar *, uint32_t, UErrorCode *); + +void addCollIterTest(TestNode** root) +{ + addTest(root, &TestPrevious, "tscoll/citertst/TestPrevious"); + addTest(root, &TestOffset, "tscoll/citertst/TestOffset"); + addTest(root, &TestSetText, "tscoll/citertst/TestSetText"); + addTest(root, &TestMaxExpansion, "tscoll/citertst/TestMaxExpansion"); + addTest(root, &TestUnicodeChar, "tscoll/citertst/TestUnicodeChar"); + addTest(root, &TestNormalizedUnicodeChar, + "tscoll/citertst/TestNormalizedUnicodeChar"); + addTest(root, &TestNormalization, "tscoll/citertst/TestNormalization"); + addTest(root, &TestBug672, "tscoll/citertst/TestBug672"); + addTest(root, &TestBug672Normalize, "tscoll/citertst/TestBug672Normalize"); + addTest(root, &TestSmallBuffer, "tscoll/citertst/TestSmallBuffer"); + addTest(root, &TestCEs, "tscoll/citertst/TestCEs"); + addTest(root, &TestDiscontiguos, "tscoll/citertst/TestDiscontiguos"); + addTest(root, &TestCEBufferOverflow, "tscoll/citertst/TestCEBufferOverflow"); + addTest(root, &TestCEValidity, "tscoll/citertst/TestCEValidity"); + addTest(root, &TestSortKeyValidity, "tscoll/citertst/TestSortKeyValidity"); +} + +/* The locales we support */ + +static const char * LOCALES[] = {"en_AU", "en_BE", "en_CA"}; + +static void TestBug672() { + UErrorCode status = U_ZERO_ERROR; + UChar pattern[20]; + UChar text[50]; + int i; + int result[3][3]; + + u_uastrcpy(pattern, "resume"); + u_uastrcpy(text, "Time to resume updating my resume."); + + for (i = 0; i < 3; ++ i) { + UCollator *coll = ucol_open(LOCALES[i], &status); + UCollationElements *pitr = ucol_openElements(coll, pattern, -1, + &status); + UCollationElements *titer = ucol_openElements(coll, text, -1, + &status); + if (U_FAILURE(status)) { + log_err("ERROR: in creation of either the collator or the collation iterator :%s\n", + myErrorName(status)); + return; + } + + log_verbose("locale tested %s\n", LOCALES[i]); + + while (ucol_next(pitr, &status) != UCOL_NULLORDER && + U_SUCCESS(status)) { + } + if (U_FAILURE(status)) { + log_err("ERROR: reversing collation iterator :%s\n", + myErrorName(status)); + return; + } + ucol_reset(pitr); + + ucol_setOffset(titer, u_strlen(pattern), &status); + if (U_FAILURE(status)) { + log_err("ERROR: setting offset in collator :%s\n", + myErrorName(status)); + return; + } + result[i][0] = ucol_getOffset(titer); + log_verbose("Text iterator set to offset %d\n", result[i][0]); + + /* Use previous() */ + ucol_previous(titer, &status); + result[i][1] = ucol_getOffset(titer); + log_verbose("Current offset %d after previous\n", result[i][1]); + + /* Add one to index */ + log_verbose("Adding one to current offset...\n"); + ucol_setOffset(titer, ucol_getOffset(titer) + 1, &status); + if (U_FAILURE(status)) { + log_err("ERROR: setting offset in collator :%s\n", + myErrorName(status)); + return; + } + result[i][2] = ucol_getOffset(titer); + log_verbose("Current offset in text = %d\n", result[i][2]); + ucol_closeElements(pitr); + ucol_closeElements(titer); + ucol_close(coll); + } + + if (uprv_memcmp(result[0], result[1], 3) != 0 || + uprv_memcmp(result[1], result[2], 3) != 0) { + log_err("ERROR: Different locales have different offsets at the same character\n"); + } +} + + + +/* Running this test with normalization enabled showed up a bug in the incremental + normalization code. */ +static void TestBug672Normalize() { + UErrorCode status = U_ZERO_ERROR; + UChar pattern[20]; + UChar text[50]; + int i; + int result[3][3]; + + u_uastrcpy(pattern, "resume"); + u_uastrcpy(text, "Time to resume updating my resume."); + + for (i = 0; i < 3; ++ i) { + UCollator *coll = ucol_open(LOCALES[i], &status); + UCollationElements *pitr = NULL; + UCollationElements *titer = NULL; + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + + pitr = ucol_openElements(coll, pattern, -1, &status); + titer = ucol_openElements(coll, text, -1, &status); + if (U_FAILURE(status)) { + log_err("ERROR: in creation of either the collator or the collation iterator :%s\n", + myErrorName(status)); + return; + } + + log_verbose("locale tested %s\n", LOCALES[i]); + + while (ucol_next(pitr, &status) != UCOL_NULLORDER && + U_SUCCESS(status)) { + } + if (U_FAILURE(status)) { + log_err("ERROR: reversing collation iterator :%s\n", + myErrorName(status)); + return; + } + ucol_reset(pitr); + + ucol_setOffset(titer, u_strlen(pattern), &status); + if (U_FAILURE(status)) { + log_err("ERROR: setting offset in collator :%s\n", + myErrorName(status)); + return; + } + result[i][0] = ucol_getOffset(titer); + log_verbose("Text iterator set to offset %d\n", result[i][0]); + + /* Use previous() */ + ucol_previous(titer, &status); + result[i][1] = ucol_getOffset(titer); + log_verbose("Current offset %d after previous\n", result[i][1]); + + /* Add one to index */ + log_verbose("Adding one to current offset...\n"); + ucol_setOffset(titer, ucol_getOffset(titer) + 1, &status); + if (U_FAILURE(status)) { + log_err("ERROR: setting offset in collator :%s\n", + myErrorName(status)); + return; + } + result[i][2] = ucol_getOffset(titer); + log_verbose("Current offset in text = %d\n", result[i][2]); + ucol_closeElements(pitr); + ucol_closeElements(titer); + ucol_close(coll); + } + + if (uprv_memcmp(result[0], result[1], 3) != 0 || + uprv_memcmp(result[1], result[2], 3) != 0) { + log_err("ERROR: Different locales have different offsets at the same character\n"); + } +} + + + + +/** + * Test for CollationElementIterator previous and next for the whole set of + * unicode characters. + */ +static void TestUnicodeChar() +{ + UChar source[0x100]; + UCollator *en_us; + UCollationElements *iter; + UErrorCode status = U_ZERO_ERROR; + UChar codepoint; + + UChar *test; + en_us = ucol_open("en_US", &status); + if (U_FAILURE(status)){ + log_err("ERROR: in creation of collation data using ucol_open()\n %s\n", + myErrorName(status)); + return; + } + + for (codepoint = 1; codepoint < 0xFFFE;) + { + test = source; + + while (codepoint % 0xFF != 0) + { + if (u_isdefined(codepoint)) + *(test ++) = codepoint; + codepoint ++; + } + + if (u_isdefined(codepoint)) + *(test ++) = codepoint; + + if (codepoint != 0xFFFF) + codepoint ++; + + *test = 0; + iter=ucol_openElements(en_us, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + /* A basic test to see if it's working at all */ + log_verbose("codepoint testing %x\n", codepoint); + backAndForth(iter); + ucol_closeElements(iter); + + /* null termination test */ + iter=ucol_openElements(en_us, source, -1, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + /* A basic test to see if it's working at all */ + backAndForth(iter); + ucol_closeElements(iter); + } + + ucol_close(en_us); +} + +/** + * Test for CollationElementIterator previous and next for the whole set of + * unicode characters with normalization on. + */ +static void TestNormalizedUnicodeChar() +{ + UChar source[0x100]; + UCollator *th_th; + UCollationElements *iter; + UErrorCode status = U_ZERO_ERROR; + UChar codepoint; + + UChar *test; + /* thai should have normalization on */ + th_th = ucol_open("th_TH", &status); + if (U_FAILURE(status)){ + log_err("ERROR: in creation of thai collation using ucol_open()\n %s\n", + myErrorName(status)); + return; + } + + for (codepoint = 1; codepoint < 0xFFFE;) + { + test = source; + + while (codepoint % 0xFF != 0) + { + if (u_isdefined(codepoint)) + *(test ++) = codepoint; + codepoint ++; + } + + if (u_isdefined(codepoint)) + *(test ++) = codepoint; + + if (codepoint != 0xFFFF) + codepoint ++; + + *test = 0; + iter=ucol_openElements(th_th, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(th_th); + return; + } + + backAndForth(iter); + ucol_closeElements(iter); + + iter=ucol_openElements(th_th, source, -1, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(th_th); + return; + } + + backAndForth(iter); + ucol_closeElements(iter); + } + + ucol_close(th_th); +} + +/** +* Test the incremental normalization +*/ +static void TestNormalization() +{ + UErrorCode status = U_ZERO_ERROR; + const char *str = + "&a < \\u0300\\u0315 < A\\u0300\\u0315 < \\u0316\\u0315B < \\u0316\\u0300\\u0315"; + UCollator *coll; + UChar rule[50]; + int rulelen = u_unescape(str, rule, 50); + int count = 0; + const char *testdata[] = + {"\\u1ED9", "o\\u0323\\u0302", + "\\u0300\\u0315", "\\u0315\\u0300", + "A\\u0300\\u0315B", "A\\u0315\\u0300B", + "A\\u0316\\u0315B", "A\\u0315\\u0316B", + "\\u0316\\u0300\\u0315", "\\u0315\\u0300\\u0316", + "A\\u0316\\u0300\\u0315B", "A\\u0315\\u0300\\u0316B", + "\\u0316\\u0315\\u0300", "A\\u0316\\u0315\\u0300B"}; + int32_t srclen; + UChar source[10]; + UCollationElements *iter; + + coll = ucol_openRules(rule, rulelen, UCOL_ON, UCOL_TERTIARY, NULL, &status); + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + if (U_FAILURE(status)){ + log_err("ERROR: in creation of collator using ucol_openRules()\n %s\n", + myErrorName(status)); + return; + } + + srclen = u_unescape(testdata[0], source, 10); + iter = ucol_openElements(coll, source, srclen, &status); + backAndForth(iter); + ucol_closeElements(iter); + + srclen = u_unescape(testdata[1], source, 10); + iter = ucol_openElements(coll, source, srclen, &status); + backAndForth(iter); + ucol_closeElements(iter); + + while (count < 12) { + srclen = u_unescape(testdata[count], source, 10); + iter = ucol_openElements(coll, source, srclen, &status); + + if (U_FAILURE(status)){ + log_err("ERROR: in creation of collator element iterator\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + + iter = ucol_openElements(coll, source, -1, &status); + + if (U_FAILURE(status)){ + log_err("ERROR: in creation of collator element iterator\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + count ++; + } + ucol_close(coll); +} + +/** + * Test for CollationElementIterator.previous() + * + * @bug 4108758 - Make sure it works with contracting characters + * + */ +static void TestPrevious() +{ + UCollator *coll=NULL; + UChar rule[50]; + UChar *source; + UCollator *c1, *c2, *c3; + UCollationElements *iter; + UErrorCode status = U_ZERO_ERROR; + + test1=(UChar*)malloc(sizeof(UChar) * 50); + test2=(UChar*)malloc(sizeof(UChar) * 50); + u_uastrcpy(test1, "What subset of all possible test cases?"); + u_uastrcpy(test2, "has the highest probability of detecting"); + coll = ucol_open("en_US", &status); + + iter=ucol_openElements(coll, test1, u_strlen(test1), &status); + log_verbose("English locale testing back and forth\n"); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(coll); + return; + } + /* A basic test to see if it's working at all */ + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(coll); + + /* Test with a contracting character sequence */ + u_uastrcpy(rule, "&a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH"); + c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + + log_verbose("Contraction rule testing back and forth with no normalization\n"); + + if (c1 == NULL || U_FAILURE(status)) + { + log_err("Couldn't create a RuleBasedCollator with a contracting sequence\n %s\n", + myErrorName(status)); + return; + } + source=(UChar*)malloc(sizeof(UChar) * 20); + u_uastrcpy(source, "abchdcba"); + iter=ucol_openElements(c1, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(c1); + + /* Test with an expanding character sequence */ + u_uastrcpy(rule, "&a < b < c/abd < d"); + c2 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status); + log_verbose("Expansion rule testing back and forth with no normalization\n"); + if (c2 == NULL || U_FAILURE(status)) + { + log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n", + myErrorName(status)); + return; + } + u_uastrcpy(source, "abcd"); + iter=ucol_openElements(c2, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(c2); + /* Now try both */ + u_uastrcpy(rule, "&a < b < c/aba < d < z < ch"); + c3 = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH,NULL, &status); + log_verbose("Expansion/contraction rule testing back and forth with no normalization\n"); + + if (c3 == NULL || U_FAILURE(status)) + { + log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n", + myErrorName(status)); + return; + } + u_uastrcpy(source, "abcdbchdc"); + iter=ucol_openElements(c3, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(c3); + source[0] = 0x0e41; + source[1] = 0x0e02; + source[2] = 0x0e41; + source[3] = 0x0e02; + source[4] = 0x0e27; + source[5] = 0x61; + source[6] = 0x62; + source[7] = 0x63; + source[8] = 0; + + coll = ucol_open("th_TH", &status); + log_verbose("Thai locale testing back and forth with normalization\n"); + iter=ucol_openElements(coll, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(coll); + + /* prev test */ + source[0] = 0x0061; + source[1] = 0x30CF; + source[2] = 0x3099; + source[3] = 0x30FC; + source[4] = 0; + + coll = ucol_open("ja_JP", &status); + log_verbose("Japanese locale testing back and forth with normalization\n"); + iter=ucol_openElements(coll, source, u_strlen(source), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + return; + } + backAndForth(iter); + ucol_closeElements(iter); + ucol_close(coll); + + free(source); + free(test1); + free(test2); +} + +/** + * Test for getOffset() and setOffset() + */ +static void TestOffset() +{ + UErrorCode status= U_ZERO_ERROR; + UCollator *en_us=NULL; + UCollationElements *iter, *pristine; + int32_t offset; + int32_t *orders; + int32_t orderLength=0; + int count = 0; + test1=(UChar*)malloc(sizeof(UChar) * 50); + test2=(UChar*)malloc(sizeof(UChar) * 50); + u_uastrcpy(test1, "What subset of all possible test cases?"); + u_uastrcpy(test2, "has the highest probability of detecting"); + en_us = ucol_open("en_US", &status); + log_verbose("Testing getOffset and setOffset for collations\n"); + iter = ucol_openElements(en_us, test1, u_strlen(test1), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + + /* testing boundaries */ + ucol_setOffset(iter, 0, &status); + if (U_FAILURE(status) || ucol_previous(iter, &status) != UCOL_NULLORDER) { + log_err("Error: After setting offset to 0, we should be at the end " + "of the backwards iteration"); + } + ucol_setOffset(iter, u_strlen(test1), &status); + if (U_FAILURE(status) || ucol_next(iter, &status) != UCOL_NULLORDER) { + log_err("Error: After setting offset to end of the string, we should " + "be at the end of the backwards iteration"); + } + + /* Run all the way through the iterator, then get the offset */ + + orders = getOrders(iter, &orderLength); + + offset = ucol_getOffset(iter); + + if (offset != u_strlen(test1)) + { + log_err("offset at end != length %d vs %d\n", offset, + u_strlen(test1) ); + } + + /* Now set the offset back to the beginning and see if it works */ + pristine=ucol_openElements(en_us, test1, u_strlen(test1), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + status = U_ZERO_ERROR; + + ucol_setOffset(iter, 0, &status); + if (U_FAILURE(status)) + { + log_err("setOffset failed. %s\n", myErrorName(status)); + } + else + { + assertEqual(iter, pristine); + } + + ucol_closeElements(pristine); + ucol_closeElements(iter); + free(orders); + + /* testing offsets in normalization buffer */ + test1[0] = 0x61; + test1[1] = 0x300; + test1[2] = 0x316; + test1[3] = 0x62; + test1[4] = 0; + ucol_setAttribute(en_us, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + iter = ucol_openElements(en_us, test1, 4, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + + count = 0; + while (ucol_next(iter, &status) != UCOL_NULLORDER && + U_SUCCESS(status)) { + switch (count) { + case 0: + if (ucol_getOffset(iter) != 1) { + log_err("ERROR: Offset of iteration should be 0\n"); + } + break; + case 3: + if (ucol_getOffset(iter) != 4) { + log_err("ERROR: Offset of iteration should be 4\n"); + } + break; + default: + if (ucol_getOffset(iter) != 3) { + log_err("ERROR: Offset of iteration should be 3\n"); + } + } + count ++; + } + + ucol_reset(iter); + count = 0; + while (ucol_previous(iter, &status) != UCOL_NULLORDER && + U_SUCCESS(status)) { + switch (count) { + case 0: + if (ucol_getOffset(iter) != 3) { + log_err("ERROR: Offset of iteration should be 3\n"); + } + break; + default: + if (ucol_getOffset(iter) != 0) { + log_err("ERROR: Offset of iteration should be 0\n"); + } + } + count ++; + } + + if(U_FAILURE(status)){ + log_err("ERROR: in iterating collation elements %s\n", + myErrorName(status)); + } + + ucol_closeElements(iter); + ucol_close(en_us); + free(test1); + free(test2); +} + +/** + * Test for setText() + */ +static void TestSetText() +{ + int32_t c,i; + UErrorCode status = U_ZERO_ERROR; + UCollator *en_us=NULL; + UCollationElements *iter1, *iter2; + test1=(UChar*)malloc(sizeof(UChar) * 50); + test2=(UChar*)malloc(sizeof(UChar) * 50); + u_uastrcpy(test1, "What subset of all possible test cases?"); + u_uastrcpy(test2, "has the highest probability of detecting"); + en_us = ucol_open("en_US", &status); + log_verbose("testing setText for Collation elements\n"); + iter1=ucol_openElements(en_us, test1, u_strlen(test1), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator1 using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + iter2=ucol_openElements(en_us, test2, u_strlen(test2), &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of collation element iterator2 using ucol_openElements()\n %s\n", + myErrorName(status)); + ucol_close(en_us); + return; + } + + /* Run through the second iterator just to exercise it */ + c = ucol_next(iter2, &status); + i = 0; + + while ( ++i < 10 && (c != UCOL_NULLORDER)) + { + if (U_FAILURE(status)) + { + log_err("iter2->next() returned an error. %s\n", myErrorName(status)); + ucol_closeElements(iter2); + ucol_closeElements(iter1); + ucol_close(en_us); + return; + } + + c = ucol_next(iter2, &status); + } + + /* Now set it to point to the same string as the first iterator */ + ucol_setText(iter2, test1, u_strlen(test1), &status); + if (U_FAILURE(status)) + { + log_err("call to iter2->setText(test1) failed. %s\n", myErrorName(status)); + } + else + { + assertEqual(iter1, iter2); + } + + /* Now set it to point to a null string with fake length*/ + ucol_setText(iter2, NULL, 2, &status); + if (U_FAILURE(status)) + { + log_err("call to iter2->setText(null) failed. %s\n", myErrorName(status)); + } + else + { + if (ucol_next(iter2, &status) != UCOL_NULLORDER) { + log_err("iter2 with null text expected to return UCOL_NULLORDER\n"); + } + } + + ucol_closeElements(iter2); + ucol_closeElements(iter1); + ucol_close(en_us); + free(test1); + free(test2); +} + +/** @bug 4108762 + * Test for getMaxExpansion() + */ +static void TestMaxExpansion() +{ + UErrorCode status = U_ZERO_ERROR; + UCollator *coll ;/*= ucol_open("en_US", &status);*/ + UChar ch = 0; + UChar32 unassigned = 0xEFFFD; + UChar supplementary[2]; + uint32_t index = 0; + UBool isError = FALSE; + uint32_t sorder = 0; + UCollationElements *iter ;/*= ucol_openElements(coll, &ch, 1, &status);*/ + uint32_t temporder = 0; + + UChar rule[256]; + u_uastrcpy(rule, "&a < ab < c/aba < d < z < ch"); + coll = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT, + UCOL_DEFAULT_STRENGTH,NULL, &status); + if(U_SUCCESS(status) && coll) { + iter = ucol_openElements(coll, &ch, 1, &status); + + while (ch < 0xFFFF && U_SUCCESS(status)) { + int count = 1; + uint32_t order; + int32_t size = 0; + + ch ++; + + ucol_setText(iter, &ch, 1, &status); + order = ucol_previous(iter, &status); + + /* thai management */ + if (order == 0) + order = ucol_previous(iter, &status); + + while (U_SUCCESS(status) && + ucol_previous(iter, &status) != UCOL_NULLORDER) { + count ++; + } + + size = ucol_getMaxExpansion(iter, order); + if (U_FAILURE(status) || size < count) { + log_err("Failure at codepoint %d, maximum expansion count < %d\n", + ch, count); + } + } + + /* testing for exact max expansion */ + ch = 0; + while (ch < 0x61) { + uint32_t order; + int32_t size; + ucol_setText(iter, &ch, 1, &status); + order = ucol_previous(iter, &status); + size = ucol_getMaxExpansion(iter, order); + if (U_FAILURE(status) || size != 1) { + log_err("Failure at codepoint %d, maximum expansion count < %d\n", + ch, 1); + } + ch ++; + } + + ch = 0x63; + ucol_setText(iter, &ch, 1, &status); + temporder = ucol_previous(iter, &status); + + if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 3) { + log_err("Failure at codepoint %d, maximum expansion count != %d\n", + ch, 3); + } + + ch = 0x64; + ucol_setText(iter, &ch, 1, &status); + temporder = ucol_previous(iter, &status); + + if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 1) { + log_err("Failure at codepoint %d, maximum expansion count != %d\n", + ch, 3); + } + + U16_APPEND(supplementary, index, 2, unassigned, isError); + ucol_setText(iter, supplementary, 2, &status); + sorder = ucol_previous(iter, &status); + + if (U_FAILURE(status) || ucol_getMaxExpansion(iter, sorder) != 2) { + log_err("Failure at codepoint %d, maximum expansion count < %d\n", + ch, 2); + } + + /* testing jamo */ + ch = 0x1165; + + ucol_setText(iter, &ch, 1, &status); + temporder = ucol_previous(iter, &status); + if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) > 3) { + log_err("Failure at codepoint %d, maximum expansion count > %d\n", + ch, 3); + } + + ucol_closeElements(iter); + ucol_close(coll); + + /* testing special jamo &a<\u1160 */ + rule[0] = 0x26; + rule[1] = 0x71; + rule[2] = 0x3c; + rule[3] = 0x1165; + rule[4] = 0x2f; + rule[5] = 0x71; + rule[6] = 0x71; + rule[7] = 0x71; + rule[8] = 0x71; + rule[9] = 0; + + coll = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT, + UCOL_DEFAULT_STRENGTH,NULL, &status); + iter = ucol_openElements(coll, &ch, 1, &status); + + temporder = ucol_previous(iter, &status); + if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 6) { + log_err("Failure at codepoint %d, maximum expansion count > %d\n", + ch, 5); + } + + ucol_closeElements(iter); + ucol_close(coll); + } else { + log_data_err("Couldn't open collator\n"); + } + +} + + +static void assertEqual(UCollationElements *i1, UCollationElements *i2) +{ + int32_t c1, c2; + int32_t count = 0; + UErrorCode status = U_ZERO_ERROR; + + do + { + c1 = ucol_next(i1, &status); + c2 = ucol_next(i2, &status); + + if (c1 != c2) + { + log_err("Error in iteration %d assetEqual between\n %d and %d, they are not equal\n", count, c1, c2); + break; + } + + count += 1; + } + while (c1 != UCOL_NULLORDER); +} + +/** + * Testing iterators with extremely small buffers + */ +static void TestSmallBuffer() +{ + UErrorCode status = U_ZERO_ERROR; + UCollator *coll; + UCollationElements *testiter, + *iter; + int32_t count = 0; + int32_t *testorders, + *orders; + + UChar teststr[500]; + UChar str[] = {0x300, 0x31A, 0}; + /* + creating a long string of decomposable characters, + since by default the writable buffer is of size 256 + */ + while (count < 500) { + if ((count & 1) == 0) { + teststr[count ++] = 0x300; + } + else { + teststr[count ++] = 0x31A; + } + } + + coll = ucol_open("th_TH", &status); + if(U_SUCCESS(status) && coll) { + testiter = ucol_openElements(coll, teststr, 500, &status); + iter = ucol_openElements(coll, str, 2, &status); + + orders = getOrders(iter, &count); + if (count != 2) { + log_err("Error collation elements size is not 2 for \\u0300\\u031A\n"); + } + + /* + this will rearrange the string data to 250 characters of 0x300 first then + 250 characters of 0x031A + */ + testorders = getOrders(testiter, &count); + + if (count != 500) { + log_err("Error decomposition does not give the right sized collation elements\n"); + } + + while (count != 0) { + /* UCA collation element for 0x0F76 */ + if ((count > 250 && testorders[-- count] != orders[1]) || + (count <= 250 && testorders[-- count] != orders[0])) { + log_err("Error decomposition does not give the right collation element at %d count\n", count); + break; + } + } + + free(testorders); + free(orders); + + ucol_reset(testiter); + /* ensures that the writable buffer was cleared */ + if (testiter->iteratordata_.writableBuffer != + testiter->iteratordata_.stackWritableBuffer) { + log_err("Error Writable buffer in collation element iterator not reset\n"); + } + + /* ensures closing of elements done properly to clear writable buffer */ + ucol_next(testiter, &status); + ucol_next(testiter, &status); + ucol_closeElements(testiter); + ucol_closeElements(iter); + ucol_close(coll); + } else { + log_data_err("Couldn't open collator\n"); + } +} + +/** +* Sniplets of code from genuca +*/ +static int32_t hex2num(char hex) { + if(hex>='0' && hex <='9') { + return hex-'0'; + } else if(hex>='a' && hex<='f') { + return hex-'a'+10; + } else if(hex>='A' && hex<='F') { + return hex-'A'+10; + } else { + return 0; + } +} + +/** +* Getting codepoints from a string +* @param str character string contain codepoints seperated by space and ended +* by a semicolon +* @param codepoints array for storage, assuming size > 5 +* @return position at the end of the codepoint section +*/ +static char * getCodePoints(char *str, UChar *codepoints) { + char *pStartCP = str; + char *pEndCP = str + 4; + + *codepoints = (UChar)((hex2num(*pStartCP) << 12) | + (hex2num(*(pStartCP + 1)) << 8) | + (hex2num(*(pStartCP + 2)) << 4) | + (hex2num(*(pStartCP + 3)))); + codepoints ++; + while (*pEndCP != ';') { + pStartCP = pEndCP + 1; + *codepoints = (UChar)((hex2num(*pStartCP) << 12) | + (hex2num(*(pStartCP + 1)) << 8) | + (hex2num(*(pStartCP + 2)) << 4) | + (hex2num(*(pStartCP + 3)))); + codepoints ++; + pEndCP = pStartCP + 4; + } + *codepoints = 0; + return pEndCP + 1; +} + +/** +* Sniplets of code from genuca +*/ +static int32_t +readElement(char **from, char *to, char separator, UErrorCode *status) +{ + if (U_SUCCESS(*status)) { + char buffer[1024]; + int32_t i = 0; + while (**from != separator) { + if (**from != ' ') { + *(buffer+i++) = **from; + } + (*from)++; + } + (*from)++; + *(buffer + i) = 0; + strcpy(to, buffer); + return i/2; + } + + return 0; +} + +/** +* Sniplets of code from genuca +*/ +static uint32_t +getSingleCEValue(char *primary, char *secondary, char *tertiary, + UErrorCode *status) +{ + if (U_SUCCESS(*status)) { + uint32_t value = 0; + char primsave = '\0'; + char secsave = '\0'; + char tersave = '\0'; + char *primend = primary+4; + char *secend = secondary+2; + char *terend = tertiary+2; + uint32_t primvalue; + uint32_t secvalue; + uint32_t tervalue; + + if (uprv_strlen(primary) > 4) { + primsave = *primend; + *primend = '\0'; + } + + if (uprv_strlen(secondary) > 2) { + secsave = *secend; + *secend = '\0'; + } + + if (uprv_strlen(tertiary) > 2) { + tersave = *terend; + *terend = '\0'; + } + + primvalue = (*primary!='\0')?uprv_strtoul(primary, &primend, 16):0; + secvalue = (*secondary!='\0')?uprv_strtoul(secondary, &secend, 16):0; + tervalue = (*tertiary!='\0')?uprv_strtoul(tertiary, &terend, 16):0; + if(primvalue <= 0xFF) { + primvalue <<= 8; + } + + value = ((primvalue << UCOL_PRIMARYORDERSHIFT) & UCOL_PRIMARYORDERMASK) + | ((secvalue << UCOL_SECONDARYORDERSHIFT) & UCOL_SECONDARYORDERMASK) + | (tervalue & UCOL_TERTIARYORDERMASK); + + if(primsave!='\0') { + *primend = primsave; + } + if(secsave!='\0') { + *secend = secsave; + } + if(tersave!='\0') { + *terend = tersave; + } + return value; + } + return 0; +} + +/** +* Getting collation elements generated from a string +* @param str character string contain collation elements contained in [] and +* seperated by space +* @param ce array for storage, assuming size > 20 +* @param status error status +* @return position at the end of the codepoint section +*/ +static char * getCEs(char *str, uint32_t *ces, UErrorCode *status) { + char *pStartCP = uprv_strchr(str, '['); + int count = 0; + char *pEndCP; + char primary[100]; + char secondary[100]; + char tertiary[100]; + + while (*pStartCP == '[') { + uint32_t primarycount = 0; + uint32_t secondarycount = 0; + uint32_t tertiarycount = 0; + uint32_t CEi = 1; + pEndCP = strchr(pStartCP, ']'); + if(pEndCP == NULL) { + break; + } + pStartCP ++; + + primarycount = readElement(&pStartCP, primary, ',', status); + secondarycount = readElement(&pStartCP, secondary, ',', status); + tertiarycount = readElement(&pStartCP, tertiary, ']', status); + + /* I want to get the CEs entered right here, including continuation */ + ces[count ++] = getSingleCEValue(primary, secondary, tertiary, status); + if (U_FAILURE(*status)) { + break; + } + + while (2 * CEi < primarycount || CEi < secondarycount || + CEi < tertiarycount) { + uint32_t value = UCOL_CONTINUATION_MARKER; /* Continuation marker */ + if (2 * CEi < primarycount) { + value |= ((hex2num(*(primary + 4 * CEi)) & 0xF) << 28); + value |= ((hex2num(*(primary + 4 * CEi + 1)) & 0xF) << 24); + } + + if (2 * CEi + 1 < primarycount) { + value |= ((hex2num(*(primary + 4 * CEi + 2)) & 0xF) << 20); + value |= ((hex2num(*(primary + 4 * CEi + 3)) &0xF) << 16); + } + + if (CEi < secondarycount) { + value |= ((hex2num(*(secondary + 2 * CEi)) & 0xF) << 12); + value |= ((hex2num(*(secondary + 2 * CEi + 1)) & 0xF) << 8); + } + + if (CEi < tertiarycount) { + value |= ((hex2num(*(tertiary + 2 * CEi)) & 0x3) << 4); + value |= (hex2num(*(tertiary + 2 * CEi + 1)) & 0xF); + } + + CEi ++; + ces[count ++] = value; + } + + pStartCP = pEndCP + 1; + } + ces[count] = 0; + return pStartCP; +} + +/** +* Getting the FractionalUCA.txt file stream +*/ +static FileStream * getFractionalUCA(void) +{ + char newPath[256]; + char backupPath[256]; + FileStream *result = NULL; + + /* Look inside ICU_DATA first */ + uprv_strcpy(newPath, ctest_dataSrcDir()); + uprv_strcat(newPath, "unidata" U_FILE_SEP_STRING ); + uprv_strcat(newPath, "FractionalUCA.txt"); + + /* As a fallback, try to guess where the source data was located + * at the time ICU was built, and look there. + */ +#if defined (U_TOPSRCDIR) + strcpy(backupPath, U_TOPSRCDIR U_FILE_SEP_STRING "data"); +#else + { + UErrorCode errorCode = U_ZERO_ERROR; + strcpy(backupPath, loadTestData(&errorCode)); + strcat(backupPath, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data"); + } +#endif + strcat(backupPath, U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING "FractionalUCA.txt"); + + result = T_FileStream_open(newPath, "rb"); + + if (result == NULL) { + result = T_FileStream_open(backupPath, "rb"); + if (result == NULL) { + log_err("Failed to open either %s or %s\n", newPath, backupPath); + } + } + return result; +} + +/** +* Testing the CEs returned by the iterator +*/ +static void TestCEs() { + FileStream *file = NULL; + char line[1024]; + char *str; + UChar codepoints[5]; + uint32_t ces[20]; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("", &status); + uint32_t lineNo = 0; + + if (U_FAILURE(status)) { + log_err("Error in opening root collator\n"); + return; + } + + file = getFractionalUCA(); + + if (file == NULL) { + log_err("*** unable to open input FractionalUCA.txt file ***\n"); + return; + } + + + while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) { + int count = 0; + UCollationElements *iter; + lineNo++; + /* skip this line if it is empty or a comment or is a return value + or start of some variable section */ + if(line[0] == 0 || line[0] == '#' || line[0] == '\n' || + line[0] == 0x000D || line[0] == '[') { + continue; + } + + str = getCodePoints(line, codepoints); + + /* these are 'fake' codepoints in the fractional UCA, and are used just + * for positioning of indirect values. They should not go through this + * test. + */ + if(*codepoints == 0xFDD0) { + continue; + } + + getCEs(str, ces, &status); + if (U_FAILURE(status)) { + log_err("Error in parsing collation elements in FractionalUCA.txt\n"); + break; + } + iter = ucol_openElements(coll, codepoints, -1, &status); + if (U_FAILURE(status)) { + log_err("Error in opening collation elements\n"); + break; + } + for (;;) { + uint32_t ce = (uint32_t)ucol_next(iter, &status); + if (ce == 0xFFFFFFFF) { + ce = 0; + } + /* we now unconditionally reorder Thai/Lao prevowels, so this + * test would fail if we don't skip here. + */ + if(UCOL_ISTHAIPREVOWEL(*codepoints) && ce == 0 && count == 0) { + continue; + } + if (ce != ces[count] || U_FAILURE(status)) { + log_err("Collation elements in FractionalUCA.txt and iterators do not match!\n"); + break; + } + if (ces[count] == 0) { + break; + } + count ++; + } + ucol_closeElements(iter); + } + + T_FileStream_close(file); + ucol_close(coll); +} + +/** +* Testing the discontigous contractions +*/ +static void TestDiscontiguos() { + const char *rulestr = + "&z < AB < X\\u0300 < ABC < X\\u0300\\u0315"; + UChar rule[50]; + int rulelen = u_unescape(rulestr, rule, 50); + const char *src[] = { + "ADB", "ADBC", "A\\u0315B", "A\\u0315BC", + /* base character blocked */ + "XD\\u0300", "XD\\u0300\\u0315", + /* non blocking combining character */ + "X\\u0319\\u0300", "X\\u0319\\u0300\\u0315", + /* blocking combining character */ + "X\\u0314\\u0300", "X\\u0314\\u0300\\u0315", + /* contraction prefix */ + "ABDC", "AB\\u0315C","X\\u0300D\\u0315", "X\\u0300\\u0319\\u0315", + "X\\u0300\\u031A\\u0315", + /* ends not with a contraction character */ + "X\\u0319\\u0300D", "X\\u0319\\u0300\\u0315D", "X\\u0300D\\u0315D", + "X\\u0300\\u0319\\u0315D", "X\\u0300\\u031A\\u0315D" + }; + const char *tgt[] = { + /* non blocking combining character */ + "A D B", "A D BC", "A \\u0315 B", "A \\u0315 BC", + /* base character blocked */ + "X D \\u0300", "X D \\u0300\\u0315", + /* non blocking combining character */ + "X\\u0300 \\u0319", "X\\u0300\\u0315 \\u0319", + /* blocking combining character */ + "X \\u0314 \\u0300", "X \\u0314 \\u0300\\u0315", + /* contraction prefix */ + "AB DC", "AB \\u0315 C","X\\u0300 D \\u0315", "X\\u0300\\u0315 \\u0319", + "X\\u0300 \\u031A \\u0315", + /* ends not with a contraction character */ + "X\\u0300 \\u0319D", "X\\u0300\\u0315 \\u0319D", "X\\u0300 D\\u0315D", + "X\\u0300\\u0315 \\u0319D", "X\\u0300 \\u031A\\u0315D" + }; + int size = 20; + UCollator *coll; + UErrorCode status = U_ZERO_ERROR; + int count = 0; + UCollationElements *iter; + UCollationElements *resultiter; + + coll = ucol_openRules(rule, rulelen, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + iter = ucol_openElements(coll, rule, 1, &status); + resultiter = ucol_openElements(coll, rule, 1, &status); + + if (U_FAILURE(status)) { + log_err("Error opening collation rules\n"); + return; + } + + while (count < size) { + UChar str[20]; + UChar tstr[20]; + int strLen = u_unescape(src[count], str, 20); + UChar *s; + + ucol_setText(iter, str, strLen, &status); + if (U_FAILURE(status)) { + log_err("Error opening collation iterator\n"); + return; + } + + u_unescape(tgt[count], tstr, 20); + s = tstr; + + log_verbose("count %d\n", count); + + for (;;) { + uint32_t ce; + UChar *e = u_strchr(s, 0x20); + if (e == 0) { + e = u_strchr(s, 0); + } + ucol_setText(resultiter, s, (int32_t)(e - s), &status); + ce = ucol_next(resultiter, &status); + if (U_FAILURE(status)) { + log_err("Error manipulating collation iterator\n"); + return; + } + while (ce != UCOL_NULLORDER) { + if (ce != (uint32_t)ucol_next(iter, &status) || + U_FAILURE(status)) { + log_err("Discontiguos contraction test mismatch\n"); + return; + } + ce = ucol_next(resultiter, &status); + if (U_FAILURE(status)) { + log_err("Error getting next collation element\n"); + return; + } + } + s = e + 1; + if (*e == 0) { + break; + } + } + ucol_reset(iter); + backAndForth(iter); + count ++; + } + ucol_closeElements(resultiter); + ucol_closeElements(iter); + ucol_close(coll); +} + +static void TestCEBufferOverflow() +{ + UChar str[UCOL_EXPAND_CE_BUFFER_SIZE + 1]; + UErrorCode status = U_ZERO_ERROR; + UChar rule[10]; + UCollator *coll; + UCollationElements *iter; + + u_uastrcpy(rule, "&z < AB"); + coll = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL,&status); + if (U_FAILURE(status)) { + log_err("Rule based collator not created for testing ce buffer overflow\n"); + return; + } + + /* 0xDCDC is a trail surrogate hence deemed unsafe by the heuristic + test. this will cause an overflow in getPrev */ + str[0] = 0x0041; /* 'A' */ + /*uprv_memset(str + 1, 0xE0, sizeof(UChar) * UCOL_EXPAND_CE_BUFFER_SIZE);*/ + uprv_memset(str + 1, 0xDC, sizeof(UChar) * UCOL_EXPAND_CE_BUFFER_SIZE); + str[UCOL_EXPAND_CE_BUFFER_SIZE] = 0x0042; /* 'B' */ + iter = ucol_openElements(coll, str, UCOL_EXPAND_CE_BUFFER_SIZE + 1, + &status); + if (ucol_previous(iter, &status) != UCOL_NULLORDER || + status != U_BUFFER_OVERFLOW_ERROR) { + log_err("CE buffer expected to overflow with long string of trail surrogates\n"); + } + ucol_closeElements(iter); + ucol_close(coll); +} + +/** +* Byte bounds checks. Checks if each byte in data is between upper and lower +* inclusive. +*/ +static UBool checkByteBounds(uint32_t data, char upper, char lower) +{ + int count = 4; + while (count > 0) { + char b = (char)(data & 0xFF); + if (b > upper || b < lower) { + return FALSE; + } + data = data >> 8; + count --; + } + return TRUE; +} + +/** +* Determines case of the string of codepoints. +* If it is a multiple codepoints it has to treated as a contraction. +*/ +#if 0 +static uint8_t getCase(const UChar *s, uint32_t len) { + UBool lower = FALSE; + UBool upper = FALSE; + UBool title = FALSE; + UErrorCode status = U_ZERO_ERROR; + UChar str[256]; + const UChar *ps = s; + + if (len == 0) { + return UCOL_LOWER_CASE; + } + + while (len > 0) { + UChar c = *ps ++; + + if (u_islower(c)) { + lower = TRUE; + } + if (u_isupper(c)) { + upper = TRUE; + } + if (u_istitle(c)) { + title = TRUE; + } + + len --; + } + if ((lower && !upper && !title) || (!lower && !upper && !title)){ + return UCOL_LOWER_CASE; + } + if (upper && !lower && !title) { + return UCOL_UPPER_CASE; + } + /* mix of cases here */ + /* len = unorm_normalize(s, len, UNORM_NFKD, 0, str, 256, &status); + if (U_FAILURE(status)) { + log_err("Error normalizing data string\n"); + return UCOL_LOWER_CASE; + }*/ + + if ((title && len >= 2) || (lower && upper)) { + return UCOL_MIXED_CASE; + } + if (u_isupper(s[0])) { + return UCOL_UPPER_CASE; + } + return UCOL_LOWER_CASE; +} +#endif + +/** +* Checking collation element validity given the boundary arguments. +*/ +static UBool checkCEValidity(const UCollator *coll, const UChar *codepoints, + int length, uint32_t primarymax, + uint32_t secondarymax) +{ + UErrorCode status = U_ZERO_ERROR; + UCollationElements *iter = ucol_openElements(coll, codepoints, length, + &status); + uint32_t ce; + UBool first = TRUE; +/* + UBool upper = FALSE; + UBool lower = FALSE; +*/ + + if (U_FAILURE(status)) { + log_err("Error creating iterator for testing validity\n"); + } + + ce = ucol_next(iter, &status); + + while (ce != UCOL_NULLORDER) { + if (ce != 0) { + uint32_t primary = UCOL_PRIMARYORDER(ce); + uint32_t secondary = UCOL_SECONDARYORDER(ce); + uint32_t tertiary = UCOL_TERTIARYORDER(ce); +/* uint32_t scasebits = tertiary & 0xC0;*/ + + if ((tertiary == 0 && secondary != 0) || + (tertiary < 0xC0 && secondary == 0 && primary != 0)) { + /* n-1th level is not zero when the nth level is + except for continuations, this is wrong */ + log_err("Lower level weight not 0 when high level weight is 0\n"); + goto fail; + } + else { + /* checks if any byte is illegal ie = 01 02 03. */ + if (checkByteBounds(ce, 0x3, 0x1)) { + log_err("Byte range in CE lies in illegal bounds 0x1 - 0x3\n"); + goto fail; + } + } + if ((primary != 0 && primary < primarymax) + || ((primary & 0xFF) == 0xFF) || (((primary>>8) & 0xFF) == 0xFF) + || ((primary & 0xFF) && ((primary & 0xFF) <= 0x03)) + || (((primary>>8) & 0xFF) && ((primary>>8) & 0xFF) <= 0x03) + || (primary >= 0xFE00 && !isContinuation(ce))) { + log_err("UCA primary weight out of bounds: %04X for string starting with %04X\n", + primary, codepoints[0]); + goto fail; + } + /* case matching not done since data generated by ken */ + if (first) { + if (secondary >= 6 && secondary <= secondarymax) { + log_err("Secondary weight out of range\n"); + goto fail; + } + first = FALSE; + } + } + ce = ucol_next(iter, &status); + } + ucol_closeElements(iter); + return TRUE; +fail : + ucol_closeElements(iter); + return FALSE; +} + +static void TestCEValidity() +{ + /* testing UCA collation elements */ + UErrorCode status = U_ZERO_ERROR; + /* en_US has no tailorings */ + UCollator *coll = ucol_open("root", &status); + /* tailored locales */ + char locale[][11] = {"fr_FR", "ko_KR", "sh_YU", "th_TH", "zh_CN", "zh__PINYIN"}; + const char *loc; + FileStream *file = getFractionalUCA(); + char line[1024]; + UChar codepoints[10]; + int count = 0; + int maxCount = 0; + UParseError parseError; + if (U_FAILURE(status)) { + log_err("en_US collator creation failed\n"); + return; + } + log_verbose("Testing UCA elements\n"); + if (file == NULL) { + log_err("Fractional UCA data can not be opened\n"); + return; + } + + while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) { + if(line[0] == 0 || line[0] == '#' || line[0] == '\n' || + line[0] == 0x000D || line[0] == '[') { + continue; + } + + getCodePoints(line, codepoints); + checkCEValidity(coll, codepoints, u_strlen(codepoints), 5, 86); + } + + log_verbose("Testing UCA elements for the whole range of unicode characters\n"); + codepoints[0] = 0; + while (codepoints[0] < 0xFFFF) { + if (u_isdefined((UChar32)codepoints[0])) { + checkCEValidity(coll, codepoints, 1, 5, 86); + } + codepoints[0] ++; + } + + ucol_close(coll); + + /* testing tailored collation elements */ + log_verbose("Testing tailored elements\n"); + if(QUICK) { + maxCount = sizeof(locale)/sizeof(locale[0]); + } else { + maxCount = uloc_countAvailable(); + } + while (count < maxCount) { + const UChar *rules = NULL, + *current = NULL; + UChar *rulesCopy = NULL; + int32_t ruleLen = 0; + + uint32_t chOffset = 0; + uint32_t chLen = 0; + uint32_t exOffset = 0; + uint32_t exLen = 0; + uint32_t prefixOffset = 0; + uint32_t prefixLen = 0; + UBool startOfRules = TRUE; + UColOptionSet opts; + + UColTokenParser src; + uint32_t strength = 0; + uint16_t specs = 0; + if(QUICK) { + loc = locale[count]; + } else { + loc = uloc_getAvailable(count); + if(!hasCollationElements(loc)) { + count++; + continue; + } + } + + log_verbose("Testing CEs for %s\n", loc); + + coll = ucol_open(loc, &status); + if (U_FAILURE(status)) { + log_err("%s collator creation failed\n", loc); + return; + } + + src.opts = &opts; + rules = ucol_getRules(coll, &ruleLen); + + if (ruleLen > 0) { + rulesCopy = (UChar *)malloc((ruleLen + + UCOL_TOK_EXTRA_RULE_SPACE_SIZE) * sizeof(UChar)); + uprv_memcpy(rulesCopy, rules, ruleLen * sizeof(UChar)); + src.current = src.source = rulesCopy; + src.end = rulesCopy + ruleLen; + src.extraCurrent = src.end; + src.extraEnd = src.end + UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,&status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + uprv_memcpy(codepoints, src.source + chOffset, + chLen * sizeof(UChar)); + codepoints[chLen] = 0; + checkCEValidity(coll, codepoints, chLen, 4, 85); + } + free(rulesCopy); + } + + ucol_close(coll); + count ++; + } + T_FileStream_close(file); +} + +static void printSortKeyError(const UChar *codepoints, int length, + uint8_t *sortkey, int sklen) +{ + int count = 0; + log_err("Sortkey not valid for "); + while (length > 0) { + log_err("0x%04x ", *codepoints); + length --; + codepoints ++; + } + log_err("\nSortkey : "); + while (count < sklen) { + log_err("0x%02x ", sortkey[count]); + count ++; + } + log_err("\n"); +} + +/** +* Checking sort key validity for all levels +*/ +static UBool checkSortKeyValidity(UCollator *coll, + const UChar *codepoints, + int length) +{ + UErrorCode status = U_ZERO_ERROR; + UCollationStrength strength[5] = {UCOL_PRIMARY, UCOL_SECONDARY, + UCOL_TERTIARY, UCOL_QUATERNARY, + UCOL_IDENTICAL}; + int strengthlen = 5; + int index = 0; + int caselevel = 0; + + while (caselevel < 1) { + if (caselevel == 0) { + ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &status); + } + else { + ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &status); + } + + while (index < strengthlen) { + int count01 = 0; + uint32_t count = 0; + uint8_t sortkey[128]; + uint32_t sklen; + + ucol_setStrength(coll, strength[index]); + sklen = ucol_getSortKey(coll, codepoints, length, sortkey, 128); + while (sortkey[count] != 0) { + if (sortkey[count] == 2 || (sortkey[count] == 3 && count01 > 0 && index != 4)) { + printSortKeyError(codepoints, length, sortkey, sklen); + return FALSE; + } + if (sortkey[count] == 1) { + count01 ++; + } + count ++; + } + + if (count + 1 != sklen || (count01 != index + caselevel)) { + printSortKeyError(codepoints, length, sortkey, sklen); + return FALSE; + } + index ++; + } + caselevel ++; + } + return TRUE; +} + +static void TestSortKeyValidity(void) +{ + /* testing UCA collation elements */ + UErrorCode status = U_ZERO_ERROR; + /* en_US has no tailorings */ + UCollator *coll = ucol_open("en_US", &status); + /* tailored locales */ + char locale[][6] = {"fr_FR", "ko_KR", "sh_YU", "th_TH", "zh_CN"}; + FileStream *file = getFractionalUCA(); + char line[1024]; + UChar codepoints[10]; + int count = 0; + UParseError parseError; + if (U_FAILURE(status)) { + log_err("en_US collator creation failed\n"); + return; + } + log_verbose("Testing UCA elements\n"); + if (file == NULL) { + log_err("Fractional UCA data can not be opened\n"); + return; + } + + while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) { + if(line[0] == 0 || line[0] == '#' || line[0] == '\n' || + line[0] == 0x000D || line[0] == '[') { + continue; + } + + getCodePoints(line, codepoints); + checkSortKeyValidity(coll, codepoints, u_strlen(codepoints)); + } + + log_verbose("Testing UCA elements for the whole range of unicode characters\n"); + codepoints[0] = 0; + + while (codepoints[0] < 0xFFFF) { + if (u_isdefined((UChar32)codepoints[0])) { + checkSortKeyValidity(coll, codepoints, 1); + } + codepoints[0] ++; + } + + ucol_close(coll); + + /* testing tailored collation elements */ + log_verbose("Testing tailored elements\n"); + while (count < 5) { + const UChar *rules = NULL, + *current = NULL; + UChar *rulesCopy = NULL; + int32_t ruleLen = 0; + + uint32_t chOffset = 0; + uint32_t chLen = 0; + uint32_t exOffset = 0; + uint32_t exLen = 0; + uint32_t prefixOffset = 0; + uint32_t prefixLen = 0; + UBool startOfRules = TRUE; + UColOptionSet opts; + + UColTokenParser src; + uint32_t strength = 0; + uint16_t specs = 0; + + coll = ucol_open(locale[count], &status); + if (U_FAILURE(status)) { + log_err("%s collator creation failed\n", locale[count]); + return; + } + + src.opts = &opts; + rules = ucol_getRules(coll, &ruleLen); + + if (ruleLen > 0) { + rulesCopy = (UChar *)malloc((ruleLen + + UCOL_TOK_EXTRA_RULE_SPACE_SIZE) * sizeof(UChar)); + uprv_memcpy(rulesCopy, rules, ruleLen * sizeof(UChar)); + src.current = src.source = rulesCopy; + src.end = rulesCopy + ruleLen; + src.extraCurrent = src.end; + src.extraEnd = src.end + UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules,&parseError, &status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + uprv_memcpy(codepoints, src.source + chOffset, + chLen * sizeof(UChar)); + codepoints[chLen] = 0; + checkSortKeyValidity(coll, codepoints, chLen); + } + free(rulesCopy); + } + + ucol_close(coll); + count ++; + } + T_FileStream_close(file); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h new file mode 100644 index 00000000000..b810131c898 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h @@ -0,0 +1,118 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2003, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CITERTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ + +/** + * Collation Iterator tests. + * (Let me reiterate my position...) + */ + +#ifndef _CITERCOLLTST +#define _CITERCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/ucoleitr.h" +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 + + /** + * Test for CollationElementIterator previous and next for the whole set of + * unicode characters. + */ + static void TestUnicodeChar(void); + /** + * Test for CollationElementIterator previous and next for the whole set of + * unicode characters with normalization on. + */ + static void TestNormalizedUnicodeChar(void); + /** + * Test incremental normalization + */ + static void TestNormalization(void); + /** + * Test for CollationElementIterator.previous() + * + * @bug 4108758 - Make sure it works with contracting characters + * + */ + static void TestPrevious(void); + + /** + * Test for getOffset() and setOffset() + */ + static void TestOffset(void); + /** + * Test for setText() + */ + static void TestSetText(void); + /** @bug 4108762 + * Test for getMaxExpansion() + */ + static void TestMaxExpansion(void); + /** + * Test Bug 672, where different locales give a different offset after + * a previous for the same string at the same position + */ + static void TestBug672(void); + + /** + * Repeat TestBug672 with normalizatin enabled - this test revealed a bug + * in incremental normalization. + */ + static void TestBug672Normalize(void); + /** + * Test iterators with an relatively small buffer + */ + static void TestSmallBuffer(void); + /** + * Tests the CEs generated by the iterators. + */ + static void TestCEs(void); + /** + * Tests the discontiguos contractions + */ + static void TestDiscontiguos(void); + /** + * Tests that the iterators bails out when the CEBuffer is exhausted + */ + static void TestCEBufferOverflow(void); + /** + * Tests the validity of CEs generated by the iterators. + * Bound checkings. + */ + static void TestCEValidity(void); + /** + * Tests the validity of sortkeys generated by the iterators. + * Bound checkings. + */ + static void TestSortKeyValidity(void); + + /*------------------------------------------------------------------------ + Internal utilities + */ + + + static void assertEqual(UCollationElements *i1, UCollationElements *i2); + + + static UChar *test1; + static UChar *test2; + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c new file mode 100644 index 00000000000..7318e07cb93 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c @@ -0,0 +1,255 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CJAPTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +* synwee Added TestBase, TestPlainDakutenHandakuten, +* TestSmallLarge, TestKatakanaHiragana, +* TestChooonKigoo +*********************************************************************************/ +/** + * CollationKannaTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "cjaptst.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {0xff9E, 0x0000}, + {0x3042, 0x0000}, + {0x30A2, 0x0000}, + {0x3042, 0x3042, 0x0000}, + {0x30A2, 0x30FC, 0x0000}, + {0x30A2, 0x30FC, 0x30C8, 0x0000} /* 6 */ +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {0xFF9F, 0x0000}, + {0x30A2, 0x0000}, + {0x3042, 0x3042, 0x0000}, + {0x30A2, 0x30FC, 0x0000}, + {0x30A2, 0x30FC, 0x30C8, 0x0000}, + {0x3042, 0x3042, 0x3068, 0x0000} /* 6 */ +}; + +const static UCollationResult results[] = { + UCOL_LESS, + UCOL_EQUAL, /*UCOL_LESS*/ /* Katakanas and Hiraganas are equal on tertiary level(ICU 2.0)*/ + UCOL_LESS, + UCOL_GREATER, /*UCOL_LESS*/ /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/ + UCOL_LESS, + UCOL_LESS, /*UCOL_GREATER*/ /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*//* 6 */ +}; + +const static UChar testBaseCases[][MAX_TOKEN_LEN] = { + {0x30AB, 0x0000}, + {0x30AB, 0x30AD, 0x0000}, + {0x30AD, 0x0000}, + {0x30AD, 0x30AD, 0x0000} +}; + +const static UChar testPlainDakutenHandakutenCases[][MAX_TOKEN_LEN] = { + {0x30CF, 0x30AB, 0x0000}, + {0x30D0, 0x30AB, 0x0000}, + {0x30CF, 0x30AD, 0x0000}, + {0x30D0, 0x30AD, 0x0000} +}; + +const static UChar testSmallLargeCases[][MAX_TOKEN_LEN] = { + {0x30C3, 0x30CF, 0x0000}, + {0x30C4, 0x30CF, 0x0000}, + {0x30C3, 0x30D0, 0x0000}, + {0x30C4, 0x30D0, 0x0000} +}; + +const static UChar testKatakanaHiraganaCases[][MAX_TOKEN_LEN] = { + {0x3042, 0x30C3, 0x0000}, + {0x30A2, 0x30C3, 0x0000}, + {0x3042, 0x30C4, 0x0000}, + {0x30A2, 0x30C4, 0x0000} +}; + +const static UChar testChooonKigooCases[][MAX_TOKEN_LEN] = { + /*0*/ {0x30AB, 0x30FC, 0x3042, 0x0000}, + /*1*/ {0x30AB, 0x30FC, 0x30A2, 0x0000}, + /*2*/ {0x30AB, 0x30A4, 0x3042, 0x0000}, + /*3*/ {0x30AB, 0x30A4, 0x30A2, 0x0000}, + /*6*/ {0x30AD, 0x30FC, 0x3042, 0x0000}, /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/ + /*7*/ {0x30AD, 0x30FC, 0x30A2, 0x0000}, /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/ + /*4*/ {0x30AD, 0x30A4, 0x3042, 0x0000}, + /*5*/ {0x30AD, 0x30A4, 0x30A2, 0x0000}, +}; + +void addKannaCollTest(TestNode** root) +{ + addTest(root, &TestTertiary, "tscoll/cjacoll/TestTertiary"); + addTest(root, &TestBase, "tscoll/cjacoll/TestBase"); + addTest(root, &TestPlainDakutenHandakuten, "tscoll/cjacoll/TestPlainDakutenHandakuten"); + addTest(root, &TestSmallLarge, "tscoll/cjacoll/TestSmallLarge"); + addTest(root, &TestKatakanaHiragana, "tscoll/cjacoll/TestKatakanaHiragana"); + addTest(root, &TestChooonKigoo, "tscoll/cjacoll/TestChooonKigoo"); +} + +static void TestTertiary( ) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing Kanna(Japan) Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status); + for (i = 0; i < 6 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +/* Testing base letters */ +static void TestBase() +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if (U_FAILURE(status)) + { + log_err("ERROR: in creation of rule based collator: %s\n", + myErrorName(status)); + return; + } + + log_verbose("Testing Japanese Base Characters Collation\n"); + ucol_setStrength(myCollation, UCOL_PRIMARY); + for (i = 0; i < 3 ; i++) + doTest(myCollation, testBaseCases[i], testBaseCases[i + 1], UCOL_LESS); + + ucol_close(myCollation); +} + +/* Testing plain, Daku-ten, Handaku-ten letters */ +static void TestPlainDakutenHandakuten(void) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if (U_FAILURE(status)) + { + log_err("ERROR: in creation of rule based collator: %s\n", + myErrorName(status)); + return; + } + + log_verbose("Testing plain, Daku-ten, Handaku-ten letters Japanese Characters Collation\n"); + ucol_setStrength(myCollation, UCOL_SECONDARY); + for (i = 0; i < 3 ; i++) + doTest(myCollation, testPlainDakutenHandakutenCases[i], + testPlainDakutenHandakutenCases[i + 1], UCOL_LESS); + + ucol_close(myCollation); +} + +/* +* Test Small, Large letters +*/ +static void TestSmallLarge(void) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if (U_FAILURE(status)) + { + log_err("ERROR: in creation of rule based collator: %s\n", + myErrorName(status)); + return; + } + + log_verbose("Testing Japanese Small and Large Characters Collation\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status); + for (i = 0; i < 3 ; i++) + doTest(myCollation, testSmallLargeCases[i], testSmallLargeCases[i + 1], + UCOL_LESS); + + ucol_close(myCollation); +} + +/* +* Test Katakana, Hiragana letters +*/ +static void TestKatakanaHiragana(void) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if (U_FAILURE(status)) + { + log_err("ERROR: in creation of rule based collator: %s\n", + myErrorName(status)); + return; + } + + log_verbose("Testing Japanese Katakana, Hiragana Characters Collation\n"); + ucol_setStrength(myCollation, UCOL_QUATERNARY); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status); + for (i = 0; i < 3 ; i++) { + doTest(myCollation, testKatakanaHiraganaCases[i], + testKatakanaHiraganaCases[i + 1], UCOL_LESS); + } + + ucol_close(myCollation); +} + +/* +* Test Choo-on kigoo +*/ +static void TestChooonKigoo(void) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("ja_JP", &status); + if (U_FAILURE(status)) + { + log_err("ERROR: in creation of rule based collator: %s\n", + myErrorName(status)); + return; + } + + log_verbose("Testing Japanese Choo-on Kigoo Characters Collation\n"); + ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_QUATERNARY, &status); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status); + for (i = 0; i < 7 ; i++) { + doTest(myCollation, testChooonKigooCases[i], testChooonKigooCases[i + 1], + UCOL_LESS); + } + + ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h new file mode 100644 index 00000000000..311976b706b --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h @@ -0,0 +1,63 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CJAPTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +* synwee Added TestBase, TestPlainDakutenHandakuten, +* TestSmallLarge, TestKatakanaHiragana, +* TestChooonKigoo +*********************************************************************************/ +/** + * CollationKannaTest(JAPAN) is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CJACOLLTST +#define _CJACOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + + +#define MAX_TOKEN_LEN 16 + + + /*perform test with strength TERTIARY*/ +static void TestTertiary(void); + +/* Testing base letters */ +static void TestBase(void); + +/* Testing plain, Daku-ten, Handaku-ten letters */ +static void TestPlainDakutenHandakuten(void); + +/* +* Test Small, Large letters +*/ +static void TestSmallLarge(void); + +/* +* Test Katakana, Hiragana letters +*/ +static void TestKatakanaHiragana(void); + +/* +* Test Choo-on kigoo +*/ +static void TestChooonKigoo(void); + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c new file mode 100644 index 00000000000..b7ba4fe9b98 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c @@ -0,0 +1,1294 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ + +#include "cintltst.h" +#include "unicode/ures.h" +#include "unicode/ucurr.h" +#include "unicode/ustring.h" +#include "unicode/uset.h" +#include "unicode/udat.h" +#include "unicode/uscript.h" +#include "unicode/ulocdata.h" +#include "cstring.h" +#include "locmap.h" +#include "uresimp.h" + +/*-------------------------------------------------------------------- + Time bomb - allows temporary behavior that expires at a given + release + ---------------------------------------------------------------------*/ +static const UVersionInfo ICU_37 = {3,7,0,0}; + +/* +returns a new UnicodeSet that is a flattened form of the original +UnicodeSet. +*/ +static USet* +createFlattenSet(USet *origSet, UErrorCode *status) { + + + USet *newSet = NULL; + int32_t origItemCount = 0; + int32_t idx, graphmeSize; + UChar32 start, end; + UChar graphme[64]; + if (U_FAILURE(*status)) { + log_err("createFlattenSet called with %s\n", u_errorName(*status)); + return NULL; + } + newSet = uset_open(1, 0); + origItemCount = uset_getItemCount(origSet); + for (idx = 0; idx < origItemCount; idx++) { + graphmeSize = uset_getItem(origSet, idx, + &start, &end, + graphme, (int32_t)(sizeof(graphme)/sizeof(graphme[0])), + status); + if (U_FAILURE(*status)) { + log_err("ERROR: uset_getItem returned %s\n", u_errorName(*status)); + *status = U_ZERO_ERROR; + } + if (graphmeSize) { + uset_addAllCodePoints(newSet, graphme, graphmeSize); + } + else { + uset_addRange(newSet, start, end); + } + } + return newSet; +} +static UBool +isCurrencyPreEuro(const char* currencyKey){ + if( strcmp(currencyKey, "PTE") == 0 || + strcmp(currencyKey, "ESP") == 0 || + strcmp(currencyKey, "LUF") == 0 || + strcmp(currencyKey, "GRD") == 0 || + strcmp(currencyKey, "BEF") == 0 || + strcmp(currencyKey, "ITL") == 0 || + strcmp(currencyKey, "EEK") == 0){ + return TRUE; + } + return FALSE; +} +static void +TestKeyInRootRecursive(UResourceBundle *root, const char *rootName, + UResourceBundle *currentBundle, const char *locale) { + UErrorCode errorCode = U_ZERO_ERROR; + UResourceBundle *subRootBundle = NULL, *subBundle = NULL; + + ures_resetIterator(root); + ures_resetIterator(currentBundle); + while (ures_hasNext(currentBundle)) { + const char *subBundleKey = NULL; + const char *currentBundleKey = NULL; + + errorCode = U_ZERO_ERROR; + currentBundleKey = ures_getKey(currentBundle); + subBundle = ures_getNextResource(currentBundle, NULL, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("Can't open a resource for locale %s. Error: %s\n", locale, u_errorName(errorCode)); + continue; + } + subBundleKey = ures_getKey(subBundle); + + + subRootBundle = ures_getByKey(root, subBundleKey, NULL, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("Can't open a resource with key \"%s\" in \"%s\" from %s for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + rootName, + locale); + ures_close(subBundle); + continue; + } + if (ures_getType(subRootBundle) != ures_getType(subBundle)) { + log_err("key \"%s\" in \"%s\" has a different type from root for locale \"%s\"\n" + "\troot=%d, locale=%d\n", + subBundleKey, + ures_getKey(currentBundle), + locale, + ures_getType(subRootBundle), + ures_getType(subBundle)); + ures_close(subBundle); + continue; + } + else if (ures_getType(subBundle) == URES_INT_VECTOR) { + int32_t minSize; + int32_t subBundleSize; + int32_t idx; + UBool sameArray = TRUE; + const int32_t *subRootBundleArr = ures_getIntVector(subRootBundle, &minSize, &errorCode); + const int32_t *subBundleArr = ures_getIntVector(subBundle, &subBundleSize, &errorCode); + + if (minSize > subBundleSize) { + minSize = subBundleSize; + log_err("Arrays are different size with key \"%s\" in \"%s\" from root for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } + + for (idx = 0; idx < minSize && sameArray; idx++) { + if (subRootBundleArr[idx] != subBundleArr[idx]) { + sameArray = FALSE; + } + if (strcmp(subBundleKey, "DateTimeElements") == 0 + && (subBundleArr[idx] < 1 || 7 < subBundleArr[idx])) + { + log_err("Value out of range with key \"%s\" at index %d in \"%s\" for locale \"%s\"\n", + subBundleKey, + idx, + ures_getKey(currentBundle), + locale); + } + } + /* Special exception es_US and DateTimeElements */ + if (sameArray + && !(strcmp(locale, "es_US") == 0 && strcmp(subBundleKey, "DateTimeElements") == 0)) + { + log_err("Integer vectors are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } + } + else if (ures_getType(subBundle) == URES_ARRAY) { + UResourceBundle *subSubBundle = ures_getByIndex(subBundle, 0, NULL, &errorCode); + UResourceBundle *subSubRootBundle = ures_getByIndex(subRootBundle, 0, NULL, &errorCode); + + if (U_SUCCESS(errorCode) + && (ures_getType(subSubBundle) == URES_ARRAY || ures_getType(subSubRootBundle) == URES_ARRAY)) + { + /* Here is one of the recursive parts */ + TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); + } + else { + int32_t minSize = ures_getSize(subRootBundle); + int32_t idx; + UBool sameArray = TRUE; + + if (minSize > ures_getSize(subBundle)) { + minSize = ures_getSize(subBundle); + } + + if ((subBundleKey == NULL + || (subBundleKey != NULL && strcmp(subBundleKey, "LocaleScript") != 0 && !isCurrencyPreEuro(subBundleKey))) + && ures_getSize(subRootBundle) != ures_getSize(subBundle)) + { + log_err("Different size array with key \"%s\" in \"%s\" from root for locale \"%s\"\n" + "\troot array size=%d, locale array size=%d\n", + subBundleKey, + ures_getKey(currentBundle), + locale, + ures_getSize(subRootBundle), + ures_getSize(subBundle)); + } + /* + if(isCurrencyPreEuro(subBundleKey) && ures_getSize(subBundle)!=3){ + log_err("Different size array with key \"%s\" in \"%s\" for locale \"%s\" the expected size is 3 got size=%d\n", + subBundleKey, + ures_getKey(currentBundle), + locale, + ures_getSize(subBundle)); + } + */ + for (idx = 0; idx < minSize; idx++) { + int32_t rootStrLen, localeStrLen; + const UChar *rootStr = ures_getStringByIndex(subRootBundle,idx,&rootStrLen,&errorCode); + const UChar *localeStr = ures_getStringByIndex(subBundle,idx,&localeStrLen,&errorCode); + if (rootStr && localeStr && U_SUCCESS(errorCode)) { + if (u_strcmp(rootStr, localeStr) != 0) { + sameArray = FALSE; + } + } + else { + log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + idx, + locale); + continue; + } + if (localeStr[0] == (UChar)0x20) { + log_err("key \"%s\" at index %d in \"%s\" starts with a space in locale \"%s\"\n", + subBundleKey, + idx, + ures_getKey(currentBundle), + locale); + } + else if (localeStr[localeStrLen - 1] == (UChar)0x20) { + log_err("key \"%s\" at index %d in \"%s\" ends with a space in locale \"%s\"\n", + subBundleKey, + idx, + ures_getKey(currentBundle), + locale); + } + else if (subBundleKey != NULL + && strcmp(subBundleKey, "DateTimePatterns") == 0) + { + int32_t quoted = 0; + const UChar *localeStrItr = localeStr; + while (*localeStrItr) { + if (*localeStrItr == (UChar)0x27 /* ' */) { + quoted++; + } + else if ((quoted % 2) == 0) { + /* Search for unquoted characters */ + if (4 <= idx && idx <= 7 + && (*localeStrItr == (UChar)0x6B /* k */ + || *localeStrItr == (UChar)0x48 /* H */ + || *localeStrItr == (UChar)0x6D /* m */ + || *localeStrItr == (UChar)0x73 /* s */ + || *localeStrItr == (UChar)0x53 /* S */ + || *localeStrItr == (UChar)0x61 /* a */ + || *localeStrItr == (UChar)0x68 /* h */ + || *localeStrItr == (UChar)0x7A /* z */)) + { + log_err("key \"%s\" at index %d has time pattern chars in date for locale \"%s\"\n", + subBundleKey, + idx, + locale); + } + else if (0 <= idx && idx <= 3 + && (*localeStrItr == (UChar)0x47 /* G */ + || *localeStrItr == (UChar)0x79 /* y */ + || *localeStrItr == (UChar)0x4D /* M */ + || *localeStrItr == (UChar)0x64 /* d */ + || *localeStrItr == (UChar)0x45 /* E */ + || *localeStrItr == (UChar)0x44 /* D */ + || *localeStrItr == (UChar)0x46 /* F */ + || *localeStrItr == (UChar)0x77 /* w */ + || *localeStrItr == (UChar)0x57 /* W */)) + { + log_err("key \"%s\" at index %d has date pattern chars in time for locale \"%s\"\n", + subBundleKey, + idx, + locale); + } + } + localeStrItr++; + } + } + else if (idx == 4 && subBundleKey != NULL + && strcmp(subBundleKey, "NumberElements") == 0 + && u_charDigitValue(localeStr[0]) != 0) + { + log_err("key \"%s\" at index %d has a non-zero based number for locale \"%s\"\n", + subBundleKey, + idx, + locale); + } + } +/* if (sameArray && strcmp(rootName, "root") == 0) { + log_err("Arrays are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + }*/ + } + ures_close(subSubBundle); + ures_close(subSubRootBundle); + } + else if (ures_getType(subBundle) == URES_STRING) { + int32_t len = 0; + const UChar *string = ures_getString(subBundle, &len, &errorCode); + if (U_FAILURE(errorCode) || string == NULL) { + log_err("Can't open a string with key \"%s\" in \"%s\" for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } else if (string[0] == (UChar)0x20) { + log_err("key \"%s\" in \"%s\" starts with a space in locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } else if (string[len - 1] == (UChar)0x20) { + log_err("key \"%s\" in \"%s\" ends with a space in locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } else if (strcmp(subBundleKey, "localPatternChars") == 0) { + /* Note: We no longer import localPatternChars data starting + * ICU 3.8. So it never comes into this else if block. (ticket#5597) + */ + + /* Check well-formedness of localPatternChars. First, the + * length must match the number of fields defined by + * DateFormat. Second, each character in the string must + * be in the set [A-Za-z]. Finally, each character must be + * unique. + */ + int32_t i,j; +#if !UCONFIG_NO_FORMATTING + if (len != UDAT_FIELD_COUNT) { + log_err("key \"%s\" has the wrong number of characters in locale \"%s\"\n", + subBundleKey, + locale); + } +#endif + /* Check char validity. */ + for (i=0; i<len; ++i) { + if (!((string[i] >= 65/*'A'*/ && string[i] <= 90/*'Z'*/) || + (string[i] >= 97/*'a'*/ && string[i] <= 122/*'z'*/))) { + log_err("key \"%s\" has illegal character '%c' in locale \"%s\"\n", + subBundleKey, + (char) string[i], + locale); + } + /* Do O(n^2) check for duplicate chars. */ + for (j=0; j<i; ++j) { + if (string[j] == string[i]) { + log_err("key \"%s\" has duplicate character '%c' in locale \"%s\"\n", + subBundleKey, + (char) string[i], + locale); + } + } + } + } + /* No fallback was done. Check for duplicate data */ + /* The ures_* API does not do fallback of sub-resource bundles, + So we can't do this now. */ +#if 0 + else if (strcmp(locale, "root") != 0 && errorCode == U_ZERO_ERROR) { + + const UChar *rootString = ures_getString(subRootBundle, &len, &errorCode); + if (U_FAILURE(errorCode) || rootString == NULL) { + log_err("Can't open a string with key \"%s\" in \"%s\" in root\n", + ures_getKey(subRootBundle), + ures_getKey(currentBundle)); + continue; + } else if (u_strcmp(string, rootString) == 0) { + if (strcmp(locale, "de_CH") != 0 && strcmp(subBundleKey, "Countries") != 0 && + strcmp(subBundleKey, "Version") != 0) { + log_err("Found duplicate data with key \"%s\" in \"%s\" in locale \"%s\"\n", + ures_getKey(subRootBundle), + ures_getKey(currentBundle), + locale); + } + else { + /* Ignore for now. */ + /* Can be fixed if fallback through de locale was done. */ + log_verbose("Skipping key %s in %s\n", subBundleKey, locale); + } + } + } +#endif + } + else if (ures_getType(subBundle) == URES_TABLE) { + if (strcmp(subBundleKey, "availableFormats")!=0) { + /* Here is one of the recursive parts */ + TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale); + } + else { + log_verbose("Skipping key %s in %s\n", subBundleKey, locale); + } + } + else if (ures_getType(subBundle) == URES_BINARY || ures_getType(subBundle) == URES_INT) { + /* Can't do anything to check it */ + /* We'll assume it's all correct */ + if (strcmp(subBundleKey, "MeasurementSystem") != 0) { + log_verbose("Skipping key \"%s\" in \"%s\" for locale \"%s\"\n", + subBundleKey, + ures_getKey(currentBundle), + locale); + } + /* Testing for MeasurementSystem is done in VerifyTranslation */ + } + else { + log_err("Type %d for key \"%s\" in \"%s\" is unknown for locale \"%s\"\n", + ures_getType(subBundle), + subBundleKey, + ures_getKey(currentBundle), + locale); + } + ures_close(subRootBundle); + ures_close(subBundle); + } +} + + +static void +testLCID(UResourceBundle *currentBundle, + const char *localeName) +{ + UErrorCode status = U_ZERO_ERROR; + uint32_t expectedLCID; + char lcidStringC[64] = {0}; + + expectedLCID = uloc_getLCID(localeName); + if (expectedLCID == 0) { + log_verbose("INFO: %-5s does not have any LCID mapping\n", + localeName); + return; + } + + status = U_ZERO_ERROR; + uprv_strcpy(lcidStringC, uprv_convertToPosix(expectedLCID, &status)); + if (U_FAILURE(status)) { + log_err("ERROR: %.4x does not have a POSIX mapping due to %s\n", + expectedLCID, u_errorName(status)); + } + + if(strcmp(localeName, lcidStringC) != 0) { + char langName[1024]; + char langLCID[1024]; + uloc_getLanguage(localeName, langName, sizeof(langName), &status); + uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status); + + if (strcmp(langName, langLCID) == 0) { + log_verbose("WARNING: %-5s resolves to %s (0x%.4x)\n", + localeName, lcidStringC, expectedLCID); + } + else { + log_err("ERROR: %-5s has 0x%.4x and the number resolves wrongfully to %s\n", + localeName, expectedLCID, lcidStringC); + } + } +} + +static void +TestLocaleStructure(void) { + UResourceBundle *root, *currentLocale; + int32_t locCount = uloc_countAvailable(); + int32_t locIndex; + UErrorCode errorCode = U_ZERO_ERROR; + const char *currLoc, *resolvedLoc; + + /* TODO: Compare against parent's data too. This code can't handle fallbacks that some tools do already. */ +/* char locName[ULOC_FULLNAME_CAPACITY]; + char *locNamePtr; + + for (locIndex = 0; locIndex < locCount; locIndex++) { + errorCode=U_ZERO_ERROR; + strcpy(locName, uloc_getAvailable(locIndex)); + locNamePtr = strrchr(locName, '_'); + if (locNamePtr) { + *locNamePtr = 0; + } + else { + strcpy(locName, "root"); + } + + root = ures_openDirect(NULL, locName, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Can't open %s\n", locName); + continue; + } +*/ + if (locCount <= 1) { + log_data_err("At least root needs to be installed\n"); + } + + root = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Can't open structLocale\n"); + return; + } + for (locIndex = 0; locIndex < locCount; locIndex++) { + errorCode=U_ZERO_ERROR; + currLoc = uloc_getAvailable(locIndex); + currentLocale = ures_open(NULL, currLoc, &errorCode); + if(errorCode != U_ZERO_ERROR) { + if(U_SUCCESS(errorCode)) { + /* It's installed, but there is no data. + It's installed for the g18n white paper [grhoten] */ + log_err("ERROR: Locale %-5s not installed, and it should be!\n", + uloc_getAvailable(locIndex)); + } else { + log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", + u_errorName(errorCode), + uloc_getAvailable(locIndex)); + } + ures_close(currentLocale); + continue; + } + ures_getStringByKey(currentLocale, "Version", NULL, &errorCode); + if(errorCode != U_ZERO_ERROR) { + log_err("No version information is available for locale %s, and it should be!\n", + currLoc); + } + else if (ures_getStringByKey(currentLocale, "Version", NULL, &errorCode)[0] == (UChar)(0x78)) { + log_verbose("WARNING: The locale %s is experimental! It shouldn't be listed as an installed locale.\n", + currLoc); + } + resolvedLoc = ures_getLocaleByType(currentLocale, ULOC_ACTUAL_LOCALE, &errorCode); + if (strcmp(resolvedLoc, currLoc) != 0) { + /* All locales have at least a Version resource. + If it's absolutely empty, then the previous test will fail too.*/ + log_err("Locale resolves to different locale. Is %s an alias of %s?\n", + currLoc, resolvedLoc); + } + TestKeyInRootRecursive(root, "root", currentLocale, currLoc); + + testLCID(currentLocale, currLoc); + + ures_close(currentLocale); + } + + ures_close(root); +} + +static void +compareArrays(const char *keyName, + UResourceBundle *fromArray, const char *fromLocale, + UResourceBundle *toArray, const char *toLocale, + int32_t start, int32_t end) +{ + int32_t fromSize = ures_getSize(fromArray); + int32_t toSize = ures_getSize(fromArray); + int32_t idx; + UErrorCode errorCode = U_ZERO_ERROR; + + if (fromSize > toSize) { + fromSize = toSize; + log_err("Arrays are different size from \"%s\" to \"%s\"\n", + fromLocale, + toLocale); + } + + for (idx = start; idx <= end; idx++) { + const UChar *fromBundleStr = ures_getStringByIndex(fromArray, idx, NULL, &errorCode); + const UChar *toBundleStr = ures_getStringByIndex(toArray, idx, NULL, &errorCode); + if (fromBundleStr && toBundleStr && u_strcmp(fromBundleStr, toBundleStr) != 0) + { + log_err("Difference for %s at index %d from %s= \"%s\" to %s= \"%s\"\n", + keyName, + idx, + fromLocale, + austrdup(fromBundleStr), + toLocale, + austrdup(toBundleStr)); + } + } +} + +static void +compareConsistentCountryInfo(const char *fromLocale, const char *toLocale) { + UErrorCode errorCode = U_ZERO_ERROR; + UResourceBundle *fromDateTimeElements, *toDateTimeElements, *fromWeekendData = NULL, *toWeekendData = NULL; + UResourceBundle *fromArray, *toArray; + UResourceBundle *fromLocaleBund = ures_open(NULL, fromLocale, &errorCode); + UResourceBundle *toLocaleBund = ures_open(NULL, toLocale, &errorCode); + UResourceBundle *toCalendar, *fromCalendar, *toGregorian, *fromGregorian; + + if(U_FAILURE(errorCode)) { + log_err("Can't open resource bundle %s or %s - %s\n", fromLocale, toLocale, u_errorName(errorCode)); + return; + } + fromCalendar = ures_getByKey(fromLocaleBund, "calendar", NULL, &errorCode); + fromGregorian = ures_getByKeyWithFallback(fromCalendar, "gregorian", NULL, &errorCode); + fromDateTimeElements = ures_getByKeyWithFallback(fromGregorian, "DateTimeElements", NULL, &errorCode); + + toCalendar = ures_getByKey(toLocaleBund, "calendar", NULL, &errorCode); + toGregorian = ures_getByKeyWithFallback(toCalendar, "gregorian", NULL, &errorCode); + toDateTimeElements = ures_getByKeyWithFallback(toGregorian, "DateTimeElements", NULL, &errorCode); + + if(U_FAILURE(errorCode)){ + log_err("Did not get DateTimeElements from the bundle %s or %s\n", fromLocale, toLocale); + goto cleanup; + } + + fromWeekendData = ures_getByKeyWithFallback(fromGregorian, "weekend", NULL, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("Did not get weekend data from the bundle %s to compare against %s\n", fromLocale, toLocale); + goto cleanup; + } + toWeekendData = ures_getByKeyWithFallback(toGregorian, "weekend", NULL, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("Did not get weekend data from the bundle %s to compare against %s\n", toLocale, fromLocale); + goto cleanup; + } + + if (strcmp(fromLocale, "ar_IN") != 0) + { + int32_t fromSize; + int32_t toSize; + int32_t idx; + const int32_t *fromBundleArr = ures_getIntVector(fromDateTimeElements, &fromSize, &errorCode); + const int32_t *toBundleArr = ures_getIntVector(toDateTimeElements, &toSize, &errorCode); + + if (fromSize > toSize) { + fromSize = toSize; + log_err("Arrays are different size with key \"DateTimeElements\" from \"%s\" to \"%s\"\n", + fromLocale, + toLocale); + } + + for (idx = 0; idx < fromSize; idx++) { + if (fromBundleArr[idx] != toBundleArr[idx]) { + log_err("Difference with key \"DateTimeElements\" at index %d from \"%s\" to \"%s\"\n", + idx, + fromLocale, + toLocale); + } + } + } + + /* test for weekend data */ + { + int32_t fromSize; + int32_t toSize; + int32_t idx; + const int32_t *fromBundleArr = ures_getIntVector(fromWeekendData, &fromSize, &errorCode); + const int32_t *toBundleArr = ures_getIntVector(toWeekendData, &toSize, &errorCode); + + if (fromSize > toSize) { + fromSize = toSize; + log_err("Arrays are different size with key \"weekend\" data from \"%s\" to \"%s\"\n", + fromLocale, + toLocale); + } + + for (idx = 0; idx < fromSize; idx++) { + if (fromBundleArr[idx] != toBundleArr[idx]) { + log_err("Difference with key \"weekend\" data at index %d from \"%s\" to \"%s\"\n", + idx, + fromLocale, + toLocale); + } + } + } + + fromArray = ures_getByKey(fromLocaleBund, "CurrencyElements", NULL, &errorCode); + toArray = ures_getByKey(toLocaleBund, "CurrencyElements", NULL, &errorCode); + if (strcmp(fromLocale, "en_CA") != 0) + { + /* The first one is probably localized. */ + compareArrays("CurrencyElements", fromArray, fromLocale, toArray, toLocale, 1, 2); + } + ures_close(fromArray); + ures_close(toArray); + + fromArray = ures_getByKey(fromLocaleBund, "NumberPatterns", NULL, &errorCode); + toArray = ures_getByKey(toLocaleBund, "NumberPatterns", NULL, &errorCode); + if (strcmp(fromLocale, "en_CA") != 0) + { + compareArrays("NumberPatterns", fromArray, fromLocale, toArray, toLocale, 0, 3); + } + ures_close(fromArray); + ures_close(toArray); + + /* Difficult to test properly */ +/* + fromArray = ures_getByKey(fromLocaleBund, "DateTimePatterns", NULL, &errorCode); + toArray = ures_getByKey(toLocaleBund, "DateTimePatterns", NULL, &errorCode); + { + compareArrays("DateTimePatterns", fromArray, fromLocale, toArray, toLocale); + } + ures_close(fromArray); + ures_close(toArray);*/ + + fromArray = ures_getByKey(fromLocaleBund, "NumberElements", NULL, &errorCode); + toArray = ures_getByKey(toLocaleBund, "NumberElements", NULL, &errorCode); + if (strcmp(fromLocale, "en_CA") != 0) + { + compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 0, 3); + /* Index 4 is a script based 0 */ + compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 5, 10); + } + ures_close(fromArray); + ures_close(toArray); + +cleanup: + ures_close(fromDateTimeElements); + ures_close(toDateTimeElements); + ures_close(fromWeekendData); + ures_close(toWeekendData); + + ures_close(fromCalendar); + ures_close(toCalendar); + ures_close(fromGregorian); + ures_close(toGregorian); + + ures_close(fromLocaleBund); + ures_close(toLocaleBund); +} + +static void +TestConsistentCountryInfo(void) { +/* UResourceBundle *fromLocale, *toLocale;*/ + int32_t locCount = uloc_countAvailable(); + int32_t fromLocIndex, toLocIndex; + + int32_t fromCountryLen, toCountryLen; + char fromCountry[ULOC_FULLNAME_CAPACITY], toCountry[ULOC_FULLNAME_CAPACITY]; + + int32_t fromVariantLen, toVariantLen; + char fromVariant[ULOC_FULLNAME_CAPACITY], toVariant[ULOC_FULLNAME_CAPACITY]; + + UErrorCode errorCode = U_ZERO_ERROR; + + for (fromLocIndex = 0; fromLocIndex < locCount; fromLocIndex++) { + const char *fromLocale = uloc_getAvailable(fromLocIndex); + + errorCode=U_ZERO_ERROR; + fromCountryLen = uloc_getCountry(fromLocale, fromCountry, ULOC_FULLNAME_CAPACITY, &errorCode); + if (fromCountryLen <= 0) { + /* Ignore countryless locales */ + continue; + } + fromVariantLen = uloc_getVariant(fromLocale, fromVariant, ULOC_FULLNAME_CAPACITY, &errorCode); + if (fromVariantLen > 0) { + /* Most variants are ignorable like PREEURO, or collation variants. */ + continue; + } + /* Start comparing only after the current index. + Previous loop should have already compared fromLocIndex. + */ + for (toLocIndex = fromLocIndex + 1; toLocIndex < locCount; toLocIndex++) { + const char *toLocale = uloc_getAvailable(toLocIndex); + + toCountryLen = uloc_getCountry(toLocale, toCountry, ULOC_FULLNAME_CAPACITY, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unknown failure fromLocale=%s toLocale=%s errorCode=%s\n", + fromLocale, toLocale, u_errorName(errorCode)); + continue; + } + + if (toCountryLen <= 0) { + /* Ignore countryless locales */ + continue; + } + toVariantLen = uloc_getVariant(toLocale, toVariant, ULOC_FULLNAME_CAPACITY, &errorCode); + if (toVariantLen > 0) { + /* Most variants are ignorable like PREEURO, or collation variants. */ + /* They're a variant for a reason. */ + continue; + } + if (strcmp(fromCountry, toCountry) == 0) { + log_verbose("comparing fromLocale=%s toLocale=%s\n", + fromLocale, toLocale); + compareConsistentCountryInfo(fromLocale, toLocale); + } + } + } +} + +static int32_t +findStringSetMismatch(const char *currLoc, const UChar *string, int32_t langSize, + const UChar *exemplarCharacters, int32_t exemplarLen, + UBool ignoreNumbers) { + UErrorCode errorCode = U_ZERO_ERROR; + USet *origSet = uset_openPatternOptions(exemplarCharacters, exemplarLen, USET_CASE_INSENSITIVE, &errorCode); + USet *exemplarSet = createFlattenSet(origSet, &errorCode); + int32_t strIdx; + uset_close(origSet); + if (U_FAILURE(errorCode)) { + log_err("%s: error uset_openPattern returned %s\n", currLoc, u_errorName(errorCode)); + return -1; + } + + for (strIdx = 0; strIdx < langSize; strIdx++) { + if (!uset_contains(exemplarSet, string[strIdx]) + && string[strIdx] != 0x0020 && string[strIdx] != 0x00A0 && string[strIdx] != 0x002e && string[strIdx] != 0x002c && string[strIdx] != 0x002d && string[strIdx] != 0x0027 + && string[strIdx] != 0x200C && string[strIdx] != 0x200D) { + if (!ignoreNumbers || (ignoreNumbers && (string[strIdx] < 0x30 || string[strIdx] > 0x39))) { + uset_close(exemplarSet); + return strIdx; + } + } + } + uset_close(exemplarSet); + return -1; +} +/* include non-invariant chars */ +static int32_t +myUCharsToChars(const UChar* us, char* cs, int32_t len){ + int32_t i=0; + for(; i< len; i++){ + if(us[i] < 0x7f){ + cs[i] = (char)us[i]; + }else{ + return -1; + } + } + return i; +} +static void +findSetMatch( UScriptCode *scriptCodes, int32_t scriptsLen, + USet *exemplarSet, + const char *locale){ + USet *scripts[10]= {0}; + char pattern[256] = { '[', ':', 0x000 }; + int32_t patternLen; + UChar uPattern[256] = {0}; + UErrorCode status = U_ZERO_ERROR; + int32_t i; + + /* create the sets with script codes */ + for(i = 0; i<scriptsLen; i++){ + strcat(pattern, uscript_getShortName(scriptCodes[i])); + strcat(pattern, ":]"); + patternLen = (int32_t)strlen(pattern); + u_charsToUChars(pattern, uPattern, patternLen); + scripts[i] = uset_openPattern(uPattern, patternLen, &status); + if(U_FAILURE(status)){ + log_err("Could not create set for patter %s. Error: %s\n", pattern, u_errorName(status)); + break; + } + pattern[2] = 0; + } + if (strcmp(locale, "uk") == 0 || strcmp(locale, "uk_UA") == 0) { + /* Special addition. Add the modifying apostrophe, which isn't in Cyrillic. */ + uset_add(scripts[0], 0x2bc); + } + if(U_SUCCESS(status)){ + UBool existsInScript = FALSE; + /* iterate over the exemplarSet and ascertain if all + * UChars in exemplarSet belong to the scripts returned + * by getScript + */ + int32_t count = uset_getItemCount(exemplarSet); + + for( i=0; i < count; i++){ + UChar32 start = 0; + UChar32 end = 0; + UChar *str = NULL; + int32_t strCapacity = 0; + + strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); + if(U_SUCCESS(status)){ + int32_t j; + if(strCapacity == 0){ + /* ok the item is a range */ + for( j = 0; j < scriptsLen; j++){ + if(uset_containsRange(scripts[j], start, end) == TRUE){ + existsInScript = TRUE; + } + } + if(existsInScript == FALSE){ + for( j = 0; j < scriptsLen; j++){ + UChar toPattern[500]={'\0'}; + char pat[500]={'\0'}; + int32_t len = uset_toPattern(scripts[j], toPattern, 500, TRUE, &status); + len = myUCharsToChars(toPattern, pat, len); + log_err("uset_indexOf(\\u%04X)=%i uset_indexOf(\\u%04X)=%i\n", start, uset_indexOf(scripts[0], start), end, uset_indexOf(scripts[0], end)); + if(len!=-1){ + log_err("Pattern: %s\n",pat); + } + } + log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); + } + }else{ + strCapacity++; /* increment for NUL termination */ + /* allocate the str and call the api again */ + str = (UChar*) malloc(U_SIZEOF_UCHAR * strCapacity); + strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status); + /* iterate over the scripts and figure out if the string contained is actually + * in the script set + */ + for( j = 0; j < scriptsLen; j++){ + if(uset_containsString(scripts[j],str, strCapacity) == TRUE){ + existsInScript = TRUE; + } + } + if(existsInScript == FALSE){ + log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale); + } + } + } + } + + } + + /* close the sets */ + for(i = 0; i<scriptsLen; i++){ + uset_close(scripts[i]); + } +} + +static void VerifyTranslation(void) { + UResourceBundle *root, *currentLocale; + int32_t locCount = uloc_countAvailable(); + int32_t locIndex; + UErrorCode errorCode = U_ZERO_ERROR; + int32_t exemplarLen; + const UChar *exemplarCharacters; + const char *currLoc; + UScriptCode scripts[USCRIPT_CODE_LIMIT]; + int32_t numScripts; + int32_t idx; + int32_t end; + UResourceBundle *resArray; + + if (locCount <= 1) { + log_data_err("At least root needs to be installed\n"); + } + + root = ures_openDirect(NULL, "root", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Can't open root\n"); + return; + } + for (locIndex = 0; locIndex < locCount; locIndex++) { + errorCode=U_ZERO_ERROR; + currLoc = uloc_getAvailable(locIndex); + currentLocale = ures_open(NULL, currLoc, &errorCode); + if(errorCode != U_ZERO_ERROR) { + if(U_SUCCESS(errorCode)) { + /* It's installed, but there is no data. + It's installed for the g18n white paper [grhoten] */ + log_err("ERROR: Locale %-5s not installed, and it should be!\n", + uloc_getAvailable(locIndex)); + } else { + log_err("%%%%%%% Unexpected error %d in %s %%%%%%%", + u_errorName(errorCode), + uloc_getAvailable(locIndex)); + } + ures_close(currentLocale); + continue; + } + exemplarCharacters = ures_getStringByKey(currentLocale, "ExemplarCharacters", &exemplarLen, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error ures_getStringByKey returned %s\n", u_errorName(errorCode)); + } + else if (QUICK && exemplarLen > 2048) { + log_verbose("skipping test for %s\n", currLoc); + } + else { + UChar langBuffer[128]; + int32_t langSize; + int32_t strIdx; + langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode)); + } + else { + strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE); + if (strIdx >= 0) { + log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters.\n", + currLoc, strIdx); + } + } + langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode)); + } + else { + strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE); + if (strIdx >= 0) { + log_err("getDisplayCountry(%s) at index %d returned characters not in the exemplar characters.\n", + currLoc, strIdx); + } + } + { + UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode); + UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode); + UResourceBundle* names = ures_getByKeyWithFallback(greg, "dayNames", NULL, &errorCode); + UResourceBundle* format = ures_getByKeyWithFallback(names, "format", NULL, &errorCode); + resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); + + if (U_FAILURE(errorCode)) { + log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); + } + if (QUICK) { + end = 1; + } + else { + end = ures_getSize(resArray); + } + + + for (idx = 0; idx < end; idx++) { + const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); + continue; + } + strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE); + if (strIdx >= 0) { + log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters.\n", + currLoc, idx, strIdx); + } + } + ures_close(resArray); + ures_close(format); + ures_close(names); + + names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode); + format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode); + resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error ures_getByKey returned %s\n", u_errorName(errorCode)); + } + if (QUICK) { + end = 1; + } + else { + end = ures_getSize(resArray); + } + + for (idx = 0; idx < end; idx++) { + const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); + if (U_FAILURE(errorCode)) { + log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode)); + continue; + } + strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE); + if (strIdx >= 0) { + log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters.\n", + currLoc, idx, strIdx); + } + } + ures_close(resArray); + ures_close(format); + ures_close(names); + ures_close(greg); + ures_close(cal); + } + errorCode = U_ZERO_ERROR; + numScripts = uscript_getCode(currLoc, scripts, sizeof(scripts)/sizeof(scripts[0]), &errorCode); + if (numScripts == 0) { + log_err("uscript_getCode(%s) doesn't work.\n", currLoc); + }else if(scripts[0] == USCRIPT_COMMON){ + log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc); + } + + /* test that the scripts are a superset of exemplar characters. */ + { + ULocaleData *uld = ulocdata_open(currLoc,&errorCode); + USet *exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode); + /* test if exemplar characters are part of script code */ + findSetMatch(scripts, numScripts, exemplarSet, currLoc); + uset_close(exemplarSet); + ulocdata_close(uld); + } + + /* test that the paperSize API works */ + { + int32_t height=0, width=0; + ulocdata_getPaperSize(currLoc, &height, &width, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); + } + if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){ + log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc); + } + } + /* test that the MeasurementSystem works API works */ + { + UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode)); + } + if(strstr(currLoc, "_US")!=NULL){ + if(measurementSystem != UMS_US){ + log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); + } + }else if(measurementSystem != UMS_SI){ + log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc); + } + } + } + ures_close(currentLocale); + } + + ures_close(root); +} + +/* adjust this limit as appropriate */ +#define MAX_SCRIPTS_PER_LOCALE 8 + +static void TestExemplarSet(void){ + int32_t i, j, k, m, n; + int32_t equalCount = 0; + UErrorCode ec = U_ZERO_ERROR; + UEnumeration* avail; + USet* exemplarSets[2]; + USet* unassignedSet; + UScriptCode code[MAX_SCRIPTS_PER_LOCALE]; + USet* codeSets[MAX_SCRIPTS_PER_LOCALE]; + int32_t codeLen; + char cbuf[32]; /* 9 should be enough */ + UChar ubuf[64]; /* adjust as needed */ + UBool existsInScript; + int32_t itemCount; + int32_t strLen; + UChar32 start, end; + + unassignedSet = NULL; + exemplarSets[0] = NULL; + exemplarSets[1] = NULL; + for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { + codeSets[i] = NULL; + } + + avail = ures_openAvailableLocales(NULL, &ec); + if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END; + n = uenum_count(avail, &ec); + if (!assertSuccess("uenum_count", &ec)) goto END; + + u_uastrcpy(ubuf, "[:unassigned:]"); + unassignedSet = uset_openPattern(ubuf, -1, &ec); + if (!assertSuccess("uset_openPattern", &ec)) goto END; + + for(i=0; i<n; i++){ + const char* locale = uenum_next(avail, NULL, &ec); + if (!assertSuccess("uenum_next", &ec)) goto END; + log_verbose("%s\n", locale); + for (k=0; k<2; ++k) { + uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE; + ULocaleData *uld = ulocdata_open(locale,&ec); + USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec); + uset_close(exemplarSets[k]); + ulocdata_close(uld); + exemplarSets[k] = exemplarSet; + if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END; + + if (uset_containsSome(exemplarSet, unassignedSet)) { + log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale); + } + codeLen = uscript_getCode(locale, code, 8, &ec); + if (!assertSuccess("uscript_getCode", &ec)) goto END; + + for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) { + uset_close(codeSets[j]); + codeSets[j] = NULL; + } + for (j=0; j<codeLen; ++j) { + uprv_strcpy(cbuf, "[:"); + if(code[j]==-1){ + log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale); + continue; + } + uprv_strcat(cbuf, uscript_getShortName(code[j])); + uprv_strcat(cbuf, ":]"); + u_uastrcpy(ubuf, cbuf); + codeSets[j] = uset_openPattern(ubuf, -1, &ec); + } + if (!assertSuccess("uset_openPattern", &ec)) goto END; + + existsInScript = FALSE; + itemCount = uset_getItemCount(exemplarSet); + for (m=0; m<itemCount && !existsInScript; ++m) { + strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf, + sizeof(ubuf)/sizeof(ubuf[0]), &ec); + /* failure here might mean str[] needs to be larger */ + if (!assertSuccess("uset_getItem", &ec)) goto END; + if (strLen == 0) { + for (j=0; j<codeLen; ++j) { + if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) { + existsInScript = TRUE; + break; + } + } + } else { + for (j=0; j<codeLen; ++j) { + if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) { + existsInScript = TRUE; + break; + } + } + } + } + + if (existsInScript == FALSE){ + log_err("ExemplarSet containment failed for locale : %s\n", locale); + } + } + assertTrue("case-folded is a superset", + uset_containsAll(exemplarSets[1], exemplarSets[0])); + if (uset_equals(exemplarSets[1], exemplarSets[0])) { + ++equalCount; + } + } + /* Note: The case-folded set should sometimes be a strict superset + and sometimes be equal. */ + assertTrue("case-folded is sometimes a strict superset, and sometimes equal", + equalCount > 0 && equalCount < n); + + END: + uenum_close(avail); + uset_close(exemplarSets[0]); + uset_close(exemplarSets[1]); + uset_close(unassignedSet); + for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) { + uset_close(codeSets[i]); + } +} + +static void TestCoverage(void){ + ULocaleDataDelimiterType types[] = { + ULOCDATA_QUOTATION_START, /* Quotation start */ + ULOCDATA_QUOTATION_END, /* Quotation end */ + ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */ + ULOCDATA_ALT_QUOTATION_END, /* Alternate quotation end */ + ULOCDATA_DELIMITER_COUNT + }; + int i; + UBool sub; + UErrorCode status = U_ZERO_ERROR; + ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status); + + if(U_FAILURE(status)){ + log_err("ulocdata_open error"); + return; + } + + + for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){ + UChar result[32] = {0,}; + status = U_ZERO_ERROR; + ulocdata_getDelimiter(uld, types[i], result, 32, &status); + if (U_FAILURE(status)){ + log_err("ulocdata_getgetDelimiter error with type %d", types[i]); + } + } + + sub = ulocdata_getNoSubstitute(uld); + ulocdata_setNoSubstitute(uld,sub); + ulocdata_close(uld); +} + +static void TestCurrencyList(void){ +#if !UCONFIG_NO_FORMATTING + UErrorCode errorCode = U_ZERO_ERROR; + int32_t structLocaleCount, currencyCount; + UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode); + const char *isoCode, *structISOCode; + UResourceBundle *subBundle; + UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Can't open structLocale\n"); + return; + } + currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode); + currencyCount = uenum_count(en, &errorCode); + structLocaleCount = ures_getSize(currencies); + if (currencyCount != structLocaleCount) { + log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount); +#if U_CHARSET_FAMILY == U_ASCII_FAMILY + ures_resetIterator(currencies); + while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) { + subBundle = ures_getNextResource(currencies, NULL, &errorCode); + structISOCode = ures_getKey(subBundle); + ures_close(subBundle); + if (strcmp(structISOCode, isoCode) != 0) { + log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode); + break; + } + } +#endif + } + ures_close(currencies); + uenum_close(en); +#endif +} + +#define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name) + +void addCLDRTest(TestNode** root); + +void addCLDRTest(TestNode** root) +{ + TESTCASE(TestLocaleStructure); + TESTCASE(TestConsistentCountryInfo); + TESTCASE(VerifyTranslation); + TESTCASE(TestExemplarSet); + TESTCASE(TestCurrencyList); + TESTCASE(TestCoverage); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c new file mode 100644 index 00000000000..d75fce50d0f --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c @@ -0,0 +1,2774 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/***************************************************************************** +* +* File CLOCTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +****************************************************************************** +*/ +#include "cloctst.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "cintltst.h" +#include "cstring.h" +#include "uparse.h" +#include "uresimp.h" + +#include "unicode/putil.h" +#include "unicode/ubrk.h" +#include "unicode/uchar.h" +#include "unicode/ucol.h" +#include "unicode/udat.h" +#include "unicode/uloc.h" +#include "unicode/umsg.h" +#include "unicode/ures.h" +#include "unicode/uset.h" +#include "unicode/ustring.h" +#include "unicode/utypes.h" +#include "unicode/ulocdata.h" +#include "unicode/parseerr.h" /* may not be included with some uconfig switches */ +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void TestNullDefault(void); +static void TestNonexistentLanguageExemplars(void); +static void TestLocDataErrorCodeChaining(void); +static void TestLanguageExemplarsFallbacks(void); + +void PrintDataTable(); + +/*--------------------------------------------------- + table of valid data + --------------------------------------------------- */ +#define LOCALE_SIZE 9 +#define LOCALE_INFO_SIZE 28 + +static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = { + /* language code */ + { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" }, + /* script code */ + { "", "", "", "", "", "Hans", "", "", "" }, + /* country code */ + { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" }, + /* variant code */ + { "", "", "", "", "NY", "", "", "", "" }, + /* full name */ + { "en_US", "fr_FR", "ca_ES", + "el_GR", "no_NO_NY", "zh_Hans_CN", + "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" }, + /* ISO-3 language */ + { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" }, + /* ISO-3 country */ + { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" }, + /* LCID */ + { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" }, + + /* display language (English) */ + { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" }, + /* display script code (English) */ + { "", "", "", "", "", "Simplified Han", "", "", "" }, + /* display country (English) */ + { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" }, + /* display variant (English) */ + { "", "", "", "", "NY", "", "", "", "" }, + /* display name (English) */ + { "English (United States)", "French (France)", "Catalan (Spain)", + "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified Han, China)", + "German (Germany, collation=Phonebook Sort Order)", "Spanish (collation=Traditional Sort Order)", "Japanese (Japan, calendar=Japanese Calendar)" }, + + /* display language (French) */ + { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" }, + /* display script code (French) */ + { "", "", "", "", "", "id\\u00e9ogrammes han (variante simplifi\\u00e9e)", "", "", "" }, + /* display country (French) */ + { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" }, + /* display variant (French) */ + { "", "", "", "", "NY", "", "", "", "" }, + /* display name (French) */ + { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)", + "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (id\\u00e9ogrammes han (variante simplifi\\u00e9e), Chine)", + "allemand (Allemagne, Ordonnancement=Ordre de l\\u2019annuaire)", "espagnol (Ordonnancement=Ordre traditionnel)", "japonais (Japon, Calendrier=Calendrier japonais)" }, + + /* display language (Catalan) */ + { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E9s", "alemany", "espanyol", "japon\\u00E8s" }, + /* display script code (Catalan) */ + { "", "", "", "", "", "Hans", "", "", "" }, + /* display country (Catalan) */ + { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" }, + /* display variant (Catalan) */ + { "", "", "", "", "NY", "", "", "", "" }, + /* display name (Catalan) */ + { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)", + "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E9s (Hans, Xina)", + "alemany (Alemanya, collation=phonebook)", "espanyol (collation=traditional)", "japon\\u00E8s (Jap\\u00F3, calendar=japanese)" }, + + /* display language (Greek) */ + { + "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac", + "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac", + "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac", + "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac", + "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac", + "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC", + "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", + "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC", + "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC" + }, + /* display script code (Greek) */ + + { "", "", "", "", "", "\\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc \\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf", "", "", "" }, + /* display country (Greek) */ + { + "\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2", + "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1", + "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1", + "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1", + "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1", + "\\u039A\\u03AF\\u03BD\\u03B1", + "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1", + "", + "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1" + }, + /* display variant (Greek) */ + { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */ + /* display name (Greek) */ + { + "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2)", + "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)", + "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)", + "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)", + "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)", + "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc \\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)", + "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1, \\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A3\\u03B5\\u03B9\\u03C1\\u03AC \\u03A4\\u03B7\\u03BB\\u03B5\\u03C6\\u03C9\\u03BD\\u03B9\\u03BA\\u03BF\\u03CD \\u039A\\u03B1\\u03C4\\u03B1\\u03BB\\u03CC\\u03B3\\u03BF\\u03C5)", + "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7\\u003D\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03A3\\u03B5\\u03B9\\u03C1\\u03AC)", + "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC (\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1, \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF)" + } +}; + +static UChar*** dataTable=0; +enum { + ENGLISH = 0, + FRENCH = 1, + CATALAN = 2, + GREEK = 3, + NORWEGIAN = 4 +}; + +enum { + LANG = 0, + SCRIPT = 1, + CTRY = 2, + VAR = 3, + NAME = 4, + LANG3 = 5, + CTRY3 = 6, + LCID = 7, + DLANG_EN = 8, + DSCRIPT_EN = 9, + DCTRY_EN = 10, + DVAR_EN = 11, + DNAME_EN = 12, + DLANG_FR = 13, + DSCRIPT_FR = 14, + DCTRY_FR = 15, + DVAR_FR = 16, + DNAME_FR = 17, + DLANG_CA = 18, + DSCRIPT_CA = 19, + DCTRY_CA = 20, + DVAR_CA = 21, + DNAME_CA = 22, + DLANG_EL = 23, + DSCRIPT_EL = 24, + DCTRY_EL = 25, + DVAR_EL = 26, + DNAME_EL = 27 +}; + +#define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name) + +void addLocaleTest(TestNode** root); + +void addLocaleTest(TestNode** root) +{ + TESTCASE(TestObsoleteNames); /* srl- move */ + TESTCASE(TestBasicGetters); + TESTCASE(TestNullDefault); + TESTCASE(TestPrefixes); + TESTCASE(TestSimpleResourceInfo); + TESTCASE(TestDisplayNames); + TESTCASE(TestGetAvailableLocales); + TESTCASE(TestDataDirectory); + TESTCASE(TestISOFunctions); + TESTCASE(TestISO3Fallback); + TESTCASE(TestUninstalledISO3Names); + TESTCASE(TestSimpleDisplayNames); + TESTCASE(TestVariantParsing); + TESTCASE(TestKeywordVariants); + TESTCASE(TestKeywordVariantParsing); + TESTCASE(TestCanonicalization); + TESTCASE(TestKeywordSet); + TESTCASE(TestKeywordSetError); + TESTCASE(TestDisplayKeywords); + TESTCASE(TestDisplayKeywordValues); + TESTCASE(TestGetBaseName); + TESTCASE(TestGetLocale); + TESTCASE(TestDisplayNameWarning); + TESTCASE(TestNonexistentLanguageExemplars); + TESTCASE(TestLocDataErrorCodeChaining); + TESTCASE(TestLanguageExemplarsFallbacks); + TESTCASE(TestCalendar); + TESTCASE(TestDateFormat); + TESTCASE(TestCollation); + TESTCASE(TestULocale); + TESTCASE(TestUResourceBundle); + TESTCASE(TestDisplayName); + TESTCASE(TestAcceptLanguage); + TESTCASE(TestGetLocaleForLCID); +} + + +/* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */ +static void TestBasicGetters() { + int32_t i; + int32_t cap; + UErrorCode status = U_ZERO_ERROR; + char *testLocale = 0; + char *temp = 0, *name = 0; + log_verbose("Testing Basic Getters\n"); + for (i = 0; i < LOCALE_SIZE; i++) { + testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1)); + strcpy(testLocale,rawData2[NAME][i]); + + log_verbose("Testing %s .....\n", testLocale); + cap=uloc_getLanguage(testLocale, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + temp=(char*)malloc(sizeof(char) * (cap+1)); + uloc_getLanguage(testLocale, temp, cap+1, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status)); + } + if (0 !=strcmp(temp,rawData2[LANG][i])) { + log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]); + } + + + cap=uloc_getCountry(testLocale, temp, cap, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + temp=(char*)realloc(temp, sizeof(char) * (cap+1)); + uloc_getCountry(testLocale, temp, cap+1, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status)); + } + if (0 != strcmp(temp, rawData2[CTRY][i])) { + log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]); + + } + + cap=uloc_getVariant(testLocale, temp, cap, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + temp=(char*)realloc(temp, sizeof(char) * (cap+1)); + uloc_getVariant(testLocale, temp, cap+1, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status)); + } + if (0 != strcmp(temp, rawData2[VAR][i])) { + log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]); + } + + cap=uloc_getName(testLocale, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + name=(char*)malloc(sizeof(char) * (cap+1)); + uloc_getName(testLocale, name, cap+1, &status); + } else if(status==U_ZERO_ERROR) { + log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale); + } + if(U_FAILURE(status)){ + log_err("ERROR: in uloc_getName %s\n", myErrorName(status)); + } + if (0 != strcmp(name, rawData2[NAME][i])){ + log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]); + } + + free(temp); + free(name); + + free(testLocale); + } +} + +static void TestNullDefault() { + UErrorCode status = U_ZERO_ERROR; + char original[ULOC_FULLNAME_CAPACITY]; + + uprv_strcpy(original, uloc_getDefault()); + uloc_setDefault("qq_BLA", &status); + if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) { + log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault()); + } + uloc_setDefault(NULL, &status); + if (uprv_strcmp(uloc_getDefault(), original) != 0) { + log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n"); + } + + { + /* Test that set & get of default locale work, and that + * default locales are cached and reused, and not overwritten. + */ + const char *n_en_US; + const char *n_fr_FR; + const char *n2_en_US; + + status = U_ZERO_ERROR; + uloc_setDefault("en_US", &status); + n_en_US = uloc_getDefault(); + if (strcmp(n_en_US, "en_US") != 0) { + log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); + } + + uloc_setDefault("fr_FR", &status); + n_fr_FR = uloc_getDefault(); + if (strcmp(n_en_US, "en_US") != 0) { + log_err("uloc_setDefault altered previously default string." + "Expected \"en_US\", got \"%s\"\n", n_en_US); + } + if (strcmp(n_fr_FR, "fr_FR") != 0) { + log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR); + } + + uloc_setDefault("en_US", &status); + n2_en_US = uloc_getDefault(); + if (strcmp(n2_en_US, "en_US") != 0) { + log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US); + } + if (n2_en_US != n_en_US) { + log_err("Default locale cache failed to reuse en_US locale.\n"); + } + + if (U_FAILURE(status)) { + log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status)); + } + + } + +} +/* Test the i- and x- and @ and . functionality +*/ + +#define PREFIXBUFSIZ 128 + +static void TestPrefixes() { + int row = 0; + int n; + const char *loc, *expected; + + static const char * const testData[][7] = + { + /* NULL canonicalize() column means "expect same as getName()" */ + {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL}, + {"en", "", "GB", "", "en-gb", "en_GB", NULL}, + {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL}, + {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL}, + {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL}, + {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL}, + + {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"}, + {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"}, + {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */ + {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"}, + {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"}, + {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"}, + {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"}, + {"no", "", "", "NY", "no__ny", "no__NY", NULL}, + {"no", "", "", "", "no@ny", "no@ny", "no__NY"}, + {"el", "Latn", "", "", "el-latn", "el_Latn", NULL}, + {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL}, + {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", NULL}, + {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL}, + {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL}, + {"12", "3456", "78", "90", "12_3456_78_90", "12_3456_78_90", NULL}, /* total garbage */ + + {NULL,NULL,NULL,NULL,NULL,NULL,NULL} + }; + + static const char * const testTitles[] = { + "uloc_getLanguage()", + "uloc_getScript()", + "uloc_getCountry()", + "uloc_getVariant()", + "name", + "uloc_getName()", + "uloc_canonicalize()" + }; + + char buf[PREFIXBUFSIZ]; + int32_t len; + UErrorCode err; + + + for(row=0;testData[row][0] != NULL;row++) { + loc = testData[row][NAME]; + log_verbose("Test #%d: %s\n", row, loc); + + err = U_ZERO_ERROR; + len=0; + buf[0]=0; + for(n=0;n<=(NAME+2);n++) { + if(n==NAME) continue; + + for(len=0;len<PREFIXBUFSIZ;len++) { + buf[len] = '%'; /* Set a tripwire.. */ + } + len = 0; + + switch(n) { + case LANG: + len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err); + break; + + case SCRIPT: + len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err); + break; + + case CTRY: + len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err); + break; + + case VAR: + len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err); + break; + + case NAME+1: + len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err); + break; + + case NAME+2: + len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err); + break; + + default: + strcpy(buf, "**??"); + len=4; + } + + if(U_FAILURE(err)) { + log_err("#%d: %s on %s: err %s\n", + row, testTitles[n], loc, u_errorName(err)); + } else { + log_verbose("#%d: %s on %s: -> [%s] (length %d)\n", + row, testTitles[n], loc, buf, len); + + if(len != (int32_t)strlen(buf)) { + log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n", + row, testTitles[n], loc, buf, len, strlen(buf)+1); + + } + + /* see if they smashed something */ + if(buf[len+1] != '%') { + log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n", + row, testTitles[n], loc, buf, buf[len+1]); + } + + expected = testData[row][n]; + if (expected == NULL && n == (NAME+2)) { + /* NULL expected canonicalize() means "expect same as getName()" */ + expected = testData[row][NAME+1]; + } + if(strcmp(buf, expected)) { + log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n", + row, testTitles[n], loc, buf, expected); + + } + } + } + } +} + + +/* testing uloc_getISO3Language(), uloc_getISO3Country(), */ +static void TestSimpleResourceInfo() { + int32_t i; + char* testLocale = 0; + UChar* expected = 0; + + const char* temp; + char temp2[20]; + testLocale=(char*)malloc(sizeof(char) * 1); + expected=(UChar*)malloc(sizeof(UChar) * 1); + + setUpDataTable(); + log_verbose("Testing getISO3Language and getISO3Country\n"); + for (i = 0; i < LOCALE_SIZE; i++) { + + testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1)); + u_austrcpy(testLocale, dataTable[NAME][i]); + + log_verbose("Testing %s ......\n", testLocale); + + temp=uloc_getISO3Language(testLocale); + expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); + u_uastrcpy(expected,temp); + if (0 != u_strcmp(expected, dataTable[LANG3][i])) { + log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected), + austrdup(dataTable[LANG3][i])); + } + + temp=uloc_getISO3Country(testLocale); + expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1)); + u_uastrcpy(expected,temp); + if (0 != u_strcmp(expected, dataTable[CTRY3][i])) { + log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected), + austrdup(dataTable[CTRY3][i])); + } + sprintf(temp2, "%x", (int)uloc_getLCID(testLocale)); + if (strcmp(temp2, rawData2[LCID][i]) != 0) { + log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]); + } + } + + free(expected); + free(testLocale); + cleanUpDataTable(); +} + +/* + * Jitterbug 2439 -- markus 20030425 + * + * The lookup of display names must not fall back through the default + * locale because that yields useless results. + */ +static void TestDisplayNames() +{ + UChar buffer[100]; + UErrorCode errorCode=U_ZERO_ERROR; + int32_t length; + log_verbose("Testing getDisplayName for different locales\n"); + + log_verbose(" In locale = en_US...\n"); + doTestDisplayNames("en_US", DLANG_EN); + log_verbose(" In locale = fr_FR....\n"); + doTestDisplayNames("fr_FR", DLANG_FR); + log_verbose(" In locale = ca_ES...\n"); + doTestDisplayNames("ca_ES", DLANG_CA); + log_verbose(" In locale = gr_EL..\n"); + doTestDisplayNames("el_GR", DLANG_EL); + + /* test that the default locale has a display name for its own language */ + errorCode=U_ZERO_ERROR; + length=uloc_getDisplayLanguage(NULL, NULL, buffer, LENGTHOF(buffer), &errorCode); + if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) { + /* check <=3 to reject getting the language code as a display name */ + log_err("unable to get a display string for the language of the default locale - %s\n", u_errorName(errorCode)); + } + + /* test that we get the language code itself for an unknown language, and a default warning */ + errorCode=U_ZERO_ERROR; + length=uloc_getDisplayLanguage("qq", "rr", buffer, LENGTHOF(buffer), &errorCode); + if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) { + log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode)); + } + + /* test that we get a default warning for a display name where one component is unknown (4255) */ + errorCode=U_ZERO_ERROR; + length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, LENGTHOF(buffer), &errorCode); + if(errorCode!=U_USING_DEFAULT_WARNING) { + log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode)); + } + + { + int32_t i; + static const char *aLocale = "es@collation=traditional;calendar=japanese"; + static const char *testL[] = { "en_US", + "fr_FR", + "ca_ES", + "el_GR" }; + static const char *expect[] = { "Spanish (calendar=Japanese Calendar, collation=Traditional Sort Order)", /* note sorted order of keywords */ + "espagnol (Calendrier=Calendrier japonais, Ordonnancement=Ordre traditionnel)", + "espanyol (calendar=japanese, collation=traditional)", + "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF, \\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03A3\\u03B5\\u03B9\\u03C1\\u03AC)" }; + UChar *expectBuffer; + + for(i=0;i<LENGTHOF(testL);i++) { + errorCode = U_ZERO_ERROR; + uloc_getDisplayName(aLocale, testL[i], buffer, LENGTHOF(buffer), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode)); + } else { + expectBuffer = CharsToUChars(expect[i]); + if(u_strcmp(buffer,expectBuffer)) { + log_err("FAIL in uloc_getDisplayName(%s,%s,..) expected '%s' got '%s'\n", aLocale, testL[i], expect[i], austrdup(buffer)); + } else { + log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]); + } + free(expectBuffer); + } + } + } +} + + +/* test for uloc_getAvialable() and uloc_countAvilable()*/ +static void TestGetAvailableLocales() +{ + + const char *locList; + int32_t locCount,i; + + log_verbose("Testing the no of avialable locales\n"); + locCount=uloc_countAvailable(); + if (locCount == 0) + log_data_err("countAvailable() returned an empty list!\n"); + + /* use something sensible w/o hardcoding the count */ + else if(locCount < 0){ + log_data_err("countAvailable() returned a wrong value!= %d\n", locCount); + } + else{ + log_info("Number of locales returned = %d\n", locCount); + } + for(i=0;i<locCount;i++){ + locList=uloc_getAvailable(i); + + log_verbose(" %s\n", locList); + } +} + +/* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */ +static void TestDataDirectory() +{ + + char oldDirectory[512]; + const char *temp,*testValue1,*testValue2,*testValue3; + const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */ + + log_verbose("Testing getDataDirectory()\n"); + temp = u_getDataDirectory(); + strcpy(oldDirectory, temp); + + testValue1=uloc_getISO3Language("en_US"); + log_verbose("first fetch of language retrieved %s\n", testValue1); + + if (0 != strcmp(testValue1,"eng")){ + log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1); + } + + /*defining the path for DataDirectory */ + log_verbose("Testing setDataDirectory\n"); + u_setDataDirectory( path ); + if(strcmp(path, u_getDataDirectory())==0) + log_verbose("setDataDirectory working fine\n"); + else + log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path); + + testValue2=uloc_getISO3Language("en_US"); + log_verbose("second fetch of language retrieved %s \n", testValue2); + + u_setDataDirectory(oldDirectory); + testValue3=uloc_getISO3Language("en_US"); + log_verbose("third fetch of language retrieved %s \n", testValue3); + + if (0 != strcmp(testValue3,"eng")) { + log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3); + } +} + + + +/*=========================================================== */ + +static UChar _NUL=0; + +static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t i; + int32_t maxresultsize; + + const char *testLocale; + + + UChar *testLang = 0; + UChar *testScript = 0; + UChar *testCtry = 0; + UChar *testVar = 0; + UChar *testName = 0; + + + UChar* expectedLang = 0; + UChar* expectedScript = 0; + UChar* expectedCtry = 0; + UChar* expectedVar = 0; + UChar* expectedName = 0; + +setUpDataTable(); + + for(i=0;i<LOCALE_SIZE; ++i) + { + testLocale=rawData2[NAME][i]; + + log_verbose("Testing..... %s\n", testLocale); + + maxresultsize=0; + maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); + uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status); + } + else + { + testLang=&_NUL; + } + if(U_FAILURE(status)){ + log_err("Error in getDisplayLanguage() %s\n", myErrorName(status)); + } + + maxresultsize=0; + maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); + uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status); + } + else + { + testScript=&_NUL; + } + if(U_FAILURE(status)){ + log_err("Error in getDisplayScript() %s\n", myErrorName(status)); + } + + maxresultsize=0; + maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); + uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status); + } + else + { + testCtry=&_NUL; + } + if(U_FAILURE(status)){ + log_err("Error in getDisplayCountry() %s\n", myErrorName(status)); + } + + maxresultsize=0; + maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); + uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status); + } + else + { + testVar=&_NUL; + } + if(U_FAILURE(status)){ + log_err("Error in getDisplayVariant() %s\n", myErrorName(status)); + } + + maxresultsize=0; + maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1)); + uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status); + } + else + { + testName=&_NUL; + } + if(U_FAILURE(status)){ + log_err("Error in getDisplayName() %s\n", myErrorName(status)); + } + + expectedLang=dataTable[compareIndex][i]; + if(u_strlen(expectedLang)== 0) + expectedLang=dataTable[DLANG_EN][i]; + + expectedScript=dataTable[compareIndex + 1][i]; + if(u_strlen(expectedScript)== 0) + expectedScript=dataTable[DSCRIPT_EN][i]; + + expectedCtry=dataTable[compareIndex + 2][i]; + if(u_strlen(expectedCtry)== 0) + expectedCtry=dataTable[DCTRY_EN][i]; + + expectedVar=dataTable[compareIndex + 3][i]; + if(u_strlen(expectedVar)== 0) + expectedVar=dataTable[DVAR_EN][i]; + + expectedName=dataTable[compareIndex + 4][i]; + if(u_strlen(expectedName) == 0) + expectedName=dataTable[DNAME_EN][i]; + + if (0 !=u_strcmp(testLang,expectedLang)) { + log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s\n", austrdup(testLang), austrdup(expectedLang), displayLocale); + } + + if (0 != u_strcmp(testScript,expectedScript)) { + log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s\n", austrdup(testScript), austrdup(expectedScript), displayLocale); + } + + if (0 != u_strcmp(testCtry,expectedCtry)) { + log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale); + } + + if (0 != u_strcmp(testVar,expectedVar)) { + log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s\n", austrdup(testVar), austrdup(expectedVar), displayLocale); + } + + if(0 != u_strcmp(testName, expectedName)) { + log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s\n", austrdup(testName), austrdup(expectedName), displayLocale); + } + + if(testName!=&_NUL) { + free(testName); + } + if(testLang!=&_NUL) { + free(testLang); + } + if(testScript!=&_NUL) { + free(testScript); + } + if(testCtry!=&_NUL) { + free(testCtry); + } + if(testVar!=&_NUL) { + free(testVar); + } + } +cleanUpDataTable(); +} + +/* test for uloc_getISOLanguages, uloc_getISOCountries */ +static void TestISOFunctions() +{ + const char* const* str=uloc_getISOLanguages(); + const char* const* str1=uloc_getISOCountries(); + const char* test; + const char *key = NULL; + int32_t count = 0, skipped = 0; + int32_t expect; + UResourceBundle *res; + UResourceBundle *subRes; + UErrorCode status = U_ZERO_ERROR; + + /* test getISOLanguages*/ + /*str=uloc_getISOLanguages(); */ + log_verbose("Testing ISO Languages: \n"); + + /* use structLocale - this data is no longer in root */ + res = ures_openDirect(loadTestData(&status), "structLocale", &status); + subRes = ures_getByKey(res, "Languages", NULL, &status); + if (U_FAILURE(status)) { + log_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status)); + return; + } + + expect = ures_getSize(subRes); + for(count = 0; *(str+count) != 0; count++) + { + key = NULL; + test = *(str+count); + status = U_ZERO_ERROR; + + do { + /* Skip over language tags. This API only returns language codes. */ + skipped += (key != NULL); + ures_getNextString(subRes, NULL, &key, &status); + } + while (key != NULL && strchr(key, '_')); + + if(key == NULL) + break; + /* TODO: Consider removing sh, which is deprecated */ + if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) { + ures_getNextString(subRes, NULL, &key, &status); + skipped++; + } +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + /* This code only works on ASCII machines where the keys are stored in ASCII order */ + if(strcmp(test,key)) { + /* The first difference usually implies the place where things get out of sync */ + log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); + } +#endif + + if(!strcmp(test,"in")) + log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); + if(!strcmp(test,"iw")) + log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); + if(!strcmp(test,"ji")) + log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); + if(!strcmp(test,"jw")) + log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); + if(!strcmp(test,"sh")) + log_err("FAIL getISOLanguages() has obsolete language code %s\n", test); + } + + expect -= skipped; /* Ignore the skipped resources from structLocale */ + + if(count!=expect) { + log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect); + } + + subRes = ures_getByKey(res, "Countries", subRes, &status); + log_verbose("Testing ISO Countries"); + skipped = 0; + expect = ures_getSize(subRes) - 1; /* Skip ZZ */ + for(count = 0; *(str1+count) != 0; count++) + { + key = NULL; + test = *(str1+count); + do { + /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */ + skipped += (key != NULL); + ures_getNextString(subRes, NULL, &key, &status); + } + while (key != NULL && strlen(key) != 2); + + if(key == NULL) + break; + /* TODO: Consider removing CS, which is deprecated */ + while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) { + ures_getNextString(subRes, NULL, &key, &status); + skipped++; + } +#if U_CHARSET_FAMILY==U_ASCII_FAMILY + /* This code only works on ASCII machines where the keys are stored in ASCII order */ + if(strcmp(test,key)) { + /* The first difference usually implies the place where things get out of sync */ + log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key); + } +#endif + if(!strcmp(test,"FX")) + log_err("FAIL getISOCountries() has obsolete country code %s\n", test); + if(!strcmp(test,"YU")) + log_err("FAIL getISOCountries() has obsolete country code %s\n", test); + if(!strcmp(test,"ZR")) + log_err("FAIL getISOCountries() has obsolete country code %s\n", test); + } + + ures_getNextString(subRes, NULL, &key, &status); + if (strcmp(key, "ZZ") != 0) { + log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key); + } +#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY + /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */ + key = NULL; + do { + /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */ + skipped += (key != NULL); + ures_getNextString(subRes, NULL, &key, &status); + } + while (U_SUCCESS(status) && key != NULL && strlen(key) != 2); +#endif + expect -= skipped; /* Ignore the skipped resources from structLocale */ + if(count!=expect) + { + log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect); + } + ures_close(subRes); + ures_close(res); +} + +static void setUpDataTable() +{ + int32_t i,j; + dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE)); + + for (i = 0; i < LOCALE_INFO_SIZE; i++) { + dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE)); + for (j = 0; j < LOCALE_SIZE; j++){ + dataTable[i][j] = CharsToUChars(rawData2[i][j]); + } + } +} + +static void cleanUpDataTable() +{ + int32_t i,j; + if(dataTable != NULL) { + for (i=0; i<LOCALE_INFO_SIZE; i++) { + for(j = 0; j < LOCALE_SIZE; j++) { + free(dataTable[i][j]); + } + free(dataTable[i]); + } + free(dataTable); + } + dataTable = NULL; +} + +/** + * @bug 4011756 4011380 + */ +static void TestISO3Fallback() +{ + const char* test="xx_YY"; + + const char * result; + + result = uloc_getISO3Language(test); + + /* Conform to C API usage */ + + if (!result || (result[0] != 0)) + log_err("getISO3Language() on xx_YY returned %s instead of \"\""); + + result = uloc_getISO3Country(test); + + if (!result || (result[0] != 0)) + log_err("getISO3Country() on xx_YY returned %s instead of \"\""); +} + +/** + * @bug 4118587 + */ +static void TestSimpleDisplayNames() +{ + /* + This test is different from TestDisplayNames because TestDisplayNames checks + fallback behavior, combination of language and country names to form locale + names, and other stuff like that. This test just checks specific language + and country codes to make sure we have the correct names for them. + */ + char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" }; + const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish", + "Zhuang" }; + UErrorCode status=U_ZERO_ERROR; + + int32_t i; + for (i = 0; i < 6; i++) { + UChar *testLang=0; + UChar *expectedLang=0; + int size=0; + size=uloc_getDisplayLanguage(languageCodes[i], "en_US", NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + testLang=(UChar*)malloc(sizeof(UChar) * (size + 1)); + uloc_getDisplayLanguage(languageCodes[i], "en_US", testLang, size + 1, &status); + } + expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1)); + u_uastrcpy(expectedLang, languageNames[i]); + if (u_strcmp(testLang, expectedLang) != 0) + log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n", + languageCodes[i], languageNames[i], austrdup(testLang)); + free(testLang); + free(expectedLang); + } + +} + +/** + * @bug 4118595 + */ +static void TestUninstalledISO3Names() +{ + /* This test checks to make sure getISO3Language and getISO3Country work right + even for locales that are not installed. */ + static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn", + "ss", "tw", "zu" }; + static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run", + "ssw", "twi", "zul" }; + static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN", + "ss_SB", "tw_TC", "zu_ZW" }; + static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG", + "SLB", "TCA", "ZWE" }; + int32_t i; + + for (i = 0; i < 8; i++) { + UErrorCode err = U_ZERO_ERROR; + const char *test; + test = uloc_getISO3Language(iso2Languages[i]); + if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err)) + log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", + iso2Languages[i], iso3Languages[i], test, myErrorName(err)); + } + for (i = 0; i < 8; i++) { + UErrorCode err = U_ZERO_ERROR; + const char *test; + test = uloc_getISO3Country(iso2Countries[i]); + if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err)) + log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", + iso2Countries[i], iso3Countries[i], test, myErrorName(err)); + } +} + + +static void TestVariantParsing() +{ + static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth"; + static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)"; + static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH"; + static const char* shortVariant="fr_FR_foo"; + static const char* bogusVariant="fr_FR__foo"; + static const char* bogusVariant2="fr_FR_foo_"; + static const char* bogusVariant3="fr_FR__foo_"; + + + UChar displayVar[100]; + UChar displayName[100]; + UErrorCode status=U_ZERO_ERROR; + UChar* got=0; + int32_t size=0; + size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + u_uastrcpy(displayVar, dispVar); + if(u_strcmp(got,displayVar)!=0) { + log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got)); + } + size=0; + size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + u_uastrcpy(displayName, dispName); + if(u_strcmp(got,displayName)!=0) { + log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got)); + } + + size=0; + status=U_ZERO_ERROR; + size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + if(strcmp(austrdup(got),"FOO")!=0) { + log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got)); + } + size=0; + status=U_ZERO_ERROR; + size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + if(strcmp(austrdup(got),"_FOO")!=0) { + log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got)); + } + size=0; + status=U_ZERO_ERROR; + size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + if(strcmp(austrdup(got),"FOO_")!=0) { + log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got)); + } + size=0; + status=U_ZERO_ERROR; + size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + got=(UChar*)realloc(got, sizeof(UChar) * (size+1)); + uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status); + } + else { + log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n"); + } + if(strcmp(austrdup(got),"_FOO_")!=0) { + log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got)); + } + free(got); +} + + +static void TestObsoleteNames(void) +{ + int32_t i; + UErrorCode status = U_ZERO_ERROR; + char buff[256]; + + static const struct + { + char locale[9]; + char lang3[4]; + char lang[4]; + char ctry3[4]; + char ctry[4]; + } tests[] = + { + { "eng_USA", "eng", "en", "USA", "US" }, + { "kok", "kok", "kok", "", "" }, + { "in", "ind", "in", "", "" }, + { "id", "ind", "id", "", "" }, /* NO aliasing */ + { "sh", "srp", "sh", "", "" }, + { "zz_CS", "", "zz", "SCG", "CS" }, + { "zz_FX", "", "zz", "FXX", "FX" }, + { "zz_RO", "", "zz", "ROU", "RO" }, + { "zz_TP", "", "zz", "TMP", "TP" }, + { "zz_TL", "", "zz", "TLS", "TL" }, + { "zz_ZR", "", "zz", "ZAR", "ZR" }, + { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */ + { "zz_ROM", "", "zz", "ROU", "RO" }, + { "zz_ROU", "", "zz", "ROU", "RO" }, + { "zz_ZAR", "", "zz", "ZAR", "ZR" }, + { "zz_TMP", "", "zz", "TMP", "TP" }, + { "zz_TLS", "", "zz", "TLS", "TL" }, + { "zz_YUG", "", "zz", "YUG", "YU" }, + { "mlt_PSE", "mlt", "mt", "PSE", "PS" }, + { "iw", "heb", "iw", "", "" }, + { "ji", "yid", "ji", "", "" }, + { "jw", "jaw", "jw", "", "" }, + { "sh", "srp", "sh", "", "" }, + { "", "", "", "", "" } + }; + + for(i=0;tests[i].locale[0];i++) + { + const char *locale; + + locale = tests[i].locale; + log_verbose("** %s:\n", locale); + + status = U_ZERO_ERROR; + if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) + { + log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", + locale, uloc_getISO3Language(locale), tests[i].lang3); + } + else + { + log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", + uloc_getISO3Language(locale) ); + } + + status = U_ZERO_ERROR; + uloc_getLanguage(locale, buff, 256, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error getting language from %s\n", locale); + } + else + { + if(strcmp(buff,tests[i].lang)) + { + log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n", + locale, buff, tests[i].lang); + } + else + { + log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff); + } + } + if(strcmp(tests[i].lang3,uloc_getISO3Language(locale))) + { + log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n", + locale, uloc_getISO3Language(locale), tests[i].lang3); + } + else + { + log_verbose(" uloc_getISO3Language()==\t\"%s\"\n", + uloc_getISO3Language(locale) ); + } + + if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale))) + { + log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n", + locale, uloc_getISO3Country(locale), tests[i].ctry3); + } + else + { + log_verbose(" uloc_getISO3Country()==\t\"%s\"\n", + uloc_getISO3Country(locale) ); + } + + status = U_ZERO_ERROR; + uloc_getCountry(locale, buff, 256, &status); + if(U_FAILURE(status)) + { + log_err("FAIL: error getting country from %s\n", locale); + } + else + { + if(strcmp(buff,tests[i].ctry)) + { + log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n", + locale, buff, tests[i].ctry); + } + else + { + log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff); + } + } + } + + if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) { + log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL")); + } + + if (uloc_getLCID("iw") != uloc_getLCID("he")) { + log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he")); + } + +#if 0 + + i = uloc_getLanguage("kok",NULL,0,&icu_err); + if(U_FAILURE(icu_err)) + { + log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err)); + } + + icu_err = U_ZERO_ERROR; + uloc_getLanguage("kok",r1_buff,12,&icu_err); + if(U_FAILURE(icu_err)) + { + log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err)); + } + + r1_addr = (char *)uloc_getISO3Language("kok"); + + icu_err = U_ZERO_ERROR; + if (strcmp(r1_buff,"kok") != 0) + { + log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff); + line--; + } + r1_addr = (char *)uloc_getISO3Language("in"); + i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); + if (strcmp(r1_buff,"id") != 0) + { + printf("uloc_getLanguage error (%s)\n",r1_buff); + line--; + } + r1_addr = (char *)uloc_getISO3Language("sh"); + i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err); + if (strcmp(r1_buff,"sr") != 0) + { + printf("uloc_getLanguage error (%s)\n",r1_buff); + line--; + } + + r1_addr = (char *)uloc_getISO3Country("zz_ZR"); + strcpy(p1_buff,"zz_"); + strcat(p1_buff,r1_addr); + i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); + if (strcmp(r1_buff,"ZR") != 0) + { + printf("uloc_getCountry error (%s)\n",r1_buff); + line--; + } + r1_addr = (char *)uloc_getISO3Country("zz_FX"); + strcpy(p1_buff,"zz_"); + strcat(p1_buff,r1_addr); + i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err); + if (strcmp(r1_buff,"FX") != 0) + { + printf("uloc_getCountry error (%s)\n",r1_buff); + line--; + } + +#endif + +} + +static void TestKeywordVariants(void) +{ + static const struct { + const char *localeID; + const char *expectedLocaleID; + const char *expectedLocaleIDNoKeywords; + const char *expectedCanonicalID; + const char *expectedKeywords[10]; + int32_t numKeywords; + UErrorCode expectedStatus; /* from uloc_openKeywords */ + } testCases[] = { + { + "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ", + "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", + "de_DE", + "de_DE@calendar=buddhist;collation=Phonebook;currency=euro", + {"calendar", "collation", "currency"}, + 3, + U_ZERO_ERROR + }, + { + "de_DE@euro", + "de_DE@euro", + "de_DE", + "de_DE@currency=EUR", + {"","","","","","",""}, + 0, + U_INVALID_FORMAT_ERROR /* must have '=' after '@' */ + }, + { + "de_DE@euro;collation=phonebook", + "de_DE", /* error result; bad format */ + "de_DE", /* error result; bad format */ + "de_DE", /* error result; bad format */ + {"","","","","","",""}, + 0, + U_INVALID_FORMAT_ERROR + } + }; + UErrorCode status = U_ZERO_ERROR; + + int32_t i = 0, j = 0; + int32_t resultLen = 0; + char buffer[256]; + UEnumeration *keywords; + int32_t keyCount = 0; + const char *keyword = NULL; + int32_t keywordLen = 0; + + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + status = U_ZERO_ERROR; + *buffer = 0; + keywords = uloc_openKeywords(testCases[i].localeID, &status); + + if(status != testCases[i].expectedStatus) { + log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n", + testCases[i].localeID, + u_errorName(testCases[i].expectedStatus), u_errorName(status)); + } + status = U_ZERO_ERROR; + if(keywords) { + if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) { + log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount); + } + if(keyCount) { + j = 0; + while((keyword = uenum_next(keywords, &keywordLen, &status))) { + if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { + log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); + } + j++; + } + j = 0; + uenum_reset(keywords, &status); + while((keyword = uenum_next(keywords, &keywordLen, &status))) { + if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) { + log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword); + } + j++; + } + } + uenum_close(keywords); + } + resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status); + if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) { + log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n", + testCases[i].localeID, testCases[i].expectedLocaleID, buffer); + } + resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status); + if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) { + log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n", + testCases[i].localeID, testCases[i].expectedCanonicalID, buffer); + } + } + +} + +static void TestKeywordVariantParsing(void) +{ + static const struct { + const char *localeID; + const char *keyword; + const char *expectedValue; + } testCases[] = { + { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" }, + { "de_DE", "collation", ""}, + { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" }, + { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" }, + }; + + UErrorCode status = U_ZERO_ERROR; + + int32_t i = 0; + int32_t resultLen = 0; + char buffer[256]; + + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + *buffer = 0; + resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status); + if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) { + log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n", + testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer); + } + } +} + +static const struct { + const char *l; /* locale */ + const char *k; /* kw */ + const char *v; /* value */ + const char *x; /* expected */ +} kwSetTestCases[] = { +#if 1 + { "en_US", "calendar", "japanese", "en_US@calendar=japanese" }, + { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" }, + { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" }, + { "en_US@calendar=slovakian", "calendar", "gregorian", "en_US@calendar=gregorian" }, /* don't know what this means, but it has the same # of chars as gregorian */ + { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" }, + { "de", "Currency", "CHF", "de@currency=CHF" }, + { "de", "Currency", "CHF", "de@currency=CHF" }, + + { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, + { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" }, + { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, + { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, + { "en_US@calendar=slovakian;collation=phonebook", "calendar", "gregorian", "en_US@calendar=gregorian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */ + { "en_US@calendar=slovakian;collation=videobook", "collation", "phonebook", "en_US@calendar=slovakian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */ + { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" }, + { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }, +#endif +#if 1 + { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" }, + { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" }, + { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" }, + { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" }, + { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" }, + { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" }, + { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" }, + { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" }, + { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" }, +#endif +#if 1 + /* removal tests */ + /* 1. removal of item at end */ + { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" }, + { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" }, + /* 2. removal of item at beginning */ + { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" }, + { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" }, + /* 3. removal of an item not there */ + { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" }, + /* 4. removal of only item */ + { "de@collation=phonebook", "collation", NULL, "de" }, +#endif + { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" } +}; + + +static void TestKeywordSet(void) +{ + int32_t i = 0; + int32_t resultLen = 0; + char buffer[1024]; + + char cbuffer[1024]; + + for(i = 0; i < sizeof(kwSetTestCases)/sizeof(kwSetTestCases[0]); i++) { + UErrorCode status = U_ZERO_ERROR; + memset(buffer,'%',1023); + strcpy(buffer, kwSetTestCases[i].l); + + uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status); + if(strcmp(buffer,cbuffer)) { + log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer); + } + /* sanity check test case results for canonicity */ + uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status); + if(strcmp(kwSetTestCases[i].x,cbuffer)) { + log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer); + } + + resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status); + if(U_FAILURE(status)) { + log_err("Err on test case %d: got error %s\n", i, u_errorName(status)); + continue; + } + if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) { + log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, + kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer)); + } else { + log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer); + } + } +} + +static void TestKeywordSetError(void) +{ + char buffer[1024]; + UErrorCode status; + int32_t res; + int32_t i; + int32_t blen; + + /* 0-test whether an error condition modifies the buffer at all */ + blen=0; + i=0; + memset(buffer,'%',1023); + status = U_ZERO_ERROR; + res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); + if(status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("expected illegal err got %s\n", u_errorName(status)); + return; + } + /* if(res!=strlen(kwSetTestCases[i].x)) { + log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); + return; + } */ + if(buffer[blen]!='%') { + log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); + return; + } + log_verbose("0-buffer modify OK\n"); + + for(i=0;i<=2;i++) { + /* 1- test a short buffer with growing text */ + blen=(int32_t)strlen(kwSetTestCases[i].l)+1; + memset(buffer,'%',1023); + strcpy(buffer,kwSetTestCases[i].l); + status = U_ZERO_ERROR; + res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); + if(status != U_BUFFER_OVERFLOW_ERROR) { + log_err("expected buffer overflow on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v); + return; + } + if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { + log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); + return; + } + if(buffer[blen]!='%') { + log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]); + return; + } + log_verbose("1/%d-buffer modify OK\n",i); + } + + for(i=3;i<=4;i++) { + /* 2- test a short buffer - text the same size or shrinking */ + blen=(int32_t)strlen(kwSetTestCases[i].l)+1; + memset(buffer,'%',1023); + strcpy(buffer,kwSetTestCases[i].l); + status = U_ZERO_ERROR; + res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status); + if(status != U_ZERO_ERROR) { + log_err("expected zero error got %s\n", u_errorName(status)); + return; + } + if(buffer[blen+1]!='%') { + log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]); + return; + } + if(res!=(int32_t)strlen(kwSetTestCases[i].x)) { + log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res); + return; + } + if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) { + log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, + kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer)); + } else { + log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v, + buffer); + } + log_verbose("2/%d-buffer modify OK\n",i); + } +} + +static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */ + const char* localeID, + char* result, + int32_t resultCapacity, + UErrorCode* ec) { + /* YOU can change this to use function pointers if you like */ + switch (selector) { + case 0: + return uloc_getName(localeID, result, resultCapacity, ec); + case 1: + return uloc_canonicalize(localeID, result, resultCapacity, ec); + default: + return -1; + } +} + +static void TestCanonicalization(void) +{ + static const struct { + const char *localeID; /* input */ + const char *getNameID; /* expected getName() result */ + const char *canonicalID; /* expected canonicalize() result */ + } testCases[] = { + { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage", + "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE", + "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"}, + { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" }, + { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" }, + { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" }, + { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" }, + { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" }, + { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" }, + { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" }, + { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" }, + { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" }, + { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" }, + { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" }, + { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" }, + { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" }, + { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" }, + { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" }, + { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" }, + { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" }, + { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" }, + { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" }, + { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" }, + { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" }, + { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */ + { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" }, + { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" }, + { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" }, + { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" }, + { "zh_TW_STROKE", "zh_TW_STROKE", "zh_Hant_TW@collation=stroke" }, + { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" }, + { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" }, + { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" }, + { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" }, + { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" }, + { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" }, + { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ }, + { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */ + { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */ + { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */ + { "en-BOONT", "en_BOONT", "en__BOONT" }, /* registered name */ + { "de-1901", "de_1901", "de__1901" }, /* registered name */ + { "de-1906", "de_1906", "de__1906" }, /* registered name */ + { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_CS" }, /* .NET name */ + { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_CS" }, /* .NET name */ + { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_CS" }, /* Linux name */ + { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */ + { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */ + { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */ + { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */ + + /* posix behavior that used to be performed by getName */ + { "mr.utf8", "mr.utf8", "mr" }, + { "de-tv.koi8r", "de_TV.koi8r", "de_TV" }, + { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" }, + { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" }, + { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" }, + { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO_NY_B" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */ + + /* fleshing out canonicalization */ + /* trim space and sort keywords, ';' is separator so not present at end in canonical form */ + { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" }, + /* already-canonical ids are not changed */ + { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" }, + /* PRE_EURO and EURO conversions don't affect other keywords */ + { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" }, + { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" }, + /* currency keyword overrides PRE_EURO and EURO currency */ + { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" }, + { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" }, + /* norwegian is just too weird, if we handle things in their full generality */ + { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ }, + + /* test cases reflecting internal resource bundle usage */ + { "root@kw=foo", "root@kw=foo", "root@kw=foo" }, + { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" }, + { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" }, + { "ja_JP", "ja_JP", "ja_JP" }, + + /* test case for "i-default" */ + { "i-default", NULL, NULL } + }; + + static const char* label[] = { "getName", "canonicalize" }; + + UErrorCode status = U_ZERO_ERROR; + int32_t i, j, resultLen = 0, origResultLen; + char buffer[256]; + + for (i=0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + for (j=0; j<2; ++j) { + const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID; + *buffer = 0; + status = U_ZERO_ERROR; + + if (expected == NULL) { + expected = uloc_getDefault(); + } + + /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */ + origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status); + if (status != U_BUFFER_OVERFLOW_ERROR) { + log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n", + label[j], testCases[i].localeID, u_errorName(status)); + continue; + } + status = U_ZERO_ERROR; + resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status); + if (U_FAILURE(status)) { + log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n", + label[j], testCases[i].localeID, u_errorName(status)); + continue; + } + if(uprv_strcmp(expected, buffer) != 0) { + log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n", + label[j], testCases[i].localeID, buffer, expected); + } else { + log_verbose("Ok: uloc_%s(%s) => \"%s\"\n", + label[j], testCases[i].localeID, buffer); + } + if (resultLen != (int32_t)strlen(buffer)) { + log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n", + label[j], testCases[i].localeID, resultLen, strlen(buffer)); + } + if (origResultLen != resultLen) { + log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n", + label[j], testCases[i].localeID, origResultLen, resultLen); + } + } + } +} + +static void TestDisplayKeywords(void) +{ + int32_t i; + + static const struct { + const char *localeID; + const char *displayLocale; + UChar displayKeyword[200]; + } testCases[] = { + { "ca_ES@currency=ESP", "de_AT", + {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}, + }, + { "ja_JP@calendar=japanese", "de", + { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} + }, + { "de_DE@collation=traditional", "de_DE", + {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000} + }, + }; + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + UErrorCode status = U_ZERO_ERROR; + const char* keyword =NULL; + int32_t keywordLen = 0; + int32_t keywordCount = 0; + UChar *displayKeyword=NULL; + int32_t displayKeywordLen = 0; + UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); + for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ + if(U_FAILURE(status)){ + log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status)); + break; + } + /* the uenum_next returns NUL terminated string */ + keyword = uenum_next(keywordEnum, &keywordLen, &status); + /* fetch the displayKeyword */ + displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; + displayKeywordLen++; /* for null termination */ + displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR); + displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status); + if(U_FAILURE(status)){ + log_err("uloc_getDisplayKeyword filed for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); + break; + } + if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){ + log_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale); + break; + } + }else{ + log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status)); + } + + free(displayKeyword); + + } + uenum_close(keywordEnum); + } +} + +static void TestDisplayKeywordValues(void){ + int32_t i; + + static const struct { + const char *localeID; + const char *displayLocale; + UChar displayKeywordValue[500]; + } testCases[] = { + { "ca_ES@currency=ESP", "de_AT", + {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0065, 0x0000} + }, + { "de_AT@currency=ATS", "fr_FR", + {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000} + }, + { "de_DE@currency=DEM", "it", + {0x004d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0054, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000} + }, + { "el_GR@currency=GRD", "en", + {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000} + }, + { "eu_ES@currency=ESP", "it_IT", + {0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0053, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000} + }, + { "de@collation=phonebook", "es", + {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000} + }, + + { "de_DE@collation=phonebook", "es", + {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000} + }, + { "es_ES@collation=traditional","de", + {0x0054, 0x0072, 0x0061, 0x0064, 0x0069, 0x0074, 0x0069, 0x006f, 0x006e, 0x0065, 0x006c, 0x006c, 0x0065, 0x0020, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000} + }, + { "ja_JP@calendar=japanese", "de", + {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000} + }, + }; + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + UErrorCode status = U_ZERO_ERROR; + const char* keyword =NULL; + int32_t keywordLen = 0; + int32_t keywordCount = 0; + UChar *displayKeywordValue = NULL; + int32_t displayKeywordValueLen = 0; + UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status); + for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){ + if(U_FAILURE(status)){ + log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", testCases[i].localeID, testCases[i].displayLocale, u_errorName(status)); + break; + } + /* the uenum_next returns NUL terminated string */ + keyword = uenum_next(keywordEnum, &keywordLen, &status); + + /* fetch the displayKeywordValue */ + displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; + displayKeywordValueLen++; /* for null termination */ + displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); + displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status); + if(U_FAILURE(status)){ + log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); + break; + } + if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){ + log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status)); + break; + } + }else{ + log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); + } + free(displayKeywordValue); + } + uenum_close(keywordEnum); + } + { + /* test a multiple keywords */ + UErrorCode status = U_ZERO_ERROR; + const char* keyword =NULL; + int32_t keywordLen = 0; + int32_t keywordCount = 0; + const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM"; + const char* displayLocale = "de"; + static const UChar expected[][50] = { + {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}, + + {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000}, + {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000}, + }; + + UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status); + + for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){ + UChar *displayKeywordValue = NULL; + int32_t displayKeywordValueLen = 0; + if(U_FAILURE(status)){ + log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status)); + break; + } + /* the uenum_next returns NUL terminated string */ + keyword = uenum_next(keywordEnum, &keywordLen, &status); + + /* fetch the displayKeywordValue */ + displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; + displayKeywordValueLen++; /* for null termination */ + displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR); + displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status); + if(U_FAILURE(status)){ + log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID, keyword, displayLocale, u_errorName(status)); + break; + } + if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){ + log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale); + break; + } + }else{ + log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status)); + } + free(displayKeywordValue); + } + uenum_close(keywordEnum); + + } + { + /* Test non existent keywords */ + UErrorCode status = U_ZERO_ERROR; + const char* localeID = "es"; + const char* displayLocale = "de"; + UChar *displayKeywordValue = NULL; + int32_t displayKeywordValueLen = 0; + + /* fetch the displayKeywordValue */ + displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status); + if(U_FAILURE(status)) { + log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status)); + } else if(displayKeywordValueLen != 0) { + log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen); + } + } +} + + +static void TestGetBaseName(void) { + static const struct { + const char *localeID; + const char *baseName; + } testCases[] = { + { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" }, + { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" }, + { "ja@calendar = buddhist", "ja" } + }; + + int32_t i = 0, baseNameLen = 0; + char baseName[256]; + UErrorCode status = U_ZERO_ERROR; + + for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) { + baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status); + if(strcmp(testCases[i].baseName, baseName)) { + log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n", + testCases[i].localeID, testCases[i].baseName, baseName); + return; + } + } + +} + + +/* Jitterbug 4115 */ +static void TestDisplayNameWarning(void) { + UChar name[256]; + int32_t size; + UErrorCode status = U_ZERO_ERROR; + + size = uloc_getDisplayLanguage("qqq", "kl", name, sizeof(name)/sizeof(name[0]), &status); + if (status != U_USING_DEFAULT_WARNING) { + log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n", + u_errorName(status)); + } +} + + +/** + * Compare two locale IDs. If they are equal, return 0. If `string' + * starts with `prefix' plus an additional element, that is, string == + * prefix + '_' + x, then return 1. Otherwise return a value < 0. + */ +static UBool _loccmp(const char* string, const char* prefix) { + int32_t slen = (int32_t)uprv_strlen(string), + plen = (int32_t)uprv_strlen(prefix); + int32_t c = uprv_strncmp(string, prefix, plen); + /* 'root' is less than everything */ + if (uprv_strcmp(prefix, "root") == 0) { + return (uprv_strcmp(string, "root") == 0) ? 0 : 1; + } + if (c) return -1; /* mismatch */ + if (slen == plen) return 0; + if (string[plen] == '_') return 1; + return -2; /* false match, e.g. "en_USX" cmp "en_US" */ +} + +static void _checklocs(const char* label, + const char* req, + const char* valid, + const char* actual) { + /* We want the valid to be strictly > the bogus requested locale, + and the valid to be >= the actual. */ + if (_loccmp(req, valid) > 0 && + _loccmp(valid, actual) >= 0) { + log_verbose("%s; req=%s, valid=%s, actual=%s\n", + label, req, valid, actual); + } else { + log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n", + label, req, valid, actual); + } +} + +static void TestGetLocale(void) { + UErrorCode ec = U_ZERO_ERROR; + UParseError pe; + UChar EMPTY[1] = {0}; + + /* === udat === */ +#if !UCONFIG_NO_FORMATTING + { + UDateFormat *obj; + const char *req = "en_US_REDWOODSHORES", *valid, *actual; + obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, + req, + NULL, 0, + NULL, 0, &ec); + if (U_FAILURE(ec)) { + log_err("udat_open failed.Error %s\n", u_errorName(ec)); + return; + } + valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("udat_getLocaleByType() failed\n"); + return; + } + _checklocs("udat", req, valid, actual); + udat_close(obj); + } +#endif + + /* === ucal === */ +#if !UCONFIG_NO_FORMATTING + { + UCalendar *obj; + const char *req = "fr_FR_PROVENCAL", *valid, *actual; + obj = ucal_open(NULL, 0, + req, + UCAL_GREGORIAN, + &ec); + if (U_FAILURE(ec)) { + log_err("ucal_open failed with error: %s\n", u_errorName(ec)); + return; + } + valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("ucal_getLocaleByType() failed\n"); + return; + } + _checklocs("ucal", req, valid, actual); + ucal_close(obj); + } +#endif + + /* === unum === */ +#if !UCONFIG_NO_FORMATTING + { + UNumberFormat *obj; + const char *req = "zh_Hant_TW_TAINAN", *valid, *actual; + obj = unum_open(UNUM_DECIMAL, + NULL, 0, + req, + &pe, &ec); + if (U_FAILURE(ec)) { + log_err("unum_open failed\n"); + return; + } + valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("unum_getLocaleByType() failed\n"); + return; + } + _checklocs("unum", req, valid, actual); + unum_close(obj); + } +#endif + + /* === umsg === */ +#if 0 + /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */ +#if !UCONFIG_NO_FORMATTING + { + UMessageFormat *obj; + const char *req = "ja_JP_TAKAYAMA", *valid, *actual; + UBool test; + obj = umsg_open(EMPTY, 0, + req, + &pe, &ec); + if (U_FAILURE(ec)) { + log_err("umsg_open failed\n"); + return; + } + valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("umsg_getLocaleByType() failed\n"); + return; + } + /* We want the valid to be strictly > the bogus requested locale, + and the valid to be >= the actual. */ + /* TODO MessageFormat is currently just storing the locale it is given. + As a result, it will return whatever it was given, even if the + locale is invalid. */ + test = (_cmpversion("3.2") <= 0) ? + /* Here is the weakened test for 3.0: */ + (_loccmp(req, valid) >= 0) : + /* Here is what the test line SHOULD be: */ + (_loccmp(req, valid) > 0); + + if (test && + _loccmp(valid, actual) >= 0) { + log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); + } else { + log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual); + } + umsg_close(obj); + } +#endif +#endif + + /* === ubrk === */ +#if !UCONFIG_NO_BREAK_ITERATION + { + UBreakIterator *obj; + const char *req = "ar_KW_ABDALI", *valid, *actual; + obj = ubrk_open(UBRK_WORD, + req, + EMPTY, + 0, + &ec); + if (U_FAILURE(ec)) { + log_err("ubrk_open failed. Error: %s \n", u_errorName(ec)); + return; + } + valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("ubrk_getLocaleByType() failed\n"); + return; + } + _checklocs("ubrk", req, valid, actual); + ubrk_close(obj); + } +#endif + + /* === ucol === */ +#if !UCONFIG_NO_COLLATION + { + UCollator *obj; + const char *req = "es_AR_BUENOSAIRES", *valid, *actual; + obj = ucol_open(req, &ec); + if (U_FAILURE(ec)) { + log_err("ucol_open failed\n"); + return; + } + valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec); + actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec); + if (U_FAILURE(ec)) { + log_err("ucol_getLocaleByType() failed\n"); + return; + } + _checklocs("ucol", req, valid, actual); + ucol_close(obj); + } +#endif +} + +static void TestNonexistentLanguageExemplars(void) { + /* JB 4068 - Nonexistent language */ + UErrorCode ec = U_ZERO_ERROR; + ULocaleData *uld = ulocdata_open("qqq",&ec); + if (ec != U_USING_DEFAULT_WARNING) { + log_err("Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n", + u_errorName(ec)); + } + uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); + ulocdata_close(uld); +} + +static void TestLocDataErrorCodeChaining(void) { + UErrorCode ec = U_USELESS_COLLATOR_ERROR; + ulocdata_open(NULL, &ec); + ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec); + ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec); + ulocdata_getMeasurementSystem(NULL, &ec); + ulocdata_getPaperSize(NULL, NULL, NULL, &ec); + if (ec != U_USELESS_COLLATOR_ERROR) { + log_err("ulocdata API changed the error code to %s\n", u_errorName(ec)); + } +} + +static void TestLanguageExemplarsFallbacks(void) { + /* Test that en_US fallsback, but en doesn't fallback. */ + UErrorCode ec = U_ZERO_ERROR; + ULocaleData *uld = ulocdata_open("en_US",&ec); + uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); + if (ec != U_USING_FALLBACK_WARNING) { + log_err("Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n", + u_errorName(ec)); + } + ulocdata_close(uld); + ec = U_ZERO_ERROR; + uld = ulocdata_open("en",&ec); + uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec)); + if (ec != U_ZERO_ERROR) { + log_err("Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n", + u_errorName(ec)); + } + ulocdata_close(uld); +} + +static void TestAcceptLanguage(void) { + UErrorCode status = U_ZERO_ERROR; + UAcceptResult outResult; + UEnumeration *available; + char tmp[200]; + int i; + int32_t rc = 0; + + struct { + int32_t httpSet; + const char *icuSet; + const char *expect; + UAcceptResult res; + } tests[] = { + /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID }, + /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID }, + /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK }, + /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED }, + /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID }, + }; + const int32_t numTests = sizeof(tests)/sizeof(tests[0]); + static const char *http[] = { + /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=.01", + /*1*/ "ja;q=0.5, en;q=0.8, tlh", + /*2*/ "en-wf, de-lx;q=0.8", + /*3*/ "mga-ie;q=0.9, tlh", + /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, " + "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, " + "es" + }; + + for(i=0;i<numTests;i++) { + outResult = -3; + status=U_ZERO_ERROR; + log_verbose("test #%d: http[%s], ICU[%s], expect %s, %d\n", + i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res); + + available = ures_openAvailableLocales(tests[i].icuSet, &status); + tmp[0]=0; + rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status); + uenum_close(available); + log_verbose(" got %s, %d [%s]\n", tmp[0]?tmp:"(EMPTY)", outResult, u_errorName(status)); + if(outResult != tests[i].res) { + log_err("FAIL: #%d: expected outResult of %d but got %d\n", i, tests[i].res, outResult); + log_info("test #%d: http[%s], ICU[%s], expect %s, %d\n", + i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res); + } + if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { + log_err("FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); + log_info("test #%d: http[%s], ICU[%s], expect %s, %d\n", + i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res); + } + } +} + +static const char* LOCALE_ALIAS[][2] = { + {"in", "id"}, + {"in_ID", "id_ID"}, + {"iw", "he"}, + {"iw_IL", "he_IL"}, + {"ji", "yi"}, + {"en_BU", "en_MM"}, + {"en_DY", "en_BJ"}, + {"en_HV", "en_BF"}, + {"en_NH", "en_VU"}, + {"en_RH", "en_ZW"}, + {"en_TP", "en_TL"}, + {"en_ZR", "en_CD"} +}; +static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){ + UErrorCode status = U_ZERO_ERROR; + int32_t len = 0; + ures_getStringByKey(resIndex, loc,&len, &status); + if(U_FAILURE(status)){ + return FALSE; + } + return TRUE; +} + +static void TestCalendar() { +#if !UCONFIG_NO_FORMATTING + int i; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); + if(U_FAILURE(status)){ + log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); + return; + } + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + UCalendar* c1 = NULL; + UCalendar* c2 = NULL; + + /*Test function "getLocale(ULocale.VALID_LOCALE)"*/ + const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); + const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); + + if(!isLocaleAvailable(resIndex, newLoc)){ + continue; + } + c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status); + c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status); + + if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) { + log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); + } + log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2); + ucal_close(c1); + ucal_close(c2); + } + ures_close(resIndex); +#endif +} + +static void TestDateFormat() { +#if !UCONFIG_NO_FORMATTING + int i; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); + if(U_FAILURE(status)){ + log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); + return; + } + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + UDateFormat* df1 = NULL; + UDateFormat* df2 = NULL; + const char* l1 = NULL; + const char* l2 = NULL; + + if(!isLocaleAvailable(resIndex, newLoc)){ + continue; + } + df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status); + df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status); + if(U_FAILURE(status)){ + log_err("Creation of date format failed %s\n", u_errorName(status)); + return; + } + /*Test function "getLocale"*/ + l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status); + l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status); + if(U_FAILURE(status)){ + log_err("Fetching the locale by type failed. %s\n", u_errorName(status)); + } + if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { + log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); + } + log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2); + udat_close(df1); + udat_close(df2); + } + ures_close(resIndex); +#endif +} + +static void TestCollation() { +#if !UCONFIG_NO_COLLATION + int i; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); + if(U_FAILURE(status)){ + log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); + return; + } + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + UCollator* c1 = NULL; + UCollator* c2 = NULL; + const char* l1 = NULL; + const char* l2 = NULL; + + status = U_ZERO_ERROR; + if(!isLocaleAvailable(resIndex, newLoc)){ + continue; + } + if(U_FAILURE(status)){ + log_err("Creation of collators failed %s\n", u_errorName(status)); + return; + } + c1 = ucol_open(oldLoc, &status); + c2 = ucol_open(newLoc, &status); + l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status); + l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status); + if(U_FAILURE(status)){ + log_err("Fetching the locale names failed failed %s\n", u_errorName(status)); + } + if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) { + log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); + } + log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2); + ucol_close(c1); + ucol_close(c2); + } + ures_close(resIndex); +#endif +} + +static void TestULocale() { + int i; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *resIndex = ures_open(NULL,"res_index", &status); + if(U_FAILURE(status)){ + log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); + return; + } + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + UChar name1[256], name2[256]; + char names1[256], names2[256]; + int32_t capacity = 256; + + status = U_ZERO_ERROR; + if(!isLocaleAvailable(resIndex, newLoc)){ + continue; + } + uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status); + if(U_FAILURE(status)){ + log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status)); + } + + uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status); + if(U_FAILURE(status)){ + log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status)); + } + + if (u_strcmp(name1, name2)!=0) { + log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); + } + u_austrcpy(names1, name1); + u_austrcpy(names2, name2); + log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2); + } + ures_close(resIndex); + +} + +static void TestUResourceBundle() { + const char* us1; + const char* us2; + + UResourceBundle* rb1 = NULL; + UResourceBundle* rb2 = NULL; + UErrorCode status = U_ZERO_ERROR; + int i; + UResourceBundle *resIndex = NULL; + if(U_FAILURE(status)){ + log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status)); + return; + } + resIndex = ures_open(NULL,"res_index", &status); + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + if(!isLocaleAvailable(resIndex, newLoc)){ + continue; + } + rb1 = ures_open(NULL, oldLoc, &status); + if (U_FAILURE(status)) { + log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); + } + + us1 = ures_getLocale(rb1, &status); + + status = U_ZERO_ERROR; + rb2 = ures_open(NULL, newLoc, &status); + if (U_FAILURE(status)) { + log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status)); + } + us2 = ures_getLocale(rb2, &status); + + if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) { + log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc); + } + + log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2); + ures_close(rb1); + rb1 = NULL; + ures_close(rb2); + rb2 = NULL; + } + ures_close(resIndex); +} + +static void TestDisplayName() { + + UChar oldCountry[256] = {'\0'}; + UChar newCountry[256] = {'\0'}; + UChar oldLang[256] = {'\0'}; + UChar newLang[256] = {'\0'}; + char country[256] ={'\0'}; + char language[256] ={'\0'}; + int32_t capacity = 256; + int i =0; + int j=0; + for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) { + const char* oldLoc = LOCALE_ALIAS[i][0]; + const char* newLoc = LOCALE_ALIAS[i][1]; + UErrorCode status = U_ZERO_ERROR; + int32_t available = uloc_countAvailable(); + + for(j=0; j<available; j++){ + + const char* dispLoc = uloc_getAvailable(j); + int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status); + int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status); + int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status); + int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status ); + + int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status); + int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status); + /* there is a display name for the current country ID */ + if(countryLen != newCountryLen ){ + if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){ + log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc); + } + } + /* there is a display name for the current lang ID */ + if(langLen!=newLangLen){ + if(u_strncmp(oldLang,newLang,oldLangLen)){ + log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); } + } + } + } +} + +static void TestGetLocaleForLCID() { + int32_t i, length, lengthPre; + const char* testLocale = 0; + UErrorCode status = U_ZERO_ERROR; + char temp2[40], temp3[40]; + uint32_t lcid; + + lcid = uloc_getLCID("en_US"); + if (lcid != 0x0409) { + log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid); + } + + lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status); + if (status != U_BUFFER_OVERFLOW_ERROR) { + log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status)); + } + else { + status = U_ZERO_ERROR; + } + + length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status); + if (U_FAILURE(status)) { + log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } + + if (length != lengthPre) { + log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre); + } + + length = uloc_getLocaleForLCID(0x12345, temp2, sizeof(temp2)/sizeof(char), &status); + if (U_SUCCESS(status)) { + log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status)); + } + status = U_ZERO_ERROR; + + log_verbose("Testing getLocaleForLCID vs. locale data\n"); + for (i = 0; i < LOCALE_SIZE; i++) { + + testLocale=rawData2[NAME][i]; + + log_verbose("Testing %s ......\n", testLocale); + + sscanf(rawData2[LCID][i], "%x", &lcid); + length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status); + if (U_FAILURE(status)) { + log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status)); + status = U_ZERO_ERROR; + continue; + } + + if (length != uprv_strlen(temp2)) { + log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2)); + } + + /* Compare language, country, script */ + length = uloc_getLanguage(temp2, temp3, sizeof(temp3)/sizeof(char), &status); + if (U_FAILURE(status)) { + log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); + status = U_ZERO_ERROR; + } + else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) { + log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2); + } + + length = uloc_getScript(temp2, temp3, sizeof(temp3)/sizeof(char), &status); + if (U_FAILURE(status)) { + log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); + status = U_ZERO_ERROR; + } + else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) { + log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2); + } + + length = uloc_getCountry(temp2, temp3, sizeof(temp3)/sizeof(char), &status); + if (U_FAILURE(status)) { + log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status)); + status = U_ZERO_ERROR; + } + else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) { + log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2); + } + } + +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h new file mode 100644 index 00000000000..c82fa356aed --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h @@ -0,0 +1,114 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CLOCTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*/ +#ifndef _CLOCTEST +#define _CLOCTEST + +#include "cintltst.h" +/*C API TEST FOR LOCALE */ + +/** + * Test functions to set and get data fields + **/ +static void TestBasicGetters(void); +static void TestPrefixes(void); +/** + * Use Locale to access Resource file data and compare against expected values + **/ +static void TestSimpleResourceInfo(void); +/** + * Use Locale to access Resource file display names and compare against expected values + **/ +static void TestDisplayNames(void); +/** + * Test getAvailableLocales + **/ + static void TestGetAvailableLocales(void); +/** + * Test functions to set and access a custom data directory + **/ + static void TestDataDirectory(void); +/** + * Test functions to test get ISO countries and Languages + **/ + static void TestISOFunctions(void); +/** + * Test functions to test get ISO3 countries and Languages Fallback + **/ + static void TestISO3Fallback(void); +/** + * Test functions to test get ISO3 countries and Languages for Uninstalled locales + **/ + static void TestUninstalledISO3Names(void); + static void TestObsoleteNames(void); +/** + * Test functions uloc_getDisplaynames() + **/ + static void TestSimpleDisplayNames(void); +/** + * Test functions uloc_getDisplaynames() + **/ + static void TestVariantParsing(void); + + /* Test getting keyword enumeratin */ + static void TestKeywordVariants(void); + + static void TestKeywordSet(void); + static void TestKeywordSetError(void); + + /* Test getting keyword values */ + static void TestKeywordVariantParsing(void); + + /* Test warning for no data in getDisplay* */ + static void TestDisplayNameWarning(void); + + /* Test uloc_getLocaleForLCID */ + static void TestGetLocaleForLCID(void); + +/** + * routine to perform subtests, used by TestDisplayNames + */ + static void doTestDisplayNames(const char* inLocale, int32_t compareIndex); + + static void TestCanonicalization(void); + + static void TestDisplayKeywords(void); + + static void TestDisplayKeywordValues(void); + + static void TestGetBaseName(void); + +static void TestGetLocale(void); + +/** + * additional intialization for datatables storing expected values + */ +static void setUpDataTable(void); +static void cleanUpDataTable(void); +/*static void displayDataTable(void);*/ +static void TestAcceptLanguage(void); + +/** + * test locale aliases +*/ +static void TestCalendar(void); +static void TestDateFormat(void); +static void TestCollation(void); +static void TestULocale(void); +static void TestUResourceBundle(void); +static void TestDisplayName(void); + +static void TestAcceptLanguage(void); + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c new file mode 100644 index 00000000000..89581eeebdb --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c @@ -0,0 +1,5075 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2001-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File cmsccoll.C +* +*******************************************************************************/ +/** + * These are the tests specific to ICU 1.8 and above, that I didn't know where + * to fit. + */ + +#include <stdio.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/ucoleitr.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "unicode/ustring.h" +#include "string.h" +#include "ucol_imp.h" +#include "ucol_tok.h" +#include "cmemory.h" +#include "cstring.h" +#include "uassert.h" +#include "unicode/parseerr.h" +#include "unicode/ucnv.h" +#include "uparse.h" + +#define LEN(a) (sizeof(a)/sizeof(a[0])) + +#define MAX_TOKEN_LEN 16 + +typedef UCollationResult tst_strcoll(void *collator, const int object, + const UChar *source, const int sLen, + const UChar *target, const int tLen); + + + +const static char cnt1[][10] = { + + "AA", + "AC", + "AZ", + "AQ", + "AB", + "ABZ", + "ABQ", + "Z", + "ABC", + "Q", + "B" +}; + +const static char cnt2[][10] = { + "DA", + "DAD", + "DAZ", + "MAR", + "Z", + "DAVIS", + "MARK", + "DAV", + "DAVI" +}; + +static void IncompleteCntTest(void) +{ + UErrorCode status = U_ZERO_ERROR; + UChar temp[90]; + UChar t1[90]; + UChar t2[90]; + + UCollator *coll = NULL; + uint32_t i = 0, j = 0; + uint32_t size = 0; + + u_uastrcpy(temp, " & Z < ABC < Q < B"); + + coll = ucol_openRules(temp, u_strlen(temp), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL,&status); + + if(U_SUCCESS(status)) { + size = sizeof(cnt1)/sizeof(cnt1[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + UCollationElements *iter; + u_uastrcpy(t1, cnt1[i]); + u_uastrcpy(t2, cnt1[j]); + doTest(coll, t1, t2, UCOL_LESS); + /* synwee : added collation element iterator test */ + iter = ucol_openElements(coll, t2, u_strlen(t2), &status); + if (U_FAILURE(status)) { + log_err("Creation of iterator failed\n"); + break; + } + backAndForth(iter); + ucol_closeElements(iter); + } + } + } + + ucol_close(coll); + + + u_uastrcpy(temp, " & Z < DAVIS < MARK <DAV"); + coll = ucol_openRules(temp, u_strlen(temp), UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status); + + if(U_SUCCESS(status)) { + size = sizeof(cnt2)/sizeof(cnt2[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + UCollationElements *iter; + u_uastrcpy(t1, cnt2[i]); + u_uastrcpy(t2, cnt2[j]); + doTest(coll, t1, t2, UCOL_LESS); + + /* synwee : added collation element iterator test */ + iter = ucol_openElements(coll, t2, u_strlen(t2), &status); + if (U_FAILURE(status)) { + log_err("Creation of iterator failed\n"); + break; + } + backAndForth(iter); + ucol_closeElements(iter); + } + } + } + + ucol_close(coll); + + +} + +const static char shifted[][20] = { + "black bird", + "black-bird", + "blackbird", + "black Bird", + "black-Bird", + "blackBird", + "black birds", + "black-birds", + "blackbirds" +}; + +const static UCollationResult shiftedTert[] = { + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_LESS, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_LESS, + UCOL_EQUAL, + UCOL_EQUAL +}; + +const static char nonignorable[][20] = { + "black bird", + "black Bird", + "black birds", + "black-bird", + "black-Bird", + "black-birds", + "blackbird", + "blackBird", + "blackbirds" +}; + +static void BlackBirdTest(void) { + UErrorCode status = U_ZERO_ERROR; + UChar t1[90]; + UChar t2[90]; + + uint32_t i = 0, j = 0; + uint32_t size = 0; + UCollator *coll = ucol_open("en_US", &status); + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status); + + if(U_SUCCESS(status)) { + size = sizeof(nonignorable)/sizeof(nonignorable[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + u_uastrcpy(t1, nonignorable[i]); + u_uastrcpy(t2, nonignorable[j]); + doTest(coll, t1, t2, UCOL_LESS); + } + } + } + + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &status); + + if(U_SUCCESS(status)) { + size = sizeof(shifted)/sizeof(shifted[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + u_uastrcpy(t1, shifted[i]); + u_uastrcpy(t2, shifted[j]); + doTest(coll, t1, t2, UCOL_LESS); + } + } + } + + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &status); + if(U_SUCCESS(status)) { + size = sizeof(shifted)/sizeof(shifted[0]); + for(i = 1; i < size; i++) { + u_uastrcpy(t1, shifted[i-1]); + u_uastrcpy(t2, shifted[i]); + doTest(coll, t1, t2, shiftedTert[i]); + } + } + + ucol_close(coll); +} + +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {0x0041/*'A'*/, 0x0300, 0x0301, 0x0000}, + {0x0041/*'A'*/, 0x0300, 0x0316, 0x0000}, + {0x0041/*'A'*/, 0x0300, 0x0000}, + {0x00C0, 0x0301, 0x0000}, + /* this would work with forced normalization */ + {0x00C0, 0x0316, 0x0000} +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {0x0041/*'A'*/, 0x0301, 0x0300, 0x0000}, + {0x0041/*'A'*/, 0x0316, 0x0300, 0x0000}, + {0x00C0, 0}, + {0x0041/*'A'*/, 0x0301, 0x0300, 0x0000}, + /* this would work with forced normalization */ + {0x0041/*'A'*/, 0x0316, 0x0300, 0x0000} +}; + +const static UCollationResult results[] = { + UCOL_GREATER, + UCOL_EQUAL, + UCOL_EQUAL, + UCOL_GREATER, + UCOL_EQUAL +}; + +static void FunkyATest(void) +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + UCollator *myCollation; + myCollation = ucol_open("en_US", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing some A letters, for some reason\n"); + ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 4 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +UColAttributeValue caseFirst[] = { + UCOL_OFF, + UCOL_LOWER_FIRST, + UCOL_UPPER_FIRST +}; + + +UColAttributeValue alternateHandling[] = { + UCOL_NON_IGNORABLE, + UCOL_SHIFTED +}; + +UColAttributeValue caseLevel[] = { + UCOL_OFF, + UCOL_ON +}; + +UColAttributeValue strengths[] = { + UCOL_PRIMARY, + UCOL_SECONDARY, + UCOL_TERTIARY, + UCOL_QUATERNARY, + UCOL_IDENTICAL +}; + +#if 0 +static const char * strengthsC[] = { + "UCOL_PRIMARY", + "UCOL_SECONDARY", + "UCOL_TERTIARY", + "UCOL_QUATERNARY", + "UCOL_IDENTICAL" +}; + +static const char * caseFirstC[] = { + "UCOL_OFF", + "UCOL_LOWER_FIRST", + "UCOL_UPPER_FIRST" +}; + + +static const char * alternateHandlingC[] = { + "UCOL_NON_IGNORABLE", + "UCOL_SHIFTED" +}; + +static const char * caseLevelC[] = { + "UCOL_OFF", + "UCOL_ON" +}; + +/* not used currently - does not test only prints */ +static void PrintMarkDavis(void) +{ + UErrorCode status = U_ZERO_ERROR; + UChar m[256]; + uint8_t sortkey[256]; + UCollator *coll = ucol_open("en_US", &status); + uint32_t h,i,j,k, sortkeysize; + uint32_t sizem = 0; + char buffer[512]; + uint32_t len = 512; + + log_verbose("PrintMarkDavis"); + + u_uastrcpy(m, "Mark Davis"); + sizem = u_strlen(m); + + + m[1] = 0xe4; + + for(i = 0; i<sizem; i++) { + fprintf(stderr, "\\u%04X ", m[i]); + } + fprintf(stderr, "\n"); + + for(h = 0; h<sizeof(caseFirst)/sizeof(caseFirst[0]); h++) { + ucol_setAttribute(coll, UCOL_CASE_FIRST, caseFirst[i], &status); + fprintf(stderr, "caseFirst: %s\n", caseFirstC[h]); + + for(i = 0; i<sizeof(alternateHandling)/sizeof(alternateHandling[0]); i++) { + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, alternateHandling[i], &status); + fprintf(stderr, " AltHandling: %s\n", alternateHandlingC[i]); + + for(j = 0; j<sizeof(caseLevel)/sizeof(caseLevel[0]); j++) { + ucol_setAttribute(coll, UCOL_CASE_LEVEL, caseLevel[j], &status); + fprintf(stderr, " caseLevel: %s\n", caseLevelC[j]); + + for(k = 0; k<sizeof(strengths)/sizeof(strengths[0]); k++) { + ucol_setAttribute(coll, UCOL_STRENGTH, strengths[k], &status); + sortkeysize = ucol_getSortKey(coll, m, sizem, sortkey, 256); + fprintf(stderr, " strength: %s\n Sortkey: ", strengthsC[k]); + fprintf(stderr, "%s\n", ucol_sortKeyToString(coll, sortkey, buffer, &len)); + } + + } + + } + + } +} +#endif + +static void BillFairmanTest(void) { +/* +** check for actual locale via ICU resource bundles +** +** lp points to the original locale ("fr_FR_....") +*/ + + UResourceBundle *lr,*cr; + UErrorCode lec = U_ZERO_ERROR; + const char *lp = "fr_FR_you_ll_never_find_this_locale"; + + log_verbose("BillFairmanTest\n"); + + lr = ures_open(NULL,lp,&lec); + if (lr) { + cr = ures_getByKey(lr,"collations",0,&lec); + if (cr) { + lp = ures_getLocale(cr,&lec); + if (lp) { + if (U_SUCCESS(lec)) { + if(strcmp(lp, "fr") != 0) { + log_err("Wrong locale for French Collation Data, expected \"fr\" got %s", lp); + } + } + } + ures_close(cr); + } + ures_close(lr); + } +} + +static void testPrimary(UCollator* col, const UChar* p,const UChar* q){ + UChar source[256] = { '\0'}; + UChar target[256] = { '\0'}; + UChar preP = 0x31a3; + UChar preQ = 0x310d; +/* + UChar preP = (*p>0x0400 && *p<0x0500)?0x00e1:0x491; + UChar preQ = (*p>0x0400 && *p<0x0500)?0x0041:0x413; +*/ + /*log_verbose("Testing primary\n");*/ + + doTest(col, p, q, UCOL_LESS); +/* + UCollationResult result = ucol_strcoll(col,p,u_strlen(p),q,u_strlen(q)); + + if(result!=UCOL_LESS){ + aescstrdup(p,utfSource,256); + aescstrdup(q,utfTarget,256); + fprintf(file,"Primary failed source: %s target: %s \n", utfSource,utfTarget); + } +*/ + source[0] = preP; + u_strcpy(source+1,p); + target[0] = preQ; + u_strcpy(target+1,q); + doTest(col, source, target, UCOL_LESS); +/* + fprintf(file,"Primary swamps 2nd failed source: %s target: %s \n", utfSource,utfTarget); +*/ +} + +static void testSecondary(UCollator* col, const UChar* p,const UChar* q){ + UChar source[256] = { '\0'}; + UChar target[256] = { '\0'}; + + /*log_verbose("Testing secondary\n");*/ + + doTest(col, p, q, UCOL_LESS); +/* + fprintf(file,"secondary failed source: %s target: %s \n", utfSource,utfTarget); +*/ + source[0] = 0x0053; + u_strcpy(source+1,p); + target[0]= 0x0073; + u_strcpy(target+1,q); + + doTest(col, source, target, UCOL_LESS); +/* + fprintf(file,"secondary swamps 3rd failed source: %s target: %s \n",utfSource,utfTarget); +*/ + + + u_strcpy(source,p); + source[u_strlen(p)] = 0x62; + source[u_strlen(p)+1] = 0; + + + u_strcpy(target,q); + target[u_strlen(q)] = 0x61; + target[u_strlen(q)+1] = 0; + + doTest(col, source, target, UCOL_GREATER); + +/* + fprintf(file,"secondary is swamped by 1 failed source: %s target: %s \n",utfSource,utfTarget); +*/ +} + +static void testTertiary(UCollator* col, const UChar* p,const UChar* q){ + UChar source[256] = { '\0'}; + UChar target[256] = { '\0'}; + + /*log_verbose("Testing tertiary\n");*/ + + doTest(col, p, q, UCOL_LESS); +/* + fprintf(file,"Tertiary failed source: %s target: %s \n",utfSource,utfTarget); +*/ + source[0] = 0x0020; + u_strcpy(source+1,p); + target[0]= 0x002D; + u_strcpy(target+1,q); + + doTest(col, source, target, UCOL_LESS); +/* + fprintf(file,"Tertiary swamps 4th failed source: %s target: %s \n", utfSource,utfTarget); +*/ + + u_strcpy(source,p); + source[u_strlen(p)] = 0xE0; + source[u_strlen(p)+1] = 0; + + u_strcpy(target,q); + target[u_strlen(q)] = 0x61; + target[u_strlen(q)+1] = 0; + + doTest(col, source, target, UCOL_GREATER); + +/* + fprintf(file,"Tertiary is swamped by 3rd failed source: %s target: %s \n",utfSource,utfTarget); +*/ +} + +static void testEquality(UCollator* col, const UChar* p,const UChar* q){ +/* + UChar source[256] = { '\0'}; + UChar target[256] = { '\0'}; +*/ + + doTest(col, p, q, UCOL_EQUAL); +/* + fprintf(file,"Primary failed source: %s target: %s \n", utfSource,utfTarget); +*/ +} + +static void testCollator(UCollator *coll, UErrorCode *status) { + const UChar *rules = NULL, *current = NULL; + int32_t ruleLen = 0; + uint32_t strength = 0; + uint32_t chOffset = 0; uint32_t chLen = 0; + uint32_t exOffset = 0; uint32_t exLen = 0; + uint32_t prefixOffset = 0; uint32_t prefixLen = 0; + uint32_t firstEx = 0; +/* uint32_t rExpsLen = 0; */ + uint32_t firstLen = 0; + UBool varT = FALSE; UBool top_ = TRUE; + uint16_t specs = 0; + UBool startOfRules = TRUE; + UBool lastReset = FALSE; + UBool before = FALSE; + uint32_t beforeStrength = 0; + UColTokenParser src; + UColOptionSet opts; + + UChar first[256]; + UChar second[256]; + UChar tempB[256]; + uint32_t tempLen; + UChar *rulesCopy = NULL; + UParseError parseError; + src.opts = &opts; + + rules = ucol_getRules(coll, &ruleLen); + if(U_SUCCESS(*status) && ruleLen > 0) { + rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar)); + uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar)); + src.current = src.source = rulesCopy; + src.end = rulesCopy+ruleLen; + src.extraCurrent = src.end; + src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + *first = *second = 0; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules,&parseError, status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0); + top_ = (UBool)((specs & UCOL_TOK_TOP) != 0); + if(top_) { /* if reset is on top, the sequence is broken. We should have an empty string */ + second[0] = 0; + } else { + u_strncpy(second,rulesCopy+chOffset, chLen); + second[chLen] = 0; + + if(exLen > 0 && firstEx == 0) { + u_strncat(first, rulesCopy+exOffset, exLen); + first[firstLen+exLen] = 0; + } + + if(lastReset == TRUE && prefixLen != 0) { + u_strncpy(first+prefixLen, first, firstLen); + u_strncpy(first, rulesCopy+prefixOffset, prefixLen); + first[firstLen+prefixLen] = 0; + firstLen = firstLen+prefixLen; + } + + if(before == TRUE) { /* swap first and second */ + u_strcpy(tempB, first); + u_strcpy(first, second); + u_strcpy(second, tempB); + + tempLen = firstLen; + firstLen = chLen; + chLen = tempLen; + + tempLen = firstEx; + firstEx = exLen; + exLen = tempLen; + if(beforeStrength < strength) { + strength = beforeStrength; + } + } + } + lastReset = FALSE; + + switch(strength){ + case UCOL_IDENTICAL: + testEquality(coll,first,second); + break; + case UCOL_PRIMARY: + testPrimary(coll,first,second); + break; + case UCOL_SECONDARY: + testSecondary(coll,first,second); + break; + case UCOL_TERTIARY: + testTertiary(coll,first,second); + break; + case UCOL_TOK_RESET: + lastReset = TRUE; + before = (UBool)((specs & UCOL_TOK_BEFORE) != 0); + if(before) { + beforeStrength = (specs & UCOL_TOK_BEFORE)-1; + } + break; + default: + break; + } + + if(before == TRUE && strength != UCOL_TOK_RESET) { /* first and second were swapped */ + before = FALSE; + } else { + firstLen = chLen; + firstEx = exLen; + u_strcpy(first, second); + } + } + free(rulesCopy); + } +} + +static UCollationResult ucaTest(void *collator, const int object, const UChar *source, const int sLen, const UChar *target, const int tLen) { + UCollator *UCA = (UCollator *)collator; + return ucol_strcoll(UCA, source, sLen, target, tLen); +} + +/* +static UCollationResult winTest(void *collator, const int object, const UChar *source, const int sLen, const UChar *target, const int tLen) { +#ifdef U_WINDOWS + LCID lcid = (LCID)collator; + return (UCollationResult)CompareString(lcid, 0, source, sLen, target, tLen); +#else + return 0; +#endif +} +*/ + +static UCollationResult swampEarlier(tst_strcoll* func, void *collator, int opts, + UChar s1, UChar s2, + const UChar *s, const uint32_t sLen, + const UChar *t, const uint32_t tLen) { + UChar source[256] = {0}; + UChar target[256] = {0}; + + source[0] = s1; + u_strcpy(source+1, s); + target[0] = s2; + u_strcpy(target+1, t); + + return func(collator, opts, source, sLen+1, target, tLen+1); +} + +static UCollationResult swampLater(tst_strcoll* func, void *collator, int opts, + UChar s1, UChar s2, + const UChar *s, const uint32_t sLen, + const UChar *t, const uint32_t tLen) { + UChar source[256] = {0}; + UChar target[256] = {0}; + + u_strcpy(source, s); + source[sLen] = s1; + u_strcpy(target, t); + target[tLen] = s2; + + return func(collator, opts, source, sLen+1, target, tLen+1); +} + +static uint32_t probeStrength(tst_strcoll* func, void *collator, int opts, + const UChar *s, const uint32_t sLen, + const UChar *t, const uint32_t tLen, + UCollationResult result) { + /*UChar fPrimary = 0x6d;*/ + /*UChar sPrimary = 0x6e;*/ + UChar fSecondary = 0x310d; + UChar sSecondary = 0x31a3; + UChar fTertiary = 0x310f; + UChar sTertiary = 0x31b7; + + UCollationResult oposite; + if(result == UCOL_EQUAL) { + return UCOL_IDENTICAL; + } else if(result == UCOL_GREATER) { + oposite = UCOL_LESS; + } else { + oposite = UCOL_GREATER; + } + + if(swampEarlier(func, collator, opts, sSecondary, fSecondary, s, sLen, t, tLen) == result) { + return UCOL_PRIMARY; + } else if((swampEarlier(func, collator, opts, sTertiary, 0x310f, s, sLen, t, tLen) == result) && + (swampEarlier(func, collator, opts, 0x310f, sTertiary, s, sLen, t, tLen) == result)) { + return UCOL_SECONDARY; + } else if((swampLater(func, collator, opts, sTertiary, fTertiary, s, sLen, t, tLen) == result) && + (swampLater(func, collator, opts, fTertiary, sTertiary, s, sLen, t, tLen) == result)) { + return UCOL_TERTIARY; + } else if((swampLater(func, collator, opts, sTertiary, 0x310f, s, sLen, t, tLen) == oposite) && + (swampLater(func, collator, opts, fTertiary, sTertiary, s, sLen, t, tLen) == oposite)) { + return UCOL_QUATERNARY; + } else { + return UCOL_IDENTICAL; + } +} + +static char *getRelationSymbol(UCollationResult res, uint32_t strength, char *buffer) { + uint32_t i = 0; + + if(res == UCOL_EQUAL || strength == 0xdeadbeef) { + buffer[0] = '='; + buffer[1] = '='; + buffer[2] = '\0'; + } else if(res == UCOL_GREATER) { + for(i = 0; i<strength+1; i++) { + buffer[i] = '>'; + } + buffer[strength+1] = '\0'; + } else { + for(i = 0; i<strength+1; i++) { + buffer[i] = '<'; + } + buffer[strength+1] = '\0'; + } + + return buffer; +} + + + +static void logFailure (const char *platform, const char *test, + const UChar *source, const uint32_t sLen, + const UChar *target, const uint32_t tLen, + UCollationResult realRes, uint32_t realStrength, + UCollationResult expRes, uint32_t expStrength, UBool error) { + + uint32_t i = 0; + + char sEsc[256], s[256], tEsc[256], t[256], b[256], output[512], relation[256]; + static int32_t maxOutputLength = 0; + int32_t outputLength; + + *sEsc = *tEsc = *s = *t = 0; + if(error == TRUE) { + log_err("Difference between expected and generated order. Run test with -v for more info\n"); + } else if(VERBOSITY == 0) { + return; + } + for(i = 0; i<sLen; i++) { + sprintf(b, "%04X", source[i]); + strcat(sEsc, "\\u"); + strcat(sEsc, b); + strcat(s, b); + strcat(s, " "); + if(source[i] < 0x80) { + sprintf(b, "(%c)", source[i]); + strcat(sEsc, b); + } + } + for(i = 0; i<tLen; i++) { + sprintf(b, "%04X", target[i]); + strcat(tEsc, "\\u"); + strcat(tEsc, b); + strcat(t, b); + strcat(t, " "); + if(target[i] < 0x80) { + sprintf(b, "(%c)", target[i]); + strcat(tEsc, b); + } + } +/* + strcpy(output, "[[ "); + strcat(output, sEsc); + strcat(output, getRelationSymbol(expRes, expStrength, relation)); + strcat(output, tEsc); + + strcat(output, " : "); + + strcat(output, sEsc); + strcat(output, getRelationSymbol(realRes, realStrength, relation)); + strcat(output, tEsc); + strcat(output, " ]] "); + + log_verbose("%s", output); +*/ + + + strcpy(output, "DIFF: "); + + strcat(output, s); + strcat(output, " : "); + strcat(output, t); + + strcat(output, test); + strcat(output, ": "); + + strcat(output, sEsc); + strcat(output, getRelationSymbol(expRes, expStrength, relation)); + strcat(output, tEsc); + + strcat(output, " "); + + strcat(output, platform); + strcat(output, ": "); + + strcat(output, sEsc); + strcat(output, getRelationSymbol(realRes, realStrength, relation)); + strcat(output, tEsc); + + outputLength = (int32_t)strlen(output); + if(outputLength > maxOutputLength) { + maxOutputLength = outputLength; + U_ASSERT(outputLength < sizeof(output)); + } + + log_verbose("%s\n", output); + +} + +/* +static void printOutRules(const UChar *rules) { + uint32_t len = u_strlen(rules); + uint32_t i = 0; + char toPrint; + uint32_t line = 0; + + fprintf(stdout, "Rules:"); + + for(i = 0; i<len; i++) { + if(rules[i]<0x7f && rules[i]>=0x20) { + toPrint = (char)rules[i]; + if(toPrint == '&') { + line = 1; + fprintf(stdout, "\n&"); + } else if(toPrint == ';') { + fprintf(stdout, "<<"); + line+=2; + } else if(toPrint == ',') { + fprintf(stdout, "<<<"); + line+=3; + } else { + fprintf(stdout, "%c", toPrint); + line++; + } + } else if(rules[i]<0x3400 || rules[i]>=0xa000) { + fprintf(stdout, "\\u%04X", rules[i]); + line+=6; + } + if(line>72) { + fprintf(stdout, "\n"); + line = 0; + } + } + + log_verbose("\n"); + +} +*/ + +static uint32_t testSwitch(tst_strcoll* func, void *collator, int opts, uint32_t strength, const UChar *first, const UChar *second, const char* msg, UBool error) { + uint32_t diffs = 0; + UCollationResult realResult; + uint32_t realStrength; + + uint32_t sLen = u_strlen(first); + uint32_t tLen = u_strlen(second); + + realResult = func(collator, opts, first, sLen, second, tLen); + realStrength = probeStrength(func, collator, opts, first, sLen, second, tLen, realResult); + + if(strength == UCOL_IDENTICAL && realResult != UCOL_IDENTICAL) { + logFailure(msg, "tailoring", first, sLen, second, tLen, realResult, realStrength, UCOL_EQUAL, strength, error); + diffs++; + } else if(realResult != UCOL_LESS || realStrength != strength) { + logFailure(msg, "tailoring", first, sLen, second, tLen, realResult, realStrength, UCOL_LESS, strength, error); + diffs++; + } + return diffs; +} + + +static void testAgainstUCA(UCollator *coll, UCollator *UCA, const char *refName, UBool error, UErrorCode *status) { + const UChar *rules = NULL, *current = NULL; + int32_t ruleLen = 0; + uint32_t strength = 0; + uint32_t chOffset = 0; uint32_t chLen = 0; + uint32_t exOffset = 0; uint32_t exLen = 0; + uint32_t prefixOffset = 0; uint32_t prefixLen = 0; +/* uint32_t rExpsLen = 0; */ + uint32_t firstLen = 0, secondLen = 0; + UBool varT = FALSE; UBool top_ = TRUE; + uint16_t specs = 0; + UBool startOfRules = TRUE; + UColTokenParser src; + UColOptionSet opts; + + UChar first[256]; + UChar second[256]; + UChar *rulesCopy = NULL; + + uint32_t UCAdiff = 0; + uint32_t Windiff = 1; + UParseError parseError; + + src.opts = &opts; + + rules = ucol_getRules(coll, &ruleLen); + + /*printOutRules(rules);*/ + + if(U_SUCCESS(*status) && ruleLen > 0) { + rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar)); + uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar)); + src.current = src.source = rulesCopy; + src.end = rulesCopy+ruleLen; + src.extraCurrent = src.end; + src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + *first = *second = 0; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0); + top_ = (UBool)((specs & UCOL_TOK_TOP) != 0); + + u_strncpy(second,rulesCopy+chOffset, chLen); + second[chLen] = 0; + secondLen = chLen; + + if(exLen > 0) { + u_strncat(first, rulesCopy+exOffset, exLen); + first[firstLen+exLen] = 0; + firstLen += exLen; + } + + if(strength != UCOL_TOK_RESET) { + if((*first<0x3400 || *first>=0xa000) && (*second<0x3400 || *second>=0xa000)) { + UCAdiff += testSwitch(&ucaTest, (void *)UCA, 0, strength, first, second, refName, error); + /*Windiff += testSwitch(&winTest, (void *)lcid, 0, strength, first, second, "Win32");*/ + } + } + + + firstLen = chLen; + u_strcpy(first, second); + + } + if(UCAdiff != 0 && Windiff != 0) { + log_verbose("\n"); + } + if(UCAdiff == 0) { + log_verbose("No immediate difference with %s!\n", refName); + } + if(Windiff == 0) { + log_verbose("No immediate difference with Win32!\n"); + } + free(rulesCopy); + } +} + +/* + * Takes two CEs (lead and continuation) and + * compares them as CEs should be compared: + * primary vs. primary, secondary vs. secondary + * tertiary vs. tertiary + */ +static int32_t compareCEs(uint32_t s1, uint32_t s2, + uint32_t t1, uint32_t t2) { + uint32_t s = 0, t = 0; + if(s1 == t1 && s2 == t2) { + return 0; + } + s = (s1 & 0xFFFF0000)|((s2 & 0xFFFF0000)>>16); + t = (t1 & 0xFFFF0000)|((t2 & 0xFFFF0000)>>16); + if(s < t) { + return -1; + } else if(s > t) { + return 1; + } else { + s = (s1 & 0x0000FF00) | (s2 & 0x0000FF00)>>8; + t = (t1 & 0x0000FF00) | (t2 & 0x0000FF00)>>8; + if(s < t) { + return -1; + } else if(s > t) { + return 1; + } else { + s = (s1 & 0x000000FF)<<8 | (s2 & 0x000000FF); + t = (t1 & 0x000000FF)<<8 | (t2 & 0x000000FF); + if(s < t) { + return -1; + } else { + return 1; + } + } + } +} + +typedef struct { + uint32_t startCE; + uint32_t startContCE; + uint32_t limitCE; + uint32_t limitContCE; +} indirectBoundaries; + +/* these values are used for finding CE values for indirect positioning. */ +/* Indirect positioning is a mechanism for allowing resets on symbolic */ +/* values. It only works for resets and you cannot tailor indirect names */ +/* An indirect name can define either an anchor point or a range. An */ +/* anchor point behaves in exactly the same way as a code point in reset */ +/* would, except that it cannot be tailored. A range (we currently only */ +/* know for the [top] range will explicitly set the upper bound for */ +/* generated CEs, thus allowing for better control over how many CEs can */ +/* be squeezed between in the range without performance penalty. */ +/* In that respect, we use [top] for tailoring of locales that use CJK */ +/* characters. Other indirect values are currently a pure convenience, */ +/* they can be used to assure that the CEs will be always positioned in */ +/* the same place relative to a point with known properties (e.g. first */ +/* primary ignorable). */ +static indirectBoundaries ucolIndirectBoundaries[15]; +static UBool indirectBoundariesSet = FALSE; +static void setIndirectBoundaries(uint32_t indexR, uint32_t *start, uint32_t *end) { + + /* Set values for the top - TODO: once we have values for all the indirects, we are going */ + /* to initalize here. */ + ucolIndirectBoundaries[indexR].startCE = start[0]; + ucolIndirectBoundaries[indexR].startContCE = start[1]; + if(end) { + ucolIndirectBoundaries[indexR].limitCE = end[0]; + ucolIndirectBoundaries[indexR].limitContCE = end[1]; + } else { + ucolIndirectBoundaries[indexR].limitCE = 0; + ucolIndirectBoundaries[indexR].limitContCE = 0; + } +} + +static void testCEs(UCollator *coll, UErrorCode *status) { + + const UChar *rules = NULL, *current = NULL; + int32_t ruleLen = 0; + + uint32_t strength = 0; + uint32_t maxStrength = UCOL_IDENTICAL; + uint32_t baseCE, baseContCE, nextCE, nextContCE, currCE, currContCE; + uint32_t lastCE; + uint32_t lastContCE; + + int32_t result = 0; + uint32_t chOffset = 0; uint32_t chLen = 0; + uint32_t exOffset = 0; uint32_t exLen = 0; + uint32_t prefixOffset = 0; uint32_t prefixLen = 0; + uint32_t oldOffset = 0; + + /* uint32_t rExpsLen = 0; */ + /* uint32_t firstLen = 0; */ + uint16_t specs = 0; + UBool varT = FALSE; UBool top_ = TRUE; + UBool startOfRules = TRUE; + UBool before = FALSE; + UColTokenParser src; + UColOptionSet opts; + UParseError parseError; + UChar *rulesCopy = NULL; + collIterate c; + UCollator *UCA = ucol_open("root", status); + UCAConstants *consts = (UCAConstants *)((uint8_t *)UCA->image + UCA->image->UCAConsts); + uint32_t UCOL_RESET_TOP_VALUE = consts->UCA_LAST_NON_VARIABLE[0], /*UCOL_RESET_TOP_CONT = consts->UCA_LAST_NON_VARIABLE[1], */ + UCOL_NEXT_TOP_VALUE = consts->UCA_FIRST_IMPLICIT[0], UCOL_NEXT_TOP_CONT = consts->UCA_FIRST_IMPLICIT[1]; + + baseCE=baseContCE=nextCE=nextContCE=currCE=currContCE=lastCE=lastContCE = UCOL_NOT_FOUND; + + src.opts = &opts; + + rules = ucol_getRules(coll, &ruleLen); + + src.invUCA = ucol_initInverseUCA(status); + + if(indirectBoundariesSet == FALSE) { + /* UCOL_RESET_TOP_VALUE */ + setIndirectBoundaries(0, consts->UCA_LAST_NON_VARIABLE, consts->UCA_FIRST_IMPLICIT); + /* UCOL_FIRST_PRIMARY_IGNORABLE */ + setIndirectBoundaries(1, consts->UCA_FIRST_PRIMARY_IGNORABLE, 0); + /* UCOL_LAST_PRIMARY_IGNORABLE */ + setIndirectBoundaries(2, consts->UCA_LAST_PRIMARY_IGNORABLE, 0); + /* UCOL_FIRST_SECONDARY_IGNORABLE */ + setIndirectBoundaries(3, consts->UCA_FIRST_SECONDARY_IGNORABLE, 0); + /* UCOL_LAST_SECONDARY_IGNORABLE */ + setIndirectBoundaries(4, consts->UCA_LAST_SECONDARY_IGNORABLE, 0); + /* UCOL_FIRST_TERTIARY_IGNORABLE */ + setIndirectBoundaries(5, consts->UCA_FIRST_TERTIARY_IGNORABLE, 0); + /* UCOL_LAST_TERTIARY_IGNORABLE */ + setIndirectBoundaries(6, consts->UCA_LAST_TERTIARY_IGNORABLE, 0); + /* UCOL_FIRST_VARIABLE */ + setIndirectBoundaries(7, consts->UCA_FIRST_VARIABLE, 0); + /* UCOL_LAST_VARIABLE */ + setIndirectBoundaries(8, consts->UCA_LAST_VARIABLE, 0); + /* UCOL_FIRST_NON_VARIABLE */ + setIndirectBoundaries(9, consts->UCA_FIRST_NON_VARIABLE, 0); + /* UCOL_LAST_NON_VARIABLE */ + setIndirectBoundaries(10, consts->UCA_LAST_NON_VARIABLE, consts->UCA_FIRST_IMPLICIT); + /* UCOL_FIRST_IMPLICIT */ + setIndirectBoundaries(11, consts->UCA_FIRST_IMPLICIT, 0); + /* UCOL_LAST_IMPLICIT */ + setIndirectBoundaries(12, consts->UCA_LAST_IMPLICIT, consts->UCA_FIRST_TRAILING); + /* UCOL_FIRST_TRAILING */ + setIndirectBoundaries(13, consts->UCA_FIRST_TRAILING, 0); + /* UCOL_LAST_TRAILING */ + setIndirectBoundaries(14, consts->UCA_LAST_TRAILING, 0); + ucolIndirectBoundaries[14].limitCE = (consts->UCA_PRIMARY_SPECIAL_MIN<<24); + indirectBoundariesSet = TRUE; + } + + + if(U_SUCCESS(*status) && ruleLen > 0) { + rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar)); + uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar)); + src.current = src.source = rulesCopy; + src.end = rulesCopy+ruleLen; + src.extraCurrent = src.end; + src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0); + top_ = (UBool)((specs & UCOL_TOK_TOP) != 0); + + uprv_init_collIterate(coll, rulesCopy+chOffset, chLen, &c); + + currCE = ucol_getNextCE(coll, &c, status); + if(currCE == 0 && UCOL_ISTHAIPREVOWEL(*(rulesCopy+chOffset))) { + log_verbose("Thai prevowel detected. Will pick next CE\n"); + currCE = ucol_getNextCE(coll, &c, status); + } + + currContCE = ucol_getNextCE(coll, &c, status); + if(!isContinuation(currContCE)) { + currContCE = 0; + } + + /* we need to repack CEs here */ + + if(strength == UCOL_TOK_RESET) { + before = (UBool)((specs & UCOL_TOK_BEFORE) != 0); + if(top_ == TRUE) { + int32_t index = src.parsedToken.indirectIndex; + + nextCE = baseCE = currCE = ucolIndirectBoundaries[index].startCE; + nextContCE = baseContCE = currContCE = ucolIndirectBoundaries[index].startContCE; + } else { + nextCE = baseCE = currCE; + nextContCE = baseContCE = currContCE; + } + maxStrength = UCOL_IDENTICAL; + } else { + if(strength < maxStrength) { + maxStrength = strength; + if(baseCE == UCOL_RESET_TOP_VALUE) { + log_verbose("Resetting to [top]\n"); + nextCE = UCOL_NEXT_TOP_VALUE; + nextContCE = UCOL_NEXT_TOP_CONT; + } else { + result = ucol_inv_getNextCE(&src, baseCE & 0xFFFFFF3F, baseContCE, &nextCE, &nextContCE, maxStrength); + } + if(result < 0) { + if(ucol_isTailored(coll, *(rulesCopy+oldOffset), status)) { + log_verbose("Reset is tailored codepoint %04X, don't know how to continue, taking next test\n", *(rulesCopy+oldOffset)); + return; + } else { + log_err("couldn't find the CE\n"); + return; + } + } + } + + currCE &= 0xFFFFFF3F; + currContCE &= 0xFFFFFFBF; + + if(maxStrength == UCOL_IDENTICAL) { + if(baseCE != currCE || baseContCE != currContCE) { + log_err("current CE (initial strength UCOL_EQUAL)\n"); + } + } else { + if(strength == UCOL_IDENTICAL) { + if(lastCE != currCE || lastContCE != currContCE) { + log_err("current CE (initial strength UCOL_EQUAL)\n"); + } + } else { + if(compareCEs(currCE, currContCE, nextCE, nextContCE) > 0) { + /*if(currCE > nextCE || (currCE == nextCE && currContCE >= nextContCE)) {*/ + log_err("current CE is not less than base CE\n"); + } + if(!before) { + if(compareCEs(currCE, currContCE, lastCE, lastContCE) < 0) { + /*if(currCE < lastCE || (currCE == lastCE && currContCE <= lastContCE)) {*/ + log_err("sequence of generated CEs is broken\n"); + } + } else { + before = FALSE; + if(compareCEs(currCE, currContCE, lastCE, lastContCE) > 0) { + /*if(currCE < lastCE || (currCE == lastCE && currContCE <= lastContCE)) {*/ + log_err("sequence of generated CEs is broken\n"); + } + } + } + } + + } + + oldOffset = chOffset; + lastCE = currCE & 0xFFFFFF3F; + lastContCE = currContCE & 0xFFFFFFBF; + } + free(rulesCopy); + } + ucol_close(UCA); +} + +#if 0 +/* these locales are now picked from index RB */ +static const char* localesToTest[] = { +"ar", "bg", "ca", "cs", "da", +"el", "en_BE", "en_US_POSIX", +"es", "et", "fi", "fr", "hi", +"hr", "hu", "is", "iw", "ja", +"ko", "lt", "lv", "mk", "mt", +"nb", "nn", "nn_NO", "pl", "ro", +"ru", "sh", "sk", "sl", "sq", +"sr", "sv", "th", "tr", "uk", +"vi", "zh", "zh_TW" +}; +#endif + +static const char* rulesToTest[] = { + /* Funky fa rule */ + "&\\u0622 < \\u0627 << \\u0671 < \\u0621", + /*"& Z < p, P",*/ + /* Cui Mins rules */ + "&[top]<o,O<p,P<q,Q<'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U & Qu<'?'",*/ + "&[top]<o,O<p,P<q,Q;'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U & Qu;'?'",*/ + "&[top]<o,O<p,P<q,Q,'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U&'Qu','?'",*/ + "&[top]<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q;'?'/u<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & Qu;'?'",*/ + "&[top]<'?';Qu<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & '?';Qu",*/ + "&[top]<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q;'?'/um<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & Qum;'?'",*/ + "&[top]<'?';Qum<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q<r,R<u,U" /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & '?';Qum"*/ +}; + + +static void TestCollations(void) { + int32_t noOfLoc = uloc_countAvailable(); + int32_t i = 0, j = 0; + + UErrorCode status = U_ZERO_ERROR; + char cName[256]; + UChar name[256]; + int32_t nameSize; + + + const char *locName = NULL; + UCollator *coll = NULL; + UCollator *UCA = ucol_open("", &status); + UColAttributeValue oldStrength = ucol_getAttribute(UCA, UCOL_STRENGTH, &status); + ucol_setAttribute(UCA, UCOL_STRENGTH, UCOL_QUATERNARY, &status); + + for(i = 0; i<noOfLoc; i++) { + status = U_ZERO_ERROR; + locName = uloc_getAvailable(i); + if(uprv_strcmp("ja", locName) == 0) { + log_verbose("Don't know how to test prefixes\n"); + continue; + } + if(hasCollationElements(locName)) { + nameSize = uloc_getDisplayName(locName, NULL, name, 256, &status); + for(j = 0; j<nameSize; j++) { + cName[j] = (char)name[j]; + } + cName[nameSize] = 0; + log_verbose("\nTesting locale %s (%s)\n", locName, cName); + coll = ucol_open(locName, &status); + if(U_SUCCESS(status)) { + testAgainstUCA(coll, UCA, "UCA", FALSE, &status); + ucol_close(coll); + } else { + log_err("Couldn't instantiate collator for locale %s, error: %s\n", locName, u_errorName(status)); + status = U_ZERO_ERROR; + } + } + } + ucol_setAttribute(UCA, UCOL_STRENGTH, oldStrength, &status); + ucol_close(UCA); +} + +static void RamsRulesTest(void) { + UErrorCode status = U_ZERO_ERROR; + int32_t i = 0; + UCollator *coll = NULL; + UChar rule[2048]; + uint32_t ruleLen; + int32_t noOfLoc = uloc_countAvailable(); + const char *locName = NULL; + + log_verbose("RamsRulesTest\n"); + + for(i = 0; i<noOfLoc; i++) { + status = U_ZERO_ERROR; + locName = uloc_getAvailable(i); + if(hasCollationElements(locName)) { + if (uprv_strcmp("ja", locName)==0) { + log_verbose("Don't know how to test Japanese because of prefixes\n"); + continue; + } + if (uprv_strcmp("de__PHONEBOOK", locName)==0) { + log_verbose("Don't know how to test Phonebook because the reset is on an expanding character\n"); + continue; + } + if (uprv_strcmp("km", locName)==0 || + uprv_strcmp("km_KH", locName)==0 || + uprv_strcmp("zh", locName)==0 || + uprv_strcmp("zh_Hant", locName)==0 ) { + continue; /* TODO: enable these locale tests after trac#6040 is fixed. */ + } + log_verbose("Testing locale %s\n", locName); + coll = ucol_open(locName, &status); + if(U_SUCCESS(status)) { + if(coll->image->jamoSpecial == TRUE) { + log_err("%s has special JAMOs\n", locName); + } + ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_OFF, &status); + testCollator(coll, &status); + testCEs(coll, &status); + ucol_close(coll); + } + } + } + + for(i = 0; i<sizeof(rulesToTest)/sizeof(rulesToTest[0]); i++) { + log_verbose("Testing rule: %s\n", rulesToTest[i]); + ruleLen = u_unescape(rulesToTest[i], rule, 2048); + coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + if(U_SUCCESS(status)) { + testCollator(coll, &status); + testCEs(coll, &status); + ucol_close(coll); + } + } + +} + +static void IsTailoredTest(void) { + UErrorCode status = U_ZERO_ERROR; + uint32_t i = 0; + UCollator *coll = NULL; + UChar rule[2048]; + UChar tailored[2048]; + UChar notTailored[2048]; + uint32_t ruleLen, tailoredLen, notTailoredLen; + + log_verbose("IsTailoredTest\n"); + + u_uastrcpy(rule, "&Z < A, B, C;c < d"); + ruleLen = u_strlen(rule); + + u_uastrcpy(tailored, "ABCcd"); + tailoredLen = u_strlen(tailored); + + u_uastrcpy(notTailored, "ZabD"); + notTailoredLen = u_strlen(notTailored); + + coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + if(U_SUCCESS(status)) { + for(i = 0; i<tailoredLen; i++) { + if(!ucol_isTailored(coll, tailored[i], &status)) { + log_err("%i: %04X should be tailored - it is reported as not\n", i, tailored[i]); + } + } + for(i = 0; i<notTailoredLen; i++) { + if(ucol_isTailored(coll, notTailored[i], &status)) { + log_err("%i: %04X should not be tailored - it is reported as it is\n", i, notTailored[i]); + } + } + ucol_close(coll); + } + else { + log_err("Can't tailor rules"); + } + /* Code coverage */ + status = U_ZERO_ERROR; + coll = ucol_open("ja", &status); + if(!ucol_isTailored(coll, 0x4E9C, &status)) { + log_err("0x4E9C should be tailored - it is reported as not\n"); + } + ucol_close(coll); +} + + +const static char chTest[][20] = { + "c", + "C", + "ca", "cb", "cx", "cy", "CZ", + "c\\u030C", "C\\u030C", + "h", + "H", + "ha", "Ha", "harly", "hb", "HB", "hx", "HX", "hy", "HY", + "ch", "cH", "Ch", "CH", + "cha", "charly", "che", "chh", "chch", "chr", + "i", "I", "iarly", + "r", "R", + "r\\u030C", "R\\u030C", + "s", + "S", + "s\\u030C", "S\\u030C", + "z", "Z", + "z\\u030C", "Z\\u030C" +}; + +static void TestChMove(void) { + UChar t1[256] = {0}; + UChar t2[256] = {0}; + + uint32_t i = 0, j = 0; + uint32_t size = 0; + UErrorCode status = U_ZERO_ERROR; + + UCollator *coll = ucol_open("cs", &status); + + if(U_SUCCESS(status)) { + size = sizeof(chTest)/sizeof(chTest[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + u_unescape(chTest[i], t1, 256); + u_unescape(chTest[j], t2, 256); + doTest(coll, t1, t2, UCOL_LESS); + } + } + } + else { + log_err("Can't open collator"); + } + ucol_close(coll); +} + + + + +const static char impTest[][20] = { + "\\u4e00", + "a", + "A", + "b", + "B", + "\\u4e01" +}; + + +static void TestImplicitTailoring(void) { + static const struct { + const char *rules; + const char *data[10]; + const uint32_t len; + } tests[] = { + { "&[before 1]\\u4e00 < b < c &[before 1]\\u4e00 < d < e", { "d", "e", "b", "c", "\\u4e00"}, 5 }, + { "&\\u4e00 < a <<< A < b <<< B", { "\\u4e00", "a", "A", "b", "B", "\\u4e01"}, 6 }, + { "&[before 1]\\u4e00 < \\u4e01 < \\u4e02", { "\\u4e01", "\\u4e02", "\\u4e00"}, 3}, + { "&[before 1]\\u4e01 < \\u4e02 < \\u4e03", { "\\u4e02", "\\u4e03", "\\u4e01"}, 3} + }; + + int32_t i = 0; + + for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len); + } + +/* + UChar t1[256] = {0}; + UChar t2[256] = {0}; + + const char *rule = "&\\u4e00 < a <<< A < b <<< B"; + + uint32_t i = 0, j = 0; + uint32_t size = 0; + uint32_t ruleLen = 0; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = NULL; + ruleLen = u_unescape(rule, t1, 256); + + coll = ucol_openRules(t1, ruleLen, UCOL_OFF, UCOL_TERTIARY,NULL, &status); + + if(U_SUCCESS(status)) { + size = sizeof(impTest)/sizeof(impTest[0]); + for(i = 0; i < size-1; i++) { + for(j = i+1; j < size; j++) { + u_unescape(impTest[i], t1, 256); + u_unescape(impTest[j], t2, 256); + doTest(coll, t1, t2, UCOL_LESS); + } + } + } + else { + log_err("Can't open collator"); + } + ucol_close(coll); + */ +} + +static void TestFCDProblem(void) { + UChar t1[256] = {0}; + UChar t2[256] = {0}; + + const char *s1 = "\\u0430\\u0306\\u0325"; + const char *s2 = "\\u04D1\\u0325"; + + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("", &status); + u_unescape(s1, t1, 256); + u_unescape(s2, t2, 256); + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); + doTest(coll, t1, t2, UCOL_EQUAL); + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + doTest(coll, t1, t2, UCOL_EQUAL); + + ucol_close(coll); +} + +#define NORM_BUFFER_TEST_LEN 32 +typedef struct { + UChar32 u; + UChar NFC[NORM_BUFFER_TEST_LEN]; + UChar NFD[NORM_BUFFER_TEST_LEN]; +} tester; + +static void TestComposeDecompose(void) { + int32_t noOfLoc; + int32_t i = 0, j = 0; + + UErrorCode status = U_ZERO_ERROR; + + const char *locName = NULL; + + uint32_t nfcSize; + uint32_t nfdSize; + tester **t; + uint32_t noCases = 0; + UCollator *coll = NULL; + UChar32 u = 0; + UChar comp[NORM_BUFFER_TEST_LEN]; + uint32_t len = 0; + UCollationElements *iter; + + noOfLoc = uloc_countAvailable(); + + t = malloc(0x30000 * sizeof(tester *)); + t[0] = (tester *)malloc(sizeof(tester)); + log_verbose("Testing UCA extensively\n"); + coll = ucol_open("", &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + + + for(u = 0; u < 0x30000; u++) { + len = 0; + UTF_APPEND_CHAR_UNSAFE(comp, len, u); + nfcSize = unorm_normalize(comp, len, UNORM_NFC, 0, t[noCases]->NFC, NORM_BUFFER_TEST_LEN, &status); + nfdSize = unorm_normalize(comp, len, UNORM_NFD, 0, t[noCases]->NFD, NORM_BUFFER_TEST_LEN, &status); + + if(nfcSize != nfdSize || (uprv_memcmp(t[noCases]->NFC, t[noCases]->NFD, nfcSize * sizeof(UChar)) != 0) + || (len != nfdSize || (uprv_memcmp(comp, t[noCases]->NFD, nfdSize * sizeof(UChar)) != 0))) { + t[noCases]->u = u; + if(len != nfdSize || (uprv_memcmp(comp, t[noCases]->NFD, nfdSize * sizeof(UChar)) != 0)) { + u_strncpy(t[noCases]->NFC, comp, len); + t[noCases]->NFC[len] = 0; + } + noCases++; + t[noCases] = (tester *)malloc(sizeof(tester)); + uprv_memset(t[noCases], 0, sizeof(tester)); + } + } + + for(u=0; u<(UChar32)noCases; u++) { + if(!ucol_equal(coll, t[u]->NFC, -1, t[u]->NFD, -1)) { + log_err("Failure: codePoint %05X fails TestComposeDecompose in the UCA\n", t[u]->u); + doTest(coll, t[u]->NFC, t[u]->NFD, UCOL_EQUAL); + } + } + /* + for(u = 0; u < 0x30000; u++) { + if(!(u&0xFFFF)) { + log_verbose("%08X ", u); + } + uprv_memset(t[noCases], 0, sizeof(tester)); + t[noCases]->u = u; + len = 0; + UTF_APPEND_CHAR_UNSAFE(comp, len, u); + comp[len] = 0; + nfcSize = unorm_normalize(comp, len, UNORM_NFC, 0, t[noCases]->NFC, NORM_BUFFER_TEST_LEN, &status); + nfdSize = unorm_normalize(comp, len, UNORM_NFD, 0, t[noCases]->NFD, NORM_BUFFER_TEST_LEN, &status); + doTest(coll, comp, t[noCases]->NFD, UCOL_EQUAL); + doTest(coll, comp, t[noCases]->NFC, UCOL_EQUAL); + } + */ + + ucol_close(coll); + + log_verbose("Testing locales, number of cases = %i\n", noCases); + for(i = 0; i<noOfLoc; i++) { + status = U_ZERO_ERROR; + locName = uloc_getAvailable(i); + if(hasCollationElements(locName)) { + char cName[256]; + UChar name[256]; + int32_t nameSize = uloc_getDisplayName(locName, NULL, name, sizeof(cName), &status); + + for(j = 0; j<nameSize; j++) { + cName[j] = (char)name[j]; + } + cName[nameSize] = 0; + log_verbose("\nTesting locale %s (%s)\n", locName, cName); + + coll = ucol_open(locName, &status); + ucol_setStrength(coll, UCOL_IDENTICAL); + iter = ucol_openElements(coll, t[u]->NFD, u_strlen(t[u]->NFD), &status); + + for(u=0; u<(UChar32)noCases; u++) { + if(!ucol_equal(coll, t[u]->NFC, -1, t[u]->NFD, -1)) { + log_err("Failure: codePoint %05X fails TestComposeDecompose for locale %s\n", t[u]->u, cName); + doTest(coll, t[u]->NFC, t[u]->NFD, UCOL_EQUAL); + log_verbose("Testing NFC\n"); + ucol_setText(iter, t[u]->NFC, u_strlen(t[u]->NFC), &status); + backAndForth(iter); + log_verbose("Testing NFD\n"); + ucol_setText(iter, t[u]->NFD, u_strlen(t[u]->NFD), &status); + backAndForth(iter); + } + } + ucol_closeElements(iter); + ucol_close(coll); + } + } + for(u = 0; u <= (UChar32)noCases; u++) { + free(t[u]); + } + free(t); +} + +static void TestEmptyRule(void) { + UErrorCode status = U_ZERO_ERROR; + UChar rulez[] = { 0 }; + UCollator *coll = ucol_openRules(rulez, 0, UCOL_OFF, UCOL_TERTIARY,NULL, &status); + + ucol_close(coll); +} + +static void TestUCARules(void) { + UErrorCode status = U_ZERO_ERROR; + UChar b[256]; + UChar *rules = b; + uint32_t ruleLen = 0; + UCollator *UCAfromRules = NULL; + UCollator *coll = ucol_open("", &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + ruleLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rules, 256); + + log_verbose("TestUCARules\n"); + if(ruleLen > 256) { + rules = (UChar *)malloc((ruleLen+1)*sizeof(UChar)); + ruleLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rules, ruleLen); + } + log_verbose("Rules length is %d\n", ruleLen); + UCAfromRules = ucol_openRules(rules, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + if(U_SUCCESS(status)) { + ucol_close(UCAfromRules); + } else { + log_verbose("Unable to create a collator from UCARules!\n"); + } +/* + u_unescape(blah, b, 256); + ucol_getSortKey(coll, b, 1, res, 256); +*/ + ucol_close(coll); + if(rules != b) { + free(rules); + } +} + + +/* Pinyin tonal order */ +/* + A < .. (\u0101) < .. (\u00e1) < .. (\u01ce) < .. (\u00e0) + (w/macron)< (w/acute)< (w/caron)< (w/grave) + E < .. (\u0113) < .. (\u00e9) < .. (\u011b) < .. (\u00e8) + I < .. (\u012b) < .. (\u00ed) < .. (\u01d0) < .. (\u00ec) + O < .. (\u014d) < .. (\u00f3) < .. (\u01d2) < .. (\u00f2) + U < .. (\u016b) < .. (\u00fa) < .. (\u01d4) < .. (\u00f9) + < .. (\u01d6) < .. (\u01d8) < .. (\u01da) < .. (\u01dc) < +.. (\u00fc) + +However, in testing we got the following order: + A < .. (\u00e1) < .. (\u00e0) < .. (\u01ce) < .. (\u0101) + (w/acute)< (w/grave)< (w/caron)< (w/macron) + E < .. (\u00e9) < .. (\u00e8) < .. (\u00ea) < .. (\u011b) < +.. (\u0113) + I < .. (\u00ed) < .. (\u00ec) < .. (\u01d0) < .. (\u012b) + O < .. (\u00f3) < .. (\u00f2) < .. (\u01d2) < .. (\u014d) + U < .. (\u00fa) < .. (\u00f9) < .. (\u01d4) < .. (\u00fc) < +.. (\u01d8) + < .. (\u01dc) < .. (\u01da) < .. (\u01d6) < .. (\u016b) +*/ + +static void TestBefore(void) { + const static char *data[] = { + "\\u0101", "\\u00e1", "\\u01ce", "\\u00e0", "A", + "\\u0113", "\\u00e9", "\\u011b", "\\u00e8", "E", + "\\u012b", "\\u00ed", "\\u01d0", "\\u00ec", "I", + "\\u014d", "\\u00f3", "\\u01d2", "\\u00f2", "O", + "\\u016b", "\\u00fa", "\\u01d4", "\\u00f9", "U", + "\\u01d6", "\\u01d8", "\\u01da", "\\u01dc", "\\u00fc" + }; + genericRulesStarter( + "&[before 1]a<\\u0101<\\u00e1<\\u01ce<\\u00e0" + "&[before 1]e<\\u0113<\\u00e9<\\u011b<\\u00e8" + "&[before 1]i<\\u012b<\\u00ed<\\u01d0<\\u00ec" + "&[before 1]o<\\u014d<\\u00f3<\\u01d2<\\u00f2" + "&[before 1]u<\\u016b<\\u00fa<\\u01d4<\\u00f9" + "&u<\\u01d6<\\u01d8<\\u01da<\\u01dc<\\u00fc", + data, sizeof(data)/sizeof(data[0])); +} + +#if 0 +/* superceded by TestBeforePinyin */ +static void TestJ784(void) { + const static char *data[] = { + "A", "\\u0101", "\\u00e1", "\\u01ce", "\\u00e0", + "E", "\\u0113", "\\u00e9", "\\u011b", "\\u00e8", + "I", "\\u012b", "\\u00ed", "\\u01d0", "\\u00ec", + "O", "\\u014d", "\\u00f3", "\\u01d2", "\\u00f2", + "U", "\\u016b", "\\u00fa", "\\u01d4", "\\u00f9", + "\\u00fc", + "\\u01d6", "\\u01d8", "\\u01da", "\\u01dc" + }; + genericLocaleStarter("zh", data, sizeof(data)/sizeof(data[0])); +} +#endif + +#if 0 +/* superceded by the changes to the lv locale */ +static void TestJ831(void) { + const static char *data[] = { + "I", + "i", + "Y", + "y" + }; + genericLocaleStarter("lv", data, sizeof(data)/sizeof(data[0])); +} +#endif + +static void TestJ815(void) { + const static char *data[] = { + "aa", + "Aa", + "ab", + "Ab", + "ad", + "Ad", + "ae", + "Ae", + "\\u00e6", + "\\u00c6", + "af", + "Af", + "b", + "B" + }; + genericLocaleStarter("fr", data, sizeof(data)/sizeof(data[0])); + genericRulesStarter("[backwards 2]&A<<\\u00e6/e<<<\\u00c6/E", data, sizeof(data)/sizeof(data[0])); +} + + +/* +"& a < b < c < d& r < c", "& a < b < d& r < c", +"& a < b < c < d& c < m", "& a < b < c < m < d", +"& a < b < c < d& a < m", "& a < m < b < c < d", +"& a <<< b << c < d& a < m", "& a <<< b << c < m < d", +"& a < b < c < d& [before 1] c < m", "& a < b < m < c < d", +"& a < b <<< c << d <<< e& [before 3] e <<< x", "& a < b <<< c << d <<< x <<< e", +"& a < b <<< c << d <<< e& [before 2] e <<< x", "& a < b <<< c <<< x << d <<< e", +"& a < b <<< c << d <<< e& [before 1] e <<< x", "& a <<< x < b <<< c << d <<< e", +"& a < b <<< c << d <<< e <<< f < g& [before 1] g < x", "& a < b <<< c << d <<< e <<< f < x < g", +*/ +static void TestRedundantRules(void) { + int32_t i; + + static const struct { + const char *rules; + const char *expectedRules; + const char *testdata[8]; + uint32_t testdatalen; + } tests[] = { + /* this test conflicts with positioning of CODAN placeholder */ + /*{ + "& a <<< b <<< c << d <<< e& [before 1] e <<< x", + "&\\u2089<<<x", + {"\\u2089", "x"}, 2 + }, */ + /* this test conflicts with the [before x] syntax tightening */ + /*{ + "& b <<< c <<< d << e <<< f& [before 1] f <<< x", + "&\\u0252<<<x", + {"\\u0252", "x"}, 2 + }, */ + /* this test conflicts with the [before x] syntax tightening */ + /*{ + "& a < b <<< c << d <<< e& [before 1] e <<< x", + "& a <<< x < b <<< c << d <<< e", + {"a", "x", "b", "c", "d", "e"}, 6 + }, */ + { + "& a < b < c < d& [before 1] c < m", + "& a < b < m < c < d", + {"a", "b", "m", "c", "d"}, 5 + }, + { + "& a < b <<< c << d <<< e& [before 3] e <<< x", + "& a < b <<< c << d <<< x <<< e", + {"a", "b", "c", "d", "x", "e"}, 6 + }, + /* this test conflicts with the [before x] syntax tightening */ + /* { + "& a < b <<< c << d <<< e& [before 2] e <<< x", + "& a < b <<< c <<< x << d <<< e", + {"a", "b", "c", "x", "d", "e"},, 6 + }, */ + { + "& a < b <<< c << d <<< e <<< f < g& [before 1] g < x", + "& a < b <<< c << d <<< e <<< f < x < g", + {"a", "b", "c", "d", "e", "f", "x", "g"}, 8 + }, + { + "& a <<< b << c < d& a < m", + "& a <<< b << c < m < d", + {"a", "b", "c", "m", "d"}, 5 + }, + { + "&a<b<<b\\u0301 &z<b", + "&a<b\\u0301 &z<b", + {"a", "b\\u0301", "z", "b"}, 4 + }, + { + "&z<m<<<q<<<m", + "&z<q<<<m", + {"z", "q", "m"},3 + }, + { + "&z<<<m<q<<<m", + "&z<q<<<m", + {"z", "q", "m"}, 3 + }, + { + "& a < b < c < d& r < c", + "& a < b < d& r < c", + {"a", "b", "d"}, 3 + }, + { + "& a < b < c < d& r < c", + "& a < b < d& r < c", + {"r", "c"}, 2 + }, + { + "& a < b < c < d& c < m", + "& a < b < c < m < d", + {"a", "b", "c", "m", "d"}, 5 + }, + { + "& a < b < c < d& a < m", + "& a < m < b < c < d", + {"a", "m", "b", "c", "d"}, 5 + } + }; + + + UCollator *credundant = NULL; + UCollator *cresulting = NULL; + UErrorCode status = U_ZERO_ERROR; + UChar rlz[2048] = { 0 }; + uint32_t rlen = 0; + + for(i = 0; i<sizeof(tests)/sizeof(tests[0]); i++) { + log_verbose("testing rule %s, expected to be %s\n", tests[i].rules, tests[i].expectedRules); + rlen = u_unescape(tests[i].rules, rlz, 2048); + + credundant = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + + rlen = u_unescape(tests[i].expectedRules, rlz, 2048); + cresulting = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status); + + testAgainstUCA(cresulting, credundant, "expected", TRUE, &status); + + ucol_close(credundant); + ucol_close(cresulting); + + log_verbose("testing using data\n"); + + genericRulesStarter(tests[i].rules, tests[i].testdata, tests[i].testdatalen); + } + +} + +static void TestExpansionSyntax(void) { + int32_t i; + + const static char *rules[] = { + "&AE <<< a << b <<< c &d <<< f", + "&AE <<< a <<< b << c << d < e < f <<< g", + "&AE <<< B <<< C / D <<< F" + }; + + const static char *expectedRules[] = { + "&A <<< a / E << b / E <<< c /E &d <<< f", + "&A <<< a / E <<< b / E << c / E << d / E < e < f <<< g", + "&A <<< B / E <<< C / ED <<< F / E" + }; + + const static char *testdata[][8] = { + {"AE", "a", "b", "c"}, + {"AE", "a", "b", "c", "d", "e", "f", "g"}, + {"AE", "B", "C"} /* / ED <<< F / E"},*/ + }; + + const static uint32_t testdatalen[] = { + 4, + 8, + 3 + }; + + + + UCollator *credundant = NULL; + UCollator *cresulting = NULL; + UErrorCode status = U_ZERO_ERROR; + UChar rlz[2048] = { 0 }; + uint32_t rlen = 0; + + for(i = 0; i<sizeof(rules)/sizeof(rules[0]); i++) { + log_verbose("testing rule %s, expected to be %s\n", rules[i], expectedRules[i]); + rlen = u_unescape(rules[i], rlz, 2048); + + credundant = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + rlen = u_unescape(expectedRules[i], rlz, 2048); + cresulting = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status); + + /* testAgainstUCA still doesn't handle expansions correctly, so this is not run */ + /* as a hard error test, but only in information mode */ + testAgainstUCA(cresulting, credundant, "expected", FALSE, &status); + + ucol_close(credundant); + ucol_close(cresulting); + + log_verbose("testing using data\n"); + + genericRulesStarter(rules[i], testdata[i], testdatalen[i]); + } +} + +static void TestCase(void) +{ + const static UChar gRules[MAX_TOKEN_LEN] = + /*" & 0 < 1,\u2461<a,A"*/ + { 0x0026, 0x0030, 0x003C, 0x0031, 0x002C, 0x2460, 0x003C, 0x0061, 0x002C, 0x0041, 0x0000 }; + + const static UChar testCase[][MAX_TOKEN_LEN] = + { + /*0*/ {0x0031 /*'1'*/, 0x0061/*'a'*/, 0x0000}, + /*1*/ {0x0031 /*'1'*/, 0x0041/*'A'*/, 0x0000}, + /*2*/ {0x2460 /*circ'1'*/, 0x0061/*'a'*/, 0x0000}, + /*3*/ {0x2460 /*circ'1'*/, 0x0041/*'A'*/, 0x0000} + }; + + const static UCollationResult caseTestResults[][9] = + { + { UCOL_LESS, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_LESS }, + { UCOL_GREATER, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_GREATER }, + { UCOL_LESS, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_GREATER, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_LESS }, + { UCOL_GREATER, UCOL_LESS, UCOL_GREATER, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_GREATER } + }; + + const static UColAttributeValue caseTestAttributes[][2] = + { + { UCOL_LOWER_FIRST, UCOL_OFF}, + { UCOL_UPPER_FIRST, UCOL_OFF}, + { UCOL_LOWER_FIRST, UCOL_ON}, + { UCOL_UPPER_FIRST, UCOL_ON} + }; + int32_t i,j,k; + UErrorCode status = U_ZERO_ERROR; + UCollationElements *iter; + UCollator *myCollation; + myCollation = ucol_open("en_US", &status); + + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing different case settings\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + + for(k = 0; k<4; k++) { + ucol_setAttribute(myCollation, UCOL_CASE_FIRST, caseTestAttributes[k][0], &status); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, caseTestAttributes[k][1], &status); + log_verbose("Case first = %d, Case level = %d\n", caseTestAttributes[k][0], caseTestAttributes[k][1]); + for (i = 0; i < 3 ; i++) { + for(j = i+1; j<4; j++) { + doTest(myCollation, testCase[i], testCase[j], caseTestResults[k][3*i+j-1]); + } + } + } + ucol_close(myCollation); + + myCollation = ucol_openRules(gRules, u_strlen(gRules), UCOL_OFF, UCOL_TERTIARY,NULL, &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing different case settings with custom rules\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + + for(k = 0; k<4; k++) { + ucol_setAttribute(myCollation, UCOL_CASE_FIRST, caseTestAttributes[k][0], &status); + ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, caseTestAttributes[k][1], &status); + for (i = 0; i < 3 ; i++) { + for(j = i+1; j<4; j++) { + log_verbose("k:%d, i:%d, j:%d\n", k, i, j); + doTest(myCollation, testCase[i], testCase[j], caseTestResults[k][3*i+j-1]); + iter=ucol_openElements(myCollation, testCase[i], u_strlen(testCase[i]), &status); + backAndForth(iter); + ucol_closeElements(iter); + iter=ucol_openElements(myCollation, testCase[j], u_strlen(testCase[j]), &status); + backAndForth(iter); + ucol_closeElements(iter); + } + } + } + ucol_close(myCollation); + { + const static char *lowerFirst[] = { + "h", + "H", + "ch", + "Ch", + "CH", + "cha", + "chA", + "Cha", + "ChA", + "CHa", + "CHA", + "i", + "I" + }; + + const static char *upperFirst[] = { + "H", + "h", + "CH", + "Ch", + "ch", + "CHA", + "CHa", + "ChA", + "Cha", + "chA", + "cha", + "I", + "i" + }; + log_verbose("mixed case test\n"); + log_verbose("lower first, case level off\n"); + genericRulesStarter("[casefirst lower]&H<ch<<<Ch<<<CH", lowerFirst, sizeof(lowerFirst)/sizeof(lowerFirst[0])); + log_verbose("upper first, case level off\n"); + genericRulesStarter("[casefirst upper]&H<ch<<<Ch<<<CH", upperFirst, sizeof(upperFirst)/sizeof(upperFirst[0])); + log_verbose("lower first, case level on\n"); + genericRulesStarter("[casefirst lower][caselevel on]&H<ch<<<Ch<<<CH", lowerFirst, sizeof(lowerFirst)/sizeof(lowerFirst[0])); + log_verbose("upper first, case level on\n"); + genericRulesStarter("[casefirst upper][caselevel on]&H<ch<<<Ch<<<CH", upperFirst, sizeof(upperFirst)/sizeof(upperFirst[0])); + } + +} + +static void TestIncrementalNormalize(void) { + + /*UChar baseA =0x61;*/ + UChar baseA =0x41; +/* UChar baseB = 0x42;*/ + static const UChar ccMix[] = {0x316, 0x321, 0x300}; + /*UChar ccMix[] = {0x61, 0x61, 0x61};*/ + /* + 0x316 is combining grave accent below, cc=220 + 0x321 is combining palatalized hook below, cc=202 + 0x300 is combining grave accent, cc=230 + */ + + int maxSLen = 2000; + /*int maxSLen = 64000;*/ + int sLen; + int i; + + UCollator *coll; + UErrorCode status = U_ZERO_ERROR; + UCollationResult result; + + int32_t myQ = QUICK; + + if(QUICK < 0) { + QUICK = 1; + } + + { + /* Test 1. Run very long unnormalized strings, to force overflow of*/ + /* most buffers along the way.*/ + UChar *strA; + UChar *strB; + + strA = malloc((maxSLen+1) * sizeof(UChar)); + strB = malloc((maxSLen+1) * sizeof(UChar)); + + coll = ucol_open("en_US", &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + + /*for (sLen = 257; sLen<maxSLen; sLen++) {*/ + /*for (sLen = 4; sLen<maxSLen; sLen++) {*/ + /*for (sLen = 1000; sLen<1001; sLen++) {*/ + for (sLen = 500; sLen<501; sLen++) { + /*for (sLen = 40000; sLen<65000; sLen+=1000) {*/ + strA[0] = baseA; + strB[0] = baseA; + for (i=1; i<=sLen-1; i++) { + strA[i] = ccMix[i % 3]; + strB[sLen-i] = ccMix[i % 3]; + } + strA[sLen] = 0; + strB[sLen] = 0; + + ucol_setStrength(coll, UCOL_TERTIARY); /* Do test with default strength, which runs*/ + doTest(coll, strA, strB, UCOL_EQUAL); /* optimized functions in the impl*/ + ucol_setStrength(coll, UCOL_IDENTICAL); /* Do again with the slow, general impl.*/ + doTest(coll, strA, strB, UCOL_EQUAL); + } + free(strA); + free(strB); + } + + QUICK = myQ; + + + /* Test 2: Non-normal sequence in a string that extends to the last character*/ + /* of the string. Checks a couple of edge cases.*/ + + { + static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0}; + static const UChar strB[] = {0x41, 0xc0, 0x316, 0}; + ucol_setStrength(coll, UCOL_TERTIARY); + doTest(coll, strA, strB, UCOL_EQUAL); + } + + /* Test 3: Non-normal sequence is terminated by a surrogate pair.*/ + + { + /* New UCA 3.1.1. + * test below used a code point from Desseret, which sorts differently + * than d800 dc00 + */ + /*UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0xD801, 0xDC00, 0};*/ + static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0xD800, 0xDC01, 0}; + static const UChar strB[] = {0x41, 0xc0, 0x316, 0xD800, 0xDC00, 0}; + ucol_setStrength(coll, UCOL_TERTIARY); + doTest(coll, strA, strB, UCOL_GREATER); + } + + /* Test 4: Imbedded nulls do not terminate a string when length is specified.*/ + + { + static const UChar strA[] = {0x41, 0x00, 0x42, 0x00}; + static const UChar strB[] = {0x41, 0x00, 0x00, 0x00}; + char sortKeyA[50]; + char sortKeyAz[50]; + char sortKeyB[50]; + char sortKeyBz[50]; + int r; + + /* there used to be -3 here. Hmmmm.... */ + /*result = ucol_strcoll(coll, strA, -3, strB, -3);*/ + result = ucol_strcoll(coll, strA, 3, strB, 3); + if (result != UCOL_GREATER) { + log_err("ERROR 1 in test 4\n"); + } + result = ucol_strcoll(coll, strA, -1, strB, -1); + if (result != UCOL_EQUAL) { + log_err("ERROR 2 in test 4\n"); + } + + ucol_getSortKey(coll, strA, 3, (uint8_t *)sortKeyA, sizeof(sortKeyA)); + ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz)); + ucol_getSortKey(coll, strB, 3, (uint8_t *)sortKeyB, sizeof(sortKeyB)); + ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz)); + + r = strcmp(sortKeyA, sortKeyAz); + if (r <= 0) { + log_err("Error 3 in test 4\n"); + } + r = strcmp(sortKeyA, sortKeyB); + if (r <= 0) { + log_err("Error 4 in test 4\n"); + } + r = strcmp(sortKeyAz, sortKeyBz); + if (r != 0) { + log_err("Error 5 in test 4\n"); + } + + ucol_setStrength(coll, UCOL_IDENTICAL); + ucol_getSortKey(coll, strA, 3, (uint8_t *)sortKeyA, sizeof(sortKeyA)); + ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz)); + ucol_getSortKey(coll, strB, 3, (uint8_t *)sortKeyB, sizeof(sortKeyB)); + ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz)); + + r = strcmp(sortKeyA, sortKeyAz); + if (r <= 0) { + log_err("Error 6 in test 4\n"); + } + r = strcmp(sortKeyA, sortKeyB); + if (r <= 0) { + log_err("Error 7 in test 4\n"); + } + r = strcmp(sortKeyAz, sortKeyBz); + if (r != 0) { + log_err("Error 8 in test 4\n"); + } + ucol_setStrength(coll, UCOL_TERTIARY); + } + + + /* Test 5: Null characters in non-normal source strings.*/ + + { + static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x42, 0x00}; + static const UChar strB[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x00, 0x00}; + char sortKeyA[50]; + char sortKeyAz[50]; + char sortKeyB[50]; + char sortKeyBz[50]; + int r; + + result = ucol_strcoll(coll, strA, 6, strB, 6); + if (result != UCOL_GREATER) { + log_err("ERROR 1 in test 5\n"); + } + result = ucol_strcoll(coll, strA, -1, strB, -1); + if (result != UCOL_EQUAL) { + log_err("ERROR 2 in test 5\n"); + } + + ucol_getSortKey(coll, strA, 6, (uint8_t *)sortKeyA, sizeof(sortKeyA)); + ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz)); + ucol_getSortKey(coll, strB, 6, (uint8_t *)sortKeyB, sizeof(sortKeyB)); + ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz)); + + r = strcmp(sortKeyA, sortKeyAz); + if (r <= 0) { + log_err("Error 3 in test 5\n"); + } + r = strcmp(sortKeyA, sortKeyB); + if (r <= 0) { + log_err("Error 4 in test 5\n"); + } + r = strcmp(sortKeyAz, sortKeyBz); + if (r != 0) { + log_err("Error 5 in test 5\n"); + } + + ucol_setStrength(coll, UCOL_IDENTICAL); + ucol_getSortKey(coll, strA, 6, (uint8_t *)sortKeyA, sizeof(sortKeyA)); + ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz)); + ucol_getSortKey(coll, strB, 6, (uint8_t *)sortKeyB, sizeof(sortKeyB)); + ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz)); + + r = strcmp(sortKeyA, sortKeyAz); + if (r <= 0) { + log_err("Error 6 in test 5\n"); + } + r = strcmp(sortKeyA, sortKeyB); + if (r <= 0) { + log_err("Error 7 in test 5\n"); + } + r = strcmp(sortKeyAz, sortKeyBz); + if (r != 0) { + log_err("Error 8 in test 5\n"); + } + ucol_setStrength(coll, UCOL_TERTIARY); + } + + + /* Test 6: Null character as base of a non-normal combining sequence.*/ + + { + static const UChar strA[] = {0x41, 0x0, 0x300, 0x316, 0x41, 0x302, 0x00}; + static const UChar strB[] = {0x41, 0x0, 0x302, 0x316, 0x41, 0x300, 0x00}; + + result = ucol_strcoll(coll, strA, 5, strB, 5); + if (result != UCOL_LESS) { + log_err("Error 1 in test 6\n"); + } + result = ucol_strcoll(coll, strA, -1, strB, -1); + if (result != UCOL_EQUAL) { + log_err("Error 2 in test 6\n"); + } + } + + ucol_close(coll); +} + + + +#if 0 +static void TestGetCaseBit(void) { + static const char *caseBitData[] = { + "a", "A", "ch", "Ch", "CH", + "\\uFF9E", "\\u0009" + }; + + static const uint8_t results[] = { + UCOL_LOWER_CASE, UCOL_UPPER_CASE, UCOL_LOWER_CASE, UCOL_MIXED_CASE, UCOL_UPPER_CASE, + UCOL_UPPER_CASE, UCOL_LOWER_CASE + }; + + uint32_t i, blen = 0; + UChar b[256] = {0}; + UErrorCode status = U_ZERO_ERROR; + UCollator *UCA = ucol_open("", &status); + uint8_t res = 0; + + for(i = 0; i<sizeof(results)/sizeof(results[0]); i++) { + blen = u_unescape(caseBitData[i], b, 256); + res = ucol_uprv_getCaseBits(UCA, b, blen, &status); + if(results[i] != res) { + log_err("Expected case = %02X, got %02X for %04X\n", results[i], res, b[0]); + } + } +} +#endif + +static void TestHangulTailoring(void) { + static const char *koreanData[] = { + "\\uac00", "\\u4f3d", "\\u4f73", "\\u5047", "\\u50f9", "\\u52a0", "\\u53ef", "\\u5475", + "\\u54e5", "\\u5609", "\\u5ac1", "\\u5bb6", "\\u6687", "\\u67b6", "\\u67b7", "\\u67ef", + "\\u6b4c", "\\u73c2", "\\u75c2", "\\u7a3c", "\\u82db", "\\u8304", "\\u8857", "\\u8888", + "\\u8a36", "\\u8cc8", "\\u8dcf", "\\u8efb", "\\u8fe6", "\\u99d5", + "\\u4EEE", "\\u50A2", "\\u5496", "\\u54FF", "\\u5777", "\\u5B8A", "\\u659D", "\\u698E", + "\\u6A9F", "\\u73C8", "\\u7B33", "\\u801E", "\\u8238", "\\u846D", "\\u8B0C" + }; + + const char *rules = + "&\\uac00 <<< \\u4f3d <<< \\u4f73 <<< \\u5047 <<< \\u50f9 <<< \\u52a0 <<< \\u53ef <<< \\u5475 " + "<<< \\u54e5 <<< \\u5609 <<< \\u5ac1 <<< \\u5bb6 <<< \\u6687 <<< \\u67b6 <<< \\u67b7 <<< \\u67ef " + "<<< \\u6b4c <<< \\u73c2 <<< \\u75c2 <<< \\u7a3c <<< \\u82db <<< \\u8304 <<< \\u8857 <<< \\u8888 " + "<<< \\u8a36 <<< \\u8cc8 <<< \\u8dcf <<< \\u8efb <<< \\u8fe6 <<< \\u99d5 " + "<<< \\u4EEE <<< \\u50A2 <<< \\u5496 <<< \\u54FF <<< \\u5777 <<< \\u5B8A <<< \\u659D <<< \\u698E " + "<<< \\u6A9F <<< \\u73C8 <<< \\u7B33 <<< \\u801E <<< \\u8238 <<< \\u846D <<< \\u8B0C"; + + + UErrorCode status = U_ZERO_ERROR; + UChar rlz[2048] = { 0 }; + uint32_t rlen = u_unescape(rules, rlz, 2048); + + UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + + log_verbose("Using start of korean rules\n"); + + if(U_SUCCESS(status)) { + genericOrderingTest(coll, koreanData, sizeof(koreanData)/sizeof(koreanData[0])); + } else { + log_err("Unable to open collator with rules %s\n", rules); + } + + log_verbose("Setting jamoSpecial to TRUE and testing once more\n"); + ((UCATableHeader *)coll->image)->jamoSpecial = TRUE; /* don't try this at home */ + genericOrderingTest(coll, koreanData, sizeof(koreanData)/sizeof(koreanData[0])); + + ucol_close(coll); + + log_verbose("Using ko__LOTUS locale\n"); + genericLocaleStarter("ko__LOTUS", koreanData, sizeof(koreanData)/sizeof(koreanData[0])); +} + +static void TestCompressOverlap(void) { + UChar secstr[150]; + UChar tertstr[150]; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll; + char result[200]; + uint32_t resultlen; + int count = 0; + char *tempptr; + + coll = ucol_open("", &status); + + if (U_FAILURE(status)) { + log_err("Collator can't be created\n"); + return; + } + while (count < 149) { + secstr[count] = 0x0020; /* [06, 05, 05] */ + tertstr[count] = 0x0020; + count ++; + } + + /* top down compression ----------------------------------- */ + secstr[count] = 0x0332; /* [, 87, 05] */ + tertstr[count] = 0x3000; /* [06, 05, 07] */ + + /* no compression secstr should have 150 secondary bytes, tertstr should + have 150 tertiary bytes. + with correct overlapping compression, secstr should have 4 secondary + bytes, tertstr should have > 2 tertiary bytes */ + resultlen = ucol_getSortKey(coll, secstr, 150, (uint8_t *)result, 250); + tempptr = uprv_strchr(result, 1) + 1; + while (*(tempptr + 1) != 1) { + /* the last secondary collation element is not checked since it is not + part of the compression */ + if (*tempptr < UCOL_COMMON_TOP2 - UCOL_TOP_COUNT2) { + log_err("Secondary compression overlapped\n"); + } + tempptr ++; + } + + /* tertiary top/bottom/common for en_US is similar to the secondary + top/bottom/common */ + resultlen = ucol_getSortKey(coll, tertstr, 150, (uint8_t *)result, 250); + tempptr = uprv_strrchr(result, 1) + 1; + while (*(tempptr + 1) != 0) { + /* the last secondary collation element is not checked since it is not + part of the compression */ + if (*tempptr < coll->tertiaryTop - coll->tertiaryTopCount) { + log_err("Tertiary compression overlapped\n"); + } + tempptr ++; + } + + /* bottom up compression ------------------------------------- */ + secstr[count] = 0; + tertstr[count] = 0; + resultlen = ucol_getSortKey(coll, secstr, 150, (uint8_t *)result, 250); + tempptr = uprv_strchr(result, 1) + 1; + while (*(tempptr + 1) != 1) { + /* the last secondary collation element is not checked since it is not + part of the compression */ + if (*tempptr > UCOL_COMMON_BOT2 + UCOL_BOT_COUNT2) { + log_err("Secondary compression overlapped\n"); + } + tempptr ++; + } + + /* tertiary top/bottom/common for en_US is similar to the secondary + top/bottom/common */ + resultlen = ucol_getSortKey(coll, tertstr, 150, (uint8_t *)result, 250); + tempptr = uprv_strrchr(result, 1) + 1; + while (*(tempptr + 1) != 0) { + /* the last secondary collation element is not checked since it is not + part of the compression */ + if (*tempptr > coll->tertiaryBottom + coll->tertiaryBottomCount) { + log_err("Tertiary compression overlapped\n"); + } + tempptr ++; + } + + ucol_close(coll); +} + +static void TestCyrillicTailoring(void) { + static const char *test[] = { + "\\u0410b", + "\\u0410\\u0306a", + "\\u04d0A" + }; + + /* Russian overrides contractions, so this test is not valid anymore */ + /*genericLocaleStarter("ru", test, 3);*/ + + genericLocaleStarter("root", test, 3); + genericRulesStarter("&\\u0410 = \\u0410", test, 3); + genericRulesStarter("&Z < \\u0410", test, 3); + genericRulesStarter("&\\u0410 = \\u0410 < \\u04d0", test, 3); + genericRulesStarter("&Z < \\u0410 < \\u04d0", test, 3); + genericRulesStarter("&\\u0410 = \\u0410 < \\u0410\\u0301", test, 3); + genericRulesStarter("&Z < \\u0410 < \\u0410\\u0301", test, 3); +} + +static void TestSuppressContractions(void) { + + static const char *testNoCont2[] = { + "\\u0410\\u0302a", + "\\u0410\\u0306b", + "\\u0410c" + }; + static const char *testNoCont[] = { + "a\\u0410", + "A\\u0410\\u0306", + "\\uFF21\\u0410\\u0302" + }; + + genericRulesStarter("[suppressContractions [\\u0400-\\u047f]]", testNoCont, 3); + genericRulesStarter("[suppressContractions [\\u0400-\\u047f]]", testNoCont2, 3); +} + +static void TestContraction(void) { + const static char *testrules[] = { + "&A = AB / B", + "&A = A\\u0306/\\u0306", + "&c = ch / h" + }; + const static UChar testdata[][2] = { + {0x0041 /* 'A' */, 0x0042 /* 'B' */}, + {0x0041 /* 'A' */, 0x0306 /* combining breve */}, + {0x0063 /* 'c' */, 0x0068 /* 'h' */} + }; + const static UChar testdata2[][2] = { + {0x0063 /* 'c' */, 0x0067 /* 'g' */}, + {0x0063 /* 'c' */, 0x0068 /* 'h' */}, + {0x0063 /* 'c' */, 0x006C /* 'l' */} + }; + const static char *testrules3[] = { + "&z < xyz &xyzw << B", + "&z < xyz &xyz << B / w", + "&z < ch &achm << B", + "&z < ch &a << B / chm", + "&\\ud800\\udc00w << B", + "&\\ud800\\udc00 << B / w", + "&a\\ud800\\udc00m << B", + "&a << B / \\ud800\\udc00m", + }; + + UErrorCode status = U_ZERO_ERROR; + UCollator *coll; + UChar rule[256] = {0}; + uint32_t rlen = 0; + int i; + + for (i = 0; i < sizeof(testrules) / sizeof(testrules[0]); i ++) { + UCollationElements *iter1; + int j = 0; + log_verbose("Rule %s for testing\n", testrules[i]); + rlen = u_unescape(testrules[i], rule, 32); + coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status); + if (U_FAILURE(status)) { + log_err("Collator creation failed %s\n", testrules[i]); + return; + } + iter1 = ucol_openElements(coll, testdata[i], 2, &status); + if (U_FAILURE(status)) { + log_err("Collation iterator creation failed\n"); + return; + } + while (j < 2) { + UCollationElements *iter2 = ucol_openElements(coll, + &(testdata[i][j]), + 1, &status); + uint32_t ce; + if (U_FAILURE(status)) { + log_err("Collation iterator creation failed\n"); + return; + } + ce = ucol_next(iter2, &status); + while (ce != UCOL_NULLORDER) { + if ((uint32_t)ucol_next(iter1, &status) != ce) { + log_err("Collation elements in contraction split does not match\n"); + return; + } + ce = ucol_next(iter2, &status); + } + j ++; + ucol_closeElements(iter2); + } + if (ucol_next(iter1, &status) != UCOL_NULLORDER) { + log_err("Collation elements not exhausted\n"); + return; + } + ucol_closeElements(iter1); + ucol_close(coll); + } + + rlen = u_unescape("& a < b < c < ch < d & c = ch / h", rule, 256); + coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status); + if (ucol_strcoll(coll, testdata2[0], 2, testdata2[1], 2) != UCOL_LESS) { + log_err("Expected \\u%04x\\u%04x < \\u%04x\\u%04x\n", + testdata2[0][0], testdata2[0][1], testdata2[1][0], + testdata2[1][1]); + return; + } + if (ucol_strcoll(coll, testdata2[1], 2, testdata2[2], 2) != UCOL_LESS) { + log_err("Expected \\u%04x\\u%04x < \\u%04x\\u%04x\n", + testdata2[1][0], testdata2[1][1], testdata2[2][0], + testdata2[2][1]); + return; + } + ucol_close(coll); + + for (i = 0; i < sizeof(testrules3) / sizeof(testrules3[0]); i += 2) { + UCollator *coll1, + *coll2; + UCollationElements *iter1, + *iter2; + UChar ch = 0x0042 /* 'B' */; + uint32_t ce; + rlen = u_unescape(testrules3[i], rule, 32); + coll1 = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status); + rlen = u_unescape(testrules3[i + 1], rule, 32); + coll2 = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status); + if (U_FAILURE(status)) { + log_err("Collator creation failed %s\n", testrules[i]); + return; + } + iter1 = ucol_openElements(coll1, &ch, 1, &status); + iter2 = ucol_openElements(coll2, &ch, 1, &status); + if (U_FAILURE(status)) { + log_err("Collation iterator creation failed\n"); + return; + } + ce = ucol_next(iter1, &status); + if (U_FAILURE(status)) { + log_err("Retrieving ces failed\n"); + return; + } + while (ce != UCOL_NULLORDER) { + if (ce != (uint32_t)ucol_next(iter2, &status)) { + log_err("CEs does not match\n"); + return; + } + ce = ucol_next(iter1, &status); + if (U_FAILURE(status)) { + log_err("Retrieving ces failed\n"); + return; + } + } + if (ucol_next(iter2, &status) != UCOL_NULLORDER) { + log_err("CEs not exhausted\n"); + return; + } + ucol_closeElements(iter1); + ucol_closeElements(iter2); + ucol_close(coll1); + ucol_close(coll2); + } +} + +static void TestExpansion(void) { + const static char *testrules[] = { + "&J << K / B & K << M", + "&J << K / B << M" + }; + const static UChar testdata[][3] = { + {0x004A /*'J'*/, 0x0041 /*'A'*/, 0}, + {0x004D /*'M'*/, 0x0041 /*'A'*/, 0}, + {0x004B /*'K'*/, 0x0041 /*'A'*/, 0}, + {0x004B /*'K'*/, 0x0043 /*'C'*/, 0}, + {0x004A /*'J'*/, 0x0043 /*'C'*/, 0}, + {0x004D /*'M'*/, 0x0043 /*'C'*/, 0} + }; + + UErrorCode status = U_ZERO_ERROR; + UCollator *coll; + UChar rule[256] = {0}; + uint32_t rlen = 0; + int i; + + for (i = 0; i < sizeof(testrules) / sizeof(testrules[0]); i ++) { + int j = 0; + log_verbose("Rule %s for testing\n", testrules[i]); + rlen = u_unescape(testrules[i], rule, 32); + coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status); + if (U_FAILURE(status)) { + log_err("Collator creation failed %s\n", testrules[i]); + return; + } + + for (j = 0; j < 5; j ++) { + doTest(coll, testdata[j], testdata[j + 1], UCOL_LESS); + } + ucol_close(coll); + } +} + +#if 0 +/* this test tests the current limitations of the engine */ +/* it always fail, so it is disabled by default */ +static void TestLimitations(void) { + /* recursive expansions */ + { + static const char *rule = "&a=b/c&d=c/e"; + static const char *tlimit01[] = {"add","b","adf"}; + static const char *tlimit02[] = {"aa","b","af"}; + log_verbose("recursive expansions\n"); + genericRulesStarter(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0])); + genericRulesStarter(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0])); + } + /* contractions spanning expansions */ + { + static const char *rule = "&a<<<c/e&g<<<eh"; + static const char *tlimit01[] = {"ad","c","af","f","ch","h"}; + static const char *tlimit02[] = {"ad","c","ch","af","f","h"}; + log_verbose("contractions spanning expansions\n"); + genericRulesStarter(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0])); + genericRulesStarter(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0])); + } + /* normalization: nulls in contractions */ + { + static const char *rule = "&a<<<\\u0000\\u0302"; + static const char *tlimit01[] = {"a","\\u0000\\u0302\\u0327"}; + static const char *tlimit02[] = {"\\u0000\\u0302\\u0327","a"}; + static const UColAttribute att[] = { UCOL_DECOMPOSITION_MODE }; + static const UColAttributeValue valOn[] = { UCOL_ON }; + static const UColAttributeValue valOff[] = { UCOL_OFF }; + + log_verbose("NULL in contractions\n"); + genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOn, 1); + genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOn, 1); + genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOff, 1); + genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOff, 1); + + } + /* normalization: contractions spanning normalization */ + { + static const char *rule = "&a<<<\\u0000\\u0302"; + static const char *tlimit01[] = {"a","\\u0000\\u0302\\u0327"}; + static const char *tlimit02[] = {"\\u0000\\u0302\\u0327","a"}; + static const UColAttribute att[] = { UCOL_DECOMPOSITION_MODE }; + static const UColAttributeValue valOn[] = { UCOL_ON }; + static const UColAttributeValue valOff[] = { UCOL_OFF }; + + log_verbose("contractions spanning normalization\n"); + genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOn, 1); + genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOn, 1); + genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOff, 1); + genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOff, 1); + + } + /* variable top: */ + { + /*static const char *rule2 = "&\\u2010<x=[variable top]<z";*/ + static const char *rule = "&\\u2010<x<[variable top]=z"; + /*static const char *rule3 = "&' '<x<[variable top]=z";*/ + static const char *tlimit01[] = {" ", "z", "zb", "a", " b", "xb", "b", "c" }; + static const char *tlimit02[] = {"-", "-x", "x","xb", "-z", "z", "zb", "-a", "a", "-b", "b", "c"}; + static const char *tlimit03[] = {" ", "xb", "z", "zb", "a", " b", "b", "c" }; + static const UColAttribute att[] = { UCOL_ALTERNATE_HANDLING, UCOL_STRENGTH }; + static const UColAttributeValue valOn[] = { UCOL_SHIFTED, UCOL_QUATERNARY }; + static const UColAttributeValue valOff[] = { UCOL_NON_IGNORABLE, UCOL_TERTIARY }; + + log_verbose("variable top\n"); + genericRulesStarterWithOptions(rule, tlimit03, sizeof(tlimit03)/sizeof(tlimit03[0]), att, valOn, sizeof(att)/sizeof(att[0])); + genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOn, sizeof(att)/sizeof(att[0])); + genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOn, sizeof(att)/sizeof(att[0])); + genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOff, sizeof(att)/sizeof(att[0])); + genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOff, sizeof(att)/sizeof(att[0])); + + } + /* case level */ + { + static const char *rule = "&c<ch<<<cH<<<Ch<<<CH"; + static const char *tlimit01[] = {"c","CH","Ch","cH","ch"}; + static const char *tlimit02[] = {"c","CH","cH","Ch","ch"}; + static const UColAttribute att[] = { UCOL_CASE_FIRST}; + static const UColAttributeValue valOn[] = { UCOL_UPPER_FIRST}; + /*static const UColAttributeValue valOff[] = { UCOL_OFF};*/ + log_verbose("case level\n"); + genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOn, sizeof(att)/sizeof(att[0])); + genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOn, sizeof(att)/sizeof(att[0])); + /*genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOff, sizeof(att)/sizeof(att[0]));*/ + /*genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOff, sizeof(att)/sizeof(att[0]));*/ + } + +} +#endif + +static void TestBocsuCoverage(void) { + UErrorCode status = U_ZERO_ERROR; + const char *testString = "\\u0041\\u0441\\u4441\\U00044441\\u4441\\u0441\\u0041"; + UChar test[256] = {0}; + uint32_t tlen = u_unescape(testString, test, 32); + uint8_t key[256] = {0}; + uint32_t klen = 0; + + UCollator *coll = ucol_open("", &status); + if(U_SUCCESS(status)) { + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_IDENTICAL, &status); + + klen = ucol_getSortKey(coll, test, tlen, key, 256); + + ucol_close(coll); + } else { + log_data_err("Couldn't open UCA\n"); + } +} + +static void TestVariableTopSetting(void) { + UErrorCode status = U_ZERO_ERROR; + const UChar *current = NULL; + uint32_t varTopOriginal = 0, varTop1, varTop2; + UCollator *coll = ucol_open("", &status); + if(U_SUCCESS(status)) { + + uint32_t strength = 0; + uint16_t specs = 0; + uint32_t chOffset = 0; + uint32_t chLen = 0; + uint32_t exOffset = 0; + uint32_t exLen = 0; + uint32_t oldChOffset = 0; + uint32_t oldChLen = 0; + uint32_t oldExOffset = 0; + uint32_t oldExLen = 0; + uint32_t prefixOffset = 0; + uint32_t prefixLen = 0; + + UBool startOfRules = TRUE; + UColTokenParser src; + UColOptionSet opts; + + UChar *rulesCopy = NULL; + uint32_t rulesLen; + + UCollationResult result; + + UChar first[256] = { 0 }; + UChar second[256] = { 0 }; + UParseError parseError; + int32_t myQ = QUICK; + + src.opts = &opts; + + if(QUICK <= 0) { + QUICK = 1; + } + + /* this test will fail when normalization is turned on */ + /* therefore we always turn off exhaustive mode for it */ + { /* QUICK > 0*/ + log_verbose("Slide variable top over UCARules\n"); + rulesLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rulesCopy, 0); + rulesCopy = (UChar *)malloc((rulesLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar)); + rulesLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rulesCopy, rulesLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE); + + if(U_SUCCESS(status) && rulesLen > 0) { + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + src.current = src.source = rulesCopy; + src.end = rulesCopy+rulesLen; + src.extraCurrent = src.end; + src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE; + + while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,&status)) != NULL) { + strength = src.parsedToken.strength; + chOffset = src.parsedToken.charsOffset; + chLen = src.parsedToken.charsLen; + exOffset = src.parsedToken.extensionOffset; + exLen = src.parsedToken.extensionLen; + prefixOffset = src.parsedToken.prefixOffset; + prefixLen = src.parsedToken.prefixLen; + specs = src.parsedToken.flags; + + startOfRules = FALSE; + { + log_verbose("%04X %d ", *(rulesCopy+chOffset), chLen); + } + if(strength == UCOL_PRIMARY) { + status = U_ZERO_ERROR; + varTopOriginal = ucol_getVariableTop(coll, &status); + varTop1 = ucol_setVariableTop(coll, rulesCopy+oldChOffset, oldChLen, &status); + if(U_FAILURE(status)) { + char buffer[256]; + char *buf = buffer; + uint32_t i = 0, j; + uint32_t CE = UCOL_NO_MORE_CES; + + /* before we start screaming, let's see if there is a problem with the rules */ + collIterate s; + uprv_init_collIterate(coll, rulesCopy+oldChOffset, oldChLen, &s); + + CE = ucol_getNextCE(coll, &s, &status); + + for(i = 0; i < oldChLen; i++) { + j = sprintf(buf, "%04X ", *(rulesCopy+oldChOffset+i)); + buf += j; + } + if(status == U_PRIMARY_TOO_LONG_ERROR) { + log_verbose("= Expected failure for %s =", buffer); + } else { + if(s.pos == s.endp) { + log_err("Unexpected failure setting variable top at offset %d. Error %s. Codepoints: %s\n", + oldChOffset, u_errorName(status), buffer); + } else { + log_verbose("There is a goofy contraction in UCA rules that does not appear in the fractional UCA. Codepoints: %s\n", + buffer); + } + } + } + varTop2 = ucol_getVariableTop(coll, &status); + if((varTop1 & 0xFFFF0000) != (varTop2 & 0xFFFF0000)) { + log_err("cannot retrieve set varTop value!\n"); + continue; + } + + if((varTop1 & 0xFFFF0000) > 0 && oldExLen == 0) { + + u_strncpy(first, rulesCopy+oldChOffset, oldChLen); + u_strncpy(first+oldChLen, rulesCopy+chOffset, chLen); + u_strncpy(first+oldChLen+chLen, rulesCopy+oldChOffset, oldChLen); + first[2*oldChLen+chLen] = 0; + + if(oldExLen == 0) { + u_strncpy(second, rulesCopy+chOffset, chLen); + second[chLen] = 0; + } else { /* This is skipped momentarily, but should work once UCARules are fully UCA conformant */ + u_strncpy(second, rulesCopy+oldExOffset, oldExLen); + u_strncpy(second+oldChLen, rulesCopy+chOffset, chLen); + u_strncpy(second+oldChLen+chLen, rulesCopy+oldExOffset, oldExLen); + second[2*oldExLen+chLen] = 0; + } + result = ucol_strcoll(coll, first, -1, second, -1); + if(result == UCOL_EQUAL) { + doTest(coll, first, second, UCOL_EQUAL); + } else { + log_verbose("Suspicious strcoll result for %04X and %04X\n", *(rulesCopy+oldChOffset), *(rulesCopy+chOffset)); + } + } + } + if(strength != UCOL_TOK_RESET) { + oldChOffset = chOffset; + oldChLen = chLen; + oldExOffset = exOffset; + oldExLen = exLen; + } + } + status = U_ZERO_ERROR; + } + else { + log_err("Unexpected failure getting rules %s\n", u_errorName(status)); + return; + } + if (U_FAILURE(status)) { + log_err("Error parsing rules %s\n", u_errorName(status)); + return; + } + status = U_ZERO_ERROR; + } + + QUICK = myQ; + + log_verbose("Testing setting variable top to contractions\n"); + { + /* uint32_t tailoredCE = UCOL_NOT_FOUND; */ + /*UChar *conts = (UChar *)((uint8_t *)coll->image + coll->image->UCAConsts+sizeof(UCAConstants));*/ + UChar *conts = (UChar *)((uint8_t *)coll->image + coll->image->contractionUCACombos); + while(*conts != 0) { + if(*(conts+2) == 0) { + varTop1 = ucol_setVariableTop(coll, conts, -1, &status); + } else { + varTop1 = ucol_setVariableTop(coll, conts, 3, &status); + } + if(U_FAILURE(status)) { + log_err("Couldn't set variable top to a contraction %04X %04X %04X\n", + *conts, *(conts+1), *(conts+2)); + status = U_ZERO_ERROR; + } + conts+=3; + } + + status = U_ZERO_ERROR; + + first[0] = 0x0040; + first[1] = 0x0050; + first[2] = 0x0000; + + ucol_setVariableTop(coll, first, -1, &status); + + if(U_SUCCESS(status)) { + log_err("Invalid contraction succeded in setting variable top!\n"); + } + + } + + log_verbose("Test restoring variable top\n"); + + status = U_ZERO_ERROR; + ucol_restoreVariableTop(coll, varTopOriginal, &status); + if(varTopOriginal != ucol_getVariableTop(coll, &status)) { + log_err("Couldn't restore old variable top\n"); + } + + log_verbose("Testing calling with error set\n"); + + status = U_INTERNAL_PROGRAM_ERROR; + varTop1 = ucol_setVariableTop(coll, first, 1, &status); + varTop2 = ucol_getVariableTop(coll, &status); + ucol_restoreVariableTop(coll, varTop2, &status); + varTop1 = ucol_setVariableTop(NULL, first, 1, &status); + varTop2 = ucol_getVariableTop(NULL, &status); + ucol_restoreVariableTop(NULL, varTop2, &status); + if(status != U_INTERNAL_PROGRAM_ERROR) { + log_err("Bad reaction to passed error!\n"); + } + free(rulesCopy); + ucol_close(coll); + } else { + log_data_err("Couldn't open UCA collator\n"); + } + +} + +static void TestNonChars(void) { + static const char *test[] = { + "\\u0000", + "\\uFFFE", "\\uFFFF", + "\\U0001FFFE", "\\U0001FFFF", + "\\U0002FFFE", "\\U0002FFFF", + "\\U0003FFFE", "\\U0003FFFF", + "\\U0004FFFE", "\\U0004FFFF", + "\\U0005FFFE", "\\U0005FFFF", + "\\U0006FFFE", "\\U0006FFFF", + "\\U0007FFFE", "\\U0007FFFF", + "\\U0008FFFE", "\\U0008FFFF", + "\\U0009FFFE", "\\U0009FFFF", + "\\U000AFFFE", "\\U000AFFFF", + "\\U000BFFFE", "\\U000BFFFF", + "\\U000CFFFE", "\\U000CFFFF", + "\\U000DFFFE", "\\U000DFFFF", + "\\U000EFFFE", "\\U000EFFFF", + "\\U000FFFFE", "\\U000FFFFF", + "\\U0010FFFE", "\\U0010FFFF" + }; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("en_US", &status); + + log_verbose("Test non characters\n"); + + if(U_SUCCESS(status)) { + genericOrderingTestWithResult(coll, test, 35, UCOL_EQUAL); + } else { + log_err("Unable to open collator\n"); + } + + ucol_close(coll); +} + +static void TestExtremeCompression(void) { + static char *test[4]; + int32_t j = 0, i = 0; + + for(i = 0; i<4; i++) { + test[i] = (char *)malloc(2048*sizeof(char)); + } + + for(j = 20; j < 500; j++) { + for(i = 0; i<4; i++) { + uprv_memset(test[i], 'a', (j-1)*sizeof(char)); + test[i][j-1] = (char)('a'+i); + test[i][j] = 0; + } + genericLocaleStarter("en_US", (const char **)test, 4); + } + + + for(i = 0; i<4; i++) { + free(test[i]); + } +} + +#if 0 +static void TestExtremeCompression(void) { + static char *test[4]; + int32_t j = 0, i = 0; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("en_US", status); + for(i = 0; i<4; i++) { + test[i] = (char *)malloc(2048*sizeof(char)); + } + for(j = 10; j < 2048; j++) { + for(i = 0; i<4; i++) { + uprv_memset(test[i], 'a', (j-2)*sizeof(char)); + test[i][j-1] = (char)('a'+i); + test[i][j] = 0; + } + } + genericLocaleStarter("en_US", (const char **)test, 4); + + for(j = 10; j < 2048; j++) { + for(i = 0; i<1; i++) { + uprv_memset(test[i], 'a', (j-1)*sizeof(char)); + test[i][j] = 0; + } + } + for(i = 0; i<4; i++) { + free(test[i]); + } +} +#endif + +static void TestSurrogates(void) { + static const char *test[] = { + "z","\\ud900\\udc25", "\\ud805\\udc50", + "\\ud800\\udc00y", "\\ud800\\udc00r", + "\\ud800\\udc00f", "\\ud800\\udc00", + "\\ud800\\udc00c", "\\ud800\\udc00b", + "\\ud800\\udc00fa", "\\ud800\\udc00fb", + "\\ud800\\udc00a", + "c", "b" + }; + + static const char *rule = + "&z < \\ud900\\udc25 < \\ud805\\udc50" + "< \\ud800\\udc00y < \\ud800\\udc00r" + "< \\ud800\\udc00f << \\ud800\\udc00" + "< \\ud800\\udc00fa << \\ud800\\udc00fb" + "< \\ud800\\udc00a < c < b" ; + + genericRulesStarter(rule, test, 14); +} + +/* This is a test for prefix implementation, used by JIS X 4061 collation rules */ +static void TestPrefix(void) { + uint32_t i; + + static const struct { + const char *rules; + const char *data[50]; + const uint32_t len; + } tests[] = { + { "&z <<< z|a", + {"zz", "za"}, 2 }, + + { "&z <<< z| a", + {"zz", "za"}, 2 }, + { "[strength I]" + "&a=\\ud900\\udc25" + "&z<<<\\ud900\\udc25|a", + {"aa", "az", "\\ud900\\udc25z", "\\ud900\\udc25a", "zz"}, 4 }, + }; + + + for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) { + genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len); + } +} + +/* This test uses data suplied by Masashiko Maedera to test the implementation */ +/* JIS X 4061 collation order implementation */ +static void TestNewJapanese(void) { + + static const char * const test1[] = { + "\\u30b7\\u30e3\\u30fc\\u30ec", + "\\u30b7\\u30e3\\u30a4", + "\\u30b7\\u30e4\\u30a3", + "\\u30b7\\u30e3\\u30ec", + "\\u3061\\u3087\\u3053", + "\\u3061\\u3088\\u3053", + "\\u30c1\\u30e7\\u30b3\\u30ec\\u30fc\\u30c8", + "\\u3066\\u30fc\\u305f", + "\\u30c6\\u30fc\\u30bf", + "\\u30c6\\u30a7\\u30bf", + "\\u3066\\u3048\\u305f", + "\\u3067\\u30fc\\u305f", + "\\u30c7\\u30fc\\u30bf", + "\\u30c7\\u30a7\\u30bf", + "\\u3067\\u3048\\u305f", + "\\u3066\\u30fc\\u305f\\u30fc", + "\\u30c6\\u30fc\\u30bf\\u30a1", + "\\u30c6\\u30a7\\u30bf\\u30fc", + "\\u3066\\u3047\\u305f\\u3041", + "\\u3066\\u3048\\u305f\\u30fc", + "\\u3067\\u30fc\\u305f\\u30fc", + "\\u30c7\\u30fc\\u30bf\\u30a1", + "\\u3067\\u30a7\\u305f\\u30a1", + "\\u30c7\\u3047\\u30bf\\u3041", + "\\u30c7\\u30a8\\u30bf\\u30a2", + "\\u3072\\u3086", + "\\u3073\\u3085\\u3042", + "\\u3074\\u3085\\u3042", + "\\u3073\\u3085\\u3042\\u30fc", + "\\u30d3\\u30e5\\u30a2\\u30fc", + "\\u3074\\u3085\\u3042\\u30fc", + "\\u30d4\\u30e5\\u30a2\\u30fc", + "\\u30d2\\u30e5\\u30a6", + "\\u30d2\\u30e6\\u30a6", + "\\u30d4\\u30e5\\u30a6\\u30a2", + "\\u3073\\u3085\\u30fc\\u3042\\u30fc", + "\\u30d3\\u30e5\\u30fc\\u30a2\\u30fc", + "\\u30d3\\u30e5\\u30a6\\u30a2\\u30fc", + "\\u3072\\u3085\\u3093", + "\\u3074\\u3085\\u3093", + "\\u3075\\u30fc\\u308a", + "\\u30d5\\u30fc\\u30ea", + "\\u3075\\u3045\\u308a", + "\\u3075\\u30a5\\u308a", + "\\u3075\\u30a5\\u30ea", + "\\u30d5\\u30a6\\u30ea", + "\\u3076\\u30fc\\u308a", + "\\u30d6\\u30fc\\u30ea", + "\\u3076\\u3045\\u308a", + "\\u30d6\\u30a5\\u308a", + "\\u3077\\u3046\\u308a", + "\\u30d7\\u30a6\\u30ea", + "\\u3075\\u30fc\\u308a\\u30fc", + "\\u30d5\\u30a5\\u30ea\\u30fc", + "\\u3075\\u30a5\\u308a\\u30a3", + "\\u30d5\\u3045\\u308a\\u3043", + "\\u30d5\\u30a6\\u30ea\\u30fc", + "\\u3075\\u3046\\u308a\\u3043", + "\\u30d6\\u30a6\\u30ea\\u30a4", + "\\u3077\\u30fc\\u308a\\u30fc", + "\\u3077\\u30a5\\u308a\\u30a4", + "\\u3077\\u3046\\u308a\\u30fc", + "\\u30d7\\u30a6\\u30ea\\u30a4", + "\\u30d5\\u30fd", + "\\u3075\\u309e", + "\\u3076\\u309d", + "\\u3076\\u3075", + "\\u3076\\u30d5", + "\\u30d6\\u3075", + "\\u30d6\\u30d5", + "\\u3076\\u309e", + "\\u3076\\u3077", + "\\u30d6\\u3077", + "\\u3077\\u309d", + "\\u30d7\\u30fd", + "\\u3077\\u3075", +}; + + static const char *test2[] = { + "\\u306f\\u309d", /* H\\u309d */ + "\\u30cf\\u30fd", /* K\\u30fd */ + "\\u306f\\u306f", /* HH */ + "\\u306f\\u30cf", /* HK */ + "\\u30cf\\u30cf", /* KK */ + "\\u306f\\u309e", /* H\\u309e */ + "\\u30cf\\u30fe", /* K\\u30fe */ + "\\u306f\\u3070", /* HH\\u309b */ + "\\u30cf\\u30d0", /* KK\\u309b */ + "\\u306f\\u3071", /* HH\\u309c */ + "\\u30cf\\u3071", /* KH\\u309c */ + "\\u30cf\\u30d1", /* KK\\u309c */ + "\\u3070\\u309d", /* H\\u309b\\u309d */ + "\\u30d0\\u30fd", /* K\\u309b\\u30fd */ + "\\u3070\\u306f", /* H\\u309bH */ + "\\u30d0\\u30cf", /* K\\u309bK */ + "\\u3070\\u309e", /* H\\u309b\\u309e */ + "\\u30d0\\u30fe", /* K\\u309b\\u30fe */ + "\\u3070\\u3070", /* H\\u309bH\\u309b */ + "\\u30d0\\u3070", /* K\\u309bH\\u309b */ + "\\u30d0\\u30d0", /* K\\u309bK\\u309b */ + "\\u3070\\u3071", /* H\\u309bH\\u309c */ + "\\u30d0\\u30d1", /* K\\u309bK\\u309c */ + "\\u3071\\u309d", /* H\\u309c\\u309d */ + "\\u30d1\\u30fd", /* K\\u309c\\u30fd */ + "\\u3071\\u306f", /* H\\u309cH */ + "\\u30d1\\u30cf", /* K\\u309cK */ + "\\u3071\\u3070", /* H\\u309cH\\u309b */ + "\\u3071\\u30d0", /* H\\u309cK\\u309b */ + "\\u30d1\\u30d0", /* K\\u309cK\\u309b */ + "\\u3071\\u3071", /* H\\u309cH\\u309c */ + "\\u30d1\\u30d1", /* K\\u309cK\\u309c */ + }; + /* + static const char *test3[] = { + "\\u221er\\u221e", + "\\u221eR#", + "\\u221et\\u221e", + "#r\\u221e", + "#R#", + "#t%", + "#T%", + "8t\\u221e", + "8T\\u221e", + "8t#", + "8T#", + "8t%", + "8T%", + "8t8", + "8T8", + "\\u03c9r\\u221e", + "\\u03a9R%", + "rr\\u221e", + "rR\\u221e", + "Rr\\u221e", + "RR\\u221e", + "RT%", + "rt8", + "tr\\u221e", + "tr8", + "TR8", + "tt8", + "\\u30b7\\u30e3\\u30fc\\u30ec", + }; + */ + static const UColAttribute att[] = { UCOL_STRENGTH }; + static const UColAttributeValue val[] = { UCOL_QUATERNARY }; + + static const UColAttribute attShifted[] = { UCOL_STRENGTH, UCOL_ALTERNATE_HANDLING}; + static const UColAttributeValue valShifted[] = { UCOL_QUATERNARY, UCOL_SHIFTED }; + + genericLocaleStarterWithOptions("ja", test1, sizeof(test1)/sizeof(test1[0]), att, val, 1); + genericLocaleStarterWithOptions("ja", test2, sizeof(test2)/sizeof(test2[0]), att, val, 1); + /*genericLocaleStarter("ja", test3, sizeof(test3)/sizeof(test3[0]));*/ + genericLocaleStarterWithOptions("ja", test1, sizeof(test1)/sizeof(test1[0]), attShifted, valShifted, 2); + genericLocaleStarterWithOptions("ja", test2, sizeof(test2)/sizeof(test2[0]), attShifted, valShifted, 2); +} + +static void TestStrCollIdenticalPrefix(void) { + const char* rule = "&\\ud9b0\\udc70=\\ud9b0\\udc71"; + const char* test[] = { + "ab\\ud9b0\\udc70", + "ab\\ud9b0\\udc71" + }; + genericRulesStarterWithResult(rule, test, sizeof(test)/sizeof(test[0]), UCOL_EQUAL); +} +/* Contractions should have all their canonically equivalent */ +/* strings included */ +static void TestContractionClosure(void) { + static const struct { + const char *rules; + const char *data[10]; + const uint32_t len; + } tests[] = { + { "&b=\\u00e4\\u00e4", + { "b", "\\u00e4\\u00e4", "a\\u0308a\\u0308", "\\u00e4a\\u0308", "a\\u0308\\u00e4" }, 5}, + { "&b=\\u00C5", + { "b", "\\u00C5", "A\\u030A", "\\u212B" }, 4}, + }; + uint32_t i; + + + for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) { + genericRulesStarterWithResult(tests[i].rules, tests[i].data, tests[i].len, UCOL_EQUAL); + } +} + +/* This tests also fails*/ +static void TestBeforePrefixFailure(void) { + static const struct { + const char *rules; + const char *data[10]; + const uint32_t len; + } tests[] = { + { "&g <<< a" + "&[before 3]\\uff41 <<< x", + {"x", "\\uff41"}, 2 }, + { "&\\u30A7=\\u30A7=\\u3047=\\uff6a" + "&\\u30A8=\\u30A8=\\u3048=\\uff74" + "&[before 3]\\u30a7<<<\\u30a9", + {"\\u30a9", "\\u30a7"}, 2 }, + { "&[before 3]\\u30a7<<<\\u30a9" + "&\\u30A7=\\u30A7=\\u3047=\\uff6a" + "&\\u30A8=\\u30A8=\\u3048=\\uff74", + {"\\u30a9", "\\u30a7"}, 2 }, + }; + uint32_t i; + + + for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) { + genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len); + } + +#if 0 + const char* rule1 = + "&\\u30A7=\\u30A7=\\u3047=\\uff6a" + "&\\u30A8=\\u30A8=\\u3048=\\uff74" + "&[before 3]\\u30a7<<<\\u30c6|\\u30fc"; + const char* rule2 = + "&[before 3]\\u30a7<<<\\u30c6|\\u30fc" + "&\\u30A7=\\u30A7=\\u3047=\\uff6a" + "&\\u30A8=\\u30A8=\\u3048=\\uff74"; + const char* test[] = { + "\\u30c6\\u30fc\\u30bf", + "\\u30c6\\u30a7\\u30bf", + }; + genericRulesStarter(rule1, test, sizeof(test)/sizeof(test[0])); + genericRulesStarter(rule2, test, sizeof(test)/sizeof(test[0])); +/* this piece of code should be in some sort of verbose mode */ +/* it gets the collation elements for elements and prints them */ +/* This is useful when trying to see whether the problem is */ + { + UErrorCode status = U_ZERO_ERROR; + uint32_t i = 0; + UCollationElements *it = NULL; + uint32_t CE; + UChar string[256]; + uint32_t uStringLen; + UCollator *coll = NULL; + + uStringLen = u_unescape(rule1, string, 256); + + coll = ucol_openRules(string, uStringLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + + /*coll = ucol_open("ja_JP_JIS", &status);*/ + it = ucol_openElements(coll, string, 0, &status); + + for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) { + log_verbose("%s\n", test[i]); + uStringLen = u_unescape(test[i], string, 256); + ucol_setText(it, string, uStringLen, &status); + + while((CE=ucol_next(it, &status)) != UCOL_NULLORDER) { + log_verbose("%08X\n", CE); + } + log_verbose("\n"); + + } + + ucol_closeElements(it); + ucol_close(coll); + } +#endif +} + +static void TestPrefixCompose(void) { + const char* rule1 = + "&\\u30a7<<<\\u30ab|\\u30fc=\\u30ac|\\u30fc"; + /* + const char* test[] = { + "\\u30c6\\u30fc\\u30bf", + "\\u30c6\\u30a7\\u30bf", + }; + */ + { + UErrorCode status = U_ZERO_ERROR; + /*uint32_t i = 0;*/ + /*UCollationElements *it = NULL;*/ +/* uint32_t CE;*/ + UChar string[256]; + uint32_t uStringLen; + UCollator *coll = NULL; + + uStringLen = u_unescape(rule1, string, 256); + + coll = ucol_openRules(string, uStringLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + ucol_close(coll); + } + + +} + +/* +[last variable] last variable value +[last primary ignorable] largest CE for primary ignorable +[last secondary ignorable] largest CE for secondary ignorable +[last tertiary ignorable] largest CE for tertiary ignorable +[top] guaranteed to be above all implicit CEs, for now and in the future (in 1.8) +*/ + +static void TestRuleOptions(void) { + /* values here are hardcoded and are correct for the current UCA + * when the UCA changes, one might be forced to change these + * values. (\\u02d0, \\U00010FFFC etc...) + */ + static const struct { + const char *rules; + const char *data[10]; + const uint32_t len; + } tests[] = { + /* - all befores here amount to zero */ + { "&[before 3][first tertiary ignorable]<<<a", + { "\\u0000", "a"}, 2 + }, /* you cannot go before first tertiary ignorable */ + + { "&[before 3][last tertiary ignorable]<<<a", + { "\\u0000", "a"}, 2 + }, /* you cannot go before last tertiary ignorable */ + + { "&[before 3][first secondary ignorable]<<<a", + { "\\u0000", "a"}, 2 + }, /* you cannot go before first secondary ignorable */ + + { "&[before 3][last secondary ignorable]<<<a", + { "\\u0000", "a"}, 2 + }, /* you cannot go before first secondary ignorable */ + + /* 'normal' befores */ + + { "&[before 3][first primary ignorable]<<<c<<<b &[first primary ignorable]<a", + { "c", "b", "\\u0332", "a" }, 4 + }, + + /* we don't have a code point that corresponds to + * the last primary ignorable + */ + { "&[before 3][last primary ignorable]<<<c<<<b &[last primary ignorable]<a", + { "\\u0332", "\\u20e3", "c", "b", "a" }, 5 + }, + + { "&[before 3][first variable]<<<c<<<b &[first variable]<a", + { "c", "b", "\\u0009", "a", "\\u000a" }, 5 + }, + + { "&[last variable]<a &[before 3][last variable]<<<c<<<b ", + { "c", "b", "\\uD834\\uDF71", "a", "\\u02d0" }, 5 + }, + + { "&[first regular]<a" + "&[before 1][first regular]<b", + { "b", "\\u02d0", "a", "\\u02d1"}, 4 + }, + + { "&[before 1][last regular]<b" + "&[last regular]<a", + { "b", "\\uD808\\uDF6E", "a", "\\u4e00" }, 4 + }, + + { "&[before 1][first implicit]<b" + "&[first implicit]<a", + { "b", "\\u4e00", "a", "\\u4e01"}, 4 + }, + + { "&[before 1][last implicit]<b" + "&[last implicit]<a", + { "b", "\\U0010FFFD", "a" }, 3 + }, + + { "&[last variable]<z" + "&[last primary ignorable]<x" + "&[last secondary ignorable]<<y" + "&[last tertiary ignorable]<<<w" + "&[top]<u", + {"\\ufffb", "w", "y", "\\u20e3", "x", "\\u137c", "z", "u"}, 7 + } + + }; + uint32_t i; + + + for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) { + genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len); + } +} + + +static void TestOptimize(void) { + /* this is not really a test - just trying out + * whether copying of UCA contents will fail + * Cannot really test, since the functionality + * remains the same. + */ + static const struct { + const char *rules; + const char *data[10]; + const uint32_t len; + } tests[] = { + /* - all befores here amount to zero */ + { "[optimize [\\uAC00-\\uD7FF]]", + { "a", "b"}, 2} + }; + uint32_t i; + + for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) { + genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len); + } +} + +/* +cycheng@ca.ibm.c... we got inconsistent results when using the UTF-16BE iterator and the UTF-8 iterator. +weiv ucol_strcollIter? +cycheng@ca.ibm.c... e.g. s1 = 0xfffc0062, and s2 = d8000021 +weiv these are the input strings? +cycheng@ca.ibm.c... yes, using the utf-16 iterator and UCA with normalization on, we have s1 > s2 +weiv will check - could be a problem with utf-8 iterator +cycheng@ca.ibm.c... but if we use the utf-8 iterator, i.e. s1 = efbfbc62 and s2 = eda08021, we have s1 < s2 +weiv hmmm +cycheng@ca.ibm.c... note that we have a standalone high surrogate +weiv that doesn't sound right +cycheng@ca.ibm.c... we got the same inconsistent results on AIX and Win2000 +weiv so you have two strings, you convert them to utf-8 and to utf-16BE +cycheng@ca.ibm.c... yes +weiv and then do the comparison +cycheng@ca.ibm.c... in one case, the input strings are in utf8, and in the other case the input strings are in utf-16be +weiv utf-16 strings look like a little endian ones in the example you sent me +weiv It could be a bug - let me try to test it out +cycheng@ca.ibm.c... ok +cycheng@ca.ibm.c... we can wait till the conf. call +cycheng@ca.ibm.c... next weke +weiv that would be great +weiv hmmm +weiv I might be wrong +weiv let me play with it some more +cycheng@ca.ibm.c... ok +cycheng@ca.ibm.c... also please check s3 = 0x0e3a0062 and s4 = 0x0e400021. both are in utf-16be +cycheng@ca.ibm.c... seems with icu 2.2 we have s3 > s4, but not in icu 2.4 that's built for db2 +cycheng@ca.ibm.c... also s1 & s2 that I sent you earlier are also in utf-16be +weiv ok +cycheng@ca.ibm.c... i ask sherman to send you more inconsistent data +weiv thanks +cycheng@ca.ibm.c... the 4 strings we sent are just samples +*/ +#if 0 +static void Alexis(void) { + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("", &status); + + + const char utf16be[2][4] = { + { (char)0xd8, (char)0x00, (char)0x00, (char)0x21 }, + { (char)0xff, (char)0xfc, (char)0x00, (char)0x62 } + }; + + const char utf8[2][4] = { + { (char)0xed, (char)0xa0, (char)0x80, (char)0x21 }, + { (char)0xef, (char)0xbf, (char)0xbc, (char)0x62 }, + }; + + UCharIterator iterU161, iterU162; + UCharIterator iterU81, iterU82; + + UCollationResult resU16, resU8; + + uiter_setUTF16BE(&iterU161, utf16be[0], 4); + uiter_setUTF16BE(&iterU162, utf16be[1], 4); + + uiter_setUTF8(&iterU81, utf8[0], 4); + uiter_setUTF8(&iterU82, utf8[1], 4); + + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + + resU16 = ucol_strcollIter(coll, &iterU161, &iterU162, &status); + resU8 = ucol_strcollIter(coll, &iterU81, &iterU82, &status); + + + if(resU16 != resU8) { + log_err("different results\n"); + } + + ucol_close(coll); +} +#endif + +#define CMSCOLL_ALEXIS2_BUFFER_SIZE 256 +static void Alexis2(void) { + UErrorCode status = U_ZERO_ERROR; + UChar U16Source[CMSCOLL_ALEXIS2_BUFFER_SIZE], U16Target[CMSCOLL_ALEXIS2_BUFFER_SIZE]; + char U16BESource[CMSCOLL_ALEXIS2_BUFFER_SIZE], U16BETarget[CMSCOLL_ALEXIS2_BUFFER_SIZE]; + char U8Source[CMSCOLL_ALEXIS2_BUFFER_SIZE], U8Target[CMSCOLL_ALEXIS2_BUFFER_SIZE]; + int32_t U16LenS = 0, U16LenT = 0, U16BELenS = 0, U16BELenT = 0, U8LenS = 0, U8LenT = 0; + + UConverter *conv = NULL; + + UCharIterator U16BEItS, U16BEItT; + UCharIterator U8ItS, U8ItT; + + UCollationResult resU16, resU16BE, resU8; + + static const char* const pairs[][2] = { + { "\\ud800\\u0021", "\\uFFFC\\u0062"}, + { "\\u0435\\u0308\\u0334", "\\u0415\\u0334\\u0340" }, + { "\\u0E40\\u0021", "\\u00A1\\u0021"}, + { "\\u0E40\\u0021", "\\uFE57\\u0062"}, + { "\\u5F20", "\\u5F20\\u4E00\\u8E3F"}, + { "\\u0000\\u0020", "\\u0000\\u0020\\u0000"}, + { "\\u0020", "\\u0020\\u0000"} +/* +5F20 (my result here) +5F204E008E3F +5F20 (your result here) +*/ + }; + + int32_t i = 0; + + UCollator *coll = ucol_open("", &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + conv = ucnv_open("UTF16BE", &status); + for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) { + U16LenS = u_unescape(pairs[i][0], U16Source, CMSCOLL_ALEXIS2_BUFFER_SIZE); + U16LenT = u_unescape(pairs[i][1], U16Target, CMSCOLL_ALEXIS2_BUFFER_SIZE); + + resU16 = ucol_strcoll(coll, U16Source, U16LenS, U16Target, U16LenT); + + log_verbose("Result of strcoll is %i\n", resU16); + + U16BELenS = ucnv_fromUChars(conv, U16BESource, CMSCOLL_ALEXIS2_BUFFER_SIZE, U16Source, U16LenS, &status); + U16BELenT = ucnv_fromUChars(conv, U16BETarget, CMSCOLL_ALEXIS2_BUFFER_SIZE, U16Target, U16LenT, &status); + + /* use the original sizes, as the result from converter is in bytes */ + uiter_setUTF16BE(&U16BEItS, U16BESource, U16LenS); + uiter_setUTF16BE(&U16BEItT, U16BETarget, U16LenT); + + resU16BE = ucol_strcollIter(coll, &U16BEItS, &U16BEItT, &status); + + log_verbose("Result of U16BE is %i\n", resU16BE); + + if(resU16 != resU16BE) { + log_verbose("Different results between UTF16 and UTF16BE for %s & %s\n", pairs[i][0], pairs[i][1]); + } + + u_strToUTF8(U8Source, CMSCOLL_ALEXIS2_BUFFER_SIZE, &U8LenS, U16Source, U16LenS, &status); + u_strToUTF8(U8Target, CMSCOLL_ALEXIS2_BUFFER_SIZE, &U8LenT, U16Target, U16LenT, &status); + + uiter_setUTF8(&U8ItS, U8Source, U8LenS); + uiter_setUTF8(&U8ItT, U8Target, U8LenT); + + resU8 = ucol_strcollIter(coll, &U8ItS, &U8ItT, &status); + + if(resU16 != resU8) { + log_verbose("Different results between UTF16 and UTF8 for %s & %s\n", pairs[i][0], pairs[i][1]); + } + + } + + ucol_close(coll); + ucnv_close(conv); +} + +static void TestHebrewUCA(void) { + UErrorCode status = U_ZERO_ERROR; + static const char *first[] = { + "d790d6b8d79cd795d6bcd7a9", + "d790d79cd79ed7a7d799d799d7a1", + "d790d6b4d79ed795d6bcd7a9", + }; + + char utf8String[3][256]; + UChar utf16String[3][256]; + + int32_t i = 0, j = 0; + int32_t sizeUTF8[3]; + int32_t sizeUTF16[3]; + + UCollator *coll = ucol_open("", &status); + /*ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);*/ + + for(i = 0; i < sizeof(first)/sizeof(first[0]); i++) { + sizeUTF8[i] = u_parseUTF8(first[i], -1, utf8String[i], 256, &status); + u_strFromUTF8(utf16String[i], 256, &sizeUTF16[i], utf8String[i], sizeUTF8[i], &status); + log_verbose("%i: "); + for(j = 0; j < sizeUTF16[i]; j++) { + /*log_verbose("\\u%04X", utf16String[i][j]);*/ + log_verbose("%04X", utf16String[i][j]); + } + log_verbose("\n"); + } + for(i = 0; i < sizeof(first)/sizeof(first[0])-1; i++) { + for(j = i + 1; j < sizeof(first)/sizeof(first[0]); j++) { + doTest(coll, utf16String[i], utf16String[j], UCOL_LESS); + } + } + + ucol_close(coll); + +} + +static void TestPartialSortKeyTermination(void) { + static const char* cases[] = { + "\\u1234\\u1234\\udc00", + "\\udc00\\ud800\\ud800" + }; + + int32_t i = sizeof(UCollator); + + UErrorCode status = U_ZERO_ERROR; + + UCollator *coll = ucol_open("", &status); + + UCharIterator iter; + + UChar currCase[256]; + int32_t length = 0; + int32_t pKeyLen = 0; + + uint8_t key[256]; + + for(i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) { + uint32_t state[2] = {0, 0}; + length = u_unescape(cases[i], currCase, 256); + uiter_setString(&iter, currCase, length); + pKeyLen = ucol_nextSortKeyPart(coll, &iter, state, key, 256, &status); + + log_verbose("Done\n"); + + } + ucol_close(coll); +} + +static void TestSettings(void) { + static const char* cases[] = { + "apple", + "Apple" + }; + + static const char* locales[] = { + "", + "en" + }; + + UErrorCode status = U_ZERO_ERROR; + + int32_t i = 0, j = 0; + + UChar source[256], target[256]; + int32_t sLen = 0, tLen = 0; + + UCollator *collateObject = NULL; + for(i = 0; i < sizeof(locales)/sizeof(locales[0]); i++) { + collateObject = ucol_open(locales[i], &status); + ucol_setStrength(collateObject, UCOL_PRIMARY); + ucol_setAttribute(collateObject, UCOL_CASE_LEVEL , UCOL_OFF, &status); + for(j = 1; j < sizeof(cases)/sizeof(cases[0]); j++) { + sLen = u_unescape(cases[j-1], source, 256); + source[sLen] = 0; + tLen = u_unescape(cases[j], target, 256); + source[tLen] = 0; + doTest(collateObject, source, target, UCOL_EQUAL); + } + ucol_close(collateObject); + } +} + +static int32_t TestEqualsForCollator(const char* locName, UCollator *source, UCollator *target) { + UErrorCode status = U_ZERO_ERROR; + int32_t errorNo = 0; + /*const UChar *sourceRules = NULL;*/ + /*int32_t sourceRulesLen = 0;*/ + UColAttributeValue french = UCOL_OFF; + int32_t cloneSize = 0; + + if(!ucol_equals(source, target)) { + log_err("Same collators, different address not equal\n"); + errorNo++; + } + ucol_close(target); + if(uprv_strcmp(ucol_getLocale(source, ULOC_REQUESTED_LOCALE, &status), ucol_getLocale(source, ULOC_ACTUAL_LOCALE, &status)) == 0) { + /* currently, safeClone is implemented through getRules/openRules + * so it is the same as the test below - I will comment that test out. + */ + /* real thing */ + target = ucol_safeClone(source, NULL, &cloneSize, &status); + if(U_FAILURE(status)) { + log_err("Error creating clone\n"); + errorNo++; + return errorNo; + } + if(!ucol_equals(source, target)) { + log_err("Collator different from it's clone\n"); + errorNo++; + } + french = ucol_getAttribute(source, UCOL_FRENCH_COLLATION, &status); + if(french == UCOL_ON) { + ucol_setAttribute(target, UCOL_FRENCH_COLLATION, UCOL_OFF, &status); + } else { + ucol_setAttribute(target, UCOL_FRENCH_COLLATION, UCOL_ON, &status); + } + if(U_FAILURE(status)) { + log_err("Error setting attributes\n"); + errorNo++; + return errorNo; + } + if(ucol_equals(source, target)) { + log_err("Collators same even when options changed\n"); + errorNo++; + } + ucol_close(target); + /* commented out since safeClone uses exactly the same technique */ + /* + sourceRules = ucol_getRules(source, &sourceRulesLen); + target = ucol_openRules(sourceRules, sourceRulesLen, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status); + if(U_FAILURE(status)) { + log_err("Error instantiating target from rules\n"); + errorNo++; + return errorNo; + } + if(!ucol_equals(source, target)) { + log_err("Collator different from collator that was created from the same rules\n"); + errorNo++; + } + ucol_close(target); + */ + } + return errorNo; +} + + +static void TestEquals(void) { + /* ucol_equals is not currently a public API. There is a chance that it will become + * something like this, but currently it is only used by RuleBasedCollator::operator== + */ + /* test whether the two collators instantiated from the same locale are equal */ + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + int32_t noOfLoc = uloc_countAvailable(); + const char *locName = NULL; + UCollator *source = NULL, *target = NULL; + int32_t i = 0; + + const char* rules[] = { + "&l < lj <<< Lj <<< LJ", + "&n < nj <<< Nj <<< NJ", + "&ae <<< \\u00e4", + "&AE <<< \\u00c4" + }; + /* + const char* badRules[] = { + "&l <<< Lj", + "&n < nj <<< nJ <<< NJ", + "&a <<< \\u00e4", + "&AE <<< \\u00c4 <<< x" + }; + */ + + UChar sourceRules[1024], targetRules[1024]; + int32_t sourceRulesSize = 0, targetRulesSize = 0; + int32_t rulesSize = sizeof(rules)/sizeof(rules[0]); + + for(i = 0; i < rulesSize; i++) { + sourceRulesSize += u_unescape(rules[i], sourceRules+sourceRulesSize, 1024 - sourceRulesSize); + targetRulesSize += u_unescape(rules[rulesSize-i-1], targetRules+targetRulesSize, 1024 - targetRulesSize); + } + + source = ucol_openRules(sourceRules, sourceRulesSize, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + target = ucol_openRules(targetRules, targetRulesSize, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status); + if(!ucol_equals(source, target)) { + log_err("Equivalent collators not equal!\n"); + } + ucol_close(source); + ucol_close(target); + + source = ucol_open("root", &status); + target = ucol_open("root", &status); + log_verbose("Testing root\n"); + if(!ucol_equals(source, source)) { + log_err("Same collator not equal\n"); + } + if(TestEqualsForCollator(locName, source, target)) { + log_err("Errors for root\n", locName); + } + ucol_close(source); + + for(i = 0; i<noOfLoc; i++) { + status = U_ZERO_ERROR; + locName = uloc_getAvailable(i); + /*if(hasCollationElements(locName)) {*/ + log_verbose("Testing equality for locale %s\n", locName); + source = ucol_open(locName, &status); + target = ucol_open(locName, &status); + if(TestEqualsForCollator(locName, source, target)) { + log_err("Errors for locale %s\n", locName); + } + ucol_close(source); + /*}*/ + } +} + +static void TestJ2726(void) { + UChar a[2] = { 0x61, 0x00 }; /*"a"*/ + UChar aSpace[3] = { 0x61, 0x20, 0x00 }; /*"a "*/ + UChar spaceA[3] = { 0x20, 0x61, 0x00 }; /*" a"*/ + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("en", &status); + ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status); + doTest(coll, a, aSpace, UCOL_EQUAL); + doTest(coll, aSpace, a, UCOL_EQUAL); + doTest(coll, a, spaceA, UCOL_EQUAL); + doTest(coll, spaceA, a, UCOL_EQUAL); + doTest(coll, spaceA, aSpace, UCOL_EQUAL); + doTest(coll, aSpace, spaceA, UCOL_EQUAL); + ucol_close(coll); +} + +static void NullRule(void) { + UChar r[3] = {0}; + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_openRules(r, 1, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + if(U_SUCCESS(status)) { + log_err("This should have been an error!\n"); + ucol_close(coll); + } else { + status = U_ZERO_ERROR; + } + coll = ucol_openRules(r, 0, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status); + if(U_FAILURE(status)) { + log_err("Empty rules should have produced a valid collator\n"); + } else { + ucol_close(coll); + } +} + +/** + * Test for CollationElementIterator previous and next for the whole set of + * unicode characters with normalization on. + */ +static void TestNumericCollation(void) +{ + UErrorCode status = U_ZERO_ERROR; + + const static char *basicTestStrings[]={ + "hello1", + "hello2", + "hello2002", + "hello2003", + "hello123456", + "hello1234567", + "hello10000000", + "hello100000000", + "hello1000000000", + "hello10000000000", + }; + + const static char *preZeroTestStrings[]={ + "avery10000", + "avery010000", + "avery0010000", + "avery00010000", + "avery000010000", + "avery0000010000", + "avery00000010000", + "avery000000010000", + }; + + const static char *thirtyTwoBitNumericStrings[]={ + "avery42949672960", + "avery42949672961", + "avery42949672962", + "avery429496729610" + }; + + const static char *supplementaryDigits[] = { + "\\uD835\\uDFCE", /* 0 */ + "\\uD835\\uDFCF", /* 1 */ + "\\uD835\\uDFD0", /* 2 */ + "\\uD835\\uDFD1", /* 3 */ + "\\uD835\\uDFCF\\uD835\\uDFCE", /* 10 */ + "\\uD835\\uDFCF\\uD835\\uDFCF", /* 11 */ + "\\uD835\\uDFCF\\uD835\\uDFD0", /* 12 */ + "\\uD835\\uDFD0\\uD835\\uDFCE", /* 20 */ + "\\uD835\\uDFD0\\uD835\\uDFCF", /* 21 */ + "\\uD835\\uDFD0\\uD835\\uDFD0" /* 22 */ + }; + + const static char *foreignDigits[] = { + "\\u0661", + "\\u0662", + "\\u0663", + "\\u0661\\u0660", + "\\u0661\\u0662", + "\\u0661\\u0663", + "\\u0662\\u0660", + "\\u0662\\u0662", + "\\u0662\\u0663", + "\\u0663\\u0660", + "\\u0663\\u0662", + "\\u0663\\u0663" + }; + + const static char *evenZeroes[] = { + "2000", + "2001", + "2002", + "2003" + }; + + UColAttribute att = UCOL_NUMERIC_COLLATION; + UColAttributeValue val = UCOL_ON; + + /* Open our collator. */ + UCollator* coll = ucol_open("root", &status); + if (U_FAILURE(status)){ + log_err("ERROR: in using ucol_open()\n %s\n", + myErrorName(status)); + return; + } + genericLocaleStarterWithOptions("root", basicTestStrings, sizeof(basicTestStrings)/sizeof(basicTestStrings[0]), &att, &val, 1); + genericLocaleStarterWithOptions("root", thirtyTwoBitNumericStrings, sizeof(thirtyTwoBitNumericStrings)/sizeof(thirtyTwoBitNumericStrings[0]), &att, &val, 1); + genericLocaleStarterWithOptions("en_US", foreignDigits, sizeof(foreignDigits)/sizeof(foreignDigits[0]), &att, &val, 1); + genericLocaleStarterWithOptions("root", supplementaryDigits, sizeof(supplementaryDigits)/sizeof(supplementaryDigits[0]), &att, &val, 1); + genericLocaleStarterWithOptions("root", evenZeroes, sizeof(evenZeroes)/sizeof(evenZeroes[0]), &att, &val, 1); + + /* Setting up our collator to do digits. */ + ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status); + if (U_FAILURE(status)){ + log_err("ERROR: in setting UCOL_NUMERIC_COLLATION as an attribute\n %s\n", + myErrorName(status)); + return; + } + + /* + Testing that prepended zeroes still yield the correct collation behavior. + We expect that every element in our strings array will be equal. + */ + genericOrderingTestWithResult(coll, preZeroTestStrings, sizeof(preZeroTestStrings)/sizeof(preZeroTestStrings[0]), UCOL_EQUAL); + + ucol_close(coll); +} + +static void TestTibetanConformance(void) +{ + const char* test[] = { + "\\u0FB2\\u0591\\u0F71\\u0061", + "\\u0FB2\\u0F71\\u0061" + }; + + UErrorCode status = U_ZERO_ERROR; + UCollator *coll = ucol_open("", &status); + UChar source[100]; + UChar target[100]; + int result; + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + if (U_SUCCESS(status)) { + u_unescape(test[0], source, 100); + u_unescape(test[1], target, 100); + doTest(coll, source, target, UCOL_EQUAL); + result = ucol_strcoll(coll, source, -1, target, -1); + log_verbose("result %d\n", result); + if (UCOL_EQUAL != result) { + log_err("Tibetan comparison error\n"); + } + } + ucol_close(coll); + + genericLocaleStarterWithResult("", test, 2, UCOL_EQUAL); +} + +static void TestPinyinProblem(void) { + static const char *test[] = { "\\u4E56\\u4E56\\u7761", "\\u4E56\\u5B69\\u5B50" }; + genericLocaleStarter("zh__PINYIN", test, sizeof(test)/sizeof(test[0])); +} + +#define TST_UCOL_MAX_INPUT 0x220001 +#define topByte 0xFF000000; +#define bottomByte 0xFF; +#define fourBytes 0xFFFFFFFF; + + +static void showImplicit(UChar32 i) { + if (i >= 0 && i <= TST_UCOL_MAX_INPUT) { + log_verbose("%08X\t%08X\n", i, uprv_uca_getImplicitFromRaw(i)); + } +} + +static void TestImplicitGeneration(void) { + UErrorCode status = U_ZERO_ERROR; + UChar32 last = 0; + UChar32 current; + UChar32 i = 0, j = 0; + UChar32 roundtrip = 0; + UChar32 lastBottom = 0; + UChar32 currentBottom = 0; + UChar32 lastTop = 0; + UChar32 currentTop = 0; + + UCollator *coll = ucol_open("root", &status); + if(U_FAILURE(status)) { + log_err("Couldn't open UCA\n"); + return; + } + + uprv_uca_getRawFromImplicit(0xE20303E7); + + for (i = 0; i <= TST_UCOL_MAX_INPUT; ++i) { + current = uprv_uca_getImplicitFromRaw(i) & fourBytes; + + /* check that it round-trips AND that all intervening ones are illegal*/ + roundtrip = uprv_uca_getRawFromImplicit(current); + if (roundtrip != i) { + log_err("No roundtrip %08X\n", i); + } + if (last != 0) { + for (j = last + 1; j < current; ++j) { + roundtrip = uprv_uca_getRawFromImplicit(j); + /* raise an error if it *doesn't* find an error*/ + if (roundtrip != -1) { + log_err("Fails to recognize illegal %08X\n", j); + } + } + } + /* now do other consistency checks*/ + lastBottom = last & bottomByte; + currentBottom = current & bottomByte; + lastTop = last & topByte; + currentTop = current & topByte; + + /* print out some values for spot-checking*/ + if (lastTop != currentTop || i == 0x10000 || i == 0x110000) { + showImplicit(i-3); + showImplicit(i-2); + showImplicit(i-1); + showImplicit(i); + showImplicit(i+1); + showImplicit(i+2); + } + last = current; + + if(uprv_uca_getCodePointFromRaw(uprv_uca_getRawFromCodePoint(i)) != i) { + log_err("No raw <-> code point roundtrip for 0x%08X\n", i); + } + } + showImplicit(TST_UCOL_MAX_INPUT-2); + showImplicit(TST_UCOL_MAX_INPUT-1); + showImplicit(TST_UCOL_MAX_INPUT); + ucol_close(coll); +} + +/** + * Iterate through the given iterator, checking to see that all the strings + * in the expected array are present. + * @param expected array of strings we expect to see, or NULL + * @param expectedCount number of elements of expected, or 0 + */ +static int32_t checkUEnumeration(const char* msg, + UEnumeration* iter, + const char** expected, + int32_t expectedCount) { + UErrorCode ec = U_ZERO_ERROR; + int32_t i = 0, n, j, bit; + int32_t seenMask = 0; + + U_ASSERT(expectedCount >= 0 && expectedCount < 31); /* [sic] 31 not 32 */ + n = uenum_count(iter, &ec); + if (!assertSuccess("count", &ec)) return -1; + log_verbose("%s = [", msg); + for (;; ++i) { + const char* s = uenum_next(iter, NULL, &ec); + if (!assertSuccess("snext", &ec) || s == NULL) break; + if (i != 0) log_verbose(","); + log_verbose("%s", s); + /* check expected list */ + for (j=0, bit=1; j<expectedCount; ++j, bit<<=1) { + if ((seenMask&bit) == 0 && + uprv_strcmp(s, expected[j]) == 0) { + seenMask |= bit; + break; + } + } + } + log_verbose("] (%d)\n", i); + assertTrue("count verified", i==n); + /* did we see all expected strings? */ + for (j=0, bit=1; j<expectedCount; ++j, bit<<=1) { + if ((seenMask&bit)!=0) { + log_verbose("Ok: \"%s\" seen\n", expected[j]); + } else { + log_err("FAIL: \"%s\" not seen\n", expected[j]); + } + } + return n; +} + +/** + * Test new API added for separate collation tree. + */ +static void TestSeparateTrees(void) { + UErrorCode ec = U_ZERO_ERROR; + UEnumeration *e = NULL; + int32_t n = -1; + UBool isAvailable; + char loc[256]; + + static const char* AVAIL[] = { "en", "de" }; + + static const char* KW[] = { "collation" }; + + static const char* KWVAL[] = { "phonebook", "stroke" }; + +#if !UCONFIG_NO_SERVICE + e = ucol_openAvailableLocales(&ec); + assertSuccess("ucol_openAvailableLocales", &ec); + assertTrue("ucol_openAvailableLocales!=0", e!=0); + n = checkUEnumeration("ucol_openAvailableLocales", e, AVAIL, LEN(AVAIL)); + /* Don't need to check n because we check list */ + uenum_close(e); +#endif + + e = ucol_getKeywords(&ec); + assertSuccess("ucol_getKeywords", &ec); + assertTrue("ucol_getKeywords!=0", e!=0); + n = checkUEnumeration("ucol_getKeywords", e, KW, LEN(KW)); + /* Don't need to check n because we check list */ + uenum_close(e); + + e = ucol_getKeywordValues(KW[0], &ec); + assertSuccess("ucol_getKeywordValues", &ec); + assertTrue("ucol_getKeywordValues!=0", e!=0); + n = checkUEnumeration("ucol_getKeywordValues", e, KWVAL, LEN(KWVAL)); + /* Don't need to check n because we check list */ + uenum_close(e); + + /* Try setting a warning before calling ucol_getKeywordValues */ + ec = U_USING_FALLBACK_WARNING; + e = ucol_getKeywordValues(KW[0], &ec); + assertSuccess("ucol_getKeywordValues [with warning code set]", &ec); + assertTrue("ucol_getKeywordValues!=0 [with warning code set]", e!=0); + n = checkUEnumeration("ucol_getKeywordValues [with warning code set]", e, KWVAL, LEN(KWVAL)); + /* Don't need to check n because we check list */ + uenum_close(e); + + /* +U_DRAFT int32_t U_EXPORT2 +ucol_getFunctionalEquivalent(char* result, int32_t resultCapacity, + const char* locale, UBool* isAvailable, + UErrorCode* status); +} +*/ + n = ucol_getFunctionalEquivalent(loc, sizeof(loc), "collation", "fr", + &isAvailable, &ec); + assertSuccess("getFunctionalEquivalent", &ec); + assertEquals("getFunctionalEquivalent(fr)", "fr", loc); + assertTrue("getFunctionalEquivalent(fr).isAvailable==TRUE", + isAvailable == TRUE); + + n = ucol_getFunctionalEquivalent(loc, sizeof(loc), "collation", "fr_FR", + &isAvailable, &ec); + assertSuccess("getFunctionalEquivalent", &ec); + assertEquals("getFunctionalEquivalent(fr_FR)", "fr", loc); + assertTrue("getFunctionalEquivalent(fr_FR).isAvailable==TRUE", + isAvailable == TRUE); +} + +/* supercedes TestJ784 */ +static void TestBeforePinyin(void) { + const static char rules[] = { + "&[before 2]A<<\\u0101<<<\\u0100<<\\u00E1<<<\\u00C1<<\\u01CE<<<\\u01CD<<\\u00E0<<<\\u00C0" + "&[before 2]e<<\\u0113<<<\\u0112<<\\u00E9<<<\\u00C9<<\\u011B<<<\\u011A<<\\u00E8<<<\\u00C8" + "&[before 2]i<<\\u012B<<<\\u012A<<\\u00ED<<<\\u00CD<<\\u01D0<<<\\u01CF<<\\u00EC<<<\\u00CC" + "&[before 2]o<<\\u014D<<<\\u014C<<\\u00F3<<<\\u00D3<<\\u01D2<<<\\u01D1<<\\u00F2<<<\\u00D2" + "&[before 2]u<<\\u016B<<<\\u016A<<\\u00FA<<<\\u00DA<<\\u01D4<<<\\u01D3<<\\u00F9<<<\\u00D9" + "&U<<\\u01D6<<<\\u01D5<<\\u01D8<<<\\u01D7<<\\u01DA<<<\\u01D9<<\\u01DC<<<\\u01DB<<\\u00FC" + }; + + const static char *test[] = { + "l\\u0101", + "la", + "l\\u0101n", + "lan ", + "l\\u0113", + "le", + "l\\u0113n", + "len" + }; + + const static char *test2[] = { + "x\\u0101", + "x\\u0100", + "X\\u0101", + "X\\u0100", + "x\\u00E1", + "x\\u00C1", + "X\\u00E1", + "X\\u00C1", + "x\\u01CE", + "x\\u01CD", + "X\\u01CE", + "X\\u01CD", + "x\\u00E0", + "x\\u00C0", + "X\\u00E0", + "X\\u00C0", + "xa", + "xA", + "Xa", + "XA", + "x\\u0101x", + "x\\u0100x", + "x\\u00E1x", + "x\\u00C1x", + "x\\u01CEx", + "x\\u01CDx", + "x\\u00E0x", + "x\\u00C0x", + "xax", + "xAx" + }; + + genericRulesStarter(rules, test, sizeof(test)/sizeof(test[0])); + genericLocaleStarter("zh", test, sizeof(test)/sizeof(test[0])); + genericRulesStarter(rules, test2, sizeof(test2)/sizeof(test2[0])); + genericLocaleStarter("zh", test2, sizeof(test2)/sizeof(test2[0])); +} + +static void TestBeforeTightening(void) { + static const struct { + const char *rules; + UErrorCode expectedStatus; + } tests[] = { + { "&[before 1]a<x", U_ZERO_ERROR }, + { "&[before 1]a<<x", U_INVALID_FORMAT_ERROR }, + { "&[before 1]a<<<x", U_INVALID_FORMAT_ERROR }, + { "&[before 1]a=x", U_INVALID_FORMAT_ERROR }, + { "&[before 2]a<x",U_INVALID_FORMAT_ERROR }, + { "&[before 2]a<<x",U_ZERO_ERROR }, + { "&[before 2]a<<<x",U_INVALID_FORMAT_ERROR }, + { "&[before 2]a=x",U_INVALID_FORMAT_ERROR }, + { "&[before 3]a<x",U_INVALID_FORMAT_ERROR }, + { "&[before 3]a<<x",U_INVALID_FORMAT_ERROR }, + { "&[before 3]a<<<x",U_ZERO_ERROR }, + { "&[before 3]a=x",U_INVALID_FORMAT_ERROR }, + { "&[before I]a = x",U_INVALID_FORMAT_ERROR } + }; + + int32_t i = 0; + + UErrorCode status = U_ZERO_ERROR; + UChar rlz[RULE_BUFFER_LEN] = { 0 }; + uint32_t rlen = 0; + + UCollator *coll = NULL; + + + for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + rlen = u_unescape(tests[i].rules, rlz, RULE_BUFFER_LEN); + coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status); + if(status != tests[i].expectedStatus) { + log_err("Opening a collator with rules %s returned error code %s, expected %s\n", + tests[i].rules, u_errorName(status), u_errorName(tests[i].expectedStatus)); + } + ucol_close(coll); + status = U_ZERO_ERROR; + } + +} + +#if 0 +&m < a +&[before 1] a < x <<< X << q <<< Q < z +assert: m <<< M < x <<< X << q <<< Q < z < a < n + +&m < a +&[before 2] a << x <<< X << q <<< Q < z +assert: m <<< M < x <<< X << q <<< Q << a < z < n + +&m < a +&[before 3] a <<< x <<< X << q <<< Q < z +assert: m <<< M < x <<< X <<< a << q <<< Q < z < n + + +&m << a +&[before 1] a < x <<< X << q <<< Q < z +assert: x <<< X << q <<< Q < z < m <<< M << a < n + +&m << a +&[before 2] a << x <<< X << q <<< Q < z +assert: m <<< M << x <<< X << q <<< Q << a < z < n + +&m << a +&[before 3] a <<< x <<< X << q <<< Q < z +assert: m <<< M << x <<< X <<< a << q <<< Q < z < n + + +&m <<< a +&[before 1] a < x <<< X << q <<< Q < z +assert: x <<< X << q <<< Q < z < n < m <<< a <<< M + +&m <<< a +&[before 2] a << x <<< X << q <<< Q < z +assert: x <<< X << q <<< Q << m <<< a <<< M < z < n + +&m <<< a +&[before 3] a <<< x <<< X << q <<< Q < z +assert: m <<< x <<< X <<< a <<< M << q <<< Q < z < n + + +&[before 1] s < x <<< X << q <<< Q < z +assert: r <<< R < x <<< X << q <<< Q < z < s < n + +&[before 2] s << x <<< X << q <<< Q < z +assert: r <<< R < x <<< X << q <<< Q << s < z < n + +&[before 3] s <<< x <<< X << q <<< Q < z +assert: r <<< R < x <<< X <<< s << q <<< Q < z < n + + +&[before 1] \u24DC < x <<< X << q <<< Q < z +assert: x <<< X << q <<< Q < z < n < m <<< \u24DC <<< M + +&[before 2] \u24DC << x <<< X << q <<< Q < z +assert: x <<< X << q <<< Q << m <<< \u24DC <<< M < z < n + +&[before 3] \u24DC <<< x <<< X << q <<< Q < z +assert: m <<< x <<< X <<< \u24DC <<< M << q <<< Q < z < n +#endif + + +#if 0 +/* requires features not yet supported */ +static void TestMoreBefore(void) { + static const struct { + const char* rules; + const char* order[16]; + int32_t size; + } tests[] = { + { "&m < a &[before 1] a < x <<< X << q <<< Q < z", + { "m","M","x","X","q","Q","z","a","n" }, 9}, + { "&m < a &[before 2] a << x <<< X << q <<< Q < z", + { "m","M","x","X","q","Q","a","z","n" }, 9}, + { "&m < a &[before 3] a <<< x <<< X << q <<< Q < z", + { "m","M","x","X","a","q","Q","z","n" }, 9}, + { "&m << a &[before 1] a < x <<< X << q <<< Q < z", + { "x","X","q","Q","z","m","M","a","n" }, 9}, + { "&m << a &[before 2] a << x <<< X << q <<< Q < z", + { "m","M","x","X","q","Q","a","z","n" }, 9}, + { "&m << a &[before 3] a <<< x <<< X << q <<< Q < z", + { "m","M","x","X","a","q","Q","z","n" }, 9}, + { "&m <<< a &[before 1] a < x <<< X << q <<< Q < z", + { "x","X","q","Q","z","n","m","a","M" }, 9}, + { "&m <<< a &[before 2] a << x <<< X << q <<< Q < z", + { "x","X","q","Q","m","a","M","z","n" }, 9}, + { "&m <<< a &[before 3] a <<< x <<< X << q <<< Q < z", + { "m","x","X","a","M","q","Q","z","n" }, 9}, + { "&[before 1] s < x <<< X << q <<< Q < z", + { "r","R","x","X","q","Q","z","s","n" }, 9}, + { "&[before 2] s << x <<< X << q <<< Q < z", + { "r","R","x","X","q","Q","s","z","n" }, 9}, + { "&[before 3] s <<< x <<< X << q <<< Q < z", + { "r","R","x","X","s","q","Q","z","n" }, 9}, + { "&[before 1] \\u24DC < x <<< X << q <<< Q < z", + { "x","X","q","Q","z","n","m","\\u24DC","M" }, 9}, + { "&[before 2] \\u24DC << x <<< X << q <<< Q < z", + { "x","X","q","Q","m","\\u24DC","M","z","n" }, 9}, + { "&[before 3] \\u24DC <<< x <<< X << q <<< Q < z", + { "m","x","X","\\u24DC","M","q","Q","z","n" }, 9} + }; + + int32_t i = 0; + + for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + genericRulesStarter(tests[i].rules, tests[i].order, tests[i].size); + } +} +#endif + +static void TestTailorNULL( void ) { + const static char* rule = "&a <<< '\\u0000'"; + UErrorCode status = U_ZERO_ERROR; + UChar rlz[RULE_BUFFER_LEN] = { 0 }; + uint32_t rlen = 0; + UChar a = 1, null = 0; + UCollationResult res = UCOL_EQUAL; + + UCollator *coll = NULL; + + + rlen = u_unescape(rule, rlz, RULE_BUFFER_LEN); + coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status); + + if(U_FAILURE(status)) { + log_err("Could not open default collator!\n"); + } else { + res = ucol_strcoll(coll, &a, 1, &null, 1); + + if(res != UCOL_LESS) { + log_err("NULL was not tailored properly!\n"); + } + } + + ucol_close(coll); +} + +static void +TestThaiSortKey(void) +{ + UChar yamakan = 0x0E4E; + UErrorCode status = U_ZERO_ERROR; + uint8_t key[256]; + int32_t keyLen = 0; + /* NOTE: there is a Thai tailoring that moves Yammakan. It should not move it, */ + /* since it stays in the same relative position. This should be addressed in CLDR */ + /* UCA 4.0 uint8_t expectedKey[256] = { 0x01, 0xd9, 0xb2, 0x01, 0x05, 0x00 }; */ + /* UCA 4.1 uint8_t expectedKey[256] = { 0x01, 0xdb, 0x3a, 0x01, 0x05, 0x00 }; */ + /* UCA 5.0 moves Yammakan */ + uint8_t expectedKey[256] = { 0x01, 0xdc, 0xce, 0x01, 0x05, 0x00 }; + UCollator *coll = ucol_open("th", &status); + if(U_FAILURE(status)) { + log_err("Could not open a collator, exiting (%s)\n", u_errorName(status)); + return; + } + + keyLen = ucol_getSortKey(coll, &yamakan, 1, key, 256); + if(strcmp((char *)key, (char *)expectedKey)) { + log_err("Yammakan key is different from ICU 34!\n"); + } + + ucol_close(coll); +} + +static void +TestUpperFirstQuaternary(void) +{ + const char* tests[] = { "B", "b", "Bb", "bB" }; + UColAttribute att[] = { UCOL_STRENGTH, UCOL_CASE_FIRST }; + UColAttributeValue attVals[] = { UCOL_QUATERNARY, UCOL_UPPER_FIRST }; + genericLocaleStarterWithOptions("root", tests, sizeof(tests)/sizeof(tests[0]), att, attVals, sizeof(att)/sizeof(att[0])); +} + +static void +TestJ4960(void) +{ + const char* tests[] = { "\\u00e2T", "aT" }; + UColAttribute att[] = { UCOL_STRENGTH, UCOL_CASE_LEVEL }; + UColAttributeValue attVals[] = { UCOL_PRIMARY, UCOL_ON }; + const char* tests2[] = { "a", "A" }; + const char* rule = "&[first tertiary ignorable]=A=a"; + UColAttribute att2[] = { UCOL_CASE_LEVEL }; + UColAttributeValue attVals2[] = { UCOL_ON }; + /* Test whether we correctly ignore primary ignorables on case level when */ + /* we have only primary & case level */ + genericLocaleStarterWithOptionsAndResult("root", tests, sizeof(tests)/sizeof(tests[0]), att, attVals, sizeof(att)/sizeof(att[0]), UCOL_EQUAL); + /* Test whether ICU4J will make case level for sortkeys that have primary strength */ + /* and case level */ + genericLocaleStarterWithOptions("root", tests2, sizeof(tests2)/sizeof(tests2[0]), att, attVals, sizeof(att)/sizeof(att[0])); + /* Test whether completely ignorable letters have case level info (they shouldn't) */ + genericRulesStarterWithOptionsAndResult(rule, tests2, sizeof(tests2)/sizeof(tests2[0]), att2, attVals2, sizeof(att2)/sizeof(att2[0]), UCOL_EQUAL); +} + +static void +TestJ5223(void) +{ + static const char *test = "this is a test string"; + UChar ustr[256]; + int32_t ustr_length = u_unescape(test, ustr, 256); + unsigned char sortkey[256]; + int32_t sortkey_length; + UErrorCode status = U_ZERO_ERROR; + static UCollator *coll = NULL; + coll = ucol_open("root", &status); + if(U_FAILURE(status)) { + log_err("Couldn't open UCA\n"); + return; + } + ucol_setStrength(coll, UCOL_PRIMARY); + ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status); + ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + if (U_FAILURE(status)) { + log_err("Failed setting atributes\n"); + return; + } + sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, NULL, 0); + if (sortkey_length > 256) return; + + /* we mark the position where the null byte should be written in advance */ + sortkey[sortkey_length-1] = 0xAA; + + /* we set the buffer size one byte higher than needed */ + sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, sortkey, + sortkey_length+1); + + /* no error occurs (for me) */ + if (sortkey[sortkey_length-1] == 0xAA) { + log_err("Hit bug at first try\n"); + } + + /* we mark the position where the null byte should be written again */ + sortkey[sortkey_length-1] = 0xAA; + + /* this time we set the buffer size to the exact amount needed */ + sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, sortkey, + sortkey_length); + + /* now the trailing null byte is not written */ + if (sortkey[sortkey_length-1] == 0xAA) { + log_err("Hit bug at second try\n"); + } + + ucol_close(coll); +} + +/* Regression test for Thai partial sort key problem */ +static void +TestJ5232(void) +{ + const static char *test[] = { + "\\u0e40\\u0e01\\u0e47\\u0e1a\\u0e40\\u0e25\\u0e47\\u0e21", + "\\u0e40\\u0e01\\u0e47\\u0e1a\\u0e40\\u0e25\\u0e48\\u0e21" + }; + + genericLocaleStarter("th", test, sizeof(test)/sizeof(test[0])); +} + +static void +TestJ5367(void) +{ + const static char *test[] = { "a", "y" }; + const char* rules = "&Ny << Y &[first secondary ignorable] <<< a"; + genericRulesStarter(rules, test, sizeof(test)/sizeof(test[0])); +} + +static void +TestVI5913(void) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t i, j; + UCollator *coll =NULL; + uint8_t resColl[100], expColl[100]; + int32_t rLen, tLen, ruleLen, sLen, kLen; + UChar rule[256]={0x26, 0x62, 0x3c, 0x1FF3, 0}; /* &a<0x1FF3-omega with Ypogegrammeni*/ + UChar rule2[256]={0x26, 0x7a, 0x3c, 0x0161, 0}; /* &z<s with caron*/ + UChar rule3[256]={0x26, 0x7a, 0x3c, 0x0061, 0x00ea, 0}; /* &z<a+e with circumflex.*/ + UChar tData[][20]={ + {0x1EAC, 0}, + {0x0041, 0x0323, 0x0302, 0}, + {0x1EA0, 0x0302, 0}, + {0x00C2, 0x0323, 0}, + {0x1ED8, 0}, /* O with dot and circumflex */ + {0x1ECC, 0x0302, 0}, + {0x1EB7, 0}, + {0x1EA1, 0x0306, 0}, + }; + UChar tailorData[][20]={ + {0x1FA2, 0}, /* Omega with 3 combining marks */ + {0x03C9, 0x0313, 0x0300, 0x0345, 0}, + {0x1FF3, 0x0313, 0x0300, 0}, + {0x1F60, 0x0300, 0x0345, 0}, + {0x1F62, 0x0345, 0}, + {0x1FA0, 0x0300, 0}, + }; + UChar tailorData2[][20]={ + {0x1E63, 0x030C, 0}, /* s with dot below + caron */ + {0x0073, 0x0323, 0x030C, 0}, + {0x0073, 0x030C, 0x0323, 0}, + }; + UChar tailorData3[][20]={ + {0x007a, 0}, /* z */ + {0x0061, 0x0065, 0}, /* a + e */ + {0x0061, 0x00ea, 0}, /* a + e with circumflex */ + {0x0061, 0x1EC7, 0}, /* a+ e with dot below and circumflex */ + {0x0061, 0x1EB9, 0x0302, 0}, /* a + e with dot below + combining circumflex */ + {0x0061, 0x00EA, 0x0323, 0}, /* a + e with circumflex + combining dot below */ + {0x00EA, 0x0323, 0}, /* e with circumflex + combining dot below */ + {0x00EA, 0}, /* e with circumflex */ + }; + + /* Test Vietnamese sort. */ + coll = ucol_open("vi", &status); + log_verbose("\n\nVI collation:"); + if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[2], u_strlen(tData[2])) ) { + log_err("\\u1EAC not equals to \\u1EA0+\\u0302\n"); + } + if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[3], u_strlen(tData[3])) ) { + log_err("\\u1EAC not equals to \\u00c2+\\u0323\n"); + } + if ( !ucol_equal(coll, tData[5], u_strlen(tData[5]), tData[4], u_strlen(tData[4])) ) { + log_err("\\u1ED8 not equals to \\u1ECC+\\u0302\n"); + } + if ( !ucol_equal(coll, tData[7], u_strlen(tData[7]), tData[6], u_strlen(tData[6])) ) { + log_err("\\u1EB7 not equals to \\u1EA1+\\u0306\n"); + } + + for (j=0; j<8; j++) { + tLen = u_strlen(tData[j]); + log_verbose("\n Data :%s \tlen: %d key: ", tData[j], tLen); + rLen = ucol_getSortKey(coll, tData[j], tLen, resColl, 100); + for(i = 0; i<rLen; i++) { + log_verbose(" %02X", resColl[i]); + } + } + + ucol_close(coll); + + /* Test Russian sort. */ + coll = ucol_open("ro", &status); + log_verbose("\n\nRO collation:"); + if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[1], u_strlen(tData[1])) ) { + log_err("\\u1EAC not equals to \\u1EA0+\\u0302\n"); + } + if ( !ucol_equal(coll, tData[4], u_strlen(tData[4]), tData[5], u_strlen(tData[5])) ) { + log_err("\\u1EAC not equals to \\u00c2+\\u0323\n"); + } + if ( !ucol_equal(coll, tData[6], u_strlen(tData[6]), tData[7], u_strlen(tData[7])) ) { + log_err("\\u1EB7 not equals to \\u1EA1+\\u0306\n"); + } + + for (j=4; j<8; j++) { + tLen = u_strlen(tData[j]); + log_verbose("\n Data :%s \tlen: %d key: ", tData[j], tLen); + rLen = ucol_getSortKey(coll, tData[j], tLen, resColl, 100); + for(i = 0; i<rLen; i++) { + log_verbose(" %02X", resColl[i]); + } + } + ucol_close(coll); + + /* Test the precomposed Greek character with 3 combining marks. */ + log_verbose("\n\nTailoring test: Greek character with 3 combining marks"); + ruleLen = u_strlen(rule); + coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + sLen = u_strlen(tailorData[0]); + for (j=1; j<6; j++) { + tLen = u_strlen(tailorData[j]); + if ( !ucol_equal(coll, tailorData[0], sLen, tailorData[j], tLen)) { + log_err("\n \\u1FA2 not equals to data[%d]:%s\n", j, tailorData[j]); + } + } + /* Test getSortKey. */ + tLen = u_strlen(tailorData[0]); + kLen=ucol_getSortKey(coll, tailorData[0], tLen, expColl, 100); + for (j=0; j<6; j++) { + tLen = u_strlen(tailorData[j]); + rLen = ucol_getSortKey(coll, tailorData[j], tLen, resColl, 100); + if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) { + log_err("\n Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen); + for(i = 0; i<rLen; i++) { + log_err(" %02X", resColl[i]); + } + } + } + ucol_close(coll); + + log_verbose("\n\nTailoring test for s with caron:"); + ruleLen = u_strlen(rule2); + coll = ucol_openRules(rule2, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + tLen = u_strlen(tailorData2[0]); + kLen=ucol_getSortKey(coll, tailorData2[0], tLen, expColl, 100); + for (j=1; j<3; j++) { + tLen = u_strlen(tailorData2[j]); + rLen = ucol_getSortKey(coll, tailorData2[j], tLen, resColl, 100); + if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) { + log_err("\n After tailoring Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen); + for(i = 0; i<rLen; i++) { + log_err(" %02X", resColl[i]); + } + } + } + ucol_close(coll); + + log_verbose("\n\nTailoring test for &z< ae with circumflex:"); + ruleLen = u_strlen(rule3); + coll = ucol_openRules(rule3, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status); + tLen = u_strlen(tailorData3[3]); + kLen=ucol_getSortKey(coll, tailorData3[3], tLen, expColl, 100); + for (j=4; j<6; j++) { + tLen = u_strlen(tailorData3[j]); + rLen = ucol_getSortKey(coll, tailorData3[j], tLen, resColl, 100); + + if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) { + log_err("\n After tailoring Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen); + for(i = 0; i<rLen; i++) { + log_err(" %02X", resColl[i]); + } + } + + log_verbose("\n Test Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen); + for(i = 0; i<rLen; i++) { + log_verbose(" %02X", resColl[i]); + } + } + ucol_close(coll); +} + +#define TSKC_DATA_SIZE 5 +#define TSKC_BUF_SIZE 50 +static void +TestSortKeyConsistency(void) +{ + UErrorCode icuRC = U_ZERO_ERROR; + UCollator* ucol; + UChar data[] = { 0xFFFD, 0x0006, 0x0006, 0x0006, 0xFFFD}; + + uint8_t bufFull[TSKC_DATA_SIZE][TSKC_BUF_SIZE]; + uint8_t bufPart[TSKC_DATA_SIZE][TSKC_BUF_SIZE]; + int32_t i, j, i2; + + ucol = ucol_openFromShortString("LEN_S4", FALSE, NULL, &icuRC); + if (U_FAILURE(icuRC)) + { + log_err("ucol_openFromShortString failed\n"); + return; + } + + for (i = 0; i < TSKC_DATA_SIZE; i++) + { + UCharIterator uiter; + uint32_t state[2] = { 0, 0 }; + int32_t dataLen = i+1; + for (j=0; j<TSKC_BUF_SIZE; j++) + bufFull[i][j] = bufPart[i][j] = 0; + + /* Full sort key */ + ucol_getSortKey(ucol, data, dataLen, bufFull[i], TSKC_BUF_SIZE); + + /* Partial sort key */ + uiter_setString(&uiter, data, dataLen); + ucol_nextSortKeyPart(ucol, &uiter, state, bufPart[i], TSKC_BUF_SIZE, &icuRC); + if (U_FAILURE(icuRC)) + { + log_err("ucol_nextSortKeyPart failed\n"); + ucol_close(ucol); + return; + } + + for (i2=0; i2<i; i2++) + { + UBool fullMatch = TRUE; + UBool partMatch = TRUE; + for (j=0; j<TSKC_BUF_SIZE; j++) + { + fullMatch = fullMatch && (bufFull[i][j] != bufFull[i2][j]); + partMatch = partMatch && (bufPart[i][j] != bufPart[i2][j]); + } + if (fullMatch != partMatch) { + log_err(fullMatch ? "full key was consistent, but partial key changed\n" + : "partial key was consistent, but full key changed\n"); + ucol_close(ucol); + return; + } + } + + } + + /*=============================================*/ + ucol_close(ucol); +} + + +#define TEST(x) addTest(root, &x, "tscoll/cmsccoll/" # x) + +void addMiscCollTest(TestNode** root) +{ + TEST(TestRuleOptions); + TEST(TestBeforePrefixFailure); + TEST(TestContractionClosure); + TEST(TestPrefixCompose); + TEST(TestStrCollIdenticalPrefix); + TEST(TestPrefix); + TEST(TestNewJapanese); + /*TEST(TestLimitations);*/ + TEST(TestNonChars); + TEST(TestExtremeCompression); + TEST(TestSurrogates); + TEST(TestVariableTopSetting); + TEST(TestBocsuCoverage); + TEST(TestCyrillicTailoring); + TEST(TestCase); + TEST(IncompleteCntTest); + TEST(BlackBirdTest); + TEST(FunkyATest); + TEST(BillFairmanTest); + TEST(RamsRulesTest); + TEST(IsTailoredTest); + TEST(TestCollations); + TEST(TestChMove); + TEST(TestImplicitTailoring); + TEST(TestFCDProblem); + TEST(TestEmptyRule); + /*TEST(TestJ784);*/ /* 'zh' locale has changed - now it is getting tested by TestBeforePinyin */ + TEST(TestJ815); + /*TEST(TestJ831);*/ /* we changed lv locale */ + TEST(TestBefore); + TEST(TestRedundantRules); + TEST(TestExpansionSyntax); + TEST(TestHangulTailoring); + TEST(TestUCARules); + TEST(TestIncrementalNormalize); + TEST(TestComposeDecompose); + TEST(TestCompressOverlap); + TEST(TestContraction); + TEST(TestExpansion); + /*TEST(PrintMarkDavis);*/ /* this test doesn't test - just prints sortkeys */ + /*TEST(TestGetCaseBit);*/ /*this one requires internal things to be exported */ + TEST(TestOptimize); + TEST(TestSuppressContractions); + TEST(Alexis2); + TEST(TestHebrewUCA); + TEST(TestPartialSortKeyTermination); + TEST(TestSettings); + TEST(TestEquals); + TEST(TestJ2726); + TEST(NullRule); + TEST(TestNumericCollation); + TEST(TestTibetanConformance); + TEST(TestPinyinProblem); + TEST(TestImplicitGeneration); + TEST(TestSeparateTrees); + TEST(TestBeforePinyin); + TEST(TestBeforeTightening); + /*TEST(TestMoreBefore);*/ + TEST(TestTailorNULL); + TEST(TestThaiSortKey); + TEST(TestUpperFirstQuaternary); + TEST(TestJ4960); + TEST(TestJ5223); + TEST(TestJ5232); + TEST(TestJ5367); + TEST(TestSortKeyConsistency); + TEST(TestVI5913); /* VI, RO tailored rules */ +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c new file mode 100644 index 00000000000..96e01877029 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c @@ -0,0 +1,1093 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CMSGTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* C API TEST FOR MESSAGE FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "unicode/uloc.h" +#include "unicode/umsg.h" +#include "unicode/udat.h" +#include "unicode/umsg.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cmsgtst.h" +#include "cformtst.h" + +static const char* const txt_testCasePatterns[] = { + "Quotes '', '{', a {0,number,integer} '{'0}", + "Quotes '', '{', a {0,number,integer} '{'0}", + "You deposited {0,number,integer} times an amount of {1,number,currency} on {2,date,short}", + "'{'2,time,full}, for {1, number }, {0,number,integer} is {2,time,full} and full date is {2,date,full}", + "'{'1,number,percent} for {0,number,integer} is {1,number,percent}", +}; + +static const char* const txt_testResultStrings[] = { + "Quotes ', {, a 1 {0}", + "Quotes ', {, a 1 {0}", + "You deposited 1 times an amount of $3,456.00 on 1/12/70", + "{2,time,full}, for 3,456, 1 is 5:46:40 AM PT and full date is Monday, January 12, 1970", + "{1,number,percent} for 1 is 345,600%" +}; + +const int32_t cnt_testCases = 5; +static UChar* testCasePatterns[5]; + +static UChar* testResultStrings[5]; + +static UBool strings_initialized = FALSE; + +/* function used to create the test patterns for testing Message formatting */ +static void InitStrings( void ) +{ + int32_t i; + if (strings_initialized) + return; + + for (i=0; i < cnt_testCases; i++ ) { + uint32_t strSize = (uint32_t)strlen(txt_testCasePatterns[i]) + 1; + testCasePatterns[i]=(UChar*)malloc(sizeof(UChar) * strSize); + u_uastrncpy(testCasePatterns[i], txt_testCasePatterns[i], strSize); + } + for (i=0; i < cnt_testCases; i++ ) { + uint32_t strSize = (uint32_t)strlen(txt_testResultStrings[i]) + 1; + testResultStrings[i] = (UChar*)malloc(sizeof(UChar) * strSize); + u_uastrncpy(testResultStrings[i], txt_testResultStrings[i], strSize); + } + + strings_initialized = TRUE; +} + +static void FreeStrings( void ) +{ + int32_t i; + if (!strings_initialized) + return; + + for (i=0; i < cnt_testCases; i++ ) { + free(testCasePatterns[i]); + } + for (i=0; i < cnt_testCases; i++ ) { + free(testResultStrings[i]); + } + strings_initialized = FALSE; +} + +/* Platform dependent test to detect if this type will return NULL when interpreted as a pointer. */ +static UBool returnsNullForType(int firstParam, ...) { + UBool isNULL; + va_list marker; + va_start(marker, firstParam); + isNULL = (UBool)(va_arg(marker, void*) == NULL); + va_end(marker); + return isNULL; +} + +/* Test u_formatMessage() with various test patterns() */ +static void MessageFormatTest( void ) +{ + UChar *str; + UChar* result; + int32_t resultLengthOut,resultlength,i, patternlength; + UErrorCode status = U_ZERO_ERROR; + UDate d1=1000000000.0; + + ctest_setTimeZone(NULL, &status); + + str=(UChar*)malloc(sizeof(UChar) * 7); + u_uastrncpy(str, "MyDisk", 7); + resultlength=1; + result=(UChar*)malloc(sizeof(UChar) * 1); + log_verbose("Testing u_formatMessage()\n"); + InitStrings(); + for (i = 0; i < cnt_testCases; i++) { + status=U_ZERO_ERROR; + patternlength=u_strlen(testCasePatterns[i]); + resultLengthOut=u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &status, 1, 3456.00, d1); + if(status== U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result,sizeof(UChar) * resultlength); + u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &status, 1, 3456.00, d1); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) ); + } + if(u_strcmp(result, testResultStrings[i])==0){ + log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); + } + else{ + log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, + austrdup(result), austrdup(testResultStrings[i]) ); + } + } + free(result); + result = NULL; + free(str); + { + + for (i = 0; i < cnt_testCases; i++) { + UParseError parseError; + status=U_ZERO_ERROR; + patternlength=u_strlen(testCasePatterns[i]); + resultlength=0; + resultLengthOut=u_formatMessageWithError( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &parseError,&status, 1, 3456.00, d1); + if(status== U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &status, 1, 3456.00, d1); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) ); + continue; + } + if(u_strcmp(result, testResultStrings[i])==0){ + log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); + } + else{ + log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, + austrdup(result), austrdup(testResultStrings[i]) ); + } + free(result); + result=NULL; + } + } + { + UErrorCode ec = U_ZERO_ERROR; + int32_t patternLength = u_strlen(testCasePatterns[0]); + + UMessageFormat formatter = umsg_open(testCasePatterns[0],patternLength,"en_US",NULL,&ec); + + if(U_FAILURE(ec)){ + log_err("umsg_open() failed for testCasePattens[%d].\n",i); + return; + } + for(i = 0;i<cnt_testCases; i++){ + UParseError parseError; + int32_t resultLength =0,count=0; + int32_t one=0; + int32_t two=0; + UDate d2=0; + + result=NULL; + patternLength = u_strlen(testCasePatterns[i]); + + umsg_applyPattern(formatter,testCasePatterns[i],patternLength,&parseError,&ec); + if(U_FAILURE(ec)){ + log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i); + return; + } + /* pre-flight */ + resultLength = umsg_format(formatter,result,resultLength,&ec,1,3456.00,d1); + if(ec==U_BUFFER_OVERFLOW_ERROR){ + ec=U_ZERO_ERROR; + result = (UChar*) malloc(U_SIZEOF_UCHAR*resultLength+2); + resultLength = umsg_format(formatter,result,resultLength+2,&ec,1,3456.00,d1); + if(U_FAILURE(ec)){ + log_err("ERROR: failure in message format on testcase %d: %s\n", i, u_errorName(status) ); + free(result); + return; + } + + if(u_strcmp(result, testResultStrings[i])==0){ + log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); + } + else{ + log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, + austrdup(result), austrdup(testResultStrings[i]) ); + } + + if (returnsNullForType(1, (double)2.0)) { + /* HP/UX and possibly other platforms don't properly check for this case. + We pass in a UDate, but the function expects a UDate *. When va_arg is used, + most compilers will return NULL, but HP-UX won't do that and will return 2 + in this case. This is a platform dependent test. + + This relies upon "undefined" behavior, as indicated by C99 7.15.1.1 paragraph 2 + */ + umsg_parse(formatter,result,resultLength,&count,&ec,one,two,d2); + if(ec!=U_ILLEGAL_ARGUMENT_ERROR){ + log_err("FAIL: Did not get expected error for umsg_parse(). Expected: U_ILLEGAL_ARGUMENT_ERROR Got: %s \n",u_errorName(ec)); + }else{ + ec = U_ZERO_ERROR; + } + } + else { + log_verbose("Warning: Returning NULL for a mismatched va_arg type isn't supported on this platform.\n", i); + } + + umsg_parse(formatter,result,resultLength,&count,&ec,&one,&two,&d2); + if(U_FAILURE(ec)){ + log_err("umsg_parse could not parse the pattern. Error: %s.\n",u_errorName(ec)); + } + free(result); + }else{ + log_err("FAIL: Expected U_BUFFER_OVERFLOW error while preflighting got: %s for testCasePatterns[%d]",u_errorName(ec),i); + } + } + umsg_close(formatter); + } + FreeStrings(); + + ctest_resetTimeZone(); +} + + +/*test u_formatMessage() with sample patterns */ +static void TestSampleMessageFormat(void) +{ + UChar *str; + UChar *result; + UChar pattern[100], expected[100]; + int32_t resultLengthOut, resultlength; + UDate d = 837039928046.0; + UErrorCode status = U_ZERO_ERROR; + + ctest_setTimeZone(NULL, &status); + + str=(UChar*)malloc(sizeof(UChar) * 15); + u_uastrcpy(str, "abc"); + + u_uastrcpy(pattern, "There are {0} files on {1,date}"); + u_uastrcpy(expected, "There are abc files on Jul 10, 1996"); + result=(UChar*)malloc(sizeof(UChar) * 1); + log_verbose("\nTesting a sample for Message format test#1\n"); + resultlength=1; + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d); + } + if(U_FAILURE(status)){ + log_err("Error: failure in message format on test#1: %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#1\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#1 \n GOT: %s EXPECTED: %s\n", + austrdup(result), austrdup(expected) ); + } + + + log_verbose("\nTesting message format with another pattern test#2\n"); + u_uastrcpy(pattern, "The disk \"{0}\" contains {1,number,integer} file(s)"); + u_uastrcpy(expected, "The disk \"MyDisk\" contains 23 file(s)"); + u_uastrcpy(str, "MyDisk"); + + resultLengthOut=u_formatMessage( "en_US", + pattern, + u_strlen(pattern), + result, + resultlength, + &status, + str, + 235); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * (resultlength+1)); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 23); + } + if(U_FAILURE(status)){ + log_err("Error: failure in message format on test#2 : %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#2\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#2\n GOT: %s EXPECTED: %s\n", + austrdup(result), austrdup(expected) ); + } + + + + log_verbose("\nTesting message format with another pattern test#3\n"); + u_uastrcpy(pattern, "You made a {0} of {1,number,currency}"); + u_uastrcpy(expected, "You made a deposit of $500.00"); + u_uastrcpy(str, "deposit"); + resultlength=0; + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, str, 500.00); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 500.00); + } + if(U_FAILURE(status)){ + log_err("Error: failure in message format on test#3 : %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#3\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#3\n GOT: %s EXPECTED %s\n", austrdup(result), + austrdup(expected) ); + } + + free(result); + free(str); + + ctest_resetTimeZone(); +} + +/* Test umsg_format() and umsg_parse() , format and parse sequence and round trip */ +static void TestNewFormatAndParseAPI(void) +{ + + UChar *result, *tzID, *str; + UChar pattern[100]; + UChar expected[100]; + int32_t resultLengthOut, resultlength; + UCalendar *cal; + UDate d1,d; + UDateFormat *def1; + UErrorCode status = U_ZERO_ERROR; + int32_t value = 0; + UChar ret[30]; + UParseError parseError; + UMessageFormat* fmt = NULL; + int32_t count=0; + + ctest_setTimeZone(NULL, &status); + + log_verbose("Testing format and parse with parse error\n"); + + str=(UChar*)malloc(sizeof(UChar) * 25); + u_uastrcpy(str, "disturbance in force"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("error in ucal_open caldef : %s\n", myErrorName(status) ); + return; + } + ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status); + d1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ + log_err("Error: failure in get millis: %s\n", myErrorName(status) ); + return; + } + + log_verbose("\nTesting with pattern test#4"); + u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}"); + u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7"); + resultlength=1; + fmt = umsg_open(pattern,u_strlen(pattern),"en_US",&parseError,&status); + if(U_FAILURE(status)){ + log_err("error in umsg_open : %s\n", u_errorName(status) ); + return; + } + result=(UChar*)malloc(sizeof(UChar) * resultlength); + + resultLengthOut=umsg_format(fmt ,result, resultlength,&status, d1, str, 7); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * resultlength); + u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7); + + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#4\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result), + austrdup(expected) ); + } + + + /*try to parse this and check*/ + log_verbose("\nTesting the parse Message test#5\n"); + + umsg_parse(fmt, result, u_strlen(result),&count,&status, &d, ret, &value); + if(U_FAILURE(status)){ + log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status)); + } + if(value!=7 && u_strcmp(str,ret)!=0) + log_err("FAIL: Error in parseMessage on test#5 \n"); + else + log_verbose("PASS: parseMessage successful on test#5\n"); + + def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status)); + }else{ + + if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0) + log_verbose("PASS: parseMessage successful test#5\n"); + else{ + log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n", + austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) ); + } + } + umsg_close(fmt); + udat_close(def1); + ucal_close(cal); + + free(result); + free(str); + free(tzID); + + ctest_resetTimeZone(); +} + +/* Test u_formatMessageWithError() and u_parseMessageWithError() , format and parse sequence and round trip */ +static void TestSampleFormatAndParseWithError(void) +{ + + UChar *result, *tzID, *str; + UChar pattern[100]; + + UChar expected[100]; + int32_t resultLengthOut, resultlength; + UCalendar *cal; + UDate d1,d; + UDateFormat *def1; + UErrorCode status = U_ZERO_ERROR; + int32_t value = 0; + UChar ret[30]; + UParseError parseError; + + ctest_setTimeZone(NULL, &status); + + log_verbose("Testing format and parse with parse error\n"); + + str=(UChar*)malloc(sizeof(UChar) * 25); + u_uastrcpy(str, "disturbance in force"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("error in ucal_open caldef : %s\n", myErrorName(status) ); + } + ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status); + d1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ + log_err("Error: failure in get millis: %s\n", myErrorName(status) ); + } + + log_verbose("\nTesting with pattern test#4"); + u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}"); + u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7"); + resultlength=1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + resultLengthOut=u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * resultlength); + u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7); + + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#4\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result), + austrdup(expected) ); + } + + + /*try to parse this and check*/ + log_verbose("\nTesting the parse Message test#5\n"); + + u_parseMessageWithError("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &parseError,&status, &d, ret, &value); + if(U_FAILURE(status)){ + log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status)); + } + if(value!=7 && u_strcmp(str,ret)!=0) + log_err("FAIL: Error in parseMessage on test#5 \n"); + else + log_verbose("PASS: parseMessage successful on test#5\n"); + + def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status)); + }else{ + + if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0) + log_verbose("PASS: parseMessage successful test#5\n"); + else{ + log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n", + austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) ); + } + } + udat_close(def1); + ucal_close(cal); + + free(result); + free(str); + free(tzID); + + ctest_resetTimeZone(); +} + +/* Test u_formatMessage() and u_parseMessage() , format and parse sequence and round trip */ +static void TestSampleFormatAndParse(void) +{ + + UChar *result, *tzID, *str; + UChar pattern[100]; + UChar expected[100]; + int32_t resultLengthOut, resultlength; + UCalendar *cal; + UDate d1,d; + UDateFormat *def1; + UErrorCode status = U_ZERO_ERROR; + int32_t value = 0; + UChar ret[30]; + + ctest_setTimeZone(NULL, &status); + + log_verbose("Testing format and parse\n"); + + str=(UChar*)malloc(sizeof(UChar) * 25); + u_uastrcpy(str, "disturbance in force"); + tzID=(UChar*)malloc(sizeof(UChar) * 4); + u_uastrcpy(tzID, "PST"); + cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); + if(U_FAILURE(status)){ + log_err("error in ucal_open caldef : %s\n", myErrorName(status) ); + } + ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status); + d1=ucal_getMillis(cal, &status); + if(U_FAILURE(status)){ + log_err("Error: failure in get millis: %s\n", myErrorName(status) ); + } + + log_verbose("\nTesting with pattern test#4"); + u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}"); + u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7"); + resultlength=1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result, sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7); + + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status)); + } + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#4\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result), + austrdup(expected) ); + } + + + /*try to parse this and check*/ + log_verbose("\nTesting the parse Message test#5\n"); + + u_parseMessage("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &status, &d, ret, &value); + if(U_FAILURE(status)){ + log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status)); + } + if(value!=7 && u_strcmp(str,ret)!=0) + log_err("FAIL: Error in parseMessage on test#5 \n"); + else + log_verbose("PASS: parseMessage successful on test#5\n"); + + def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status); + if(U_FAILURE(status)) + { + log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status)); + }else{ + + if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0) + log_verbose("PASS: parseMessage successful test#5\n"); + else{ + log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n", + austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) ); + } + } + udat_close(def1); + ucal_close(cal); + + free(result); + free(str); + free(tzID); + + ctest_resetTimeZone(); +} + +/* test message format with a choice option */ +static void TestMsgFormatChoice(void) +{ + UChar* str; + UErrorCode status = U_ZERO_ERROR; + UChar *result; + UChar pattern[100]; + UChar expected[100]; + int32_t resultlength,resultLengthOut; + + str=(UChar*)malloc(sizeof(UChar) * 25); + u_uastrcpy(str, "MyDisk"); + log_verbose("Testing message format with choice test #6\n:"); + /*There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.*/ + u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number,integer} files}"); + u_uastrcpy(expected, "The disk MyDisk contains 100 files"); + resultlength=0; + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 100., str); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 100., str); + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#6\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#6\n GOT %s EXPECTED %s\n", austrdup(result), + austrdup(expected) ); + } + free(result); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on test#6 : %s\n", myErrorName(status)); + } + + log_verbose("Testing message format with choice test #7\n:"); + u_uastrcpy(expected, "The disk MyDisk contains no files"); + resultlength=0; + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 0., str); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 0., str); + + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#7\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#7\n GOT: %s EXPECTED %s\n", austrdup(result), + austrdup(expected) ); + } + free(result); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on test#7 : %s\n", myErrorName(status)); + } + + log_verbose("Testing message format with choice test #8\n:"); + u_uastrcpy(expected, "The disk MyDisk contains one file"); + resultlength=0; + resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 1., str); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 1., str); + + if(u_strcmp(result, expected)==0) + log_verbose("PASS: MessagFormat successful on test#8\n"); + else{ + log_err("FAIL: Error in MessageFormat on test#8\n GOT %s EXPECTED: %s\n", austrdup(result), + austrdup(expected) ); + } + + free(result); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on test#8 : %s\n", myErrorName(status)); + } + + free(str); + +} + +/*test u_parseMessage() with various test patterns */ +static void TestParseMessage(void) +{ + UChar pattern[100]; + UChar source[100]; + UErrorCode status = U_ZERO_ERROR; + int32_t value; + UChar str[10]; + UChar res[10]; + + log_verbose("\nTesting a sample for parse Message test#9\n"); + + u_uastrcpy(source, "You deposited an amount of $500.00"); + u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}"); + u_uastrcpy(res,"deposited"); + + u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value); + if(U_FAILURE(status)){ + log_err("ERROR: failure in parse Message on test#9: %s\n", myErrorName(status)); + } + if(value==500.00 && u_strcmp(str,res)==0) + log_verbose("PASS: parseMessage successful on test#9\n"); + else + log_err("FAIL: Error in parseMessage on test#9 \n"); + + + + log_verbose("\nTesting a sample for parse Message test#10\n"); + + u_uastrcpy(source, "There are 123 files on MyDisk created"); + u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created"); + u_uastrcpy(res,"MyDisk"); + + u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str); + if(U_FAILURE(status)){ + log_err("ERROR: failure in parse Message on test#10: %s\n", myErrorName(status)); + } + if(value==123.00 && u_strcmp(str,res)==0) + log_verbose("PASS: parseMessage successful on test#10\n"); + else + log_err("FAIL: Error in parseMessage on test#10 \n"); + + + +} + +static int32_t CallFormatMessage(const char* locale, UChar* testCasePattern, int32_t patternLength, + UChar* result, int32_t resultLength, UErrorCode *status, ...) +{ + int32_t len = 0; + va_list ap; + va_start(ap, status); + len = u_vformatMessage(locale, testCasePattern, patternLength, result, resultLength, ap, status); + va_end(ap); + return len; +} + +/* Test u_vformatMessage() with various test patterns. */ +static void TestMessageFormatWithValist( void ) +{ + + UChar *str; + UChar* result; + int32_t resultLengthOut,resultlength,i, patternlength; + UErrorCode status = U_ZERO_ERROR; + UDate d1=1000000000.0; + + ctest_setTimeZone(NULL, &status); + + str=(UChar*)malloc(sizeof(UChar) * 7); + u_uastrcpy(str, "MyDisk"); + resultlength=1; + result=(UChar*)malloc(sizeof(UChar) * 1); + log_verbose("Testing u_formatMessage90\n"); + InitStrings(); + for (i = 0; i < cnt_testCases; i++) { + status=U_ZERO_ERROR; + patternlength=u_strlen(testCasePatterns[i]); + resultLengthOut=CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &status, 1, 3456.00, d1); + if(status== U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultLengthOut+1; + result=(UChar*)realloc(result,sizeof(UChar) * resultlength); + CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength, + &status, 1, 3456.00, d1); + } + if(U_FAILURE(status)){ + log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) ); + } + if(u_strcmp(result, testResultStrings[i])==0){ + log_verbose("PASS: MessagFormat successful on testcase : %d\n", i); + } + else{ + log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i, + austrdup(result), austrdup(testResultStrings[i]) ); + } + } + free(result); + free(str); + FreeStrings(); + + ctest_resetTimeZone(); +} + +static void CallParseMessage(const char* locale, UChar* pattern, int32_t patternLength, + UChar* source, int32_t sourceLength, UErrorCode *status, ...) +{ + va_list ap; + va_start(ap, status); + u_vparseMessage(locale, pattern, patternLength, source, sourceLength, ap, status); + va_end(ap); +} + +/*test u_vparseMessage() with various test patterns */ +static void TestParseMessageWithValist(void) +{ + UChar pattern[100]; + UChar source[100]; + UErrorCode status = U_ZERO_ERROR; + int32_t value; + UChar str[10]; + UChar res[10]; + + log_verbose("\nTesting a sample for parse Message test#9\n"); + + u_uastrcpy(source, "You deposited an amount of $500.00"); + u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}"); + u_uastrcpy(res,"deposited"); + + CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value); + if(U_FAILURE(status)){ + log_err("ERROR: failure in parse Message on test#9: %s\n", myErrorName(status)); + } + if(value==500.00 && u_strcmp(str,res)==0) + log_verbose("PASS: parseMessage successful on test#9\n"); + else + log_err("FAIL: Error in parseMessage on test#9 \n"); + + + log_verbose("\nTesting a sample for parse Message test#10\n"); + + u_uastrcpy(source, "There are 123 files on MyDisk created"); + u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created"); + u_uastrcpy(res,"MyDisk"); + + CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str); + if(U_FAILURE(status)){ + log_err("ERROR: failure in parse Message on test#10: %s\n", myErrorName(status)); + } + if(value==123.00 && u_strcmp(str,res)==0) + log_verbose("PASS: parseMessage successful on test#10\n"); + else + log_err("FAIL: Error in parseMessage on test#10 \n"); +} + +/** + * Regression test for ICU4C Jitterbug 904 + */ +static void TestJ904(void) { + UChar pattern[256]; + UChar result[256]; + UChar string[16]; + char cresult[256]; + int32_t length; + UErrorCode status = U_ZERO_ERROR; + const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}"; + const char* EXP = "Number 0,143, String foo, Date 12:34:56.789"; + + ctest_setTimeZone(NULL, &status); + + u_uastrcpy(string, "foo"); + /* Slight hack here -- instead of date pattern HH:mm:ss.SSS, use + * 12:mm:ss.SSS. Why? So this test generates the same output -- + * "12:34:56.789" -- regardless of time zone (as long as we aren't + * in one of the 30 minute offset zones!). */ + u_uastrcpy(pattern, PAT); + length = u_formatMessage("nl", pattern, u_strlen(pattern), + result, 256, &status, + string, 1/7.0, + 789.0+1000*(56+60*(34+60*12))); + + u_austrncpy(cresult, result, sizeof(cresult)); + + /* This test passes if it DOESN'T CRASH. However, we test the + * output anyway. If the string doesn't match in the date part, + * check to see that the machine doesn't have an unusual time zone + * offset, that is, one with a non-zero minutes/seconds offset + * from GMT -- see above. */ + if (strcmp(cresult, EXP) == 0) { + log_verbose("Ok: \"%s\"\n", cresult); + } else { + log_err("FAIL: got \"%s\", expected \"%s\"\n", cresult, EXP); + } + + ctest_resetTimeZone(); +} + +static void OpenMessageFormatTest(void) +{ + UMessageFormat *f1, *f2, *f3; + UChar pattern[256]; + UChar result[256]; + char cresult[256]; + UParseError parseError; + const char* locale = "hi_IN"; + char* retLoc; + const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}"; + int32_t length=0; + UErrorCode status = U_ZERO_ERROR; + + u_uastrncpy(pattern, PAT, sizeof(pattern)/sizeof(pattern[0])); + + /* Test umsg_open */ + f1 = umsg_open(pattern,length,NULL,NULL,&status); + + if(U_FAILURE(status)) + { + log_err("umsg_open failed with pattern %s. Error: \n", PAT, u_errorName(status)); + return; + } + + /* Test umsg_open with parse error */ + status = U_ZERO_ERROR; + f2 = umsg_open(pattern,length,NULL,&parseError,&status); + + if(U_FAILURE(status)) + { + log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT, u_errorName(status)); + return; + } + + /* Test umsg_clone */ + status = U_ZERO_ERROR; + f3 = umsg_clone(f1,&status); + if(U_FAILURE(status)) + { + log_err("umsg_clone failed. Error %s \n", u_errorName(status)); + } + + /* Test umsg_setLocale */ + umsg_setLocale(f1,locale); + /* Test umsg_getLocale */ + retLoc = (char*)umsg_getLocale(f1); + if(strcmp(retLoc,locale)!=0) + { + log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale, retLoc); + } + + /* Test umsg_applyPattern */ + status = U_ZERO_ERROR; + umsg_applyPattern(f1,pattern,(int32_t)strlen(PAT),NULL,&status); + if(U_FAILURE(status)) + { + log_err("umsg_applyPattern failed. Error %s \n",u_errorName(status)); + } + + /* Test umsg_toPattern */ + umsg_toPattern(f1,result,256,&status); + if(U_FAILURE(status) ){ + log_err("umsg_toPattern method failed. Error: %s \n",u_errorName(status)); + } else { + if(u_strcmp(result,pattern)!=0){ + u_UCharsToChars(result,cresult,256); + log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT,cresult); + } + } + /* umsg_format umsg_parse */ + + umsg_close(f1); + umsg_close(f2); + umsg_close(f3); +} + +static void MessageLength(void) +{ + UErrorCode status = U_ZERO_ERROR; + const char patChars[] = {"123{0}456{0}"}; + const char expectedChars[] = {"123abc"}; + UChar pattern[sizeof(patChars)]; + UChar arg[] = {0x61,0x62,0x63,0}; + UChar result[128] = {0}; + UChar expected[sizeof(expectedChars)]; + + u_uastrncpy(pattern, patChars, sizeof(pattern)/sizeof(pattern[0])); + u_uastrncpy(expected, expectedChars, sizeof(expected)/sizeof(expected[0])); + + u_formatMessage("en_US", pattern, 6, result, sizeof(result)/sizeof(result[0]), &status, arg); + if (U_FAILURE(status)) { + log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status)); + } + if (u_strcmp(result, expected) != 0) { + log_err("u_formatMessage didn't return expected result\n"); + } +} + +static void TestErrorChaining(void) { + UErrorCode status = U_USELESS_COLLATOR_ERROR; + + umsg_open(NULL, 0, NULL, NULL, &status); + umsg_applyPattern(NULL, NULL, 0, NULL, &status); + umsg_toPattern(NULL, NULL, 0, &status); + umsg_clone(NULL, &status); + umsg_format(NULL, NULL, 0, &status); + umsg_parse(NULL, NULL, 0, NULL, &status); + umsg_close(NULL); + + /* All of this code should have done nothing. */ + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Status got changed to %s\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + umsg_open(NULL, 0, NULL, NULL, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + umsg_applyPattern(NULL, NULL, 0, NULL, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + umsg_toPattern(NULL, NULL, 0, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + umsg_clone(NULL, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status)); + } +} + +void addMsgForTest(TestNode** root); + +void addMsgForTest(TestNode** root) +{ + addTest(root, &OpenMessageFormatTest, "tsformat/cmsgtst/OpenMessageFormatTest"); + addTest(root, &MessageFormatTest, "tsformat/cmsgtst/MessageFormatTest"); + addTest(root, &TestSampleMessageFormat, "tsformat/cmsgtst/TestSampleMessageFormat"); + addTest(root, &TestSampleFormatAndParse, "tsformat/cmsgtst/TestSampleFormatAndParse"); + addTest(root, &TestSampleFormatAndParseWithError, "tsformat/cmsgtst/TestSampleFormatAndParseWithError"); + addTest(root, &TestNewFormatAndParseAPI, "tsformat/cmsgtst/TestNewFormatAndParseAPI"); + addTest(root, &TestMsgFormatChoice, "tsformat/cmsgtst/TestMsgFormatChoice"); + addTest(root, &TestParseMessage, "tsformat/cmsgtst/TestParseMessage"); + addTest(root, &TestMessageFormatWithValist, "tsformat/cmsgtst/TestMessageFormatWithValist"); + addTest(root, &TestParseMessageWithValist, "tsformat/cmsgtst/TestParseMessageWithValist"); + addTest(root, &TestJ904, "tsformat/cmsgtst/TestJ904"); + addTest(root, &MessageLength, "tsformat/cmsgtst/MessageLength"); + addTest(root, &TestErrorChaining, "tsformat/cmsgtst/TestErrorChaining"); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h new file mode 100644 index 00000000000..6936283980e --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h @@ -0,0 +1,60 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CMSGTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* C API TEST FOR MESSAGE FORMAT */ +#ifndef _CMSGFRMTST +#define _CMSGFRMTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + + +/* The function used to test the Message format API*/ + + /** + * Test u_formatMessage() with various test patterns + **/ + static void MessageFormatTest(void); + /** + * Test u_formatMessage() with sample test Patterns + **/ + static void TestSampleMessageFormat(void); + /** + * Test format and parse sequence and roundtrip + **/ + static void TestSampleFormatAndParse(void); + /** + * Test u_formatMessage() with choice option + **/ + static void TestMsgFormatChoice(void); + /** + * Test u_parseMessage() with various test patterns() + **/ + static void TestParseMessage(void); + /** + * function used to set up various patterns used for testing u_formatMessage() + **/ + static void InitStrings( void ); + + /** + * Regression test for ICU4C Jitterbug 904 + */ + static void TestJ904(void); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c new file mode 100644 index 00000000000..152351487b5 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c @@ -0,0 +1,951 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation + * and others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CNMDPTST.C +* +* Madhu Katragadda Creation +* Modification History: +* +* Date Name Description +* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes +******************************************************************************* +*/ + +/* C DEPTH TEST FOR NUMBER FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/ucurr.h" +#include "unicode/uloc.h" +#include "unicode/unum.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cnmdptst.h" +#include "cmemory.h" +#include "cstring.h" + +#define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; } + +void addNumFrDepTest(TestNode** root); +static void TestCurrencyPreEuro(void); +static void TestCurrencyObject(void); + +void addNumFrDepTest(TestNode** root) +{ + addTest(root, &TestPatterns, "tsformat/cnmdptst/TestPatterns"); + addTest(root, &TestQuotes, "tsformat/cnmdptst/TestQuotes"); + addTest(root, &TestExponential, "tsformat/cnmdptst/TestExponential"); + addTest(root, &TestCurrencySign, "tsformat/cnmdptst/TestCurrencySign"); + addTest(root, &TestCurrency, "tsformat/cnmdptst/TestCurrency"); + addTest(root, &TestCurrencyPreEuro, "tsformat/cnmdptst/TestCurrencyPreEuro"); + addTest(root, &TestCurrencyObject, "tsformat/cnmdptst/TestCurrencyObject"); + addTest(root, &TestRounding487, "tsformat/cnmdptst/TestRounding487"); + addTest(root, &TestDoubleAttribute, "tsformat/cnmdptst/TestDoubleAttribute"); + addTest(root, &TestSecondaryGrouping, "tsformat/cnmdptst/TestSecondaryGrouping"); + addTest(root, &TestCurrencyKeywords, "tsformat/cnmdptst/TestCurrencyKeywords"); + addTest(root, &TestRounding5350, "tsformat/cnmdptst/TestRounding5350"); +} + +/*Test Various format patterns*/ +static void TestPatterns(void) +{ + int32_t pat_length, i, lneed; + UNumberFormat *fmt; + UChar upat[5]; + UChar unewpat[5]; + UChar unum[5]; + UChar *unewp=NULL; + UChar *str=NULL; + UErrorCode status = U_ZERO_ERROR; + const char* pat[] = { "#.#", "#.", ".#", "#" }; + const char* newpat[] = { "#0.#", "#0.", "#.0", "#" }; + const char* num[] = { "0", "0.", ".0", "0" }; + + log_verbose("\nTesting different format patterns\n"); + pat_length = sizeof(pat) / sizeof(pat[0]); + for (i=0; i < pat_length; ++i) + { + status = U_ZERO_ERROR; + u_uastrcpy(upat, pat[i]); + fmt= unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: Number format constructor failed for pattern %s\n", pat[i]); + continue; + } + lneed=0; + lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status= U_ZERO_ERROR; + unewp=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_toPattern(fmt, FALSE, unewp, lneed+1, &status); + } + if(U_FAILURE(status)){ + log_err("FAIL: Number format extracting the pattern failed for %s\n", pat[i]); + } + u_uastrcpy(unewpat, newpat[i]); + if(u_strcmp(unewp, unewpat) != 0) + log_err("FAIL: Pattern %s should be transmute to %s; %s seen instead\n", pat[i], newpat[i], austrdup(unewp) ); + + lneed=0; + lneed=unum_format(fmt, 0, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_format(fmt, 0, str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + u_uastrcpy(unum, num[i]); + if (u_strcmp(str, unum) != 0) + { + log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat[i], num[i], austrdup(str) ); + + } + free(unewp); + free(str); + unum_close(fmt); + } +} + +/* Test the handling of quotes*/ +static void TestQuotes(void) +{ + int32_t lneed; + UErrorCode status=U_ZERO_ERROR; + UChar pat[15]; + UChar res[15]; + UChar *str=NULL; + UNumberFormat *fmt; + char tempBuf[256]; + log_verbose("\nTestting the handling of quotes in number format\n"); + u_uastrcpy(pat, "a'fo''o'b#"); + fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status); + if(U_FAILURE(status)){ + log_err("Error in number format costruction using pattern \"a'fo''o'b#\"\n"); + } + lneed=0; + lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_format(fmt, 123, str, lneed+1, NULL, &status); + } + if(U_FAILURE(status) || !str) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + return; + } + log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) ); + log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) ); + u_uastrcpy(res, "afo'ob123"); + if(u_strcmp(str, res) != 0) + log_err("FAIL: Expected afo'ob123"); + + free(str); + unum_close(fmt); + + + u_uastrcpy(pat, ""); + u_uastrcpy(pat, "a''b#"); + + + fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status); + if(U_FAILURE(status)){ + log_err("Error in number format costruction using pattern \"a''b#\"\n"); + } + lneed=0; + lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_format(fmt, 123, str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) ); + log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) ); + u_uastrcpy(res, ""); + u_uastrcpy(res, "a'b123"); + if(u_strcmp(str, res) != 0) + log_err("FAIL: Expected a'b123\n"); + + free(str); + unum_close(fmt); +} + +/* Test exponential pattern*/ +static void TestExponential(void) +{ + int32_t pat_length, val_length, lval_length; + int32_t ival, ilval, p, v, lneed; + UNumberFormat *fmt; + int32_t ppos; + UChar *upat; + UChar pattern[20]; + UChar *str=NULL; + UChar uvalfor[20], ulvalfor[20]; + char tempMsgBug[256]; + double a; + UErrorCode status = U_ZERO_ERROR; +#ifdef OS390 + static const double val[] = { 0.01234, 123456789, 1.23e75, -3.141592653e-78 }; +#else + static const double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 }; +#endif + static const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" }; + static const int32_t lval[] = { 0, -1, 1, 123456789 }; + + static const char* valFormat[] = + { + "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271", + "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272", + "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273", + "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" + }; + static const char* lvalFormat[] = + { + "0E0", "-1E0", "1E0", "1.2346E8", + "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07", + "0E000", "-1E000", "1E000", "123.4568E006", + "0E0", "[1E0]", "1E0", "1.235E8" + }; + static const double valParse[] = + { +#ifdef OS390 + 0.01234, 123460000, 1.23E75, -3.1416E-78, + 0.01234, 123460000, 1.23E75, -3.1416E-78, + 0.01234, 123456800, 1.23E75, -3.141593E-78, + 0.01234, 123500000, 1.23E75, -3.142E-78 +#else + /* We define the whole IEEE 754 number in the 4th column because + Visual Age 7 has a bug in rounding numbers. */ + 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271, + 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271, + 0.01234, 123456800, 1.23E300, -3.1415929999999999E-271, + 0.01234, 123500000, 1.23E300, -3.1420000000000001E-271 +#endif + }; + static const int32_t lvalParse[] = + { + 0, -1, 1, 123460000, + 0, -1, 1, 123460000, + 0, -1, 1, 123456800, + 0, -1, 1, 123500000 + }; + + + pat_length = sizeof(pat) / sizeof(pat[0]); + val_length = sizeof(val) / sizeof(val[0]); + lval_length = sizeof(lval) / sizeof(lval[0]); + ival = 0; + ilval = 0; + for (p=0; p < pat_length; ++p) + { + upat=(UChar*)malloc(sizeof(UChar) * (strlen(pat[p])+1) ); + u_uastrcpy(upat, pat[p]); + fmt=unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: Bad status returned by Number format construction with pattern %s\n, pat[i]"); + continue; + } + lneed= u_strlen(upat) + 1; + unum_toPattern(fmt, FALSE, pattern, lneed, &status); + log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat, u_austrcpy(tempMsgBug, pattern) ); + for (v=0; v<val_length; ++v) + { + /*format*/ + lneed=0; + lneed=unum_formatDouble(fmt, val[v], NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_formatDouble(fmt, val[v], str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + + + + u_uastrcpy(uvalfor, valFormat[v+ival]); + if(u_strcmp(str, uvalfor) != 0) + log_verbose("FAIL: Expected %s ( %s )\n", valFormat[v+ival], u_austrcpy(tempMsgBug, uvalfor) ); + + /*parsing*/ + ppos=0; + a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status); + if (ppos== u_strlen(str)) { + if (a != valParse[v+ival]) + log_err("FAIL: Expected: %e, Got: %g\n", valParse[v+ival], a); + } + else + log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a); + + free(str); + } + for (v=0; v<lval_length; ++v) + { + /*format*/ + lneed=0; + lneed=unum_formatDouble(fmt, lval[v], NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_formatDouble(fmt, lval[v], str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/ + u_uastrcpy(ulvalfor, lvalFormat[v+ilval]); + if(u_strcmp(str, ulvalfor) != 0) + log_err("FAIL: Expected %s ( %s )\n", valFormat[v+ilval], austrdup(ulvalfor) ); + + /*parsing*/ + ppos=0; + a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status); + if (ppos== u_strlen(str)) { + /*printf(" Parse -> %e\n", a);*/ + if (a != lvalParse[v+ilval]) + log_err("FAIL: Expected : %e\n", valParse[v+ival]); + } + else + log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a); + + free(str); + + } + ival += val_length; + ilval += lval_length; + unum_close(fmt); + free(upat); + } +} + +/** + * Test the handling of the currency symbol in patterns. + */ +static void TestCurrencySign(void) +{ + int32_t lneed; + UNumberFormat *fmt; + UChar *pattern=NULL; + UChar *str=NULL; + UChar *pat=NULL; + UChar *res=NULL; + UErrorCode status = U_ZERO_ERROR; + char tempBuf[256]; + + pattern=(UChar*)malloc(sizeof(UChar) * (strlen("*#,##0.00;-*#,##0.00") + 1) ); + u_uastrcpy(pattern, "*#,##0.00;-*#,##0.00"); + pattern[0]=pattern[11]=0xa4; /* insert latin-1 currency symbol */ + fmt = unum_open(UNUM_IGNORE,pattern, u_strlen(pattern), "en_US",NULL, &status); + if(U_FAILURE(status)){ + log_err("Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" \n"); + } + lneed=0; + lneed=unum_formatDouble(fmt, 1234.56, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_formatDouble(fmt, 1234.56, str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + lneed=0; + lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + pat=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_formatDouble(fmt, FALSE, pat, lneed+1, NULL, &status); + } + log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf, pat)); + log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf, str) ); + if(U_SUCCESS(status) && str) { + res=(UChar*)malloc(sizeof(UChar) * (strlen("$1,234.56")+1) ); + u_uastrcpy(res, "$1,234.56"); + if (u_strcmp(str, res) !=0) log_err("FAIL: Expected $1,234.56\n"); + } else { + log_err("Error formatting\n"); + } + free(str); + free(res); + free(pat); + + lneed=0; + lneed=unum_formatDouble(fmt, -1234.56, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + unum_formatDouble(fmt, -1234.56, str, lneed+1, NULL, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + if(str) { + res=(UChar*)malloc(sizeof(UChar) * (strlen("-$1,234.56")+1) ); + u_uastrcpy(res, "-$1,234.56"); + if (u_strcmp(str, res) != 0) log_err("FAIL: Expected -$1,234.56\n"); + free(str); + free(res); + } + + unum_close(fmt); + free(pattern); +} + +/** + * Test localized currency patterns. + */ +static void TestCurrency(void) +{ + UNumberFormat *currencyFmt; + UChar *str; + int32_t lneed, i; + UFieldPosition pos; + UChar res[100]; + UErrorCode status = U_ZERO_ERROR; + const char* locale[]={"fr_CA", "de_DE_PREEURO", "fr_FR_PREEURO"}; + const char* result[]={"1,50 $", "1,50 DM", "1,50 F"}; + log_verbose("\nTesting the number format with different currency patterns\n"); + for(i=0; i < 3; i++) + { + str=NULL; + currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status); + + if(U_FAILURE(status)){ + log_err("Error in the construction of number format with style currency:\n%s\n", + myErrorName(status)); + } else { + lneed=0; + lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + pos.field = 0; + unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status); + } + + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); + } else { + u_charsToUChars(result[i], res, (int32_t)strlen(result[i])+1); + + if (u_strcmp(str, res) != 0){ + log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i], aescstrdup(str, -1), locale[i]); + } + } + } + + unum_close(currencyFmt); + free(str); + } +} +/** + * Test localized currency patterns for PREEURO variants. + */ +static void TestCurrencyPreEuro(void) +{ + UNumberFormat *currencyFmt; + UChar *str=NULL, *res=NULL; + int32_t lneed, i; + UFieldPosition pos; + UErrorCode status = U_ZERO_ERROR; + + const char* locale[]={ + "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO", + "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO", + "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO", + "nl_NL_PREEURO", + }; + + const char* result[]={ + "2 \\u20A7", "2 F", "\\u00A31.50", "1,50\\u00A0mk", "2 F", "\\u20A4 2", + "1$50 Esc.", "\\u00F6S 1,50", "1,50\\u0394\\u03C1\\u03C7", "2 \\u20A7", "1,50 FB", "\\u00a31.50", + "1,50 BF", "1,50 DM", "1,50 BF", "2 \\u20A7", "1,50 F", "2 \\u20A7", + "fl 1,50" + }; + + log_verbose("\nTesting the number format with different currency patterns\n"); + for(i=0; i < 19; i++) + { + char curID[256] = {0}; + uloc_canonicalize(locale[i], curID, 256, &status); + if(U_FAILURE(status)){ + log_err("Could not canonicalize %s. Error: %s \n", locale[i], u_errorName(status)); + continue; + } + currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,curID,NULL, &status); + + if(U_FAILURE(status)){ + log_err("Error in the construction of number format with style currency:\n%s\n", + myErrorName(status)); + } else { + lneed=0; + lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status); + + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + pos.field = 0; + unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status); + } + + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); + } else { + res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) ); + u_unescape(result[i],res,(int32_t)(strlen(result[i])+1)); + + if (u_strcmp(str, res) != 0){ + log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]); + } + } + } + + unum_close(currencyFmt); + free(str); + free(res); + } +} + +/** + * Test currency "object" (we use this name to match the other C++ + * test name and the Jave name). Actually, test ISO currency code + * support in the C API. + */ +static void TestCurrencyObject(void) +{ + UNumberFormat *currencyFmt; + UChar *str=NULL, *res=NULL; + int32_t lneed, i; + UFieldPosition pos; + UErrorCode status = U_ZERO_ERROR; + + const char* locale[]={ + "fr_FR", + "fr_FR", + }; + + const char* currency[]={ + "", + "JPY", + }; + + const char* result[]={ + "1\\u00A0234,56 \\u20AC", + "1\\u00A0235 \\u00A5JP", + }; + + log_verbose("\nTesting the number format with different currency codes\n"); + for(i=0; i < 2; i++) + { + char cStr[20]={0}; + UChar isoCode[16]={0}; + currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status); + if(U_FAILURE(status)){ + log_err("Error in the construction of number format with style currency:\n%s\n", + myErrorName(status)); + } else { + if (*currency[i]) { + u_uastrcpy(isoCode, currency[i]); + unum_setTextAttribute(currencyFmt, UNUM_CURRENCY_CODE, + isoCode, u_strlen(isoCode), &status); + + if(U_FAILURE(status)) { + log_err("FAIL: can't set currency code %s\n", myErrorName(status) ); + } + } + + unum_getTextAttribute(currencyFmt, UNUM_CURRENCY_CODE, + isoCode, sizeof(isoCode), &status); + + if(U_FAILURE(status)) { + log_err("FAIL: can't get currency code %s\n", myErrorName(status) ); + } + + u_UCharsToChars(isoCode,cStr,u_strlen(isoCode)); + log_verbose("ISO code %s\n", cStr); + if (*currency[i] && uprv_strcmp(cStr, currency[i])) { + log_err("FAIL: currency should be %s, but is %s\n", currency[i], cStr); + } + + lneed=0; + lneed= unum_formatDouble(currencyFmt, 1234.56, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + str=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + pos.field = 0; + unum_formatDouble(currencyFmt, 1234.56, str, lneed+1, &pos, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); + } else { + res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) ); + u_unescape(result[i],res, (int32_t)(strlen(result[i])+1)); + if (u_strcmp(str, res) != 0){ + log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]); + } + } + } + + unum_close(currencyFmt); + free(str); + free(res); + } +} + +/** + * Test proper rounding by the format method. + */ +static void TestRounding487(void) +{ + UNumberFormat *nnf; + UErrorCode status = U_ZERO_ERROR; + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */ + nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status); + + if(U_FAILURE(status)){ + log_err("FAIL: failure in the construction of number format: %s\n", myErrorName(status)); + } else { + roundingTest(nnf, 0.00159999, 4, "0.0016"); + roundingTest(nnf, 0.00995, 4, "0.01"); + + roundingTest(nnf, 12.3995, 3, "12.4"); + + roundingTest(nnf, 12.4999, 0, "12"); + roundingTest(nnf, - 19.5, 0, "-20"); + } + + unum_close(nnf); +} + +/*-------------------------------------*/ + +static void roundingTest(UNumberFormat* nf, double x, int32_t maxFractionDigits, const char* expected) +{ + UChar *out = NULL; + UChar *res; + UFieldPosition pos; + UErrorCode status; + int32_t lneed; + status=U_ZERO_ERROR; + unum_setAttribute(nf, UNUM_MAX_FRACTION_DIGITS, maxFractionDigits); + lneed=0; + lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + out=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + pos.field=0; + unum_formatDouble(nf, x, out, lneed+1, &pos, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); + } + /*Need to use log_verbose here. Problem with the float*/ + /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/ + res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) ); + u_uastrcpy(res, expected); + if (u_strcmp(out, res) != 0) + log_err("FAIL: Expected: %s or %s\n", expected, austrdup(res) ); + free(res); + if(out != NULL) { + free(out); + } +} + +/* + * Testing unum_getDoubleAttribute and unum_setDoubleAttribute() + */ +static void TestDoubleAttribute(void) +{ + double mydata[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99}; + double dvalue; + int i; + UErrorCode status=U_ZERO_ERROR; + UNumberFormatAttribute attr; + UNumberFormatStyle style= UNUM_DEFAULT; + UNumberFormat *def; + + log_verbose("\nTesting get and set DoubleAttributes\n"); + def=unum_open(style, NULL,0,NULL,NULL, &status); + + if (U_FAILURE(status)) { + log_err("Fail: error creating a default number formatter\n"); + } else { + attr=UNUM_ROUNDING_INCREMENT; + dvalue=unum_getDoubleAttribute(def, attr); + for (i = 0; i<9 ; i++) + { + dvalue = mydata[i]; + unum_setDoubleAttribute(def, attr, dvalue); + if(unum_getDoubleAttribute(def,attr)!=mydata[i]) + log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n"); + else + log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n"); + } + } + + unum_close(def); +} + +/** + * Test the functioning of the secondary grouping value. + */ +static void TestSecondaryGrouping(void) { + UErrorCode status = U_ZERO_ERROR; + UNumberFormat *f = NULL, *g= NULL; + UNumberFormat *us = unum_open(UNUM_DECIMAL,NULL,0, "en_US", NULL,&status); + UFieldPosition pos; + UChar resultBuffer[512]; + int32_t l = 1876543210L; + UBool ok = TRUE; + UChar buffer[512]; + int32_t i; + UBool expectGroup = FALSE, isGroup = FALSE; + + u_uastrcpy(buffer, "#,##,###"); + f = unum_open(UNUM_IGNORE,buffer, -1, "en_US",NULL, &status); + CHECK(status, "DecimalFormat ct"); + + pos.field = 0; + unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status); + u_uastrcpy(buffer, "12,34,56,789"); + if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status)) + { + log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,34,56,789"); + } + if (pos.beginIndex != 0 && pos.endIndex != 12) { + log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos.beginIndex, pos.endIndex); + } + memset(resultBuffer,0, sizeof(UChar)*512); + unum_toPattern(f, FALSE, resultBuffer, 512, &status); + u_uastrcpy(buffer, "#,##,###"); + if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status)) + { + log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,##,###"); + } + memset(resultBuffer,0, sizeof(UChar)*512); + u_uastrcpy(buffer, "#,###"); + unum_applyPattern(f, FALSE, buffer, -1,NULL,NULL); + if (U_FAILURE(status)) + { + log_err("Fail: applyPattern call failed\n"); + } + unum_setAttribute(f, UNUM_SECONDARY_GROUPING_SIZE, 4); + unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status); + u_uastrcpy(buffer, "12,3456,789"); + if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status)) + { + log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,3456,789"); + } + memset(resultBuffer,0, sizeof(UChar)*512); + unum_toPattern(f, FALSE, resultBuffer, 512, &status); + u_uastrcpy(buffer, "#,####,###"); + if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status)) + { + log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,####,###"); + } + memset(resultBuffer,0, sizeof(UChar)*512); + g = unum_open(UNUM_DECIMAL, NULL,0,"hi_IN",NULL, &status); + if (U_FAILURE(status)) + { + log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n"); + } + + unum_format(g, l, resultBuffer, 512, &pos, &status); + unum_close(g); + /* expect "1,87,65,43,210", but with Hindi digits */ + /* 01234567890123 */ + if (u_strlen(resultBuffer) != 14) { + ok = FALSE; + } else { + for (i=0; i<u_strlen(resultBuffer); ++i) { + expectGroup = FALSE; + switch (i) { + case 1: + case 4: + case 7: + case 10: + expectGroup = TRUE; + break; + } + /* Later -- fix this to get the actual grouping */ + /* character from the resource bundle. */ + isGroup = (UBool)(resultBuffer[i] == 0x002C); + if (isGroup != expectGroup) { + ok = FALSE; + break; + } + } + } + if (!ok) { + log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer); + } + unum_close(f); + unum_close(us); +} + +static void TestCurrencyKeywords(void) +{ + static const char * const currencies[] = { + "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD", + "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS", + "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF", + "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND", + "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ", + "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD", + "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF", + "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK", + "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK", + "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB", + "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF", + "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP", + "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF", + "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP", + "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD", + "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO", + "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR", + "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF", + "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL", + "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP", + "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP", + "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG", + "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN", + "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP", + "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR", + "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK", + "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC", + "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS", + "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS", + "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD", + "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST", + "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR", + "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS", + "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR", + "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD" + }; + + UErrorCode status = U_ZERO_ERROR; + int32_t i = 0, j = 0; + int32_t noLocales = uloc_countAvailable(); + char locale[256]; + char currLoc[256]; + UChar result[4]; + UChar currBuffer[256]; + + + for(i = 0; i < noLocales; i++) { + strcpy(currLoc, uloc_getAvailable(i)); + for(j = 0; j < sizeof(currencies)/sizeof(currencies[0]); j++) { + strcpy(locale, currLoc); + strcat(locale, "@currency="); + strcat(locale, currencies[j]); + ucurr_forLocale(locale, result, 4, &status); + u_charsToUChars(currencies[j], currBuffer, 3); + currBuffer[3] = 0; + if(u_strcmp(currBuffer, result) != 0) { + log_err("Didn't get the right currency for %s\n", locale); + } + } + + } +} + +/** + * Test proper handling of rounding modes. + */ +static void TestRounding5350(void) +{ + UNumberFormat *nnf; + UErrorCode status = U_ZERO_ERROR; + /* this is supposed to open default date format, but later on it treats it like it is "en_US" + - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ + /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */ + nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status); + + if(U_FAILURE(status)){ + log_err("FAIL: failure in the construction of number format: %s\n", myErrorName(status)); + return; + } + + unum_setAttribute(nnf, UNUM_MAX_FRACTION_DIGITS, 2); + roundingTest2(nnf, -0.125, UNUM_ROUND_CEILING, "-0.12"); + roundingTest2(nnf, -0.125, UNUM_ROUND_FLOOR, "-0.13"); + roundingTest2(nnf, -0.125, UNUM_ROUND_DOWN, "-0.12"); + roundingTest2(nnf, -0.125, UNUM_ROUND_UP, "-0.13"); + roundingTest2(nnf, 0.125, UNUM_FOUND_HALFEVEN, "0.12"); + roundingTest2(nnf, 0.135, UNUM_ROUND_HALFDOWN, "0.13"); + roundingTest2(nnf, 0.125, UNUM_ROUND_HALFUP, "0.13"); + roundingTest2(nnf, 0.135, UNUM_FOUND_HALFEVEN, "0.14"); + /* The following are exactly represented, and shouldn't round */ + roundingTest2(nnf, 1.00, UNUM_ROUND_UP, "1"); + roundingTest2(nnf, 24.25, UNUM_ROUND_UP, "24.25"); + roundingTest2(nnf, 24.25, UNUM_ROUND_CEILING, "24.25"); + roundingTest2(nnf, -24.25, UNUM_ROUND_UP, "-24.25"); + + /* Differences pretty far out there */ + roundingTest2(nnf, 1.0000001, UNUM_ROUND_CEILING, "1.01"); + roundingTest2(nnf, 1.0000001, UNUM_ROUND_FLOOR, "1"); + roundingTest2(nnf, 1.0000001, UNUM_ROUND_DOWN, "1"); + roundingTest2(nnf, 1.0000001, UNUM_ROUND_UP, "1.01"); + roundingTest2(nnf, 1.0000001, UNUM_FOUND_HALFEVEN, "1"); + roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFDOWN, "1"); + roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFUP, "1"); + + roundingTest2(nnf, -1.0000001, UNUM_ROUND_CEILING, "-1"); + roundingTest2(nnf, -1.0000001, UNUM_ROUND_FLOOR, "-1.01"); + roundingTest2(nnf, -1.0000001, UNUM_ROUND_DOWN, "-1"); + roundingTest2(nnf, -1.0000001, UNUM_ROUND_UP, "-1.01"); + roundingTest2(nnf, -1.0000001, UNUM_FOUND_HALFEVEN, "-1"); + roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFDOWN, "-1"); + roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFUP, "-1"); + + unum_close(nnf); +} + +/*-------------------------------------*/ + +static void roundingTest2(UNumberFormat* nf, double x, int32_t roundingMode, const char* expected) +{ + UChar *out = NULL; + UChar *res; + UFieldPosition pos; + UErrorCode status; + int32_t lneed; + status=U_ZERO_ERROR; + unum_setAttribute(nf, UNUM_ROUNDING_MODE, roundingMode); + lneed=0; + lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + out=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); + pos.field=0; + unum_formatDouble(nf, x, out, lneed+1, &pos, &status); + } + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) ); + } + /*Need to use log_verbose here. Problem with the float*/ + /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/ + res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) ); + u_uastrcpy(res, expected); + if (u_strcmp(out, res) != 0) + log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected, austrdup(out) ); + free(res); + if(out != NULL) { + free(out); + } +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h new file mode 100644 index 00000000000..c437490fabf --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h @@ -0,0 +1,60 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2003, 2007 International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CNMDPTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* C DEPTH TEST FOR NUMBER FORMAT */ + +#ifndef _CNUMDEPTST +#define _CNUMDEPTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + +/* The function used to test differnet format patterns*/ +static void TestPatterns(void); + +/* Test the handling of quotes*/ +static void TestQuotes(void); + +/* Test patterns with exponential representation*/ +static void TestExponential(void); + +/* Test the handling of the currency symbol in patterns. */ +static void TestCurrencySign(void); + +/* Test proper rounding by the format method.*/ +static void TestRounding487(void); + +/* Test proper handling of rounding modes. */ +static void TestRounding5350(void); + +/* Test localized currency patterns. */ +static void TestCurrency(void); + +/* Test getDoubleAttribute and getDoubleAttribute */ +static void TestDoubleAttribute(void); + +static void TestSecondaryGrouping(void); + +/*Internal functions used*/ +static void roundingTest(UNumberFormat*, double, int32_t, const char*); +static void roundingTest2(UNumberFormat*, double, int32_t, const char*); + +static void TestCurrencyKeywords(void); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c new file mode 100644 index 00000000000..99e6540386a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c @@ -0,0 +1,1517 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CNORMTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +* synwee added test for quick check +* synwee added test for checkFCD +*********************************************************************************/ +/*tests for u_normalization*/ +#include "unicode/utypes.h" +#include "unicode/unorm.h" +#include "unormimp.h" +#include "cintltst.h" + +#if UCONFIG_NO_NORMALIZATION + +void addNormTest(TestNode** root) { + /* no normalization - nothing to do */ +} + +#else + +#include <stdlib.h> +#include <time.h> +#include "unicode/uchar.h" +#include "unicode/ustring.h" +#include "unicode/unorm.h" +#include "cnormtst.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof ((array)[0])) + +static void +TestAPI(void); + +static void +TestNormCoverage(void); + +static void +TestConcatenate(void); + +static void +TestNextPrevious(void); + +static void TestIsNormalized(void); + +static void +TestFCNFKCClosure(void); + +static void +TestQuickCheckPerCP(void); + +static void +TestComposition(void); + +const static char* canonTests[][3] = { + /* Input*/ /*Decomposed*/ /*Composed*/ + { "cat", "cat", "cat" }, + { "\\u00e0ardvark", "a\\u0300ardvark", "\\u00e0ardvark", }, + + { "\\u1e0a", "D\\u0307", "\\u1e0a" }, /* D-dot_above*/ + { "D\\u0307", "D\\u0307", "\\u1e0a" }, /* D dot_above*/ + + { "\\u1e0c\\u0307", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_below dot_above*/ + { "\\u1e0a\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_above dot_below */ + { "D\\u0307\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D dot_below dot_above */ + + { "\\u1e10\\u0307\\u0323", "D\\u0327\\u0323\\u0307", "\\u1e10\\u0323\\u0307" }, /*D dot_below cedilla dot_above*/ + { "D\\u0307\\u0328\\u0323", "D\\u0328\\u0323\\u0307", "\\u1e0c\\u0328\\u0307" }, /* D dot_above ogonek dot_below*/ + + { "\\u1E14", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron-grave*/ + { "\\u0112\\u0300", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron + grave*/ + { "\\u00c8\\u0304", "E\\u0300\\u0304", "\\u00c8\\u0304" }, /* E-grave + macron*/ + + { "\\u212b", "A\\u030a", "\\u00c5" }, /* angstrom_sign*/ + { "\\u00c5", "A\\u030a", "\\u00c5" }, /* A-ring*/ + + { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" }, + { "\\u00C4\\uFB03n", "A\\u0308\\uFB03n", "\\u00C4\\uFB03n" }, + + { "Henry IV", "Henry IV", "Henry IV" }, + { "Henry \\u2163", "Henry \\u2163", "Henry \\u2163" }, + + { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/ + { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/ + { "\\uFF76\\uFF9E", "\\uFF76\\uFF9E", "\\uFF76\\uFF9E" }, /* hw_ka + hw_ten*/ + { "\\u30AB\\uFF9E", "\\u30AB\\uFF9E", "\\u30AB\\uFF9E" }, /* ka + hw_ten*/ + { "\\uFF76\\u3099", "\\uFF76\\u3099", "\\uFF76\\u3099" }, /* hw_ka + ten*/ + { "A\\u0300\\u0316", "A\\u0316\\u0300", "\\u00C0\\u0316" } /* hw_ka + ten*/ +}; + +const static char* compatTests[][3] = { + /* Input*/ /*Decomposed */ /*Composed*/ + { "cat", "cat", "cat" }, + + { "\\uFB4f", "\\u05D0\\u05DC", "\\u05D0\\u05DC" }, /* Alef-Lamed vs. Alef, Lamed*/ + + { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" }, + { "\\u00C4\\uFB03n", "A\\u0308ffin", "\\u00C4ffin" }, /* ffi ligature -> f + f + i*/ + + { "Henry IV", "Henry IV", "Henry IV" }, + { "Henry \\u2163", "Henry IV", "Henry IV" }, + + { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/ + { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/ + + { "\\uFF76\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + ten*/ + + /*These two are broken in Unicode 2.1.2 but fixed in 2.1.5 and later*/ + { "\\uFF76\\uFF9E", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + hw_ten*/ + { "\\u30AB\\uFF9E", "\\u30AB\\u3099", "\\u30AC" } /* ka + hw_ten*/ + +}; + +void addNormTest(TestNode** root); + +void addNormTest(TestNode** root) +{ + addTest(root, &TestAPI, "tscoll/cnormtst/TestAPI"); + addTest(root, &TestDecomp, "tscoll/cnormtst/TestDecomp"); + addTest(root, &TestCompatDecomp, "tscoll/cnormtst/TestCompatDecomp"); + addTest(root, &TestCanonDecompCompose, "tscoll/cnormtst/TestCanonDecompCompose"); + addTest(root, &TestCompatDecompCompose, "tscoll/cnormtst/CompatDecompCompose"); + addTest(root, &TestNull, "tscoll/cnormtst/TestNull"); + addTest(root, &TestQuickCheck, "tscoll/cnormtst/TestQuickCheck"); + addTest(root, &TestQuickCheckPerCP, "tscoll/cnormtst/TestQuickCheckPerCP"); + addTest(root, &TestIsNormalized, "tscoll/cnormtst/TestIsNormalized"); + addTest(root, &TestCheckFCD, "tscoll/cnormtst/TestCheckFCD"); + addTest(root, &TestNormCoverage, "tscoll/cnormtst/TestNormCoverage"); + addTest(root, &TestConcatenate, "tscoll/cnormtst/TestConcatenate"); + addTest(root, &TestNextPrevious, "tscoll/cnormtst/TestNextPrevious"); + addTest(root, &TestFCNFKCClosure, "tscoll/cnormtst/TestFCNFKCClosure"); + addTest(root, &TestComposition, "tscoll/cnormtst/TestComposition"); +} + +void TestDecomp() +{ + UErrorCode status = U_ZERO_ERROR; + int32_t x, neededLen, resLen; + UChar *source=NULL, *result=NULL; + status = U_ZERO_ERROR; + resLen=0; + log_verbose("Testing unorm_normalize with Decomp canonical\n"); + for(x=0; x < LENGTHOF(canonTests); x++) + { + source=CharsToUChars(canonTests[x][0]); + neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resLen=neededLen+1; + result=(UChar*)malloc(sizeof(UChar*) * resLen); + unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, result, resLen, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); + } else { + assertEqual(result, canonTests[x][1], x); + } + free(result); + free(source); + } +} + +void TestCompatDecomp() +{ + UErrorCode status = U_ZERO_ERROR; + int32_t x, neededLen, resLen; + UChar *source=NULL, *result=NULL; + status = U_ZERO_ERROR; + resLen=0; + log_verbose("Testing unorm_normalize with Decomp compat\n"); + for(x=0; x < LENGTHOF(compatTests); x++) + { + source=CharsToUChars(compatTests[x][0]); + neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resLen=neededLen+1; + result=(UChar*)malloc(sizeof(UChar*) * resLen); + unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, result, resLen, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); + } else { + assertEqual(result, compatTests[x][1], x); + } + free(result); + free(source); + } +} + +void TestCanonDecompCompose() +{ + UErrorCode status = U_ZERO_ERROR; + int32_t x, neededLen, resLen; + UChar *source=NULL, *result=NULL; + status = U_ZERO_ERROR; + resLen=0; + log_verbose("Testing unorm_normalize with Decomp can compose compat\n"); + for(x=0; x < LENGTHOF(canonTests); x++) + { + source=CharsToUChars(canonTests[x][0]); + neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resLen=neededLen+1; + result=(UChar*)malloc(sizeof(UChar*) * resLen); + unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, result, resLen, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source),myErrorName(status) ); + } else { + assertEqual(result, canonTests[x][2], x); + } + free(result); + free(source); + } +} + +void TestCompatDecompCompose() +{ + UErrorCode status = U_ZERO_ERROR; + int32_t x, neededLen, resLen; + UChar *source=NULL, *result=NULL; + status = U_ZERO_ERROR; + resLen=0; + log_verbose("Testing unorm_normalize with compat decomp compose can\n"); + for(x=0; x < LENGTHOF(compatTests); x++) + { + source=CharsToUChars(compatTests[x][0]); + neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, NULL, 0, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resLen=neededLen+1; + result=(UChar*)malloc(sizeof(UChar*) * resLen); + unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, result, resLen, &status); + } + if(U_FAILURE(status)){ + log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) ); + } else { + assertEqual(result, compatTests[x][2], x); + } + free(result); + free(source); + } +} + + +/* +static void assertEqual(const UChar* result, const UChar* expected, int32_t index) +{ + if(u_strcmp(result, expected)!=0){ + log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, austrdup(expected), + austrdup(result) ); + } +} +*/ + +static void assertEqual(const UChar* result, const char* expected, int32_t index) +{ + UChar *expectedUni = CharsToUChars(expected); + if(u_strcmp(result, expectedUni)!=0){ + log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, expected, + austrdup(result) ); + } + free(expectedUni); +} + +static void TestNull_check(UChar *src, int32_t srcLen, + UChar *exp, int32_t expLen, + UNormalizationMode mode, + const char *name) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t len, i; + + UChar result[50]; + + + status = U_ZERO_ERROR; + + for(i=0;i<50;i++) + { + result[i] = 0xFFFD; + } + + len = unorm_normalize(src, srcLen, mode, 0, result, 50, &status); + + if(U_FAILURE(status)) { + log_err("unorm_normalize(%s) with 0x0000 failed: %s\n", name, u_errorName(status)); + } else if (len != expLen) { + log_err("unorm_normalize(%s) with 0x0000 failed: Expected len %d, got %d\n", name, expLen, len); + } + + { + for(i=0;i<len;i++){ + if(exp[i] != result[i]) { + log_err("unorm_normalize(%s): @%d, expected \\u%04X got \\u%04X\n", + name, + i, + exp[i], + result[i]); + return; + } + log_verbose(" %d: \\u%04X\n", i, result[i]); + } + } + + log_verbose("unorm_normalize(%s) with 0x0000: OK\n", name); +} + +void TestNull() +{ + + UChar source_comp[] = { 0x0061, 0x0000, 0x0044, 0x0307 }; + int32_t source_comp_len = 4; + UChar expect_comp[] = { 0x0061, 0x0000, 0x1e0a }; + int32_t expect_comp_len = 3; + + UChar source_dcmp[] = { 0x1e0A, 0x0000, 0x0929 }; + int32_t source_dcmp_len = 3; + UChar expect_dcmp[] = { 0x0044, 0x0307, 0x0000, 0x0928, 0x093C }; + int32_t expect_dcmp_len = 5; + + TestNull_check(source_comp, + source_comp_len, + expect_comp, + expect_comp_len, + UNORM_NFC, + "UNORM_NFC"); + + TestNull_check(source_dcmp, + source_dcmp_len, + expect_dcmp, + expect_dcmp_len, + UNORM_NFD, + "UNORM_NFD"); + + TestNull_check(source_comp, + source_comp_len, + expect_comp, + expect_comp_len, + UNORM_NFKC, + "UNORM_NFKC"); + + +} + +static void TestQuickCheckResultNO() +{ + const UChar CPNFD[] = {0x00C5, 0x0407, 0x1E00, 0x1F57, 0x220C, + 0x30AE, 0xAC00, 0xD7A3, 0xFB36, 0xFB4E}; + const UChar CPNFC[] = {0x0340, 0x0F93, 0x1F77, 0x1FBB, 0x1FEB, + 0x2000, 0x232A, 0xF900, 0xFA1E, 0xFB4E}; + const UChar CPNFKD[] = {0x00A0, 0x02E4, 0x1FDB, 0x24EA, 0x32FE, + 0xAC00, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D}; + const UChar CPNFKC[] = {0x00A0, 0x017F, 0x2000, 0x24EA, 0x32FE, + 0x33FE, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D}; + + + const int SIZE = 10; + + int count = 0; + UErrorCode error = U_ZERO_ERROR; + + for (; count < SIZE; count ++) + { + if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) != + UNORM_NO) + { + log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]); + return; + } + if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) != + UNORM_NO) + { + log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); + return; + } + if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) != + UNORM_NO) + { + log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]); + return; + } + if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != + UNORM_NO) + { + log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); + return; + } + } +} + + +static void TestQuickCheckResultYES() +{ + const UChar CPNFD[] = {0x00C6, 0x017F, 0x0F74, 0x1000, 0x1E9A, + 0x2261, 0x3075, 0x4000, 0x5000, 0xF000}; + const UChar CPNFC[] = {0x0400, 0x0540, 0x0901, 0x1000, 0x1500, + 0x1E9A, 0x3000, 0x4000, 0x5000, 0xF000}; + const UChar CPNFKD[] = {0x00AB, 0x02A0, 0x1000, 0x1027, 0x2FFB, + 0x3FFF, 0x4FFF, 0xA000, 0xF000, 0xFA27}; + const UChar CPNFKC[] = {0x00B0, 0x0100, 0x0200, 0x0A02, 0x1000, + 0x2010, 0x3030, 0x4000, 0xA000, 0xFA0E}; + + const int SIZE = 10; + int count = 0; + UErrorCode error = U_ZERO_ERROR; + + UChar cp = 0; + while (cp < 0xA0) + { + if (unorm_quickCheck(&cp, 1, UNORM_NFD, &error) != UNORM_YES) + { + log_err("ERROR in NFD quick check at U+%04x\n", cp); + return; + } + if (unorm_quickCheck(&cp, 1, UNORM_NFC, &error) != + UNORM_YES) + { + log_err("ERROR in NFC quick check at U+%04x\n", cp); + return; + } + if (unorm_quickCheck(&cp, 1, UNORM_NFKD, &error) != UNORM_YES) + { + log_err("ERROR in NFKD quick check at U+%04x\n", cp); + return; + } + if (unorm_quickCheck(&cp, 1, UNORM_NFKC, &error) != + UNORM_YES) + { + log_err("ERROR in NFKC quick check at U+%04x\n", cp); + return; + } + cp ++; + } + + for (; count < SIZE; count ++) + { + if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) != + UNORM_YES) + { + log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]); + return; + } + if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) + != UNORM_YES) + { + log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); + return; + } + if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) != + UNORM_YES) + { + log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]); + return; + } + if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != + UNORM_YES) + { + log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); + return; + } + } +} + +static void TestQuickCheckResultMAYBE() +{ + const UChar CPNFC[] = {0x0306, 0x0654, 0x0BBE, 0x102E, 0x1161, + 0x116A, 0x1173, 0x1175, 0x3099, 0x309A}; + const UChar CPNFKC[] = {0x0300, 0x0654, 0x0655, 0x09D7, 0x0B3E, + 0x0DCF, 0xDDF, 0x102E, 0x11A8, 0x3099}; + + + const int SIZE = 10; + + int count = 0; + UErrorCode error = U_ZERO_ERROR; + + /* NFD and NFKD does not have any MAYBE codepoints */ + for (; count < SIZE; count ++) + { + if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) != + UNORM_MAYBE) + { + log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]); + return; + } + if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) != + UNORM_MAYBE) + { + log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]); + return; + } + } +} + +static void TestQuickCheckStringResult() +{ + int count; + UChar *d = NULL; + UChar *c = NULL; + UErrorCode error = U_ZERO_ERROR; + + for (count = 0; count < LENGTHOF(canonTests); count ++) + { + d = CharsToUChars(canonTests[count][1]); + c = CharsToUChars(canonTests[count][2]); + if (unorm_quickCheck(d, u_strlen(d), UNORM_NFD, &error) != + UNORM_YES) + { + log_err("ERROR in NFD quick check for string at count %d\n", count); + return; + } + + if (unorm_quickCheck(c, u_strlen(c), UNORM_NFC, &error) == + UNORM_NO) + { + log_err("ERROR in NFC quick check for string at count %d\n", count); + return; + } + + free(d); + free(c); + } + + for (count = 0; count < LENGTHOF(compatTests); count ++) + { + d = CharsToUChars(compatTests[count][1]); + c = CharsToUChars(compatTests[count][2]); + if (unorm_quickCheck(d, u_strlen(d), UNORM_NFKD, &error) != + UNORM_YES) + { + log_err("ERROR in NFKD quick check for string at count %d\n", count); + return; + } + + if (unorm_quickCheck(c, u_strlen(c), UNORM_NFKC, &error) != + UNORM_YES) + { + log_err("ERROR in NFKC quick check for string at count %d\n", count); + return; + } + + free(d); + free(c); + } +} + +void TestQuickCheck() +{ + TestQuickCheckResultNO(); + TestQuickCheckResultYES(); + TestQuickCheckResultMAYBE(); + TestQuickCheckStringResult(); +} + +/* + * The intltest/NormalizerConformanceTest tests a lot of strings that _are_ + * normalized, and some that are not. + * Here we pick some specific cases and test the C API. + */ +static void TestIsNormalized(void) { + static const UChar notNFC[][8]={ /* strings that are not in NFC */ + { 0x62, 0x61, 0x300, 0x63, 0 }, /* 0061 0300 compose */ + { 0xfb1d, 0 }, /* excluded from composition */ + { 0x0627, 0x0653, 0 }, /* 0627 0653 compose */ + { 0x3071, 0x306f, 0x309a, 0x3073, 0 } /* 306F 309A compose */ + }; + static const UChar notNFKC[][8]={ /* strings that are not in NFKC */ + { 0x1100, 0x1161, 0 }, /* Jamo compose */ + { 0x1100, 0x314f, 0 }, /* compatibility Jamo compose */ + { 0x03b1, 0x1f00, 0x0345, 0x03b3, 0 } /* 1F00 0345 compose */ + }; + + int32_t i; + UErrorCode errorCode; + + /* API test */ + + /* normal case with length>=0 (length -1 used for special cases below) */ + errorCode=U_ZERO_ERROR; + if(!unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error: !isNormalized(<U+0300>, NFC) (%s)\n", u_errorName(errorCode)); + } + + /* incoming U_FAILURE */ + errorCode=U_TRUNCATED_CHAR_FOUND; + (void)unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode); + if(errorCode!=U_TRUNCATED_CHAR_FOUND) { + log_err("error: isNormalized(U_TRUNCATED_CHAR_FOUND) changed the error code to %s\n", u_errorName(errorCode)); + } + + /* NULL source */ + errorCode=U_ZERO_ERROR; + (void)unorm_isNormalized(NULL, 1, UNORM_NFC, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error: isNormalized(NULL) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode)); + } + + /* bad length */ + errorCode=U_ZERO_ERROR; + (void)unorm_isNormalized(notNFC[0]+2, -2, UNORM_NFC, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error: isNormalized([-2]) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode)); + } + + /* specific cases */ + for(i=0; i<LENGTHOF(notNFC); ++i) { + errorCode=U_ZERO_ERROR; + if(unorm_isNormalized(notNFC[i], -1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error: isNormalized(notNFC[%d], NFC) is wrong (%s)\n", i, u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + if(unorm_isNormalized(notNFC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error: isNormalized(notNFC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode)); + } + } + for(i=0; i<LENGTHOF(notNFKC); ++i) { + errorCode=U_ZERO_ERROR; + if(unorm_isNormalized(notNFKC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error: isNormalized(notNFKC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode)); + } + } +} + +void TestCheckFCD() +{ + UErrorCode status = U_ZERO_ERROR; + static const UChar FAST_[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A}; + static const UChar FALSE_[] = {0x0001, 0x0002, 0x02EA, 0x03EB, 0x0300, 0x0301, + 0x02B9, 0x0314, 0x0315, 0x0316}; + static const UChar TRUE_[] = {0x0030, 0x0040, 0x0440, 0x056D, 0x064F, 0x06E7, + 0x0050, 0x0730, 0x09EE, 0x1E10}; + + static const UChar datastr[][5] = + { {0x0061, 0x030A, 0x1E05, 0x0302, 0}, + {0x0061, 0x030A, 0x00E2, 0x0323, 0}, + {0x0061, 0x0323, 0x00E2, 0x0323, 0}, + {0x0061, 0x0323, 0x1E05, 0x0302, 0} }; + static const UBool result[] = {UNORM_YES, UNORM_NO, UNORM_NO, UNORM_YES}; + + static const UChar datachar[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, + 0x0307, 0x0308, 0x0309, 0x030a, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, + 0x0327, 0x0328, 0x0329, 0x032a, + 0x1e00, 0x1e01, 0x1e02, 0x1e03, 0x1e04, 0x1e05, 0x1e06, + 0x1e07, 0x1e08, 0x1e09, 0x1e0a}; + + int count = 0; + + if (unorm_quickCheck(FAST_, 10, UNORM_FCD, &status) != UNORM_YES) + log_err("unorm_quickCheck(FCD) failed: expected value for fast unorm_quickCheck is UNORM_YES\n"); + if (unorm_quickCheck(FALSE_, 10, UNORM_FCD, &status) != UNORM_NO) + log_err("unorm_quickCheck(FCD) failed: expected value for error unorm_quickCheck is UNORM_NO\n"); + if (unorm_quickCheck(TRUE_, 10, UNORM_FCD, &status) != UNORM_YES) + log_err("unorm_quickCheck(FCD) failed: expected value for correct unorm_quickCheck is UNORM_YES\n"); + + if (U_FAILURE(status)) + log_err("unorm_quickCheck(FCD) failed: %s\n", u_errorName(status)); + + while (count < 4) + { + UBool fcdresult = unorm_quickCheck(datastr[count], 4, UNORM_FCD, &status); + if (U_FAILURE(status)) { + log_err("unorm_quickCheck(FCD) failed: exception occured at data set %d\n", count); + break; + } + else { + if (result[count] != fcdresult) { + log_err("unorm_quickCheck(FCD) failed: Data set %d expected value %d\n", count, + result[count]); + } + } + count ++; + } + + /* random checks of long strings */ + status = U_ZERO_ERROR; + srand((unsigned)time( NULL )); + + for (count = 0; count < 50; count ++) + { + int size = 0; + UBool testresult = UNORM_YES; + UChar data[20]; + UChar norm[100]; + UChar nfd[100]; + int normsize = 0; + int nfdsize = 0; + + while (size != 19) { + data[size] = datachar[(rand() * 50) / RAND_MAX]; + log_verbose("0x%x", data[size]); + normsize += unorm_normalize(data + size, 1, UNORM_NFD, 0, + norm + normsize, 100 - normsize, &status); + if (U_FAILURE(status)) { + log_err("unorm_quickCheck(FCD) failed: exception occured at data generation\n"); + break; + } + size ++; + } + log_verbose("\n"); + + nfdsize = unorm_normalize(data, size, UNORM_NFD, 0, + nfd, 100, &status); + if (U_FAILURE(status)) { + log_err("unorm_quickCheck(FCD) failed: exception occured at normalized data generation\n"); + } + + if (nfdsize != normsize || u_memcmp(nfd, norm, nfdsize) != 0) { + testresult = UNORM_NO; + } + if (testresult == UNORM_YES) { + log_verbose("result UNORM_YES\n"); + } + else { + log_verbose("result UNORM_NO\n"); + } + + if (unorm_quickCheck(data, size, UNORM_FCD, &status) != testresult || U_FAILURE(status)) { + log_err("unorm_quickCheck(FCD) failed: expected %d for random data\n", testresult); + } + } +} + +static void +TestAPI() { + static const UChar in[]={ 0x68, 0xe4 }; + UChar out[20]={ 0xffff, 0xffff, 0xffff, 0xffff }; + UErrorCode errorCode; + int32_t length; + + /* try preflighting */ + errorCode=U_ZERO_ERROR; + length=unorm_normalize(in, 2, UNORM_NFD, 0, NULL, 0, &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3) { + log_err("unorm_normalize(pure preflighting NFD)=%ld failed with %s\n", length, u_errorName(errorCode)); + return; + } + + errorCode=U_ZERO_ERROR; + length=unorm_normalize(in, 2, UNORM_NFD, 0, out, 3, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unorm_normalize(NFD)=%ld failed with %s\n", length, u_errorName(errorCode)); + return; + } + if(length!=3 || out[2]!=0x308 || out[3]!=0xffff) { + log_err("unorm_normalize(NFD ma<umlaut>)=%ld failed with out[]=U+%04x U+%04x U+%04x U+%04x\n", length, out[0], out[1], out[2], out[3]); + return; + } +} + +/* test cases to improve test code coverage */ +enum { + HANGUL_K_KIYEOK=0x3131, /* NFKD->Jamo L U+1100 */ + HANGUL_K_WEO=0x315d, /* NFKD->Jamo V U+116f */ + HANGUL_K_KIYEOK_SIOS=0x3133, /* NFKD->Jamo T U+11aa */ + + HANGUL_KIYEOK=0x1100, /* Jamo L U+1100 */ + HANGUL_WEO=0x116f, /* Jamo V U+116f */ + HANGUL_KIYEOK_SIOS=0x11aa, /* Jamo T U+11aa */ + + HANGUL_AC00=0xac00, /* Hangul syllable = Jamo LV U+ac00 */ + HANGUL_SYLLABLE=0xac00+14*28+3, /* Hangul syllable = U+1100 * U+116f * U+11aa */ + + MUSICAL_VOID_NOTEHEAD=0x1d157, + MUSICAL_HALF_NOTE=0x1d15e, /* NFC/NFD->Notehead+Stem */ + MUSICAL_STEM=0x1d165, /* cc=216 */ + MUSICAL_STACCATO=0x1d17c /* cc=220 */ +}; + +static void +TestNormCoverage() { + UChar input[1000], expect[1000], output[1000]; + UErrorCode errorCode; + int32_t i, length, inLength, expectLength, hangulPrefixLength, preflightLength; + + /* create a long and nasty string with NFKC-unsafe characters */ + inLength=0; + + /* 3 Jamos L/V/T, all 8 combinations normal/compatibility */ + input[inLength++]=HANGUL_KIYEOK; + input[inLength++]=HANGUL_WEO; + input[inLength++]=HANGUL_KIYEOK_SIOS; + + input[inLength++]=HANGUL_KIYEOK; + input[inLength++]=HANGUL_WEO; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + input[inLength++]=HANGUL_KIYEOK; + input[inLength++]=HANGUL_K_WEO; + input[inLength++]=HANGUL_KIYEOK_SIOS; + + input[inLength++]=HANGUL_KIYEOK; + input[inLength++]=HANGUL_K_WEO; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_WEO; + input[inLength++]=HANGUL_KIYEOK_SIOS; + + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_WEO; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_K_WEO; + input[inLength++]=HANGUL_KIYEOK_SIOS; + + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_K_WEO; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + /* Hangul LV with normal/compatibility Jamo T */ + input[inLength++]=HANGUL_AC00; + input[inLength++]=HANGUL_KIYEOK_SIOS; + + input[inLength++]=HANGUL_AC00; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + /* compatibility Jamo L, V */ + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_K_WEO; + + hangulPrefixLength=inLength; + + input[inLength++]=UTF16_LEAD(MUSICAL_HALF_NOTE); + input[inLength++]=UTF16_TRAIL(MUSICAL_HALF_NOTE); + for(i=0; i<200; ++i) { + input[inLength++]=UTF16_LEAD(MUSICAL_STACCATO); + input[inLength++]=UTF16_TRAIL(MUSICAL_STACCATO); + input[inLength++]=UTF16_LEAD(MUSICAL_STEM); + input[inLength++]=UTF16_TRAIL(MUSICAL_STEM); + } + + /* (compatibility) Jamo L, T do not compose */ + input[inLength++]=HANGUL_K_KIYEOK; + input[inLength++]=HANGUL_K_KIYEOK_SIOS; + + /* quick checks */ + errorCode=U_ZERO_ERROR; + if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFD, &errorCode) || U_FAILURE(errorCode)) { + log_err("error unorm_quickCheck(long input, UNORM_NFD)!=NO (%s)\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKD, &errorCode) || U_FAILURE(errorCode)) { + log_err("error unorm_quickCheck(long input, UNORM_NFKD)!=NO (%s)\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error unorm_quickCheck(long input, UNORM_NFC)!=NO (%s)\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) { + log_err("error unorm_quickCheck(long input, UNORM_NFKC)!=NO (%s)\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_FCD, &errorCode) || U_FAILURE(errorCode)) { + log_err("error unorm_quickCheck(long input, UNORM_FCD)!=NO (%s)\n", u_errorName(errorCode)); + } + + /* NFKC */ + expectLength=0; + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_SYLLABLE; + + expect[expectLength++]=HANGUL_AC00+3; + + expect[expectLength++]=HANGUL_AC00+3; + + expect[expectLength++]=HANGUL_AC00+14*28; + + expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD); + expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); + for(i=0; i<200; ++i) { + expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); + } + for(i=0; i<200; ++i) { + expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO); + } + + expect[expectLength++]=HANGUL_KIYEOK; + expect[expectLength++]=HANGUL_KIYEOK_SIOS; + + /* try destination overflow first */ + errorCode=U_ZERO_ERROR; + preflightLength=unorm_normalize(input, inLength, + UNORM_NFKC, 0, + output, 100, /* too short */ + &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR) { + log_err("error unorm_normalize(long input, output too short, UNORM_NFKC) did not overflow but %s\n", u_errorName(errorCode)); + } + + /* real NFKC */ + errorCode=U_ZERO_ERROR; + length=unorm_normalize(input, inLength, + UNORM_NFKC, 0, + output, sizeof(output)/U_SIZEOF_UCHAR, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error unorm_normalize(long input, UNORM_NFKC) failed with %s\n", u_errorName(errorCode)); + } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) { + log_err("error unorm_normalize(long input, UNORM_NFKC) produced wrong result\n"); + for(i=0; i<length; ++i) { + if(output[i]!=expect[i]) { + log_err(" NFKC[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]); + break; + } + } + } + if(length!=preflightLength) { + log_err("error unorm_normalize(long input, UNORM_NFKC)==%ld but preflightLength==%ld\n", length, preflightLength); + } + + /* FCD */ + u_memcpy(expect, input, hangulPrefixLength); + expectLength=hangulPrefixLength; + + expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD); + expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); + for(i=0; i<200; ++i) { + expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM); + } + for(i=0; i<200; ++i) { + expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO); + expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO); + } + + expect[expectLength++]=HANGUL_K_KIYEOK; + expect[expectLength++]=HANGUL_K_KIYEOK_SIOS; + + errorCode=U_ZERO_ERROR; + length=unorm_normalize(input, inLength, + UNORM_FCD, 0, + output, sizeof(output)/U_SIZEOF_UCHAR, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error unorm_normalize(long input, UNORM_FCD) failed with %s\n", u_errorName(errorCode)); + } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) { + log_err("error unorm_normalize(long input, UNORM_FCD) produced wrong result\n"); + for(i=0; i<length; ++i) { + if(output[i]!=expect[i]) { + log_err(" FCD[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]); + break; + } + } + } +} + +/* API test for unorm_concatenate() - for real test strings see intltest/tstnorm.cpp */ +static void +TestConcatenate(void) { + /* "re + 'sume'" */ + static const UChar + left[]={ + 0x72, 0x65, 0 + }, + right[]={ + 0x301, 0x73, 0x75, 0x6d, 0xe9, 0 + }, + expect[]={ + 0x72, 0xe9, 0x73, 0x75, 0x6d, 0xe9, 0 + }; + + UChar buffer[100]; + UErrorCode errorCode; + int32_t length; + + /* left with length, right NUL-terminated */ + errorCode=U_ZERO_ERROR; + length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); + if(U_FAILURE(errorCode) || length!=6 || 0!=u_memcmp(buffer, expect, length)) { + log_err("error: unorm_concatenate()=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); + } + + /* preflighting */ + errorCode=U_ZERO_ERROR; + length=unorm_concatenate(left, 2, right, -1, NULL, 0, UNORM_NFC, 0, &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6) { + log_err("error: unorm_concatenate(preflighting)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); + } + + buffer[2]=0x5555; + errorCode=U_ZERO_ERROR; + length=unorm_concatenate(left, 2, right, -1, buffer, 1, UNORM_NFC, 0, &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6 || buffer[2]!=0x5555) { + log_err("error: unorm_concatenate(preflighting 2)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode)); + } + + /* enter with U_FAILURE */ + buffer[2]=0xaaaa; + errorCode=U_UNEXPECTED_TOKEN; + length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); + if(errorCode!=U_UNEXPECTED_TOKEN || buffer[2]!=0xaaaa) { + log_err("error: unorm_concatenate(failure)=%ld failed with %s\n", length, u_errorName(errorCode)); + } + + /* illegal arguments */ + buffer[2]=0xaaaa; + errorCode=U_ZERO_ERROR; + length=unorm_concatenate(NULL, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[2]!=0xaaaa) { + log_err("error: unorm_concatenate(left=NULL)=%ld failed with %s\n", length, u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + length=unorm_concatenate(left, 2, right, -1, NULL, 100, UNORM_NFC, 0, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error: unorm_concatenate(buffer=NULL)=%ld failed with %s\n", length, u_errorName(errorCode)); + } +} + +enum { + _PLUS=0x2b +}; + +static const char *const _modeString[UNORM_MODE_COUNT]={ + "0", "NONE", "NFD", "NFKD", "NFC", "NFKC", "FCD" +}; + +static void +_testIter(const UChar *src, int32_t srcLength, + UCharIterator *iter, UNormalizationMode mode, UBool forward, + const UChar *out, int32_t outLength, + const int32_t *srcIndexes, int32_t srcIndexesLength) { + UChar buffer[4]; + const UChar *expect, *outLimit, *in; + int32_t length, i, expectLength, expectIndex, prevIndex, index, inLength; + UErrorCode errorCode; + UBool neededToNormalize, expectNeeded; + + errorCode=U_ZERO_ERROR; + outLimit=out+outLength; + if(forward) { + expect=out; + i=index=0; + } else { + expect=outLimit; + i=srcIndexesLength-2; + index=srcLength; + } + + for(;;) { + prevIndex=index; + if(forward) { + if(!iter->hasNext(iter)) { + return; + } + length=unorm_next(iter, + buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + mode, 0, + (UBool)(out!=NULL), &neededToNormalize, + &errorCode); + expectIndex=srcIndexes[i+1]; + in=src+prevIndex; + inLength=expectIndex-prevIndex; + + if(out!=NULL) { + /* get output piece from between plus signs */ + expectLength=0; + while((expect+expectLength)!=outLimit && expect[expectLength]!=_PLUS) { + ++expectLength; + } + expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength)); + } else { + expect=in; + expectLength=inLength; + expectNeeded=FALSE; + } + } else { + if(!iter->hasPrevious(iter)) { + return; + } + length=unorm_previous(iter, + buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + mode, 0, + (UBool)(out!=NULL), &neededToNormalize, + &errorCode); + expectIndex=srcIndexes[i]; + in=src+expectIndex; + inLength=prevIndex-expectIndex; + + if(out!=NULL) { + /* get output piece from between plus signs */ + expectLength=0; + while(expect!=out && expect[-1]!=_PLUS) { + ++expectLength; + --expect; + } + expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength)); + } else { + expect=in; + expectLength=inLength; + expectNeeded=FALSE; + } + } + index=iter->getIndex(iter, UITER_CURRENT); + + if(U_FAILURE(errorCode)) { + log_err("error unorm iteration (next/previous %d %s)[%d]: %s\n", + forward, _modeString[mode], i, u_errorName(errorCode)); + return; + } + if(expectIndex!=index) { + log_err("error unorm iteration (next/previous %d %s): index[%d] wrong, got %d expected %d\n", + forward, _modeString[mode], i, index, expectIndex); + return; + } + if(expectLength!=length) { + log_err("error unorm iteration (next/previous %d %s): length[%d] wrong, got %d expected %d\n", + forward, _modeString[mode], i, length, expectLength); + return; + } + if(0!=u_memcmp(expect, buffer, length)) { + log_err("error unorm iteration (next/previous %d %s): output string[%d] wrong\n", + forward, _modeString[mode], i); + return; + } + if(neededToNormalize!=expectNeeded) { + } + + if(forward) { + expect+=expectLength+1; /* go after the + */ + ++i; + } else { + --expect; /* go before the + */ + --i; + } + } +} + +static void +TestNextPrevious() { + static const UChar + src[]={ /* input string */ + 0xa0, 0xe4, 0x63, 0x302, 0x327, 0xac00, 0x3133 + }, + nfd[]={ /* + separates expected output pieces */ + 0xa0, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x3133 + }, + nfkd[]={ + 0x20, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x11aa + }, + nfc[]={ + 0xa0, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac00, _PLUS, 0x3133 + }, + nfkc[]={ + 0x20, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac03 + }, + fcd[]={ + 0xa0, _PLUS, 0xe4, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0xac00, _PLUS, 0x3133 + }; + + /* expected iterator indexes in the source string for each iteration piece */ + static const int32_t + nfdIndexes[]={ + 0, 1, 2, 5, 6, 7 + }, + nfkdIndexes[]={ + 0, 1, 2, 5, 6, 7 + }, + nfcIndexes[]={ + 0, 1, 2, 5, 6, 7 + }, + nfkcIndexes[]={ + 0, 1, 2, 5, 7 + }, + fcdIndexes[]={ + 0, 1, 2, 5, 6, 7 + }; + + UCharIterator iter; + + UChar buffer[4]; + int32_t length; + + UBool neededToNormalize; + UErrorCode errorCode; + + uiter_setString(&iter, src, sizeof(src)/U_SIZEOF_UCHAR); + + /* test iteration with doNormalize */ + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4); + + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4); + + /* test iteration without doNormalize */ + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4); + iter.index=0; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4); + + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4); + iter.index=iter.length; + _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4); + + /* try without neededToNormalize */ + errorCode=U_ZERO_ERROR; + buffer[0]=5; + iter.index=1; + length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + UNORM_NFD, 0, TRUE, NULL, + &errorCode); + if(U_FAILURE(errorCode) || length!=2 || buffer[0]!=nfd[2] || buffer[1]!=nfd[3]) { + log_err("error unorm_next(without needed) %s\n", u_errorName(errorCode)); + return; + } + + /* preflight */ + neededToNormalize=9; + iter.index=1; + length=unorm_next(&iter, NULL, 0, + UNORM_NFD, 0, TRUE, &neededToNormalize, + &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2) { + log_err("error unorm_next(pure preflighting) %s\n", u_errorName(errorCode)); + return; + } + + errorCode=U_ZERO_ERROR; + buffer[0]=buffer[1]=5; + neededToNormalize=9; + iter.index=1; + length=unorm_next(&iter, buffer, 1, + UNORM_NFD, 0, TRUE, &neededToNormalize, + &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2 || buffer[1]!=5) { + log_err("error unorm_next(preflighting) %s\n", u_errorName(errorCode)); + return; + } + + /* no iterator */ + errorCode=U_ZERO_ERROR; + buffer[0]=buffer[1]=5; + neededToNormalize=9; + iter.index=1; + length=unorm_next(NULL, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + UNORM_NFD, 0, TRUE, &neededToNormalize, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error unorm_next(no iterator) %s\n", u_errorName(errorCode)); + return; + } + + /* illegal mode */ + buffer[0]=buffer[1]=5; + neededToNormalize=9; + iter.index=1; + length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + (UNormalizationMode)0, 0, TRUE, &neededToNormalize, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error unorm_next(illegal mode) %s\n", u_errorName(errorCode)); + return; + } + + /* error coming in */ + errorCode=U_MISPLACED_QUANTIFIER; + buffer[0]=5; + iter.index=1; + length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + UNORM_NFD, 0, TRUE, NULL, + &errorCode); + if(errorCode!=U_MISPLACED_QUANTIFIER) { + log_err("error unorm_next(U_MISPLACED_QUANTIFIER) %s\n", u_errorName(errorCode)); + return; + } + + /* missing pErrorCode */ + buffer[0]=5; + iter.index=1; + length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + UNORM_NFD, 0, TRUE, NULL, + NULL); + if(iter.index!=1 || buffer[0]!=5) { + log_err("error unorm_next(pErrorCode==NULL) %s\n", u_errorName(errorCode)); + return; + } +} + +static void +TestFCNFKCClosure(void) { + static const struct { + UChar32 c; + const UChar s[6]; + } tests[]={ + { 0x037A, { 0x0020, 0x03B9, 0 } }, + { 0x03D2, { 0x03C5, 0 } }, + { 0x20A8, { 0x0072, 0x0073, 0 } }, + { 0x210B, { 0x0068, 0 } }, + { 0x210C, { 0x0068, 0 } }, + { 0x2121, { 0x0074, 0x0065, 0x006C, 0 } }, + { 0x2122, { 0x0074, 0x006D, 0 } }, + { 0x2128, { 0x007A, 0 } }, + { 0x1D5DB, { 0x0068, 0 } }, + { 0x1D5ED, { 0x007A, 0 } }, + { 0x0061, { 0 } } + }; + + UChar buffer[8]; + UErrorCode errorCode; + int32_t i, length; + + for(i=0; i<LENGTHOF(tests); ++i) { + errorCode=U_ZERO_ERROR; + length=u_getFC_NFKC_Closure(tests[i].c, buffer, LENGTHOF(buffer), &errorCode); + if(U_FAILURE(errorCode) || length!=u_strlen(buffer) || 0!=u_strcmp(tests[i].s, buffer)) { + log_err("u_getFC_NFKC_Closure(U+%04lx) is wrong (%s)\n", tests[i].c, u_errorName(errorCode)); + } + } + + /* error handling */ + errorCode=U_ZERO_ERROR; + length=u_getFC_NFKC_Closure(0x5c, NULL, LENGTHOF(buffer), &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("u_getFC_NFKC_Closure(dest=NULL) is wrong (%s)\n", u_errorName(errorCode)); + } + + length=u_getFC_NFKC_Closure(0x5c, buffer, LENGTHOF(buffer), &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("u_getFC_NFKC_Closure(U_FAILURE) is wrong (%s)\n", u_errorName(errorCode)); + } +} + +static void +TestQuickCheckPerCP() { + UErrorCode errorCode; + UChar32 c, lead, trail; + UChar s[U16_MAX_LENGTH], nfd[16]; + int32_t length, lccc1, lccc2, tccc1, tccc2; + int32_t qc1, qc2; + + if( + u_getIntPropertyMaxValue(UCHAR_NFD_QUICK_CHECK)!=(int32_t)UNORM_YES || + u_getIntPropertyMaxValue(UCHAR_NFKD_QUICK_CHECK)!=(int32_t)UNORM_YES || + u_getIntPropertyMaxValue(UCHAR_NFC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE || + u_getIntPropertyMaxValue(UCHAR_NFKC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE || + u_getIntPropertyMaxValue(UCHAR_LEAD_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) || + u_getIntPropertyMaxValue(UCHAR_TRAIL_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) + ) { + log_err("wrong result from one of the u_getIntPropertyMaxValue(UCHAR_NF*_QUICK_CHECK) or UCHAR_*_CANONICAL_COMBINING_CLASS\n"); + } + + /* + * compare the quick check property values for some code points + * to the quick check results for checking same-code point strings + */ + errorCode=U_ZERO_ERROR; + c=0; + while(c<0x110000) { + length=0; + U16_APPEND_UNSAFE(s, length, c); + + qc1=u_getIntPropertyValue(c, UCHAR_NFC_QUICK_CHECK); + qc2=unorm_quickCheck(s, length, UNORM_NFC, &errorCode); + if(qc1!=qc2) { + log_err("u_getIntPropertyValue(NFC)=%d != %d=unorm_quickCheck(NFC) for U+%04x\n", qc1, qc2, c); + } + + qc1=u_getIntPropertyValue(c, UCHAR_NFD_QUICK_CHECK); + qc2=unorm_quickCheck(s, length, UNORM_NFD, &errorCode); + if(qc1!=qc2) { + log_err("u_getIntPropertyValue(NFD)=%d != %d=unorm_quickCheck(NFD) for U+%04x\n", qc1, qc2, c); + } + + qc1=u_getIntPropertyValue(c, UCHAR_NFKC_QUICK_CHECK); + qc2=unorm_quickCheck(s, length, UNORM_NFKC, &errorCode); + if(qc1!=qc2) { + log_err("u_getIntPropertyValue(NFKC)=%d != %d=unorm_quickCheck(NFKC) for U+%04x\n", qc1, qc2, c); + } + + qc1=u_getIntPropertyValue(c, UCHAR_NFKD_QUICK_CHECK); + qc2=unorm_quickCheck(s, length, UNORM_NFKD, &errorCode); + if(qc1!=qc2) { + log_err("u_getIntPropertyValue(NFKD)=%d != %d=unorm_quickCheck(NFKD) for U+%04x\n", qc1, qc2, c); + } + + length=unorm_normalize(s, length, UNORM_NFD, 0, nfd, LENGTHOF(nfd), &errorCode); + /* length-length == 0 is used to get around a compiler warning. */ + U16_GET(nfd, 0, length-length, length, lead); + U16_GET(nfd, 0, length-1, length, trail); + + lccc1=u_getIntPropertyValue(c, UCHAR_LEAD_CANONICAL_COMBINING_CLASS); + lccc2=u_getCombiningClass(lead); + tccc1=u_getIntPropertyValue(c, UCHAR_TRAIL_CANONICAL_COMBINING_CLASS); + tccc2=u_getCombiningClass(trail); + + if(lccc1!=lccc2) { + log_err("u_getIntPropertyValue(lccc)=%d != %d=u_getCombiningClass(lead) for U+%04x\n", + lccc1, lccc2, c); + } + if(tccc1!=tccc2) { + log_err("u_getIntPropertyValue(tccc)=%d != %d=u_getCombiningClass(trail) for U+%04x\n", + tccc1, tccc2, c); + } + + /* skip some code points */ + c=(20*c)/19+1; + } +} + +static void +TestComposition(void) { + static const struct { + UNormalizationMode mode; + uint32_t options; + UChar input[12]; + UChar expect[12]; + } cases[]={ + /* + * special cases for UAX #15 bug + * see Unicode Public Review Issue #29 + * at http://www.unicode.org/review/resolved-pri.html#pri29 + */ + { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0x1100, 0x0300, 0x1161, 0x0327 } }, + { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 } }, + { UNORM_NFC, 0, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac00, 0x0327, 0x0300, 0x11a8 } }, + { UNORM_NFC, 0, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b47, 0x0300, 0x0b3e } }, + + { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0xac00, 0x0300, 0x0327 } }, + { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0xac01, 0x0300, 0x0327 } }, + { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac01, 0x0327, 0x0300 } }, + { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b4b, 0x0300 } } + + /* TODO: add test cases for UNORM_FCC here (j2151) */ + }; + + UChar output[16]; + UErrorCode errorCode; + int32_t i, length; + + for(i=0; i<LENGTHOF(cases); ++i) { + errorCode=U_ZERO_ERROR; + length=unorm_normalize( + cases[i].input, -1, + cases[i].mode, cases[i].options, + output, LENGTHOF(output), + &errorCode); + if( U_FAILURE(errorCode) || + length!=u_strlen(cases[i].expect) || + 0!=u_memcmp(output, cases[i].expect, length) + ) { + log_err("unexpected result for case %d\n", i); + } + } +} + +#endif /* #if !UCONFIG_NO_NORMALIZATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h new file mode 100644 index 00000000000..bc213a486aa --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h @@ -0,0 +1,43 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CNORMTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +* synwee added test for quick check +* synwee added test for checkFCD +********************************************************************************* +*/ +#ifndef _NORMTST +#define _NORMTST +/** + * tests for u_normalization + */ + +#include "cintltst.h" + + void TestDecomp(void); + void TestCompatDecomp(void); + void TestCanonDecompCompose(void); + void TestCompatDecompCompose(void); + void TestNull(void); + void TestQuickCheck(void); + void TestCheckFCD(void); + + /*internal functions*/ + +/* static void assertEqual(const UChar* result, const UChar* expected, int32_t index); +*/ + static void assertEqual(const UChar* result, const char* expected, int32_t index); + + + + + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c new file mode 100644 index 00000000000..7a8df1f70b4 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c @@ -0,0 +1,1399 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CNUMTST.C +* +* Madhu Katragadda Creation +* +* Modification History: +* +* Date Name Description +* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes +* 07/15/99 helena Ported to HPUX 10/11 CC. +********************************************************************************* +*/ + +/* C API TEST FOR NUMBER FORMAT */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uloc.h" +#include "unicode/unum.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cnumtst.h" +#include "cmemory.h" +#include "putilimp.h" + +#define LENGTH(arr) (sizeof(arr)/sizeof(arr[0])) + +void addNumForTest(TestNode** root); +static void TestTextAttributeCrash(void); + +#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) + +void addNumForTest(TestNode** root) +{ + TESTCASE(TestNumberFormat); + TESTCASE(TestSignificantDigits); + TESTCASE(TestNumberFormatPadding); + TESTCASE(TestInt64Format); + TESTCASE(TestNonExistentCurrency); + TESTCASE(TestCurrencyRegression); + TESTCASE(TestTextAttributeCrash); + TESTCASE(TestRBNFFormat); +} + +/** copy src to dst with unicode-escapes for values < 0x20 and > 0x7e, null terminate if possible */ +static int32_t ustrToAstr(const UChar* src, int32_t srcLength, char* dst, int32_t dstLength) { + static const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + char *p = dst; + const char *e = p + dstLength; + if (srcLength < 0) { + const UChar* s = src; + while (*s) { + ++s; + } + srcLength = (int32_t)(s - src); + } + while (p < e && --srcLength >= 0) { + UChar c = *src++; + if (c == 0xd || c == 0xa || c == 0x9 || (c>= 0x20 && c <= 0x7e)) { + *p++ = (char) c & 0x7f; + } else if (e - p >= 6) { + *p++ = '\\'; + *p++ = 'u'; + *p++ = hex[(c >> 12) & 0xf]; + *p++ = hex[(c >> 8) & 0xf]; + *p++ = hex[(c >> 4) & 0xf]; + *p++ = hex[c & 0xf]; + } else { + break; + } + } + if (p < e) { + *p = 0; + } + return (int32_t)(p - dst); +} + +/* test Number Format API */ +static void TestNumberFormat() +{ + UChar *result=NULL; + UChar temp1[512]; + UChar temp2[512]; + + UChar temp[5]; + + UChar prefix[5]; + UChar suffix[5]; + UChar symbol[20]; + int32_t resultlength; + int32_t resultlengthneeded; + int32_t parsepos; + double d1 = -1.0; + int32_t l1; + double d = -10456.37; + double a = 1234.56, a1 = 1235.0; + int32_t l = 100000000; + UFieldPosition pos1; + UFieldPosition pos2; + int32_t numlocales; + int32_t i; + + UNumberFormatAttribute attr; + UNumberFormatSymbol symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; + int32_t newvalue; + UErrorCode status=U_ZERO_ERROR; + UNumberFormatStyle style= UNUM_DEFAULT; + UNumberFormat *pattern; + UNumberFormat *def, *fr, *cur_def, *cur_fr, *per_def, *per_fr, + *cur_frpattern, *myclone, *spellout_def; + + /* Testing unum_open() with various Numberformat styles and locales*/ + status = U_ZERO_ERROR; + log_verbose("Testing unum_open() with default style and locale\n"); + def=unum_open(style, NULL,0,NULL, NULL,&status); + + /* Might as well pack it in now if we can't even get a default NumberFormat... */ + if(U_FAILURE(status)) + { + log_err("Error in creating default NumberFormat using unum_open(): %s\n", myErrorName(status)); + return; + } + + log_verbose("\nTesting unum_open() with french locale and default style(decimal)\n"); + fr=unum_open(style,NULL,0, "fr_FR",NULL, &status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat (french): %s\n", myErrorName(status)); + + log_verbose("\nTesting unum_open(currency,NULL,status)\n"); + style=UNUM_CURRENCY; + /* Can't hardcode the result to assume the default locale is "en_US". */ + cur_def=unum_open(style, NULL,0,"en_US", NULL, &status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat using \n unum_open(currency, NULL, &status) %s\n", + myErrorName(status) ); + + log_verbose("\nTesting unum_open(currency, frenchlocale, status)\n"); + cur_fr=unum_open(style,NULL,0, "fr_FR", NULL, &status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat using unum_open(currency, french, &status): %s\n", + myErrorName(status)); + + log_verbose("\nTesting unum_open(percent, NULL, status)\n"); + style=UNUM_PERCENT; + per_def=unum_open(style,NULL,0, NULL,NULL, &status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat using unum_open(percent, NULL, &status): %s\n", myErrorName(status)); + + log_verbose("\nTesting unum_open(percent,frenchlocale, status)\n"); + per_fr=unum_open(style, NULL,0,"fr_FR", NULL,&status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat using unum_open(percent, french, &status): %s\n", myErrorName(status)); + + log_verbose("\nTesting unum_open(spellout, NULL, status)"); + style=UNUM_SPELLOUT; + spellout_def=unum_open(style, NULL, 0, "en_US", NULL, &status); + if(U_FAILURE(status)) + log_err("Error: could not create NumberFormat using unum_open(spellout, NULL, &status): %s\n", myErrorName(status)); + + /* Testing unum_clone(..) */ + log_verbose("\nTesting unum_clone(fmt, status)"); + status = U_ZERO_ERROR; + myclone = unum_clone(def,&status); + if(U_FAILURE(status)) + log_err("Error: could not clone unum_clone(def, &status): %s\n", myErrorName(status)); + else + { + log_verbose("unum_clone() successful\n"); + } + + /*Testing unum_getAvailable() and unum_countAvailable()*/ + log_verbose("\nTesting getAvailableLocales and countAvailable()\n"); + numlocales=unum_countAvailable(); + if(numlocales < 0) + log_err("error in countAvailable"); + else{ + log_verbose("unum_countAvialable() successful\n"); + log_verbose("The no: of locales where number formattting is applicable is %d\n", numlocales); + } + for(i=0;i<numlocales;i++) + { + log_verbose("%s\n", unum_getAvailable(i)); + if (unum_getAvailable(i) == 0) + log_err("No locale for which number formatting patterns are applicable\n"); + else + log_verbose("A locale %s for which number formatting patterns are applicable\n",unum_getAvailable(i)); + } + + + /*Testing unum_format() and unum_formatdouble()*/ + u_uastrcpy(temp1, "$100,000,000.00"); + + log_verbose("\nTesting unum_format() \n"); + resultlength=0; + pos1.field = 0; /* Integer Section */ + resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); +/* for (i = 0; i < 100000; i++) */ + { + unum_format(cur_def, l, result, resultlength, &pos1, &status); + } + } + + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) ); + } + if(u_strcmp(result, temp1)==0) + log_verbose("Pass: Number formatting using unum_format() successful\n"); + else + log_err("Fail: Error in number Formatting using unum_format()\n"); + if(pos1.beginIndex == 1 && pos1.endIndex == 12) + log_verbose("Pass: Complete number formatting using unum_format() successful\n"); + else + log_err("Fail: Error in complete number Formatting using unum_format()\nGot: b=%d end=%d\nExpected: b=1 end=12\n", + pos1.beginIndex, pos1.endIndex); + +free(result); + result = 0; + + log_verbose("\nTesting unum_formatDouble()\n"); + u_uastrcpy(temp1, "($10,456.37)"); + resultlength=0; + pos2.field = 1; /* Fractional Section */ + resultlengthneeded=unum_formatDouble(cur_def, d, NULL, resultlength, &pos2, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); +/* for (i = 0; i < 100000; i++) */ + { + unum_formatDouble(cur_def, d, result, resultlength, &pos2, &status); + } + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status)); + } + if(result && u_strcmp(result, temp1)==0) + log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n"); + else + log_err("FAIL: Error in number formatting using unum_formatDouble()\n"); + if(pos2.beginIndex == 9 && pos2.endIndex == 11) + log_verbose("Pass: Complete number formatting using unum_format() successful\n"); + else + log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=9 end=11", + pos1.beginIndex, pos1.endIndex); + + + /* Testing unum_parse() and unum_parseDouble() */ + log_verbose("\nTesting unum_parseDouble()\n"); +/* for (i = 0; i < 100000; i++)*/ + if (result != NULL) + { + parsepos=0; + d1=unum_parseDouble(cur_def, result, u_strlen(result), &parsepos, &status); + } + else { + log_err("result is NULL\n"); + } + if(U_FAILURE(status)) + { + log_err("parse failed. The error is : %s\n", myErrorName(status)); + } + + if(d1!=d) + log_err("Fail: Error in parsing\n"); + else + log_verbose("Pass: parsing successful\n"); + if (result) + free(result); + result = 0; + + + /* Testing unum_formatDoubleCurrency / unum_parseDoubleCurrency */ + log_verbose("\nTesting unum_formatDoubleCurrency\n"); + u_uastrcpy(temp1, "Y1,235"); + temp1[0] = 0xA5; /* Yen sign */ + u_uastrcpy(temp, "JPY"); + resultlength=0; + pos2.field = 0; /* integer part */ + resultlengthneeded=unum_formatDoubleCurrency(cur_def, a, temp, NULL, resultlength, &pos2, &status); + if (status==U_BUFFER_OVERFLOW_ERROR) { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_formatDoubleCurrency(cur_def, a, temp, result, resultlength, &pos2, &status); + } + if (U_FAILURE(status)) { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status)); + } + if (result && u_strcmp(result, temp1)==0) { + log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n"); + } else { + log_err("FAIL: Error in number formatting using unum_formatDouble()\n"); + } + if (pos2.beginIndex == 1 && pos2.endIndex == 6) { + log_verbose("Pass: Complete number formatting using unum_format() successful\n"); + } else { + log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=1 end=6\n", + pos1.beginIndex, pos1.endIndex); + } + + log_verbose("\nTesting unum_parseDoubleCurrency\n"); + parsepos=0; + if (result == NULL) { + log_err("result is NULL\n"); + } + else { + d1=unum_parseDoubleCurrency(cur_def, result, u_strlen(result), &parsepos, temp2, &status); + if (U_FAILURE(status)) { + log_err("parse failed. The error is : %s\n", myErrorName(status)); + } + /* Note: a==1234.56, but on parse expect a1=1235.0 */ + if (d1!=a1) { + log_err("Fail: Error in parsing currency, got %f, expected %f\n", d1, a1); + } else { + log_verbose("Pass: parsed currency ammount successfully\n"); + } + if (u_strcmp(temp2, temp)==0) { + log_verbose("Pass: parsed correct currency\n"); + } else { + log_err("Fail: parsed incorrect currency\n"); + } + } + +free(result); + result = 0; + + +/* performance testing */ + u_uastrcpy(temp1, "$462.12345"); + resultlength=u_strlen(temp1); +/* for (i = 0; i < 100000; i++) */ + { + parsepos=0; + d1=unum_parseDouble(cur_def, temp1, resultlength, &parsepos, &status); + } + if(U_FAILURE(status)) + { + log_err("parse failed. The error is : %s\n", myErrorName(status)); + } + + if(d1!=462.12345) + log_err("Fail: Error in parsing\n"); + else + log_verbose("Pass: parsing successful\n"); + +free(result); + + u_uastrcpy(temp1, "($10,456.3E1])"); + parsepos=0; + d1=unum_parseDouble(cur_def, temp1, u_strlen(temp1), &parsepos, &status); + if(U_SUCCESS(status)) + { + log_err("Error in unum_parseDouble(..., %s, ...): %s\n", temp1, myErrorName(status)); + } + + + log_verbose("\nTesting unum_format()\n"); + status=U_ZERO_ERROR; + resultlength=0; + parsepos=0; + resultlengthneeded=unum_format(per_fr, l, NULL, resultlength, &pos1, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); +/* for (i = 0; i < 100000; i++)*/ + { + unum_format(per_fr, l, result, resultlength, &pos1, &status); + } + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status)); + } + + + log_verbose("\nTesting unum_parse()\n"); +/* for (i = 0; i < 100000; i++) */ + { + parsepos=0; + l1=unum_parse(per_fr, result, u_strlen(result), &parsepos, &status); + } + if(U_FAILURE(status)) + { + log_err("parse failed. The error is : %s\n", myErrorName(status)); + } + + if(l1!=l) + log_err("Fail: Error in parsing\n"); + else + log_verbose("Pass: parsing successful\n"); + +free(result); + + /* create a number format using unum_openPattern(....)*/ + log_verbose("\nTesting unum_openPattern()\n"); + u_uastrcpy(temp1, "#,##0.0#;(#,##0.0#)"); + pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status); + if(U_FAILURE(status)) + { + log_err("error in unum_openPattern(): %s\n", myErrorName(status) );; + } + else + log_verbose("Pass: unum_openPattern() works fine\n"); + + /*test for unum_toPattern()*/ + log_verbose("\nTesting unum_toPattern()\n"); + resultlength=0; + resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_toPattern(pattern, FALSE, result, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status)); + } + else + { + if(u_strcmp(result, temp1)!=0) + log_err("FAIL: Error in extracting the pattern using unum_toPattern()\n"); + else + log_verbose("Pass: extracted the pattern correctly using unum_toPattern()\n"); +free(result); + } + + /*Testing unum_getSymbols() and unum_setSymbols()*/ + log_verbose("\nTesting unum_getSymbols and unum_setSymbols()\n"); + /*when we try to change the symbols of french to default we need to apply the pattern as well to fetch correct results */ + resultlength=0; + resultlengthneeded=unum_toPattern(cur_def, FALSE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_toPattern(cur_def, FALSE, result, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status)); + } + + status=U_ZERO_ERROR; + cur_frpattern=unum_open(UNUM_IGNORE,result, u_strlen(result), "fr_FR",NULL, &status); + if(U_FAILURE(status)) + { + log_err("error in unum_openPattern(): %s\n", myErrorName(status)); + } + +free(result); + + /*getting the symbols of cur_def */ + /*set the symbols of cur_frpattern to cur_def */ + for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) { + status=U_ZERO_ERROR; + unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status); + unum_setSymbol(cur_frpattern, symType, temp1, -1, &status); + if(U_FAILURE(status)) + { + log_err("Error in get/set symbols: %s\n", myErrorName(status)); + } + } + + /*format to check the result */ + resultlength=0; + resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_format(cur_def, l, result, resultlength, &pos1, &status); + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status)); + } + + if(U_FAILURE(status)){ + log_err("Fail: error in unum_setSymbols: %s\n", myErrorName(status)); + } + unum_applyPattern(cur_frpattern, FALSE, result, u_strlen(result),NULL,NULL); + + for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) { + status=U_ZERO_ERROR; + unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status); + unum_getSymbol(cur_frpattern, symType, temp2, sizeof(temp2), &status); + if(U_FAILURE(status) || u_strcmp(temp1, temp2) != 0) + { + log_err("Fail: error in getting symbols\n"); + } + else + log_verbose("Pass: get and set symbols successful\n"); + } + + /*format and check with the previous result */ + + resultlength=0; + resultlengthneeded=unum_format(cur_frpattern, l, NULL, resultlength, &pos1, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + unum_format(cur_frpattern, l, temp1, resultlength, &pos1, &status); + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status)); + } + /* TODO: + * This test fails because we have not called unum_applyPattern(). + * Currently, such an applyPattern() does not exist on the C API, and + * we have jitterbug 411 for it. + * Since it is close to the 1.5 release, I (markus) am disabling this test just + * for this release (I added the test itself only last week). + * For the next release, we need to fix this. + * Then, remove the uprv_strcmp("1.5", ...) and this comment, and the include "cstring.h" at the beginning of this file. + */ + if(u_strcmp(result, temp1) != 0) { + log_err("Formatting failed after setting symbols. result=%s temp1=%s\n", result, temp1); + } + + + /*----------- */ + +free(result); + + /* Testing unum_get/setSymbol() */ + for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) { + symbol[0] = (UChar)(0x41 + i); + symbol[1] = (UChar)(0x61 + i); + unum_setSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, 2, &status); + if(U_FAILURE(status)) { + log_err("Error from unum_setSymbol(%d): %s\n", i, myErrorName(status)); + return; + } + } + for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) { + resultlength = unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status); + if(U_FAILURE(status)) { + log_err("Error from unum_getSymbol(%d): %s\n", i, myErrorName(status)); + return; + } + if(resultlength != 2 || symbol[0] != 0x41 + i || symbol[1] != 0x61 + i) { + log_err("Failure in unum_getSymbol(%d): got unexpected symbol\n", i); + } + } + /*try getting from a bogus symbol*/ + unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status); + if(U_SUCCESS(status)){ + log_err("Error : Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol"); + } + if(U_FAILURE(status)){ + if(status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("Error: Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol, Got %s\n", myErrorName(status)); + } + } + status=U_ZERO_ERROR; + + /* Testing unum_getTextAttribute() and unum_setTextAttribute()*/ + log_verbose("\nTesting getting and setting text attributes\n"); + resultlength=5; + unum_getTextAttribute(cur_fr, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status)); + } + unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status); + if(U_FAILURE(status)) + { + log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status)); + } + unum_getTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, suffix, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status)); + } + if(u_strcmp(suffix,temp)!=0) + log_err("Fail:Error in setTextAttribute or getTextAttribute in setting and getting suffix\n"); + else + log_verbose("Pass: setting and getting suffix works fine\n"); + /*set it back to normal */ + u_uastrcpy(temp,"$"); + unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status); + + /*checking some more text setter conditions */ + u_uastrcpy(prefix, "+"); + unum_setTextAttribute(def, UNUM_POSITIVE_PREFIX, prefix, u_strlen(prefix) , &status); + if(U_FAILURE(status)) + { + log_err("error in setting the text attributes : %s\n", myErrorName(status)); + } + unum_getTextAttribute(def, UNUM_POSITIVE_PREFIX, temp, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("error in getting the text attributes : %s\n", myErrorName(status)); + } + + if(u_strcmp(prefix, temp)!=0) + log_err("ERROR: get and setTextAttributes with positive prefix failed\n"); + else + log_verbose("Pass: get and setTextAttributes with positive prefix works fine\n"); + + u_uastrcpy(prefix, "+"); + unum_setTextAttribute(def, UNUM_NEGATIVE_PREFIX, prefix, u_strlen(prefix), &status); + if(U_FAILURE(status)) + { + log_err("error in setting the text attributes : %s\n", myErrorName(status)); + } + unum_getTextAttribute(def, UNUM_NEGATIVE_PREFIX, temp, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("error in getting the text attributes : %s\n", myErrorName(status)); + } + if(u_strcmp(prefix, temp)!=0) + log_err("ERROR: get and setTextAttributes with negative prefix failed\n"); + else + log_verbose("Pass: get and setTextAttributes with negative prefix works fine\n"); + + u_uastrcpy(suffix, "+"); + unum_setTextAttribute(def, UNUM_NEGATIVE_SUFFIX, suffix, u_strlen(suffix) , &status); + if(U_FAILURE(status)) + { + log_err("error in setting the text attributes: %s\n", myErrorName(status)); + } + + unum_getTextAttribute(def, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("error in getting the text attributes : %s\n", myErrorName(status)); + } + if(u_strcmp(suffix, temp)!=0) + log_err("ERROR: get and setTextAttributes with negative suffix failed\n"); + else + log_verbose("Pass: get and settextAttributes with negative suffix works fine\n"); + + u_uastrcpy(suffix, "++"); + unum_setTextAttribute(def, UNUM_POSITIVE_SUFFIX, suffix, u_strlen(suffix) , &status); + if(U_FAILURE(status)) + { + log_err("error in setting the text attributes: %s\n", myErrorName(status)); + } + + unum_getTextAttribute(def, UNUM_POSITIVE_SUFFIX, temp, resultlength, &status); + if(U_FAILURE(status)) + { + log_err("error in getting the text attributes : %s\n", myErrorName(status)); + } + if(u_strcmp(suffix, temp)!=0) + log_err("ERROR: get and setTextAttributes with negative suffix failed\n"); + else + log_verbose("Pass: get and settextAttributes with negative suffix works fine\n"); + + /*Testing unum_getAttribute and unum_setAttribute() */ + log_verbose("\nTesting get and set Attributes\n"); + attr=UNUM_GROUPING_SIZE; + newvalue=unum_getAttribute(def, attr); + newvalue=2; + unum_setAttribute(def, attr, newvalue); + if(unum_getAttribute(def,attr)!=2) + log_err("Fail: error in setting and getting attributes for UNUM_GROUPING_SIZE\n"); + else + log_verbose("Pass: setting and getting attributes for UNUM_GROUPING_SIZE works fine\n"); + + attr=UNUM_MULTIPLIER; + newvalue=unum_getAttribute(def, attr); + newvalue=8; + unum_setAttribute(def, attr, newvalue); + if(unum_getAttribute(def,attr) != 8) + log_err("error in setting and getting attributes for UNUM_MULTIPLIER\n"); + else + log_verbose("Pass:setting and getting attributes for UNUM_MULTIPLIER works fine\n"); + + attr=UNUM_SECONDARY_GROUPING_SIZE; + newvalue=unum_getAttribute(def, attr); + newvalue=2; + unum_setAttribute(def, attr, newvalue); + if(unum_getAttribute(def,attr) != 2) + log_err("error in setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE\n"); + else + log_verbose("Pass:setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE works fine\n"); + + /*testing set and get Attributes extensively */ + log_verbose("\nTesting get and set attributes extensively\n"); + for(attr=UNUM_PARSE_INT_ONLY; attr<= UNUM_PADDING_POSITION; attr=(UNumberFormatAttribute)((int32_t)attr + 1) ) + { + newvalue=unum_getAttribute(fr, attr); + unum_setAttribute(def, attr, newvalue); + if(unum_getAttribute(def,attr)!=unum_getAttribute(fr, attr)) + log_err("error in setting and getting attributes\n"); + else + log_verbose("Pass: attributes set and retrieved successfully\n"); + } + + /*testing spellout format to make sure we can use it successfully.*/ + log_verbose("\nTesting spellout format\n"); + if (spellout_def) + { + static const int32_t values[] = { 0, -5, 105, 1005, 105050 }; + for (i = 0; i < LENGTH(values); ++i) { + UChar buffer[128]; + int32_t len; + int32_t value = values[i]; + status = U_ZERO_ERROR; + len = unum_format(spellout_def, value, buffer, LENGTH(buffer), NULL, &status); + if(U_FAILURE(status)) { + log_err("Error in formatting using unum_format(spellout_fmt, ...): %s\n", myErrorName(status)); + } else { + int32_t pp = 0; + int32_t parseResult; + char logbuf[256]; + ustrToAstr(buffer, len, logbuf, LENGTH(logbuf)); + log_verbose("formatted %d as '%s', length: %d\n", value, logbuf, len); + + parseResult = unum_parse(spellout_def, buffer, len, &pp, &status); + if (U_FAILURE(status)) { + log_err("Error in parsing using unum_format(spellout_fmt, ...): %s\n", myErrorName(status)); + } else if (parseResult != value) { + log_err("unum_format result %d != value %d\n", parseResult, value); + } + } + } + } + else { + log_err("Spellout format is unavailable\n"); + } + + /*closing the NumberFormat() using unum_close(UNumberFormat*)")*/ + unum_close(def); + unum_close(fr); + unum_close(cur_def); + unum_close(cur_fr); + unum_close(per_def); + unum_close(per_fr); + unum_close(spellout_def); + unum_close(pattern); + unum_close(cur_frpattern); + unum_close(myclone); + +} + +static void TestSignificantDigits() +{ + UChar temp[128]; + int32_t resultlengthneeded; + int32_t resultlength; + UErrorCode status = U_ZERO_ERROR; + UChar *result = NULL; + UNumberFormat* fmt; + double d = 123456.789; + + u_uastrcpy(temp, "###0.0#"); + fmt=unum_open(UNUM_IGNORE, temp, -1, NULL, NULL,&status); + if (U_FAILURE(status)) { + log_err("got unexpected error for unum_open: '%s'\n", u_errorName(status)); + } + unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE); + unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 6); + + u_uastrcpy(temp, "123457"); + resultlength=0; + resultlengthneeded=unum_formatDouble(fmt, d, NULL, resultlength, NULL, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_formatDouble(fmt, d, result, resultlength, NULL, &status); + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status)); + return; + } + if(u_strcmp(result, temp)==0) + log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n"); + else + log_err("FAIL: Error in number formatting using unum_formatDouble()\n"); + free(result); + unum_close(fmt); +} + +static void TestNumberFormatPadding() +{ + UChar *result=NULL; + UChar temp1[512]; + + UErrorCode status=U_ZERO_ERROR; + int32_t resultlength; + int32_t resultlengthneeded; + UNumberFormat *pattern; + double d1; + double d = -10456.37; + UFieldPosition pos1; + int32_t parsepos; + + /* create a number format using unum_openPattern(....)*/ + log_verbose("\nTesting unum_openPattern() with padding\n"); + u_uastrcpy(temp1, "*#,##0.0#*;(#,##0.0#)"); + status=U_ZERO_ERROR; + pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status); + if(U_SUCCESS(status)) + { + log_err("error in unum_openPattern(%s): %s\n", temp1, myErrorName(status) );; + } + else + { + unum_close(pattern); + } + +/* u_uastrcpy(temp1, "*x#,###,###,##0.0#;(*x#,###,###,##0.0#)"); */ + u_uastrcpy(temp1, "*x#,###,###,##0.0#;*x(###,###,##0.0#)"); + status=U_ZERO_ERROR; + pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), "en_US",NULL, &status); + if(U_FAILURE(status)) + { + log_err("error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) );; + } + else { + log_verbose("Pass: padding unum_openPattern() works fine\n"); + + /*test for unum_toPattern()*/ + log_verbose("\nTesting padding unum_toPattern()\n"); + resultlength=0; + resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_toPattern(pattern, FALSE, result, resultlength, &status); + } + if(U_FAILURE(status)) + { + log_err("error in extracting the padding pattern from UNumberFormat: %s\n", myErrorName(status)); + } + else + { + if(u_strcmp(result, temp1)!=0) + log_err("FAIL: Error in extracting the padding pattern using unum_toPattern()\n"); + else + log_verbose("Pass: extracted the padding pattern correctly using unum_toPattern()\n"); +free(result); + } +/* u_uastrcpy(temp1, "(xxxxxxx10,456.37)"); */ + u_uastrcpy(temp1, "xxxxx(10,456.37)"); + resultlength=0; + pos1.field = 1; /* Fraction field */ + resultlengthneeded=unum_formatDouble(pattern, d, NULL, resultlength, &pos1, &status); + if(status==U_BUFFER_OVERFLOW_ERROR) + { + status=U_ZERO_ERROR; + resultlength=resultlengthneeded+1; + result=(UChar*)malloc(sizeof(UChar) * resultlength); + unum_formatDouble(pattern, d, result, resultlength, NULL, &status); + } + if(U_FAILURE(status)) + { + log_err("Error in formatting using unum_formatDouble(.....) with padding : %s\n", myErrorName(status)); + } + else + { + if(u_strcmp(result, temp1)==0) + log_verbose("Pass: Number Formatting using unum_formatDouble() padding Successful\n"); + else + log_err("FAIL: Error in number formatting using unum_formatDouble() with padding\n"); + if(pos1.beginIndex == 13 && pos1.endIndex == 15) + log_verbose("Pass: Complete number formatting using unum_formatDouble() successful\n"); + else + log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=13 end=15\n", + pos1.beginIndex, pos1.endIndex); + + + /* Testing unum_parse() and unum_parseDouble() */ + log_verbose("\nTesting padding unum_parseDouble()\n"); + parsepos=0; + d1=unum_parseDouble(pattern, result, u_strlen(result), &parsepos, &status); + if(U_FAILURE(status)) + { + log_err("padding parse failed. The error is : %s\n", myErrorName(status)); + } + + if(d1!=d) + log_err("Fail: Error in padding parsing\n"); + else + log_verbose("Pass: padding parsing successful\n"); +free(result); + } + } + + unum_close(pattern); +} + +static UBool +withinErr(double a, double b, double err) { + return uprv_fabs(a - b) < uprv_fabs(a * err); +} + +static void TestInt64Format() { + UChar temp1[512]; + UChar result[512]; + UNumberFormat *fmt; + UErrorCode status = U_ZERO_ERROR; + const double doubleInt64Max = (double)U_INT64_MAX; + const double doubleInt64Min = (double)U_INT64_MIN; + const double doubleBig = 10.0 * (double)U_INT64_MAX; + int32_t val32; + int64_t val64; + double valDouble; + int32_t parsepos; + + /* create a number format using unum_openPattern(....) */ + log_verbose("\nTesting Int64Format\n"); + u_uastrcpy(temp1, "#.#E0"); + fmt = unum_open(UNUM_IGNORE, temp1, u_strlen(temp1), NULL, NULL, &status); + if(U_FAILURE(status)) { + log_err("error in unum_openPattern(): %s\n", myErrorName(status)); + } else { + unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 20); + unum_formatInt64(fmt, U_INT64_MAX, result, 512, NULL, &status); + if (U_FAILURE(status)) { + log_err("error in unum_format(): %s\n", myErrorName(status)); + } else { + log_verbose("format int64max: '%s'\n", result); + parsepos = 0; + val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status); + if (status != U_INVALID_FORMAT_ERROR) { + log_err("parse didn't report error: %s\n", myErrorName(status)); + } else if (val32 != INT32_MAX) { + log_err("parse didn't pin return value, got: %d\n", val32); + } + + status = U_ZERO_ERROR; + parsepos = 0; + val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status); + if (U_FAILURE(status)) { + log_err("parseInt64 returned error: %s\n", myErrorName(status)); + } else if (val64 != U_INT64_MAX) { + log_err("parseInt64 returned incorrect value, got: %ld\n", val64); + } + + status = U_ZERO_ERROR; + parsepos = 0; + valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status); + if (U_FAILURE(status)) { + log_err("parseDouble returned error: %s\n", myErrorName(status)); + } else if (valDouble != doubleInt64Max) { + log_err("parseDouble returned incorrect value, got: %g\n", valDouble); + } + } + + unum_formatInt64(fmt, U_INT64_MIN, result, 512, NULL, &status); + if (U_FAILURE(status)) { + log_err("error in unum_format(): %s\n", myErrorName(status)); + } else { + log_verbose("format int64min: '%s'\n", result); + parsepos = 0; + val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status); + if (status != U_INVALID_FORMAT_ERROR) { + log_err("parse didn't report error: %s\n", myErrorName(status)); + } else if (val32 != INT32_MIN) { + log_err("parse didn't pin return value, got: %d\n", val32); + } + + status = U_ZERO_ERROR; + parsepos = 0; + val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status); + if (U_FAILURE(status)) { + log_err("parseInt64 returned error: %s\n", myErrorName(status)); + } else if (val64 != U_INT64_MIN) { + log_err("parseInt64 returned incorrect value, got: %ld\n", val64); + } + + status = U_ZERO_ERROR; + parsepos = 0; + valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status); + if (U_FAILURE(status)) { + log_err("parseDouble returned error: %s\n", myErrorName(status)); + } else if (valDouble != doubleInt64Min) { + log_err("parseDouble returned incorrect value, got: %g\n", valDouble); + } + } + + unum_formatDouble(fmt, doubleBig, result, 512, NULL, &status); + if (U_FAILURE(status)) { + log_err("error in unum_format(): %s\n", myErrorName(status)); + } else { + log_verbose("format doubleBig: '%s'\n", result); + parsepos = 0; + val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status); + if (status != U_INVALID_FORMAT_ERROR) { + log_err("parse didn't report error: %s\n", myErrorName(status)); + } else if (val32 != INT32_MAX) { + log_err("parse didn't pin return value, got: %d\n", val32); + } + + status = U_ZERO_ERROR; + parsepos = 0; + val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status); + if (status != U_INVALID_FORMAT_ERROR) { + log_err("parseInt64 didn't report error error: %s\n", myErrorName(status)); + } else if (val64 != U_INT64_MAX) { + log_err("parseInt64 returned incorrect value, got: %ld\n", val64); + } + + status = U_ZERO_ERROR; + parsepos = 0; + valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status); + if (U_FAILURE(status)) { + log_err("parseDouble returned error: %s\n", myErrorName(status)); + } else if (!withinErr(valDouble, doubleBig, 1e-15)) { + log_err("parseDouble returned incorrect value, got: %g\n", valDouble); + } + } + } + unum_close(fmt); +} + + +static void test_fmt(UNumberFormat* fmt, UBool isDecimal) { + char temp[512]; + UChar buffer[512]; + int32_t BUFSIZE = sizeof(buffer)/sizeof(buffer[0]); + double vals[] = { + -.2, 0, .2, 5.5, 15.2, 250, 123456789 + }; + int i; + + for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) { + UErrorCode status = U_ZERO_ERROR; + unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status); + if (U_FAILURE(status)) { + log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status)); + } else { + u_austrcpy(temp, buffer); + log_verbose("formatting %g returned '%s'\n", vals[i], temp); + } + } + + /* check APIs now */ + { + UErrorCode status = U_ZERO_ERROR; + UParseError perr; + u_uastrcpy(buffer, "#,##0.0#"); + unum_applyPattern(fmt, FALSE, buffer, -1, &perr, &status); + if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) { + log_err("got unexpected error for applyPattern: '%s'\n", u_errorName(status)); + } + } + + { + int isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE); + log_verbose("lenient: 0x%x\n", isLenient); + if (isDecimal ? (isLenient != -1) : (isLenient == TRUE)) { + log_err("didn't expect lenient value: %d\n", isLenient); + } + + unum_setAttribute(fmt, UNUM_LENIENT_PARSE, TRUE); + isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE); + if (isDecimal ? (isLenient != -1) : (isLenient == FALSE)) { + log_err("didn't expect lenient value after set: %d\n", isLenient); + } + } + + { + double val2; + double val = unum_getDoubleAttribute(fmt, UNUM_LENIENT_PARSE); + if (val != -1) { + log_err("didn't expect double attribute\n"); + } + val = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT); + if ((val == -1) == isDecimal) { + log_err("didn't expect -1 rounding increment\n"); + } + unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, val+.5); + val2 = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT); + if (isDecimal && (val2 - val != .5)) { + log_err("set rounding increment had no effect on decimal format"); + } + } + + { + UErrorCode status = U_ZERO_ERROR; + int len = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status); + if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) { + log_err("got unexpected error for get default ruleset: '%s'\n", u_errorName(status)); + } + if (U_SUCCESS(status)) { + u_austrcpy(temp, buffer); + log_verbose("default ruleset: '%s'\n", temp); + } + + status = U_ZERO_ERROR; + len = unum_getTextAttribute(fmt, UNUM_PUBLIC_RULESETS, buffer, BUFSIZE, &status); + if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) { + log_err("got unexpected error for get public rulesets: '%s'\n", u_errorName(status)); + } + if (U_SUCCESS(status)) { + u_austrcpy(temp, buffer); + log_verbose("public rulesets: '%s'\n", temp); + + /* set the default ruleset to the first one found, and retry */ + + if (len > 0) { + for (i = 0; i < len && temp[i] != ';'; ++i){}; + if (i < len) { + buffer[i] = 0; + unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status); + if (U_FAILURE(status)) { + log_err("unexpected error setting default ruleset: '%s'\n", u_errorName(status)); + } else { + int len2 = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status); + if (U_FAILURE(status)) { + log_err("could not fetch default ruleset: '%s'\n", u_errorName(status)); + } else if (len2 != i) { + u_austrcpy(temp, buffer); + log_err("unexpected ruleset len: %d ex: %d val: %s\n", len2, i, temp); + } else { + for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) { + status = U_ZERO_ERROR; + unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status); + if (U_FAILURE(status)) { + log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status)); + } else { + u_austrcpy(temp, buffer); + log_verbose("formatting %g returned '%s'\n", vals[i], temp); + } + } + } + } + } + } + } + } + + { + UErrorCode status = U_ZERO_ERROR; + unum_toPattern(fmt, FALSE, buffer, BUFSIZE, &status); + if (U_SUCCESS(status)) { + u_austrcpy(temp, buffer); + log_verbose("pattern: '%s'\n", temp); + } else if (status != U_BUFFER_OVERFLOW_ERROR) { + log_err("toPattern failed unexpectedly: %s\n", u_errorName(status)); + } else { + log_verbose("pattern too long to display\n"); + } + } + + { + UErrorCode status = U_ZERO_ERROR; + int len = unum_getSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, BUFSIZE, &status); + if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) { + log_err("unexpected error getting symbol: '%s'\n", u_errorName(status)); + } + + unum_setSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, len, &status); + if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) { + log_err("unexpected error setting symbol: '%s'\n", u_errorName(status)); + } + } +} + +static void TestNonExistentCurrency() { + UNumberFormat *format; + UErrorCode status = U_ZERO_ERROR; + UChar currencySymbol[8]; + static const UChar QQQ[] = {0x51, 0x51, 0x51, 0}; + + /* Get a non-existent currency and make sure it returns the correct currency code. */ + format = unum_open(UNUM_CURRENCY, NULL, 0, "th_TH@currency=QQQ", NULL, &status); + if (format == NULL || U_FAILURE(status)) { + log_err("unum_open did not return expected result for non-existent requested currency: '%s'\n", u_errorName(status)); + } + else { + unum_getSymbol(format, + UNUM_CURRENCY_SYMBOL, + currencySymbol, + sizeof(currencySymbol)/sizeof(currencySymbol[0]), + &status); + if (u_strcmp(currencySymbol, QQQ) != 0) { + log_err("unum_open set the currency to QQQ\n"); + } + } + unum_close(format); +} + +static void TestRBNFFormat() { + UErrorCode status; + UParseError perr; + UChar pat[1024]; + UChar tempUChars[512]; + UNumberFormat *formats[5]; + int COUNT = sizeof(formats)/sizeof(formats[0]); + int i; + + for (i = 0; i < COUNT; ++i) { + formats[i] = 0; + } + + /* instantiation */ + status = U_ZERO_ERROR; + u_uastrcpy(pat, "#,##0.0#;(#,##0.0#)"); + formats[0] = unum_open(UNUM_PATTERN_DECIMAL, pat, -1, "en_US", &perr, &status); + if (U_FAILURE(status)) { + log_err("unable to open decimal pattern"); + } + + status = U_ZERO_ERROR; + formats[1] = unum_open(UNUM_SPELLOUT, NULL, 0, "en_US", &perr, &status); + if (U_FAILURE(status)) { + log_err("unable to open spellout"); + } + + status = U_ZERO_ERROR; + formats[2] = unum_open(UNUM_ORDINAL, NULL, 0, "en_US", &perr, &status); + if (U_FAILURE(status)) { + log_err("unable to open ordinal"); + } + + status = U_ZERO_ERROR; + formats[3] = unum_open(UNUM_DURATION, NULL, 0, "en_US", &perr, &status); + if (U_FAILURE(status)) { + log_err("unable to open duration"); + } + + status = U_ZERO_ERROR; + u_uastrcpy(pat, + "%standard:\n" + "-x: minus >>;\n" + "x.x: << point >>;\n" + "zero; one; two; three; four; five; six; seven; eight; nine;\n" + "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n" + "seventeen; eighteen; nineteen;\n" + "20: twenty[->>];\n" + "30: thirty[->>];\n" + "40: forty[->>];\n" + "50: fifty[->>];\n" + "60: sixty[->>];\n" + "70: seventy[->>];\n" + "80: eighty[->>];\n" + "90: ninety[->>];\n" + "100: =#,##0=;\n"); + u_uastrcpy(tempUChars, + "%simple:\n" + "=%standard=;\n" + "20: twenty[ and change];\n" + "30: thirty[ and change];\n" + "40: forty[ and change];\n" + "50: fifty[ and change];\n" + "60: sixty[ and change];\n" + "70: seventy[ and change];\n" + "80: eighty[ and change];\n" + "90: ninety[ and change];\n" + "100: =#,##0=;\n" + "%bogus:\n" + "0.x: tiny;\n" + "x.x: << point something;\n" + "=%standard=;\n" + "20: some reasonable number;\n" + "100: some substantial number;\n" + "100,000,000: some huge number;\n"); + /* This is to get around some compiler warnings about char * string length. */ + u_strcat(pat, tempUChars); + formats[4] = unum_open(UNUM_PATTERN_RULEBASED, pat, -1, "en_US", &perr, &status); + if (U_FAILURE(status)) { + log_err("unable to open rulebased pattern"); + } + + for (i = 0; i < COUNT; ++i) { + log_verbose("\n\ntesting format %d\n", i); + test_fmt(formats[i], (UBool)(i == 0)); + } + + for (i = 0; i < COUNT; ++i) { + unum_close(formats[i]); + } +} + +static void TestCurrencyRegression(void) { +/* + I've found a case where unum_parseDoubleCurrency is not doing what I +expect. The value I pass in is $1234567890q123460000.00 and this +returns with a status of zero error & a parse pos of 22 (I would +expect a parse error at position 11). + +I stepped into DecimalFormat::subparse() and it looks like it parses +the first 10 digits and then stops parsing at the q but doesn't set an +error. Then later in DecimalFormat::parse() the value gets crammed +into a long (which greatly truncates the value). + +This is very problematic for me 'cause I try to remove chars that are +invalid but this allows my users to enter bad chars and truncates +their data! +*/ + + UChar buf[1024]; + UChar currency[8]; + char acurrency[16]; + double d; + UNumberFormat *cur; + int32_t pos; + UErrorCode status = U_ZERO_ERROR; + const int32_t expected = 11; + + currency[0]=0; + u_uastrcpy(buf, "$1234567890q643210000.00"); + cur = unum_open(UNUM_CURRENCY, NULL,0,"en_US", NULL, &status); + + if(U_FAILURE(status)) { + log_err("unum_open failed: %s\n", u_errorName(status)); + return; + } + + status = U_ZERO_ERROR; /* so we can test it later. */ + pos = 0; + + d = unum_parseDoubleCurrency(cur, + buf, + -1, + &pos, /* 0 = start */ + currency, + &status); + + u_austrcpy(acurrency, currency); + + if(U_FAILURE(status) || (pos != expected)) { + log_err("unum_parseDoubleCurrency should have failed with pos %d, but gave: value %.9f, err %s, pos=%d, currency [%s]\n", + expected, d, u_errorName(status), pos, acurrency); + } else { + log_verbose("unum_parseDoubleCurrency failed, value %.9f err %s, pos %d, currency [%s]\n", d, u_errorName(status), pos, acurrency); + } + + unum_close(cur); +} + +static void TestTextAttributeCrash(void) { + UChar ubuffer[64] = {0x0049,0x004E,0x0052,0}; + static const UChar expectedNeg[] = {0x0049,0x004E,0x0052,0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0}; + static const UChar expectedPos[] = {0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0}; + int32_t used; + UErrorCode status = U_ZERO_ERROR; + UNumberFormat *nf = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status); + if (U_FAILURE(status)) { + log_err("FAILED 1\n"); + return; + } + unum_setTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, 3, &status); + /* + * the usual negative prefix and suffix seem to be '($' and ')' at this point + * also crashes if UNUM_NEGATIVE_SUFFIX is substituted for UNUM_NEGATIVE_PREFIX here + */ + used = unum_getTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, 64, &status); + unum_setTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, used, &status); + if (U_FAILURE(status)) { + log_err("FAILED 2\n"); exit(1); + } + log_verbose("attempting to format...\n"); + used = unum_formatDouble(nf, -1234.5, ubuffer, 64, NULL, &status); + if (U_FAILURE(status) || 64 < used) { + log_err("Failed formatting %s\n", u_errorName(status)); + return; + } + if (u_strcmp(expectedNeg, ubuffer) == 0) { + log_err("Didn't get expected negative result\n"); + } + used = unum_formatDouble(nf, 1234.5, ubuffer, 64, NULL, &status); + if (U_FAILURE(status) || 64 < used) { + log_err("Failed formatting %s\n", u_errorName(status)); + return; + } + if (u_strcmp(expectedPos, ubuffer) == 0) { + log_err("Didn't get expected positive result\n"); + } + unum_close(nf); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h new file mode 100644 index 00000000000..93851dc733e --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h @@ -0,0 +1,61 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2005, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CNUMTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +/* C API TEST FOR NUMBER FORMAT */ +#ifndef _CNUMFRMTST +#define _CNUMFRMTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "cintltst.h" + + +/** + * The function used to test the Number format API + **/ +static void TestNumberFormat(void); + +/** + * The function used to test significant digits in the Number format API + **/ +static void TestSignificantDigits(void); + +/** + * The function used to test the Number format API with padding + **/ +static void TestNumberFormatPadding(void); + +/** + * The function used to test the Number format API with padding + **/ +static void TestInt64Format(void); + +static void TestNonExistentCurrency(void); + +/** + * Test RBNF access through unumfmt APIs. + **/ +static void TestRBNFFormat(void); + +/** + * Test some Currency stuff + **/ +static void TestCurrencyRegression(void); + + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c b/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c new file mode 100644 index 00000000000..8e9f3609118 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c @@ -0,0 +1,17 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2003, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ + +#include "ucol_imp.h" + +#if !UCONFIG_NO_COLLATION + +int TestBufferSize(void); /* keep gcc happy */ + +int TestBufferSize(void) +{ + return (U_COL_SAFECLONE_BUFFERSIZE < sizeof(UCollator)); +} +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c new file mode 100644 index 00000000000..8d6d7b67278 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c @@ -0,0 +1,107 @@ +/* +********************************************************************** +* Copyright (c) 2003, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +* Author: Alan Liu +* Created: March 20 2003 +* Since: ICU 2.6 +********************************************************************** +*/ +#include "cintltst.h" +#include "cmemory.h" +#include "cstring.h" +#include "unicode/ucat.h" +#include "unicode/ustring.h" + +/**********************************************************************/ +/* Prototypes */ + +void TestMessageCatalog(void); + +/**********************************************************************/ +/* Add our tests into the hierarchy */ + +void addPosixTest(TestNode** root); + +void addPosixTest(TestNode** root) +{ + addTest(root, &TestMessageCatalog, "tsutil/cposxtst/TestMessageCatalog"); +} + +/**********************************************************************/ +/* Test basic ucat.h API */ + +void TestMessageCatalog(void) { + + UErrorCode ec = U_ZERO_ERROR; + u_nl_catd catd; + const char* DATA[] = { + /* set_num, msg_num, expected string result, expected error code */ + "1", "4", "Good morning.", "U_ZERO_ERROR", + "1", "5", "Good afternoon.", "U_ZERO_ERROR", + "1", "6", "FAIL", "U_MISSING_RESOURCE_ERROR", + "1", "7", "Good evening.", "U_ZERO_ERROR", + "1", "8", "Good night.", "U_ZERO_ERROR", + "1", "9", "FAIL", "U_MISSING_RESOURCE_ERROR", + "3", "1", "FAIL", "U_MISSING_RESOURCE_ERROR", + "4", "14", "Please ", "U_ZERO_ERROR", + "4", "15", "FAIL", "U_MISSING_RESOURCE_ERROR", + "4", "19", "Thank you.", "U_ZERO_ERROR", + "4", "20", "Sincerely,", "U_ZERO_ERROR", + NULL + }; + const UChar FAIL[] = {0x46, 0x41, 0x49, 0x4C, 0x00}; /* "FAIL" */ + int32_t i; + const char *path = loadTestData(&ec); + + if (U_FAILURE(ec)) { + log_err("FAIL: loadTestData => %s\n", u_errorName(ec)); + return; + } + + catd = u_catopen(path, "mc", &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: u_catopen => %s\n", u_errorName(ec)); + return; + } + + for (i=0; DATA[i]!=NULL; i+=4) { + int32_t set_num = T_CString_stringToInteger(DATA[i], 10); + int32_t msg_num = T_CString_stringToInteger(DATA[i+1], 10); + UChar exp[128]; + int32_t len = -1; + const char* err; + char str[128]; + const UChar* ustr; + + u_uastrcpy(exp, DATA[i+2]); + + ec = U_ZERO_ERROR; + ustr = u_catgets(catd, set_num, msg_num, FAIL, &len, &ec); + u_austrcpy(str, ustr); + err = u_errorName(ec); + + log_verbose("u_catgets(%d, %d) => \"%s\", len=%d, %s\n", + set_num, msg_num, str, len, err); + + if (u_strcmp(ustr, exp) != 0) { + log_err("FAIL: u_catgets => \"%s\", exp. \"%s\"\n", + str, DATA[i+2]); + } + + if (len != (int32_t) uprv_strlen(DATA[i+2])) { + log_err("FAIL: u_catgets => len=%d, exp. %d\n", + len, uprv_strlen(DATA[i+2])); + } + + if (uprv_strcmp(err, DATA[i+3]) != 0) { + log_err("FAIL: u_catgets => %s, exp. %s\n", + err, DATA[i+3]); + } + } + + u_catclose(catd); +} + +/*eof*/ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c new file mode 100644 index 00000000000..1f5cf321aa3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c @@ -0,0 +1,1014 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CRESTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +* 06/14/99 stephen Updated for RB API changes (no suffix). +******************************************************************************** +*/ + + +#include "unicode/utypes.h" +#include "cintltst.h" +#include "unicode/ustring.h" +#include "cstring.h" +#include "filestrm.h" +#include <stdlib.h> + +#define RESTEST_HEAP_CHECK 0 + +#include "unicode/ures.h" +#include "crestst.h" +#include "unicode/ctest.h" + +#include "ucol_imp.h" /* collation */ + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void TestOpenDirect(void); +static void TestFallback(void); +static void TestTable32(void); +static void TestFileStream(void); +/*****************************************************************************/ + +const UChar kERROR[] = { 0x0045 /*E*/, 0x0052 /*'R'*/, 0x0052 /*'R'*/, + 0x004F /*'O'*/, 0x0052/*'R'*/, 0x0000 /*'\0'*/}; + +/*****************************************************************************/ + +enum E_Where +{ + e_Root, + e_te, + e_te_IN, + e_Where_count +}; +typedef enum E_Where E_Where; +/*****************************************************************************/ + +#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); } + +#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); } + + +/* Array of our test objects */ + +static struct +{ + const char* name; + UErrorCode expected_constructor_status; + E_Where where; + UBool like[e_Where_count]; + UBool inherits[e_Where_count]; +} param[] = +{ + /* "te" means test */ + /* "IN" means inherits */ + /* "NE" or "ne" means "does not exist" */ + + { "root", U_ZERO_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }, + { "te", U_ZERO_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, + { "te_IN", U_ZERO_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, + { "te_NE", U_USING_FALLBACK_WARNING, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, + { "te_IN_NE", U_USING_FALLBACK_WARNING, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, + { "ne", U_USING_DEFAULT_WARNING, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } } +}; + +static int32_t bundles_count = sizeof(param) / sizeof(param[0]); + + + +/***************************************************************************************/ + +/* Array of our test objects */ + +void addResourceBundleTest(TestNode** root); + +void addResourceBundleTest(TestNode** root) +{ + addTest(root, &TestConstruction1, "tsutil/crestst/TestConstruction1"); + addTest(root, &TestOpenDirect, "tsutil/crestst/TestOpenDirect"); + addTest(root, &TestResourceBundles, "tsutil/crestst/TestResourceBundles"); + addTest(root, &TestTable32, "tsutil/crestst/TestTable32"); + addTest(root, &TestFallback, "tsutil/crestst/TestFallback"); + addTest(root, &TestAliasConflict, "tsutil/crestst/TestAliasConflict"); + addTest(root, &TestFileStream, "tsutil/crestst/TestFileStream"); + addTest(root, &TestGetSize, "tsutil/crestst/TestGetSize"); + addTest(root, &TestGetLocaleByType, "tsutil/crestst/TestGetLocaleByType"); +} + + +/***************************************************************************************/ +void TestAliasConflict(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *he = NULL; + UResourceBundle *iw = NULL; + const UChar *result = NULL; + int32_t resultLen; + + he = ures_open(NULL, "he", &status); + iw = ures_open(NULL, "iw", &status); + if(U_FAILURE(status)) { + log_err("Failed to get resource with %s\n", myErrorName(status)); + } + ures_close(iw); + result = ures_getStringByKey(he, "ExemplarCharacters", &resultLen, &status); + if(U_FAILURE(status) || result == NULL) { + log_err("Failed to get resource with %s\n", myErrorName(status)); + } + ures_close(he); +} + + +void TestResourceBundles() +{ + UErrorCode status = U_ZERO_ERROR; + loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + testTag("only_in_Root", TRUE, FALSE, FALSE); + testTag("in_Root_te", TRUE, TRUE, FALSE); + testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE); + testTag("in_Root_te_IN", TRUE, FALSE, TRUE); + testTag("only_in_te", FALSE, TRUE, FALSE); + testTag("only_in_te_IN", FALSE, FALSE, TRUE); + testTag("in_te_te_IN", FALSE, TRUE, TRUE); + testTag("nonexistent", FALSE, FALSE, FALSE); + + log_verbose("Passed:= %d Failed= %d \n", pass, fail); +} + +void TestConstruction1() +{ + UResourceBundle *test1 = 0, *test2 = 0; + const UChar *result1, *result2; + int32_t resultLen; + UChar temp[7]; + + UErrorCode err = U_ZERO_ERROR; + const char* testdatapath ; + const char* locale="te_IN"; + + log_verbose("Testing ures_open()......\n"); + + + testdatapath=loadTestData(&err); + if(U_FAILURE(err)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(err)); + return; + } + + test1=ures_open(testdatapath, NULL, &err); + if(U_FAILURE(err)) + { + log_err("construction of %s did not succeed : %s \n",NULL, myErrorName(err)); + return; + } + + + test2=ures_open(testdatapath, locale, &err); + if(U_FAILURE(err)) + { + log_err("construction of %s did not succeed : %s \n",locale, myErrorName(err)); + return; + } + result1= ures_getStringByKey(test1, "string_in_Root_te_te_IN", &resultLen, &err); + result2= ures_getStringByKey(test2, "string_in_Root_te_te_IN", &resultLen, &err); + + + if (U_FAILURE(err)) { + log_err("Something threw an error in TestConstruction(): %s\n", myErrorName(err)); + return; + } + + u_uastrcpy(temp, "TE_IN"); + + if(u_strcmp(result2, temp)!=0) + { + int n; + + log_err("Construction test failed for ures_open();\n"); + if(!VERBOSITY) + log_info("(run verbose for more information)\n"); + + log_verbose("\nGot->"); + for(n=0;result2[n];n++) + { + log_verbose("%04X ",result2[n]); + } + log_verbose("<\n"); + + log_verbose("\nWant>"); + for(n=0;temp[n];n++) + { + log_verbose("%04X ",temp[n]); + } + log_verbose("<\n"); + + } + + log_verbose("for string_in_Root_te_te_IN, default.txt had %s\n", austrdup(result1)); + log_verbose("for string_in_Root_te_te_IN, te_IN.txt had %s\n", austrdup(result2)); + + /* Test getVersionNumber*/ + log_verbose("Testing version number\n"); + log_verbose("for getVersionNumber : %s\n", ures_getVersionNumber(test1)); + + ures_close(test1); + ures_close(test2); +} + +/*****************************************************************************/ +/*****************************************************************************/ + +UBool testTag(const char* frag, + UBool in_Root, + UBool in_te, + UBool in_te_IN) +{ + int32_t passNum=pass; + + /* Make array from input params */ + + UBool is_in[3]; + const char *NAME[] = { "ROOT", "TE", "TE_IN" }; + + /* Now try to load the desired items */ + UResourceBundle* theBundle = NULL; + char tag[99]; + char action[256]; + UErrorCode status = U_ZERO_ERROR,expected_resource_status = U_ZERO_ERROR; + UChar* base = NULL; + UChar* expected_string = NULL; + const UChar* string = NULL; + char item_tag[10]; + int32_t i,j; + int32_t actual_bundle; + int32_t resultLen; + const char *testdatapath = loadTestData(&status); + + is_in[0] = in_Root; + is_in[1] = in_te; + is_in[2] = in_te_IN; + + strcpy(item_tag, "tag"); + + status = U_ZERO_ERROR; + theBundle = ures_open(testdatapath, "root", &status); + if(U_FAILURE(status)) + { + ures_close(theBundle); + log_err("Couldn't open root bundle in %s", testdatapath); + return FALSE; + } + ures_close(theBundle); + theBundle = NULL; + + + for (i=0; i<bundles_count; ++i) + { + strcpy(action,"construction for"); + strcat(action, param[i].name); + + + status = U_ZERO_ERROR; + + theBundle = ures_open(testdatapath, param[i].name, &status); + /*theBundle = ures_open("c:\\icu\\icu\\source\\test\\testdata\\testdata", param[i].name, &status);*/ + + CONFIRM_ErrorCode(status,param[i].expected_constructor_status); + + + + if(i == 5) + actual_bundle = 0; /* ne -> default */ + else if(i == 3) + actual_bundle = 1; /* te_NE -> te */ + else if(i == 4) + actual_bundle = 2; /* te_IN_NE -> te_IN */ + else + actual_bundle = i; + + expected_resource_status = U_MISSING_RESOURCE_ERROR; + for (j=e_te_IN; j>=e_Root; --j) + { + if (is_in[j] && param[i].inherits[j]) + { + + if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */ + expected_resource_status = U_ZERO_ERROR; + else if(j == 0) + expected_resource_status = U_USING_DEFAULT_WARNING; + else + expected_resource_status = U_USING_FALLBACK_WARNING; + + log_verbose("%s[%d]::%s: in<%d:%s> inherits<%d:%s>. actual_bundle=%s\n", + param[i].name, + i, + frag, + j, + is_in[j]?"Yes":"No", + j, + param[i].inherits[j]?"Yes":"No", + param[actual_bundle].name); + + break; + } + } + + for (j=param[i].where; j>=0; --j) + { + if (is_in[j]) + { + if(base != NULL) { + free(base); + base = NULL; + } + + base=(UChar*)malloc(sizeof(UChar)*(strlen(NAME[j]) + 1)); + u_uastrcpy(base,NAME[j]); + + break; + } + else { + if(base != NULL) { + free(base); + base = NULL; + } + base = (UChar*) malloc(sizeof(UChar) * 1); + *base = 0x0000; + } + } + + /*-------------------------------------------------------------------- */ + /* string */ + + strcpy(tag,"string_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action, ".ures_get(" ); + strcat(action,tag); + strcat(action, ")"); + + string= kERROR; + + status = U_ZERO_ERROR; + + ures_getStringByKey(theBundle, tag, &resultLen, &status); + if(U_SUCCESS(status)) + { + status = U_ZERO_ERROR; + string=ures_getStringByKey(theBundle, tag, &resultLen, &status); + } + + log_verbose("%s got %d, expected %d\n", action, status, expected_resource_status); + + CONFIRM_ErrorCode(status, expected_resource_status); + + + if(U_SUCCESS(status)){ + expected_string=(UChar*)malloc(sizeof(UChar)*(u_strlen(base) + 3)); + u_strcpy(expected_string,base); + + } + else + { + expected_string = (UChar*)malloc(sizeof(UChar)*(u_strlen(kERROR) + 1)); + u_strcpy(expected_string,kERROR); + + } + + CONFIRM_EQ(string, expected_string); + + free(expected_string); + ures_close(theBundle); + } + free(base); + return (UBool)(passNum == pass); +} + +void record_pass() +{ + ++pass; +} + +void record_fail() +{ + ++fail; +} + +/** + * Test to make sure that the U_USING_FALLBACK_ERROR and U_USING_DEFAULT_ERROR + * are set correctly + */ + +static void TestFallback() +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *fr_FR = NULL; + UResourceBundle *subResource = NULL; + const UChar *junk; /* ignored */ + int32_t resultLen; + + log_verbose("Opening fr_FR.."); + fr_FR = ures_open(NULL, "fr_FR", &status); + if(U_FAILURE(status)) + { + log_err("Couldn't open fr_FR - %d\n", status); + return; + } + + status = U_ZERO_ERROR; + + + /* clear it out.. just do some calls to get the gears turning */ + junk = ures_getStringByKey(fr_FR, "LocaleID", &resultLen, &status); + status = U_ZERO_ERROR; + junk = ures_getStringByKey(fr_FR, "LocaleString", &resultLen, &status); + status = U_ZERO_ERROR; + junk = ures_getStringByKey(fr_FR, "LocaleID", &resultLen, &status); + status = U_ZERO_ERROR; + + /* OK first one. This should be a Default value. */ + subResource = ures_getByKey(fr_FR, "MeasurementSystem", NULL, &status); + if(status != U_USING_DEFAULT_WARNING) + { + log_data_err("Expected U_USING_DEFAULT_ERROR when trying to get CurrencyMap from fr_FR, got %s\n", + u_errorName(status)); + } + ures_close(subResource); + status = U_ZERO_ERROR; + + /* and this is a Fallback, to fr */ + junk = ures_getStringByKey(fr_FR, "Countries", &resultLen, &status); + if(status != U_USING_FALLBACK_WARNING) + { + log_data_err("Expected U_USING_FALLBACK_ERROR when trying to get Countries from fr_FR, got %s\n", + u_errorName(status)); + } + + status = U_ZERO_ERROR; + + ures_close(fr_FR); +} + +static void +TestOpenDirect(void) { + UResourceBundle *idna_rules, *casing, *te_IN, *ne, *item; + UErrorCode errorCode; + + /* + * test that ures_openDirect() opens a resource bundle + * where one can look up its own items but not fallback items + * from root or similar + */ + errorCode=U_ZERO_ERROR; + idna_rules=ures_openDirect(loadTestData(&errorCode), "idna_rules", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ures_openDirect(\"idna_rules\") failed: %s\n", u_errorName(errorCode)); + return; + } + + if(0!=uprv_strcmp("idna_rules", ures_getLocale(idna_rules, &errorCode))) { + log_err("ures_openDirect(\"idna_rules\").getLocale()!=idna_rules\n"); + } + errorCode=U_ZERO_ERROR; + + /* try an item in idna_rules, must work */ + item=ures_getByKey(idna_rules, "UnassignedSet", NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("translit_index.getByKey(local key) failed: %s\n", u_errorName(errorCode)); + errorCode=U_ZERO_ERROR; + } else { + ures_close(item); + } + + /* try an item in root, must fail */ + item=ures_getByKey(idna_rules, "ShortLanguage", NULL, &errorCode); + if(U_FAILURE(errorCode)) { + errorCode=U_ZERO_ERROR; + } else { + log_err("idna_rules.getByKey(root key) succeeded!\n"); + ures_close(item); + } + ures_close(idna_rules); + + /* now make sure that "idna_rules" will not work with ures_open() */ + errorCode=U_ZERO_ERROR; + idna_rules=ures_open("testdata", "idna_rules", &errorCode); + if(U_FAILURE(errorCode) || errorCode==U_USING_DEFAULT_WARNING || errorCode==U_USING_FALLBACK_WARNING) { + /* falling back to default or root is ok */ + errorCode=U_ZERO_ERROR; + } else if(0!=uprv_strcmp("idna_rules", ures_getLocale(idna_rules, &errorCode))) { + /* Opening this file will work in "files mode" on Windows and the Mac, + which have case insensitive file systems */ + log_err("ures_open(\"idna_rules\") succeeded, should fail! Got: %s\n", u_errorName(errorCode)); + } + ures_close(idna_rules); + + /* ures_openDirect("translit_index_WronG") must fail */ + idna_rules=ures_openDirect(NULL, "idna_rules_WronG", &errorCode); + if(U_FAILURE(errorCode)) { + errorCode=U_ZERO_ERROR; + } else { + log_err("ures_openDirect(\"idna_rules_WronG\") succeeded, should fail!\n"); + } + ures_close(idna_rules); + + errorCode = U_USING_FALLBACK_WARNING;; + idna_rules=ures_openDirect("testdata", "idna_rules", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ures_openDirect(\"idna_rules\") failed when U_USING_FALLBACK_WARNING was set prior to call: %s\n", u_errorName(errorCode)); + return; + } + ures_close(idna_rules); + + /* + * ICU 3.6 has new resource bundle syntax and data for bundles that do not + * participate in locale fallback. Now, + * - ures_open() works like ures_openDirect() on a bundle with a top-level + * type of ":table(nofallback)" _if_ the bundle exists + * - ures_open() will continue to find a root bundle if the requested one + * does not exist, unlike ures_openDirect() + * + * Test with a different bundle than above to avoid confusion in the cache. + */ + + /* + * verify that ures_open("casing"), which now has a nofallback declaration, + * does not enable fallbacks + */ + errorCode=U_ZERO_ERROR; + casing=ures_open("testdata", "casing", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ures_open(\"casing\") failed: %s\n", u_errorName(errorCode)); + return; + } + + errorCode=U_ZERO_ERROR; + item=ures_getByKey(casing, "Info", NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("casing.getByKey(Info) failed - %s\n", u_errorName(errorCode)); + } else { + ures_close(item); + } + + errorCode=U_ZERO_ERROR; + item=ures_getByKey(casing, "ShortLanguage", NULL, &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("casing.getByKey(root key) succeeded despite nofallback declaration - %s\n", u_errorName(errorCode)); + ures_close(item); + } + ures_close(casing); + + /* + * verify that ures_open("ne") finds the root bundle but + * ures_openDirect("ne") does not + */ + errorCode=U_ZERO_ERROR; + ne=ures_open("testdata", "ne", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ures_open(\"ne\") failed (expected to get root): %s\n", u_errorName(errorCode)); + } + if(errorCode!=U_USING_DEFAULT_WARNING || 0!=uprv_strcmp("root", ures_getLocale(ne, &errorCode))) { + log_err("ures_open(\"ne\") found something other than \"root\" - %s\n", u_errorName(errorCode)); + } + ures_close(ne); + + errorCode=U_ZERO_ERROR; + ne=ures_openDirect("testdata", "ne", &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("ures_openDirect(\"ne\") succeeded unexpectedly\n"); + ures_close(ne); + } + + /* verify that ures_openDirect("te_IN") does not enable fallbacks */ + errorCode=U_ZERO_ERROR; + te_IN=ures_openDirect("testdata", "te_IN", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ures_open(\"te_IN\") failed: %s\n", u_errorName(errorCode)); + return; + } + errorCode=U_ZERO_ERROR; + item=ures_getByKey(te_IN, "ShortLanguage", NULL, &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("te_IN.getByKey(root key) succeeded despite use of ures_openDirect() - %s\n", u_errorName(errorCode)); + ures_close(item); + } + ures_close(te_IN); +} + +static int32_t +parseTable32Key(const char *key) { + int32_t number; + char c; + + number=0; + while((c=*key++)!=0) { + number<<=1; + if(c=='1') { + number|=1; + } + } + return number; +} + +static void +TestTable32(void) { + static const struct { + const char *key; + int32_t number; + } testcases[]={ + { "ooooooooooooooooo", 0 }, + { "oooooooooooooooo1", 1 }, + { "ooooooooooooooo1o", 2 }, + { "oo11ooo1ooo11111o", 25150 }, + { "oo11ooo1ooo111111", 25151 }, + { "o1111111111111111", 65535 }, + { "1oooooooooooooooo", 65536 }, + { "1ooooooo11o11ooo1", 65969 }, + { "1ooooooo11o11oo1o", 65970 }, + { "1ooooooo111oo1111", 65999 } + }; + + /* ### TODO UResourceBundle staticItem={ 0 }; - need to know the size */ + UResourceBundle *res, *item; + const UChar *s; + const char *key; + UErrorCode errorCode; + int32_t i, j, number, parsedNumber, length, count; + + errorCode=U_ZERO_ERROR; + res=ures_open(loadTestData(&errorCode), "testtable32", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("unable to open testdata/testtable32.res - %s\n", u_errorName(errorCode)); + return; + } + if(ures_getType(res)!=URES_TABLE) { + log_data_err("testdata/testtable32.res has type %d instead of URES_TABLE\n", ures_getType(res)); + } + + count=ures_getSize(res); + if(count!=66000) { + log_err("testdata/testtable32.res should have 66000 entries but has %d\n", count); + } + + /* get the items by index */ + item=NULL; + for(i=0; i<count; ++i) { + item=ures_getByIndex(res, i, item, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to get item %d of %d in testdata/testtable32.res - %s\n", + i, count, u_errorName(errorCode)); + break; + } + + key=ures_getKey(item); + parsedNumber=parseTable32Key(key); + + switch(ures_getType(item)) { + case URES_STRING: + s=ures_getString(item, &length, &errorCode); + if(U_FAILURE(errorCode) || s==NULL) { + log_err("unable to access the string \"%s\" at %d in testdata/testtable32.res - %s\n", + key, i, u_errorName(errorCode)); + number=-1; + } else { + j=0; + U16_NEXT(s, j, length, number); + } + break; + case URES_INT: + number=ures_getInt(item, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to access the integer \"%s\" at %d in testdata/testtable32.res - %s\n", + key, i, u_errorName(errorCode)); + number=-1; + } + break; + default: + log_err("unexpected resource type %d for \"%s\" at %d in testdata/testtable32.res - %s\n", + ures_getType(item), key, i, u_errorName(errorCode)); + number=-1; + break; + } + + if(number>=0 && number!=parsedNumber) { + log_err("\"%s\" at %d in testdata/testtable32.res has a string/int value of %d, expected %d\n", + key, i, number, parsedNumber); + } + } + + /* search for some items by key */ + for(i=0; i<LENGTHOF(testcases); ++i) { + item=ures_getByKey(res, testcases[i].key, item, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to find the key \"%s\" in testdata/testtable32.res - %s\n", + testcases[i].key, u_errorName(errorCode)); + continue; + } + + switch(ures_getType(item)) { + case URES_STRING: + s=ures_getString(item, &length, &errorCode); + if(U_FAILURE(errorCode) || s==NULL) { + log_err("unable to access the string \"%s\" in testdata/testtable32.res - %s\n", + testcases[i].key, u_errorName(errorCode)); + number=-1; + } else { + j=0; + U16_NEXT(s, j, length, number); + } + break; + case URES_INT: + number=ures_getInt(item, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to access the integer \"%s\" in testdata/testtable32.res - %s\n", + testcases[i].key, u_errorName(errorCode)); + number=-1; + } + break; + default: + log_err("unexpected resource type %d for \"%s\" in testdata/testtable32.res - %s\n", + ures_getType(item), testcases[i].key, u_errorName(errorCode)); + number=-1; + break; + } + + if(number>=0 && number!=testcases[i].number) { + log_err("\"%s\" in testdata/testtable32.res has a string/int value of %d, expected %d\n", + testcases[i].key, number, testcases[i].number); + } + + key=ures_getKey(item); + if(0!=uprv_strcmp(key, testcases[i].key)) { + log_err("\"%s\" in testdata/testtable32.res claims to have the key \"%s\"\n", + testcases[i].key, key); + } + } + + ures_close(item); + ures_close(res); +} + +static void TestFileStream(void){ + int32_t c = 0; + int32_t c1=0; + UErrorCode status = U_ZERO_ERROR; + const char* testdatapath = loadTestData(&status); + char* fileName = (char*) malloc(uprv_strlen(testdatapath) +10); + FileStream* stream = NULL; + /* these should not be closed */ + FileStream* pStdin = T_FileStream_stdin(); + FileStream* pStdout = T_FileStream_stdout(); + FileStream* pStderr = T_FileStream_stderr(); + + const char* testline = "This is a test line"; + int32_t bufLen = (int32_t)strlen(testline)+10; + char* buf = (char*) malloc(bufLen); + int32_t retLen = 0; + + if(pStdin==NULL){ + log_err("failed to get T_FileStream_stdin()"); + } + if(pStdout==NULL){ + log_err("failed to get T_FileStream_stdout()"); + } + if(pStderr==NULL){ + log_err("failed to get T_FileStream_stderr()"); + } + + uprv_strcpy(fileName,testdatapath); + uprv_strcat(fileName,".dat"); + stream = T_FileStream_open(fileName, "r"); + if(stream==NULL){ + log_data_err("T_FileStream_open failed to open %s\n",fileName); + } else { + if(!T_FileStream_file_exists(fileName)){ + log_data_err("T_FileStream_file_exists failed to verify existence of %s \n",fileName); + } + + retLen=T_FileStream_read(stream,&c,1); + if(retLen==0){ + log_data_err("T_FileStream_read failed to read from %s \n",fileName); + } + retLen=0; + T_FileStream_rewind(stream); + T_FileStream_read(stream,&c1,1); + if(c!=c1){ + log_data_err("T_FileStream_rewind failed to rewind %s \n",fileName); + } + T_FileStream_rewind(stream); + c1 = T_FileStream_peek(stream); + if(c!=c1){ + log_data_err("T_FileStream_peek failed to peekd %s \n",fileName); + } + c = T_FileStream_getc(stream); + T_FileStream_ungetc(c,stream); + if(c!= T_FileStream_getc(stream)){ + log_data_err("T_FileStream_ungetc failed to d %s \n",fileName); + } + + if(T_FileStream_size(stream)<=0){ + log_data_err("T_FileStream_size failed to d %s \n",fileName); + } + if(T_FileStream_error(stream)){ + log_data_err("T_FileStream_error shouldn't have an error %s\n",fileName); + } + if(!T_FileStream_error(NULL)){ + log_err("T_FileStream_error didn't get an error %s\n",fileName); + } + T_FileStream_putc(stream, 0x20); + if(!T_FileStream_error(stream)){ + /* + Warning + writing to a read-only file may not consistently fail on all platforms + (e.g. HP-UX, FreeBSD, MacOSX) + */ + log_verbose("T_FileStream_error didn't get an error when writing to a readonly file %s\n",fileName); + } + + T_FileStream_close(stream); + } + /* test writing function */ + stream=NULL; + uprv_strcpy(fileName,testdatapath); + uprv_strcat(fileName,".tmp"); + stream = T_FileStream_open(fileName,"w+"); + + if(stream == NULL){ + log_data_err("Could not open %s for writing\n",fileName); + } else { + c= '$'; + T_FileStream_putc(stream,c); + T_FileStream_rewind(stream); + if(c != T_FileStream_getc(stream)){ + log_data_err("T_FileStream_putc failed %s\n",fileName); + } + + T_FileStream_rewind(stream); + T_FileStream_writeLine(stream,testline); + T_FileStream_rewind(stream); + T_FileStream_readLine(stream,buf,bufLen); + if(uprv_strncmp(testline, buf,uprv_strlen(buf))!=0){ + log_data_err("T_FileStream_writeLine failed %s\n",fileName); + } + + T_FileStream_rewind(stream); + T_FileStream_write(stream,testline,(int32_t)strlen(testline)); + T_FileStream_rewind(stream); + retLen = T_FileStream_read(stream, buf, bufLen); + if(uprv_strncmp(testline, buf,retLen)!=0){ + log_data_err("T_FileStream_write failed %s\n",fileName); + } + + T_FileStream_close(stream); + } + if(!T_FileStream_remove(fileName)){ + log_data_err("T_FileStream_remove failed to delete %s\n",fileName); + } + + + free(fileName); + free(buf); + +} + +static void TestGetSize(void) { + const struct { + const char* key; + int32_t size; + } test[] = { + { "zerotest", 1}, + { "one", 1}, + { "importtest", 1}, + { "integerarray", 1}, + { "emptyarray", 0}, + { "emptytable", 0}, + { "emptystring", 1}, /* empty string is still a string */ + { "emptyint", 1}, + { "emptybin", 1}, + { "testinclude", 1}, + { "collations", 1}, /* not 2 - there is hidden %%CollationBin */ + }; + + UErrorCode status = U_ZERO_ERROR; + + UResourceBundle *rb = NULL; + UResourceBundle *res = NULL; + UResourceBundle *helper = NULL; + const char* testdatapath = loadTestData(&status); + int32_t i = 0, j = 0; + int32_t size = 0; + + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s\n", u_errorName(status)); + return; + } + + rb = ures_open(testdatapath, "testtypes", &status); + if(U_FAILURE(status)) + { + log_err("Could not testtypes resource bundle %s\n", u_errorName(status)); + return; + } + + for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) { + res = ures_getByKey(rb, test[i].key, res, &status); + if(U_FAILURE(status)) + { + log_err("Couldn't find the key %s. Error: %s\n", test[i].key, u_errorName(status)); + ures_close(rb); + return; + } + size = ures_getSize(res); + if(size != test[i].size) { + log_err("Expected size %i, got size %i for key %s\n", test[i].size, size, test[i].key); + for(j = 0; j < size; j++) { + helper = ures_getByIndex(res, j, helper, &status); + log_err("%s\n", ures_getKey(helper)); + } + } + } + ures_close(helper); + ures_close(res); + ures_close(rb); +} + +static void TestGetLocaleByType(void) { + static const struct { + const char *requestedLocale; + const char *resourceKey; + const char *validLocale; + const char *actualLocale; + } test[] = { + { "te_IN_BLAH", "string_only_in_te_IN", "te_IN", "te_IN" }, + { "te_IN_BLAH", "string_only_in_te", "te_IN", "te" }, + { "te_IN_BLAH", "string_only_in_Root", "te_IN", "root" }, + { "te_IN_BLAH_01234567890_01234567890_01234567890_01234567890_01234567890_01234567890", "array_2d_only_in_Root", "te_IN", "root" }, + { "te_IN_BLAH@currency=euro", "array_2d_only_in_te_IN", "te_IN", "te_IN" }, + { "te_IN_BLAH@collation=phonebook;calendar=thai", "array_2d_only_in_te", "te_IN", "te" } + }; + + UErrorCode status = U_ZERO_ERROR; + + UResourceBundle *rb = NULL; + UResourceBundle *res = NULL; + const char* testdatapath = loadTestData(&status); + int32_t i = 0; + const char *locale = NULL; + + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s\n", u_errorName(status)); + return; + } + + for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) { + rb = ures_open(testdatapath, test[i].requestedLocale, &status); + if(U_FAILURE(status)) + { + log_err("Could not open resource bundle %s (error %s)\n", test[i].requestedLocale, u_errorName(status)); + status = U_ZERO_ERROR; + continue; + } + + res = ures_getByKey(rb, test[i].resourceKey, res, &status); + if(U_FAILURE(status)) + { + log_err("Couldn't find the key %s. Error: %s\n", test[i].resourceKey, u_errorName(status)); + ures_close(rb); + status = U_ZERO_ERROR; + continue; + } + + locale = ures_getLocaleByType(res, ULOC_REQUESTED_LOCALE, &status); + if(locale) { + log_err("Requested locale should return NULL\n"); + } + locale = ures_getLocaleByType(res, ULOC_VALID_LOCALE, &status); + if(!locale || strcmp(locale, test[i].validLocale) != 0) { + log_err("Expected valid locale to be %s. Got %s\n", test[i].requestedLocale, locale); + } + locale = ures_getLocaleByType(res, ULOC_ACTUAL_LOCALE, &status); + if(!locale || strcmp(locale, test[i].actualLocale) != 0) { + log_err("Expected actual locale to be %s. Got %s\n", test[i].requestedLocale, locale); + } + ures_close(rb); + } + ures_close(res); +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h new file mode 100644 index 00000000000..de11a959ddd --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h @@ -0,0 +1,55 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2004, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CRESTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +********************************************************************************* +*/ +#ifndef _CRESTST +#define _CRESTST +/* C API TEST FOR RESOURCEBUNDLE */ +#include "cintltst.h" + + + + + void addTestResourceBundleTest(TestNode**); + + /** + * Perform several extensive tests using the subtest routine testTag + */ + void TestResourceBundles(void); + /** + * Test construction of ResourceBundle accessing a custom test resource-file + */ + void TestConstruction1(void); + + void TestConstruction2(void); + + void TestAliasConflict(void); + + static void TestGetSize(void); + + static void TestGetLocaleByType(void); + + /** + * extensive subtests called by TestResourceBundles + **/ + + UBool testTag(const char* frag, UBool in_Root, UBool in_te, UBool in_te_IN); + + void record_pass(void); + void record_fail(void); + + + int32_t pass; + int32_t fail; + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c new file mode 100644 index 00000000000..159235d4755 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c @@ -0,0 +1,2950 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CRESTST.C +* +* Modification History: +* Name Date Description +* Madhu Katragadda 05/09/2000 Ported Tests for New ResourceBundle API +* Madhu Katragadda 05/24/2000 Added new tests to test RES_BINARY for collationElements +******************************************************************************** +*/ + + +#include <time.h> +#include "unicode/utypes.h" +#include "cintltst.h" +#include "unicode/putil.h" +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "string.h" +#include "cstring.h" +#include "unicode/uchar.h" +#include "ucol_imp.h" /* for U_ICUDATA_COLL */ +#include "ubrkimpl.h" /* for U_ICUDATA_BRKITR */ +#define RESTEST_HEAP_CHECK 0 + +#include "unicode/uloc.h" +#include "uresimp.h" +#include "creststn.h" +#include "unicode/ctest.h" +#include "ucbuf.h" +static int32_t pass; +static int32_t fail; + +/*****************************************************************************/ +/** + * Return a random unsigned long l where 0N <= l <= ULONG_MAX. + */ + +static uint32_t +randul() +{ + uint32_t l=0; + int32_t i; + static UBool initialized = FALSE; + if (!initialized) + { + srand((unsigned)time(NULL)); + initialized = TRUE; + } + /* Assume rand has at least 12 bits of precision */ + + for (i=0; i<sizeof(l); ++i) + ((char*)&l)[i] = (char)((rand() & 0x0FF0) >> 4); + return l; +} + +/** + * Return a random double x where 0.0 <= x < 1.0. + */ +static double +randd() +{ + return ((double)randul()) / UINT32_MAX; +} + +/** + * Return a random integer i where 0 <= i < n. + */ +static int32_t randi(int32_t n) +{ + return (int32_t)(randd() * n); +} +/***************************************************************************************/ +/** + * Convert an integer, positive or negative, to a character string radix 10. + */ +static char* +itoa1(int32_t i, char* buf) +{ + char *p = 0; + char* result = buf; + /* Handle negative */ + if(i < 0) { + *buf++ = '-'; + i = -i; + } + + /* Output digits in reverse order */ + p = buf; + do { + *p++ = (char)('0' + (i % 10)); + i /= 10; + } + while(i); + *p-- = 0; + + /* Reverse the string */ + while(buf < p) { + char c = *buf; + *buf++ = *p; + *p-- = c; + } + + return result; +} +static const int32_t kERROR_COUNT = -1234567; +static const UChar kERROR[] = { 0x0045 /*E*/, 0x0052 /*'R'*/, 0x0052 /*'R'*/, + 0x004F /*'O'*/, 0x0052/*'R'*/, 0x0000 /*'\0'*/}; + +/*****************************************************************************/ + +enum E_Where +{ + e_Root, + e_te, + e_te_IN, + e_Where_count +}; +typedef enum E_Where E_Where; +/*****************************************************************************/ + +#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); } +#define CONFIRM_INT_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of %d\n", action, actual, expected); } +#define CONFIRM_INT_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x >= %d\n", action, actual, expected); } +#define CONFIRM_INT_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x != %d\n", action, actual, expected); } +/*#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); } */ +static void +CONFIRM_ErrorCode(UErrorCode actual,UErrorCode expected) +{ + if ((expected)==(actual)) + { + record_pass(); + } else { + record_fail(); + /*log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); */ + log_err("returned %s instead of %s\n", myErrorName(actual), myErrorName(expected)); + } +} + + +/* Array of our test objects */ + +static struct +{ + const char* name; + UErrorCode expected_constructor_status; + E_Where where; + UBool like[e_Where_count]; + UBool inherits[e_Where_count]; +} +param[] = +{ + /* "te" means test */ + /* "IN" means inherits */ + /* "NE" or "ne" means "does not exist" */ + + { "root", U_ZERO_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }, + { "te", U_ZERO_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, + { "te_IN", U_ZERO_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, + { "te_NE", U_USING_FALLBACK_WARNING, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, + { "te_IN_NE", U_USING_FALLBACK_WARNING, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, + { "ne", U_USING_DEFAULT_WARNING, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } } +}; + +static int32_t bundles_count = sizeof(param) / sizeof(param[0]); + + +/*static void printUChars(UChar*);*/ +static void TestDecodedBundle(void); +static void TestGetKeywordValues(void); +static void TestGetFunctionalEquivalent(void); +static void TestCLDRStyleAliases(void); +static void TestFallbackCodes(void); +static void TestGetUTF8String(void); + +/***************************************************************************************/ + +/* Array of our test objects */ + +void addNEWResourceBundleTest(TestNode** root) +{ + addTest(root, &TestErrorCodes, "tsutil/creststn/TestErrorCodes"); + addTest(root, &TestEmptyBundle, "tsutil/creststn/TestEmptyBundle"); + addTest(root, &TestConstruction1, "tsutil/creststn/TestConstruction1"); + addTest(root, &TestResourceBundles, "tsutil/creststn/TestResourceBundles"); + addTest(root, &TestFallback, "tsutil/creststn/TestFallback"); + addTest(root, &TestGetVersion, "tsutil/creststn/TestGetVersion"); + addTest(root, &TestGetVersionColl, "tsutil/creststn/TestGetVersionColl"); + addTest(root, &TestAliasConflict, "tsutil/creststn/TestAliasConflict"); + addTest(root, &TestNewTypes, "tsutil/creststn/TestNewTypes"); + addTest(root, &TestEmptyTypes, "tsutil/creststn/TestEmptyTypes"); + addTest(root, &TestBinaryCollationData, "tsutil/creststn/TestBinaryCollationData"); + addTest(root, &TestAPI, "tsutil/creststn/TestAPI"); + addTest(root, &TestErrorConditions, "tsutil/creststn/TestErrorConditions"); + addTest(root, &TestDecodedBundle, "tsutil/creststn/TestDecodedBundle"); + addTest(root, &TestResourceLevelAliasing, "tsutil/creststn/TestResourceLevelAliasing"); + addTest(root, &TestDirectAccess, "tsutil/creststn/TestDirectAccess"); + addTest(root, &TestGetKeywordValues, "tsutil/creststn/TestGetKeywordValues"); + addTest(root, &TestGetFunctionalEquivalent,"tsutil/creststn/TestGetFunctionalEquivalent"); + addTest(root, &TestJB3763, "tsutil/creststn/TestJB3763"); + addTest(root, &TestXPath, "tsutil/creststn/TestXPath"); + addTest(root, &TestCLDRStyleAliases, "tsutil/creststn/TestCLDRStyleAliases"); + addTest(root, &TestFallbackCodes, "tsutil/creststn/TestFallbackCodes"); + addTest(root, &TestStackReuse, "tsutil/creststn/TestStackReuse"); + addTest(root, &TestGetUTF8String, "tsutil/creststn/TestGetUTF8String"); +} + + +/***************************************************************************************/ +static const char* norwayNames[] = { + "no_NO_NY", + "no_NO", + "no", + "nn_NO", + "nn", + "nb_NO", + "nb" +}; + +static const char* norwayLocales[] = { + "nn_NO", + "nb_NO", + "nb", + "nn_NO", + "nn", + "nb_NO", + "nb" +}; + +static void checkStatus(int32_t line, UErrorCode expected, UErrorCode status) { + if(U_FAILURE(status)) { + log_data_err("Resource not present, cannot test (%s:%d)\n", __FILE__, line); + } + if(status != expected) { + log_err("%s:%d: Expected error code %s, got error code %s\n", __FILE__, line, u_errorName(expected), u_errorName(status)); + } +} + +static void TestErrorCodes(void) { + UErrorCode status = U_USING_DEFAULT_WARNING; + + UResourceBundle *r = NULL, *r2 = NULL; + + /* First check with ICUDATA */ + /* first bundle should return fallback warning */ + r = ures_open(NULL, "ti_ER_ASSAB", &status); + checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status); + ures_close(r); + + /* this bundle should return zero error, so it shouldn't change the status*/ + status = U_USING_DEFAULT_WARNING; + r = ures_open(NULL, "ti_ER", &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + + /* we look up the resource which is aliased, but it lives in fallback */ + if(U_SUCCESS(status) && r != NULL) { + status = U_USING_DEFAULT_WARNING; + r2 = ures_getByKey(r, "Languages", NULL, &status); /* languages of 'ti' aliases to 'am' */ + checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status); + } + ures_close(r); + + /* this bundle should return zero error, so it shouldn't change the status*/ + status = U_USING_DEFAULT_WARNING; + r = ures_open(NULL, "ti", &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + + /* we look up the resource which is aliased and at our level */ + if(U_SUCCESS(status) && r != NULL) { + status = U_USING_DEFAULT_WARNING; + r2 = ures_getByKey(r, "Languages", r2, &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + } + ures_close(r); + + status = U_USING_FALLBACK_WARNING; + r = ures_open(NULL, "nolocale", &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + ures_close(r); + ures_close(r2); + + /** Now, with the collation bundle **/ + + /* first bundle should return fallback warning */ + r = ures_open(U_ICUDATA_COLL, "sr_YU_VOJVODINA", &status); + checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status); + ures_close(r); + + /* this bundle should return zero error, so it shouldn't change the status*/ + status = U_USING_FALLBACK_WARNING; + r = ures_open(U_ICUDATA_COLL, "sr", &status); + checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status); + + /* we look up the resource which is aliased */ + if(U_SUCCESS(status) && r != NULL) { + status = U_USING_DEFAULT_WARNING; + r2 = ures_getByKey(r, "collations", NULL, &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + } + ures_close(r); + + /* this bundle should return zero error, so it shouldn't change the status*/ + status = U_USING_DEFAULT_WARNING; + r = ures_open(U_ICUDATA_COLL, "sr", &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + + /* we look up the resource which is aliased and at our level */ + if(U_SUCCESS(status) && r != NULL) { + status = U_USING_DEFAULT_WARNING; + r2 = ures_getByKey(r, "collations", r2, &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + } + ures_close(r); + + status = U_USING_FALLBACK_WARNING; + r = ures_open(U_ICUDATA_COLL, "nolocale", &status); + checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status); + ures_close(r); + ures_close(r2); +} + +static void TestAliasConflict(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *he = NULL; + UResourceBundle *iw = NULL; + UResourceBundle *norway = NULL; + const UChar *result = NULL; + int32_t resultLen; + uint32_t size = 0; + uint32_t i = 0; + const char *realName = NULL; + + he = ures_open(NULL, "he", &status); + iw = ures_open(NULL, "iw", &status); + if(U_FAILURE(status)) { + log_err("Failed to get resource with %s\n", myErrorName(status)); + } + ures_close(iw); + result = ures_getStringByKey(he, "ExemplarCharacters", &resultLen, &status); + if(U_FAILURE(status) || result == NULL) { + log_err("Failed to get resource ExemplarCharacters with %s\n", myErrorName(status)); + } + ures_close(he); + + size = sizeof(norwayNames)/sizeof(norwayNames[0]); + for(i = 0; i < size; i++) { + status = U_ZERO_ERROR; + norway = ures_open(NULL, norwayNames[i], &status); + if(U_FAILURE(status)) { + log_err("Failed to get resource with %s for %s\n", myErrorName(status), norwayNames[i]); + continue; + } + realName = ures_getLocale(norway, &status); + log_verbose("ures_getLocale(\"%s\")=%s\n", norwayNames[i], realName); + if(realName == NULL || strcmp(norwayLocales[i], realName) != 0) { + log_data_err("Wrong locale name for %s, expected %s, got %s\n", norwayNames[i], norwayLocales[i], realName); + } + ures_close(norway); + } +} + +static void TestDecodedBundle(){ + + UErrorCode error = U_ZERO_ERROR; + + UResourceBundle* resB; + + const UChar* srcFromRes; + int32_t len; + static const UChar uSrc[] = { + 0x0009,0x092F,0x0941,0x0928,0x0947,0x0938,0x094D,0x0915,0x094B,0x0020,0x002E,0x0915,0x0947,0x0020,0x002E,0x090F, + 0x0915,0x0020,0x002E,0x0905,0x0927,0x094D,0x092F,0x092F,0x0928,0x0020,0x002E,0x0915,0x0947,0x0020,0x0905,0x0928, + 0x0941,0x0938,0x093E,0x0930,0x0020,0x0031,0x0039,0x0039,0x0030,0x0020,0x0924,0x0915,0x0020,0x0915,0x0902,0x092A, + 0x094D,0x092F,0x0942,0x091F,0x0930,0x002D,0x092A,0x094D,0x0930,0x092C,0x0902,0x0927,0x093F,0x0924,0x0020,0x0938, + 0x0942,0x091A,0x0928,0x093E,0x092A,0x094D,0x0930,0x0923,0x093E,0x0932,0x0940,0x0020,0x002E,0x0915,0x0947,0x0020, + 0x002E,0x092F,0x094B,0x0917,0x0926,0x093E,0x0928,0x0020,0x002E,0x0915,0x0947,0x0020,0x002E,0x092B,0x0932,0x0938, + 0x094D,0x0935,0x0930,0x0942,0x092A,0x0020,0x002E,0x0935,0x093F,0x0936,0x094D,0x0935,0x0020,0x002E,0x092E,0x0947, + 0x0902,0x0020,0x002E,0x0938,0x093E,0x0932,0x093E,0x0928,0x093E,0x0020,0x002E,0x0032,0x0032,0x0030,0x0030,0x0020, + 0x0905,0x0930,0x092C,0x0020,0x0930,0x0941,0x092A,0x092F,0x0947,0x0020,0x092E,0x0942,0x0932,0x094D,0x092F,0x0915, + 0x0940,0x0020,0x002E,0x0034,0x0935,0x0938,0x094D,0x0924,0x0941,0x0913,0x0902,0x0020,0x002E,0x0034,0x0915,0x093E, + 0x0020,0x002E,0x0034,0x0909,0x0924,0x094D,0x092A,0x093E,0x0926,0x0928,0x0020,0x002E,0x0034,0x0939,0x094B,0x0917, + 0x093E,0x002C,0x0020,0x002E,0x0033,0x091C,0x092C,0x0915,0x093F,0x0020,0x002E,0x0033,0x0915,0x0902,0x092A,0x094D, + 0x092F,0x0942,0x091F,0x0930,0x0020,0x002E,0x0033,0x0915,0x093E,0x0020,0x002E,0x0033,0x0915,0x0941,0x0932,0x0020, + 0x002E,0x0033,0x092F,0x094B,0x0917,0x0926,0x093E,0x0928,0x0020,0x002E,0x0033,0x0907,0x0938,0x0938,0x0947,0x0915, + 0x0939,0x093F,0x0020,0x002E,0x002F,0x091C,0x094D,0x092F,0x093E,0x0926,0x093E,0x0020,0x002E,0x002F,0x0939,0x094B, + 0x0917,0x093E,0x0964,0x0020,0x002E,0x002F,0x0905,0x0928,0x0941,0x0938,0x0902,0x0927,0x093E,0x0928,0x0020,0x002E, + 0x002F,0x0915,0x0940,0x0020,0x002E,0x002F,0x091A,0x0930,0x092E,0x0020,0x0938,0x0940,0x092E,0x093E,0x0913,0x0902, + 0x0020,0x092A,0x0930,0x0020,0x092A,0x0939,0x0941,0x0902,0x091A,0x0928,0x0947,0x0020,0x0915,0x0947,0x0020,0x0932, + 0x093F,0x090F,0x0020,0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x090F,0x0915,0x0020,0x002E,0x002F, + 0x0906,0x092E,0x0020,0x002E,0x002F,0x091C,0x0930,0x0942,0x0930,0x0924,0x0020,0x002E,0x002F,0x091C,0x0948,0x0938, + 0x093E,0x0020,0x092C,0x0928,0x0020,0x0917,0x092F,0x093E,0x0020,0x0939,0x0948,0x0964,0x0020,0x092D,0x093E,0x0930, + 0x0924,0x0020,0x092E,0x0947,0x0902,0x0020,0x092D,0x0940,0x002C,0x0020,0x0916,0x093E,0x0938,0x0915,0x0930,0x0020, + 0x092E,0x094C,0x091C,0x0942,0x0926,0x093E,0x0020,0x0938,0x0930,0x0915,0x093E,0x0930,0x0928,0x0947,0x002C,0x0020, + 0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x0020,0x0915,0x0947,0x0020,0x092A,0x094D,0x0930,0x092F, + 0x094B,0x0917,0x0020,0x092A,0x0930,0x0020,0x091C,0x092C,0x0930,0x0926,0x0938,0x094D,0x0924,0x0020,0x090F,0x095C, + 0x0020,0x0932,0x0917,0x093E,0x092F,0x0940,0x0020,0x0939,0x0948,0x002C,0x0020,0x0915,0x093F,0x0902,0x0924,0x0941, + 0x0020,0x0907,0x0938,0x0915,0x0947,0x0020,0x0938,0x0930,0x092A,0x091F,0x0020,0x0926,0x094C,0x095C,0x0932,0x0917, + 0x093E,0x0928,0x0947,0x0020,0x002E,0x0032,0x0915,0x0947,0x0020,0x002E,0x0032,0x0932,0x093F,0x090F,0x0020,0x002E, + 0x0032,0x0915,0x094D,0x092F,0x093E,0x0020,0x002E,0x0032,0x0938,0x092A,0x093E,0x091F,0x0020,0x002E,0x0032,0x0930, + 0x093E,0x0938,0x094D,0x0924,0x093E,0x0020,0x002E,0x0032,0x0909,0x092A,0x0932,0x092C,0x094D,0x0927,0x0020,0x002E, + 0x0939,0x0948,0x002C,0x0020,0x002E,0x0905,0x0925,0x0935,0x093E,0x0020,0x002E,0x0935,0x093F,0x0936,0x094D,0x0935, + 0x0020,0x002E,0x092E,0x0947,0x0902,0x0020,0x002E,0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x0020, + 0x002E,0x0915,0x0940,0x0938,0x092B,0x0932,0x0924,0x093E,0x0020,0x002E,0x0033,0x0935,0x0020,0x002E,0x0033,0x0935, + 0x093F,0x092B,0x0932,0x0924,0x093E,0x0020,0x002E,0x0033,0x0938,0x0947,0x0020,0x002E,0x0033,0x0938,0x092C,0x0915, + 0x0020,0x002E,0x0033,0x0932,0x0947,0x0020,0x002E,0x0033,0x0915,0x0930,0x0020,0x002E,0x0033,0x0915,0x094D,0x092F, + 0x093E,0x0020,0x002E,0x0033,0x0939,0x092E,0x0020,0x002E,0x0033,0x0907,0x0938,0x0915,0x093E,0x0020,0x002E,0x0033, + 0x092F,0x0941,0x0915,0x094D,0x0924,0x093F,0x092A,0x0942,0x0930,0x094D,0x0923,0x0020,0x002E,0x0032,0x0935,0x093F, + 0x0938,0x094D,0x0924,0x093E,0x0930,0x0020,0x0905,0x092A,0x0947,0x0915,0x094D,0x0937,0x093F,0x0924,0x0020,0x0915, + 0x0930,0x0020,0x0938,0x0915,0x0947,0x0902,0x0917,0x0947,0x0020,0x003F,0x0020, + 0 + }; + + /* pre-flight */ + int32_t num =0; + const char *testdatapath = loadTestData(&error); + resB = ures_open(testdatapath, "iscii", &error); + srcFromRes=tres_getString(resB,-1,"str",&len,&error); + if(U_FAILURE(error)){ +#if UCONFIG_NO_LEGACY_CONVERSION + log_info("Couldn't load iscii.bin from test data bundle, (because UCONFIG_NO_LEGACY_CONVERSION is turned on)\n"); +#else + log_err("Could not find iscii.bin from test data bundle. Error: %s\n", u_errorName(error)); +#endif + ures_close(resB); + return; + } + if(u_strncmp(srcFromRes,uSrc,len)!=0){ + log_err("Genrb produced res files after decoding failed\n"); + } + while(num<len){ + if(uSrc[num]!=srcFromRes[num]){ + log_verbose(" Expected: 0x%04X Got: 0x%04X \n", uSrc[num],srcFromRes[num]); + } + num++; + } + if (len != u_strlen(uSrc)) { + log_err("Genrb produced a string larger than expected\n"); + } + ures_close(resB); +} + +static void TestNewTypes() { + UResourceBundle* theBundle = NULL; + char action[256]; + const char* testdatapath; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle* res = NULL; + uint8_t *binResult = NULL; + int32_t len = 0; + int32_t i = 0; + int32_t intResult = 0; + uint32_t uintResult = 0; + const UChar *empty = NULL; + const UChar *zeroString; + UChar expected[] = { 'a','b','c','\0','d','e','f' }; + const char* expect ="tab:\t cr:\r ff:\f newline:\n backslash:\\\\ quote=\\\' doubleQuote=\\\" singlequoutes=''"; + UChar uExpect[200]; + + testdatapath=loadTestData(&status); + + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + theBundle = ures_open(testdatapath, "testtypes", &status); + + empty = tres_getString(theBundle, -1, "emptystring", &len, &status); + if(empty && (*empty != 0 || len != 0)) { + log_err("Empty string returned invalid value\n"); + } + + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + + CONFIRM_INT_NE(theBundle, NULL); + + /* This test reads the string "abc\u0000def" from the bundle */ + /* if everything is working correctly, the size of this string */ + /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/ + + strcpy(action, "getting and testing of string with embeded zero"); + res = ures_getByKey(theBundle, "zerotest", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_STRING); + zeroString=tres_getString(res, -1, NULL, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(len, 7); + CONFIRM_INT_NE(len, 3); + } + for(i=0;i<len;i++){ + if(zeroString[i]!= expected[i]){ + log_verbose("Output did not match Expected: \\u%4X Got: \\u%4X", expected[i], zeroString[i]); + } + } + + strcpy(action, "getting and testing of binary type"); + res = ures_getByKey(theBundle, "binarytest", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_BINARY); + binResult=(uint8_t*)ures_getBinary(res, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(len, 15); + for(i = 0; i<15; i++) { + CONFIRM_INT_EQ(binResult[i], i); + } + } + + strcpy(action, "getting and testing of imported binary type"); + res = ures_getByKey(theBundle, "importtest", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_BINARY); + binResult=(uint8_t*)ures_getBinary(res, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(len, 15); + for(i = 0; i<15; i++) { + CONFIRM_INT_EQ(binResult[i], i); + } + } + + strcpy(action, "getting and testing of integer types"); + res = ures_getByKey(theBundle, "one", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT); + intResult=ures_getInt(res, &status); + uintResult = ures_getUInt(res, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(uintResult, (uint32_t)intResult); + CONFIRM_INT_EQ(intResult, 1); + } + + strcpy(action, "getting minusone"); + res = ures_getByKey(theBundle, "minusone", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT); + intResult=ures_getInt(res, &status); + uintResult = ures_getUInt(res, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(uintResult, 0x0FFFFFFF); /* a 28 bit integer */ + CONFIRM_INT_EQ(intResult, -1); + CONFIRM_INT_NE(uintResult, (uint32_t)intResult); + } + + strcpy(action, "getting plusone"); + res = ures_getByKey(theBundle, "plusone", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT); + intResult=ures_getInt(res, &status); + uintResult = ures_getUInt(res, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(uintResult, (uint32_t)intResult); + CONFIRM_INT_EQ(intResult, 1); + } + + res = ures_getByKey(theBundle, "onehundredtwentythree", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT); + intResult=ures_getInt(res, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(intResult, 123); + } + + /* this tests if escapes are preserved or not */ + { + const UChar* str = tres_getString(theBundle,-1,"testescape",&len,&status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + if(U_SUCCESS(status)){ + u_charsToUChars(expect,uExpect,(int32_t)strlen(expect)+1); + if(u_strcmp(uExpect,str)){ + log_err("Did not get the expected string for testescape\n"); + } + } + } + /* this tests if unescaping works are expected */ + len=0; + { + char pattern[2048] = ""; + int32_t patternLen; + UChar* expectedEscaped; + const UChar* got; + int32_t expectedLen; + + /* This strcpy fixes compiler warnings about long strings */ + strcpy(pattern, "[ \\\\u0020 \\\\u00A0 \\\\u1680 \\\\u2000 \\\\u2001 \\\\u2002 \\\\u2003 \\\\u2004 \\\\u2005 \\\\u2006 \\\\u2007 " + "\\\\u2008 \\\\u2009 \\\\u200A \\u200B \\\\u202F \\u205F \\\\u3000 \\u0000-\\u001F \\u007F \\u0080-\\u009F " + "\\\\u06DD \\\\u070F \\\\u180E \\\\u200C \\\\u200D \\\\u2028 \\\\u2029 \\\\u2060 \\\\u2061 \\\\u2062 \\\\u2063 " + "\\\\u206A-\\\\u206F \\\\uFEFF \\\\uFFF9-\\uFFFC \\U0001D173-\\U0001D17A \\U000F0000-\\U000FFFFD " + "\\U00100000-\\U0010FFFD \\uFDD0-\\uFDEF \\uFFFE-\\uFFFF \\U0001FFFE-\\U0001FFFF \\U0002FFFE-\\U0002FFFF " + ); + strcat(pattern, + "\\U0003FFFE-\\U0003FFFF \\U0004FFFE-\\U0004FFFF \\U0005FFFE-\\U0005FFFF \\U0006FFFE-\\U0006FFFF " + "\\U0007FFFE-\\U0007FFFF \\U0008FFFE-\\U0008FFFF \\U0009FFFE-\\U0009FFFF \\U000AFFFE-\\U000AFFFF " + "\\U000BFFFE-\\U000BFFFF \\U000CFFFE-\\U000CFFFF \\U000DFFFE-\\U000DFFFF \\U000EFFFE-\\U000EFFFF " + "\\U000FFFFE-\\U000FFFFF \\U0010FFFE-\\U0010FFFF \\uD800-\\uDFFF \\\\uFFF9 \\\\uFFFA \\\\uFFFB " + "\\uFFFC \\uFFFD \\u2FF0-\\u2FFB \\u0340 \\u0341 \\\\u200E \\\\u200F \\\\u202A \\\\u202B \\\\u202C " + ); + strcat(pattern, + "\\\\u202D \\\\u202E \\\\u206A \\\\u206B \\\\u206C \\\\u206D \\\\u206E \\\\u206F \\U000E0001 \\U000E0020-\\U000E007F " + "]" + ); + + patternLen = (int32_t)uprv_strlen(pattern); + expectedEscaped = (UChar*)malloc(U_SIZEOF_UCHAR * patternLen); + got = tres_getString(theBundle,-1,"test_unescaping",&len,&status); + expectedLen = u_unescape(pattern,expectedEscaped,patternLen); + if(got==NULL || u_strncmp(expectedEscaped,got,expectedLen)!=0 || expectedLen != len){ + log_err("genrb failed to unescape string\n"); + } + if(got != NULL){ + for(i=0;i<expectedLen;i++){ + if(expectedEscaped[i] != got[i]){ + log_verbose("Expected: 0x%04X Got: 0x%04X \n",expectedEscaped[i], got[i]); + } + } + } + free(expectedEscaped); + status = U_ZERO_ERROR; + } + /* test for jitterbug#1435 */ + { + const UChar* str = tres_getString(theBundle,-1,"test_underscores",&len,&status); + expect ="test message ...."; + u_charsToUChars(expect,uExpect,(int32_t)strlen(expect)+1); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + if(u_strcmp(uExpect,str)){ + log_err("Did not get the expected string for test_underscores.\n"); + } + } + /* test for jitterbug#2626 */ +#if !UCONFIG_NO_COLLATION + { + UResourceBundle* resB = NULL; + const UChar* str = NULL; + int32_t strLength = 0; + const UChar my[] = {0x0026,0x0027,0x0075,0x0027,0x0020,0x003d,0x0020,0x0027,0xff55,0x0027,0x0000}; /* &'\u0075' = '\uFF55' */ + status = U_ZERO_ERROR; + resB = ures_getByKey(theBundle, "collations", resB, &status); + resB = ures_getByKey(resB, "standard", resB, &status); + str = tres_getString(resB,-1,"Sequence",&strLength,&status); + if(!str || U_FAILURE(status)) { + log_data_err("Could not load collations from theBundle: %s\n", u_errorName(status)); + } else if(u_strcmp(my,str) != 0){ + log_err("Did not get the expected string for escaped \\u0075\n"); + } + ures_close(resB); + } +#endif + { + const char *sourcePath = ctest_dataSrcDir(); + int32_t srcPathLen = (int32_t)strlen(sourcePath); + const char *deltaPath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; + int32_t deltaPathLen = (int32_t)strlen(deltaPath); + char *testDataFileName = (char *) malloc( srcPathLen+ deltaPathLen + 50 ); + char *path = testDataFileName; + + strcpy(path, sourcePath); + path += srcPathLen; + strcpy(path, deltaPath); + path += deltaPathLen; + status = U_ZERO_ERROR; + { + int32_t strLen =0; + const UChar* str = tres_getString(theBundle, -1, "testincludeUTF",&strLen,&status); + strcpy(path, "riwords.txt"); + path[strlen("riwords.txt")]=0; + if(U_FAILURE(status)){ + log_err("Could not get testincludeUTF resource from testtypes bundle. Error: %s\n",u_errorName(status)); + }else{ + /* open the file */ + const char* cp = NULL; + UCHARBUF* ucbuf = ucbuf_open(testDataFileName,&cp,FALSE,FALSE,&status); + len = 0; + if(U_SUCCESS(status)){ + const UChar* buffer = ucbuf_getBuffer(ucbuf,&len,&status); + if(U_SUCCESS(status)){ + /* verify the contents */ + if(strLen != len ){ + log_err("Did not get the expected len for riwords. Expected: %i , Got: %i\n", len ,strLen); + } + /* test string termination */ + if(u_strlen(str) != strLen || str[strLen]!= 0 ){ + log_err("testinclude not null terminated!\n"); + } + if(u_strncmp(str, buffer,strLen)!=0){ + log_err("Did not get the expected string from riwords. Include functionality failed for genrb.\n"); + } + }else{ + log_err("ucbuf failed to open %s. Error: %s\n", testDataFileName, u_errorName(status)); + } + + ucbuf_close(ucbuf); + }else{ + log_err("Could not get riwords.txt (path : %s). Error: %s\n",testDataFileName,u_errorName(status)); + } + } + } + status = U_ZERO_ERROR; + { + int32_t strLen =0; + const UChar* str = tres_getString(theBundle, -1, "testinclude",&strLen,&status); + strcpy(path, "translit_rules.txt"); + path[strlen("translit_rules.txt")]=0; + + if(U_FAILURE(status)){ + log_err("Could not get testinclude resource from testtypes bundle. Error: %s\n",u_errorName(status)); + }else{ + /* open the file */ + const char* cp=NULL; + UCHARBUF* ucbuf = ucbuf_open(testDataFileName,&cp,FALSE,FALSE,&status); + len = 0; + if(U_SUCCESS(status)){ + const UChar* buffer = ucbuf_getBuffer(ucbuf,&len,&status); + if(U_SUCCESS(status)){ + /* verify the contents */ + if(strLen != len ){ + log_err("Did not get the expected len for translit_rules. Expected: %i , Got: %i\n", len ,strLen); + } + if(u_strncmp(str, buffer,strLen)!=0){ + log_err("Did not get the expected string from translit_rules. Include functionality failed for genrb.\n"); + } + }else{ + log_err("ucbuf failed to open %s. Error: %s\n", testDataFileName, u_errorName(status)); + } + ucbuf_close(ucbuf); + }else{ + log_err("Could not get translit_rules.txt (path : %s). Error: %s\n",testDataFileName,u_errorName(status)); + } + } + } + free(testDataFileName); + } + ures_close(res); + ures_close(theBundle); + +} + +static void TestEmptyTypes() { + UResourceBundle* theBundle = NULL; + char action[256]; + const char* testdatapath; + UErrorCode status = U_ZERO_ERROR; + UResourceBundle* res = NULL; + UResourceBundle* resArray = NULL; + const uint8_t *binResult = NULL; + int32_t len = 0; + int32_t intResult = 0; + const UChar *zeroString; + const int32_t *zeroIntVect; + + strcpy(action, "Construction of testtypes bundle"); + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + theBundle = ures_open(testdatapath, "testtypes", &status); + + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + + CONFIRM_INT_NE(theBundle, NULL); + + /* This test reads the string "abc\u0000def" from the bundle */ + /* if everything is working correctly, the size of this string */ + /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/ + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of explicit string of zero length string"); + res = ures_getByKey(theBundle, "emptyexplicitstring", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_STRING); + zeroString=tres_getString(res, -1, NULL, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(len, 0); + CONFIRM_INT_EQ(u_strlen(zeroString), 0); + } + else { + log_err("Couldn't get emptyexplicitstring\n"); + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of normal string of zero length string"); + res = ures_getByKey(theBundle, "emptystring", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_STRING); + zeroString=tres_getString(res, -1, NULL, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(len, 0); + CONFIRM_INT_EQ(u_strlen(zeroString), 0); + } + else { + log_err("Couldn't get emptystring\n"); + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of empty int"); + res = ures_getByKey(theBundle, "emptyint", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT); + intResult=ures_getInt(res, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(intResult, 0); + } + else { + log_err("Couldn't get emptystring\n"); + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of zero length intvector"); + res = ures_getByKey(theBundle, "emptyintv", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_INT_VECTOR); + + if(U_FAILURE(status)){ + log_err("Couldn't get emptyintv key %s\n", u_errorName(status)); + } + else { + zeroIntVect=ures_getIntVector(res, &len, &status); + if(!U_SUCCESS(status) || resArray != NULL || len != 0) { + log_err("Shouldn't get emptyintv\n"); + } + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of zero length emptybin"); + res = ures_getByKey(theBundle, "emptybin", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_BINARY); + + if(U_FAILURE(status)){ + log_err("Couldn't get emptybin key %s\n", u_errorName(status)); + } + else { + binResult=ures_getBinary(res, &len, &status); + if(!U_SUCCESS(status) || binResult != NULL || len != 0) { + log_err("Shouldn't get emptybin\n"); + } + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of zero length emptyarray"); + res = ures_getByKey(theBundle, "emptyarray", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_ARRAY); + + if(U_FAILURE(status)){ + log_err("Couldn't get emptyarray key %s\n", u_errorName(status)); + } + else { + resArray=ures_getByIndex(res, 0, resArray, &status); + if(U_SUCCESS(status) || resArray != NULL){ + log_err("Shouldn't get emptyarray\n"); + } + } + + status = U_ZERO_ERROR; + strcpy(action, "getting and testing of zero length emptytable"); + res = ures_getByKey(theBundle, "emptytable", res, &status); + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(res), URES_TABLE); + + if(U_FAILURE(status)){ + log_err("Couldn't get emptytable key %s\n", u_errorName(status)); + } + else { + resArray=ures_getByIndex(res, 0, resArray, &status); + if(U_SUCCESS(status) || resArray != NULL){ + log_err("Shouldn't get emptytable\n"); + } + } + + ures_close(res); + ures_close(theBundle); +} + +static void TestEmptyBundle(){ + UErrorCode status = U_ZERO_ERROR; + const char* testdatapath=NULL; + UResourceBundle *resb=0, *dResB=0; + + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + resb = ures_open(testdatapath, "testempty", &status); + + if(U_SUCCESS(status)){ + dResB = ures_getByKey(resb,"test",dResB,&status); + if(status!= U_MISSING_RESOURCE_ERROR){ + log_err("Did not get the expected error from an empty resource bundle. Expected : %s Got: %s\n", + u_errorName(U_MISSING_RESOURCE_ERROR),u_errorName(status)); + } + } + ures_close(dResB); + ures_close(resb); +} + +static void TestBinaryCollationData(){ + UErrorCode status=U_ZERO_ERROR; + const char* locale="te"; +#if !UCONFIG_NO_COLLATION + const char* testdatapath; +#endif + UResourceBundle *teRes = NULL; + UResourceBundle *coll=NULL; + UResourceBundle *binColl = NULL; + uint8_t *binResult = NULL; + int32_t len=0; + const char* action="testing the binary collaton data"; + +#if !UCONFIG_NO_COLLATION + log_verbose("Testing binary collation data resource......\n"); + + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + + teRes=ures_open(testdatapath, locale, &status); + if(U_FAILURE(status)){ + log_err("ERROR: Failed to get resource for \"te\" with %s", myErrorName(status)); + return; + } + status=U_ZERO_ERROR; + coll = ures_getByKey(teRes, "collations", coll, &status); + coll = ures_getByKey(coll, "standard", coll, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(coll), URES_TABLE); + binColl=ures_getByKey(coll, "%%CollationBin", binColl, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_EQ(ures_getType(binColl), URES_BINARY); + binResult=(uint8_t*)ures_getBinary(binColl, &len, &status); + if(U_SUCCESS(status)){ + CONFIRM_ErrorCode(status, U_ZERO_ERROR); + CONFIRM_INT_GE(len, 1); + } + + }else{ + log_err("ERROR: ures_getByKey(locale(te), %%CollationBin) failed\n"); + } + } + else{ + log_err("ERROR: ures_getByKey(locale(te), collations) failed\n"); + return; + } + ures_close(binColl); + ures_close(coll); + ures_close(teRes); +#endif +} + +static void TestAPI() { + UErrorCode status=U_ZERO_ERROR; + int32_t len=0; + const char* key=NULL; + const UChar* value=NULL; + const char* testdatapath; + UChar* utestdatapath=NULL; + char convOutput[256]; + UChar largeBuffer[1025]; + UResourceBundle *teRes = NULL; + UResourceBundle *teFillin=NULL; + UResourceBundle *teFillin2=NULL; + + log_verbose("Testing ures_openU()......\n"); + + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + len =(int32_t)strlen(testdatapath); + utestdatapath = (UChar*) malloc((len+10)*sizeof(UChar)); + + u_charsToUChars(testdatapath, utestdatapath, (int32_t)strlen(testdatapath)+1); +#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) && U_FILE_SEP_CHAR == '\\' + { + /* Convert all backslashes to forward slashes so that we can make sure that ures_openU + can handle invariant characters. */ + UChar *backslash; + while ((backslash = u_strchr(utestdatapath, 0x005C))) { + *backslash = 0x002F; + } + } +#endif + + u_memset(largeBuffer, 0x0030, sizeof(largeBuffer)/sizeof(largeBuffer[0])); + largeBuffer[sizeof(largeBuffer)/sizeof(largeBuffer[0])-1] = 0; + + /*Test ures_openU */ + + status = U_ZERO_ERROR; + ures_close(ures_openU(largeBuffer, "root", &status)); + if(status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_openU() worked when the path is very large. It returned %s\n", myErrorName(status)); + } + + status = U_ZERO_ERROR; + ures_close(ures_openU(NULL, "root", &status)); + if(U_FAILURE(status)){ + log_err("ERROR: ures_openU() failed path = NULL with %s\n", myErrorName(status)); + } + + status = U_ILLEGAL_ARGUMENT_ERROR; + if(ures_openU(NULL, "root", &status) != NULL){ + log_err("ERROR: ures_openU() worked with error status with %s\n", myErrorName(status)); + } + + status = U_ZERO_ERROR; + teRes=ures_openU(utestdatapath, "te", &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_openU() failed path =%s with %s\n", austrdup(utestdatapath), myErrorName(status)); + return; + } + /*Test ures_getLocale() */ + log_verbose("Testing ures_getLocale() .....\n"); + if(strcmp(ures_getLocale(teRes, &status), "te") != 0){ + log_err("ERROR: ures_getLocale() failed. Expected = te_TE Got = %s\n", ures_getLocale(teRes, &status)); + } + /*Test ures_getNextString() */ + teFillin=ures_getByKey(teRes, "tagged_array_in_te_te_IN", teFillin, &status); + key=ures_getKey(teFillin); + value=(UChar*)ures_getNextString(teFillin, &len, &key, &status); + ures_resetIterator(NULL); + value=(UChar*)ures_getNextString(teFillin, &len, &key, &status); + if(status !=U_INDEX_OUTOFBOUNDS_ERROR){ + log_err("ERROR: calling getNextString where index out of bounds should return U_INDEX_OUTOFBOUNDS_ERROR, Got : %s\n", + myErrorName(status)); + } + ures_resetIterator(teRes); + /*Test ures_getNextResource() where resource is table*/ + status=U_ZERO_ERROR; +#if (U_CHARSET_FAMILY == U_ASCII_FAMILY) + /* The next key varies depending on the charset. */ + teFillin=ures_getNextResource(teRes, teFillin, &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_getNextResource() failed \n"); + } + key=ures_getKey(teFillin); + /*if(strcmp(key, "%%CollationBin") != 0){*/ + /*if(strcmp(key, "array_2d_in_Root_te") != 0){*/ /* added "aliasClient" that goes first */ + if(strcmp(key, "a") != 0){ + log_err("ERROR: ures_getNextResource() failed\n"); + } +#endif + + /*Test ures_getByIndex on string Resource*/ + teFillin=ures_getByKey(teRes, "string_only_in_te", teFillin, &status); + teFillin2=ures_getByIndex(teFillin, 0, teFillin2, &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_getByIndex on string resource failed\n"); + } + if(strcmp(u_austrcpy(convOutput, tres_getString(teFillin2, -1, NULL, &len, &status)), "TE") != 0){ + status=U_ZERO_ERROR; + log_err("ERROR: ures_getByIndex on string resource fetched the key=%s, expected \"TE\" \n", austrdup(ures_getString(teFillin2, &len, &status))); + } + + /*ures_close(teRes);*/ + + /*Test ures_openFillIn*/ + log_verbose("Testing ures_openFillIn......\n"); + status=U_ZERO_ERROR; + ures_openFillIn(teRes, testdatapath, "te", &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_openFillIn failed\n"); + return; + } + if(strcmp(ures_getLocale(teRes, &status), "te") != 0){ + log_err("ERROR: ures_openFillIn did not open the ResourceBundle correctly\n"); + } + ures_getByKey(teRes, "string_only_in_te", teFillin, &status); + teFillin2=ures_getNextResource(teFillin, teFillin2, &status); + if(ures_getType(teFillin2) != URES_STRING){ + log_err("ERROR: getType for getNextResource after ures_openFillIn failed\n"); + } + teFillin2=ures_getNextResource(teFillin, teFillin2, &status); + if(status !=U_INDEX_OUTOFBOUNDS_ERROR){ + log_err("ERROR: calling getNextResource where index out of bounds should return U_INDEX_OUTOFBOUNDS_ERROR, Got : %s\n", + myErrorName(status)); + } + + ures_close(teFillin); + ures_close(teFillin2); + ures_close(teRes); + + /* Test that ures_getLocale() returns the "real" locale ID */ + status=U_ZERO_ERROR; + teRes=ures_open(NULL, "dE_At_NOWHERE_TO_BE_FOUND", &status); + if(U_FAILURE(status)) { + log_data_err("unable to open a locale resource bundle from \"dE_At_NOWHERE_TO_BE_FOUND\"(%s)\n", u_errorName(status)); + } else { + if(0!=strcmp("de_AT", ures_getLocale(teRes, &status))) { + log_data_err("ures_getLocale(\"dE_At_NOWHERE_TO_BE_FOUND\")=%s but must be de_AT\n", ures_getLocale(teRes, &status)); + } + ures_close(teRes); + } + + /* same test, but with an aliased locale resource bundle */ + status=U_ZERO_ERROR; + teRes=ures_open(NULL, "iW_Il_depRecaTed_HebreW", &status); + if(U_FAILURE(status)) { + log_data_err("unable to open a locale resource bundle from \"iW_Il_depRecaTed_HebreW\"(%s)\n", u_errorName(status)); + } else { + if(0!=strcmp("he_IL", ures_getLocale(teRes, &status))) { + log_data_err("ures_getLocale(\"iW_Il_depRecaTed_HebreW\")=%s but must be he_IL\n", ures_getLocale(teRes, &status)); + } + ures_close(teRes); + } + free(utestdatapath); +} + +static void TestErrorConditions(){ + UErrorCode status=U_ZERO_ERROR; + const char *key=NULL; + const UChar *value=NULL; + const char* testdatapath; + UChar* utestdatapath; + int32_t len=0; + UResourceBundle *teRes = NULL; + UResourceBundle *coll=NULL; + UResourceBundle *binColl = NULL; + UResourceBundle *teFillin=NULL; + UResourceBundle *teFillin2=NULL; + uint8_t *binResult = NULL; + int32_t resultLen; + + + testdatapath = loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + len = (int32_t)strlen(testdatapath); + utestdatapath = (UChar*) malloc(sizeof(UChar) *(len+10)); + u_uastrcpy(utestdatapath, testdatapath); + + /*Test ures_openU with status != U_ZERO_ERROR*/ + log_verbose("Testing ures_openU() with status != U_ZERO_ERROR.....\n"); + status=U_ILLEGAL_ARGUMENT_ERROR; + teRes=ures_openU(utestdatapath, "te", &status); + if(U_FAILURE(status)){ + log_verbose("ures_openU() failed as expected path =%s with status != U_ZERO_ERROR\n", testdatapath); + }else{ + log_err("ERROR: ures_openU() is supposed to fail path =%s with status != U_ZERO_ERROR\n", austrdup(utestdatapath)); + ures_close(teRes); + } + /*Test ures_openFillIn with UResourceBundle = NULL*/ + log_verbose("Testing ures_openFillIn with UResourceBundle = NULL.....\n"); + status=U_ZERO_ERROR; + ures_openFillIn(NULL, testdatapath, "te", &status); + if(status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_openFillIn with UResourceBundle= NULL should fail. Expected U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getLocale() with status != U_ZERO_ERROR*/ + status=U_ZERO_ERROR; + teRes=ures_openU(utestdatapath, "te", &status); + if(U_FAILURE(status)){ + log_err("ERROR: ures_openU() failed path =%s with %s\n", austrdup(utestdatapath), myErrorName(status)); + return; + } + status=U_ILLEGAL_ARGUMENT_ERROR; + if(ures_getLocale(teRes, &status) != NULL){ + log_err("ERROR: ures_getLocale is supposed to fail with errorCode != U_ZERO_ERROR\n"); + } + /*Test ures_getLocale() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getLocale(NULL, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getLocale is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getSize() with UResourceBundle = NULL */ + status=U_ZERO_ERROR; + if(ures_getSize(NULL) != 0){ + log_err("ERROR: ures_getSize() should return 0 when UResourceBundle=NULL. Got =%d\n", ures_getSize(NULL)); + } + /*Test ures_getType() with UResourceBundle = NULL should return URES_NONE==-1*/ + status=U_ZERO_ERROR; + if(ures_getType(NULL) != URES_NONE){ + log_err("ERROR: ures_getType() should return URES_NONE when UResourceBundle=NULL. Got =%d\n", ures_getType(NULL)); + } + /*Test ures_getKey() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getKey(NULL) != NULL){ + log_err("ERROR: ures_getKey() should return NULL when UResourceBundle=NULL. Got =%d\n", ures_getKey(NULL)); + } + /*Test ures_hasNext() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_hasNext(NULL) != FALSE){ + log_err("ERROR: ures_hasNext() should return FALSE when UResourceBundle=NULL. Got =%d\n", ures_hasNext(NULL)); + } + /*Test ures_get() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getStringByKey(NULL, "string_only_in_te", &resultLen, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_get is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getByKey() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + teFillin=ures_getByKey(NULL, "string_only_in_te", teFillin, &status); + if( teFillin != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getByKey is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getByKey() with status != U_ZERO_ERROR*/ + teFillin=ures_getByKey(NULL, "string_only_in_te", teFillin, &status); + if(teFillin != NULL ){ + log_err("ERROR: ures_getByKey is supposed to fail when errorCode != U_ZERO_ERROR\n"); + } + /*Test ures_getStringByKey() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getStringByKey(NULL, "string_only_in_te", &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getStringByKey is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getStringByKey() with status != U_ZERO_ERROR*/ + if(ures_getStringByKey(teRes, "string_only_in_te", &len, &status) != NULL){ + log_err("ERROR: ures_getStringByKey is supposed to fail when status != U_ZERO_ERROR. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getString() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getString(NULL, &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getString is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getString() with status != U_ZERO_ERROR*/ + if(ures_getString(teRes, &len, &status) != NULL){ + log_err("ERROR: ures_getString is supposed to fail when status != U_ZERO_ERROR. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getBinary() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + if(ures_getBinary(NULL, &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getBinary is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n", + myErrorName(status)); + } + /*Test ures_getBinary(0 status != U_ILLEGAL_ARGUMENT_ERROR*/ + status=U_ZERO_ERROR; + coll = ures_getByKey(teRes, "collations", coll, &status); + coll = ures_getByKey(teRes, "standard", coll, &status); + binColl=ures_getByKey(coll, "%%CollationBin", binColl, &status); + + status=U_ILLEGAL_ARGUMENT_ERROR; + binResult=(uint8_t*)ures_getBinary(binColl, &len, &status); + if(binResult != NULL){ + log_err("ERROR: ures_getBinary() with status != U_ZERO_ERROR is supposed to fail\n"); + } + + /*Test ures_getNextResource() with status != U_ZERO_ERROR*/ + teFillin=ures_getNextResource(teRes, teFillin, &status); + if(teFillin != NULL){ + log_err("ERROR: ures_getNextResource() with errorCode != U_ZERO_ERROR is supposed to fail\n"); + } + /*Test ures_getNextResource() with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + teFillin=ures_getNextResource(NULL, teFillin, &status); + if(teFillin != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getNextResource() with UResourceBundle = NULL is supposed to fail. Expected : U_IILEGAL_ARGUMENT_ERROR, Got : %s\n", + myErrorName(status)); + } + /*Test ures_getNextString with errorCode != U_ZERO_ERROR*/ + teFillin=ures_getByKey(teRes, "tagged_array_in_te_te_IN", teFillin, &status); + key=ures_getKey(teFillin); + status = U_ILLEGAL_ARGUMENT_ERROR; + value=(UChar*)ures_getNextString(teFillin, &len, &key, &status); + if(value != NULL){ + log_err("ERROR: ures_getNextString() with errorCode != U_ZERO_ERROR is supposed to fail\n"); + } + /*Test ures_getNextString with UResourceBundle = NULL*/ + status=U_ZERO_ERROR; + value=(UChar*)ures_getNextString(NULL, &len, &key, &status); + if(value != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getNextString() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getByIndex with errorCode != U_ZERO_ERROR*/ + status=U_ZERO_ERROR; + teFillin=ures_getByKey(teRes, "array_only_in_te", teFillin, &status); + if(ures_countArrayItems(teRes, "array_only_in_te", &status) != 4) { + log_err("ERROR: Wrong number of items in an array!\n"); + } + status=U_ILLEGAL_ARGUMENT_ERROR; + teFillin2=ures_getByIndex(teFillin, 0, teFillin2, &status); + if(teFillin2 != NULL){ + log_err("ERROR: ures_getByIndex() with errorCode != U_ZERO_ERROR is supposed to fail\n"); + } + /*Test ures_getByIndex with UResourceBundle = NULL */ + status=U_ZERO_ERROR; + teFillin2=ures_getByIndex(NULL, 0, teFillin2, &status); + if(status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getByIndex() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getStringByIndex with errorCode != U_ZERO_ERROR*/ + status=U_ZERO_ERROR; + teFillin=ures_getByKey(teRes, "array_only_in_te", teFillin, &status); + status=U_ILLEGAL_ARGUMENT_ERROR; + value=(UChar*)ures_getStringByIndex(teFillin, 0, &len, &status); + if( value != NULL){ + log_err("ERROR: ures_getSringByIndex() with errorCode != U_ZERO_ERROR is supposed to fail\n"); + } + /*Test ures_getStringByIndex with UResourceBundle = NULL */ + status=U_ZERO_ERROR; + value=(UChar*)ures_getStringByIndex(NULL, 0, &len, &status); + if(value != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getStringByIndex() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getStringByIndex with UResourceBundle = NULL */ + status=U_ZERO_ERROR; + value=(UChar*)ures_getStringByIndex(teFillin, 9999, &len, &status); + if(value != NULL || status != U_MISSING_RESOURCE_ERROR){ + log_err("ERROR: ures_getStringByIndex() with index that is too big is supposed to fail\n Expected: U_MISSING_RESOURCE_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getInt() where UResourceBundle = NULL */ + status=U_ZERO_ERROR; + if(ures_getInt(NULL, &status) != -1 && status != U_ILLEGAL_ARGUMENT_ERROR){ + log_err("ERROR: ures_getInt() with UResourceBundle = NULL should fail. Expected: U_IILEGAL_ARGUMENT_ERROR, Got: %s\n", + myErrorName(status)); + } + /*Test ures_getInt() where status != U_ZERO_ERROR */ + if(ures_getInt(teRes, &status) != -1){ + log_err("ERROR: ures_getInt() with errorCode != U_ZERO_ERROR should fail\n"); + } + + ures_close(teFillin); + ures_close(teFillin2); + ures_close(coll); + ures_close(binColl); + ures_close(teRes); + free(utestdatapath); + + +} + +static void TestGetVersion(){ + UVersionInfo minVersionArray = {0x01, 0x00, 0x00, 0x00}; + UVersionInfo maxVersionArray = {0x50, 0xc0, 0xcf, 0xcf}; + UVersionInfo versionArray; + UErrorCode status= U_ZERO_ERROR; + UResourceBundle* resB = NULL; + int i=0, j = 0; + int locCount = uloc_countAvailable(); + const char *locName = "root"; + + log_verbose("The ures_getVersion tests begin : \n"); + + for(j = -1; j < locCount; j++) { + if(j >= 0) { + locName = uloc_getAvailable(j); + } + log_verbose("Testing version number for locale %s\n", locName); + resB = ures_open(NULL,locName, &status); + if (U_FAILURE(status)) { + log_err("Resource bundle creation for locale %s failed.: %s\n", locName, myErrorName(status)); + ures_close(resB); + return; + } + ures_getVersion(resB, versionArray); + for (i=0; i<4; ++i) { + if (versionArray[i] < minVersionArray[i] || + versionArray[i] > maxVersionArray[i]) + { + log_err("Testing ures_getVersion(%-5s) - unexpected result: %d.%d.%d.%d\n", + locName, versionArray[0], versionArray[1], versionArray[2], versionArray[3]); + break; + } + } + ures_close(resB); + } +} + + +static void TestGetVersionColl(){ + UVersionInfo minVersionArray = {0x00, 0x00, 0x00, 0x00}; + UVersionInfo maxVersionArray = {0x50, 0x80, 0xcf, 0xcf}; + UVersionInfo versionArray; + UErrorCode status= U_ZERO_ERROR; + UResourceBundle* resB = NULL; + UEnumeration *locs= NULL; + int i=0; + const char *locName = "root"; + int32_t locLen; + const UChar* rules =NULL; + int32_t len = 0; + + log_verbose("The ures_getVersion(%s) tests begin : \n", U_ICUDATA_COLL); + locs = ures_openAvailableLocales(U_ICUDATA_COLL, &status); + if (U_FAILURE(status)) { + log_err("enumeration of %s failed.: %s\n", U_ICUDATA_COLL, myErrorName(status)); + return; + } + + do{ + log_verbose("Testing version number for locale %s\n", locName); + resB = ures_open(U_ICUDATA_COLL,locName, &status); + if (U_FAILURE(status)) { + log_err("Resource bundle creation for locale %s:%s failed.: %s\n", U_ICUDATA_COLL, locName, myErrorName(status)); + ures_close(resB); + return; + } + /* test NUL termination of UCARules */ + rules = tres_getString(resB,-1,"UCARules",&len, &status); + if(!rules || U_FAILURE(status)) { + log_data_err("Could not load UCARules for locale %s\n", locName); + continue; + } + if(u_strlen(rules) != len){ + log_err("UCARules string not nul terminated! \n"); + } + ures_getVersion(resB, versionArray); + for (i=0; i<4; ++i) { + if (versionArray[i] < minVersionArray[i] || + versionArray[i] > maxVersionArray[i]) + { + log_err("Testing ures_getVersion(%-5s) - unexpected result: %d.%d.%d.%d\n", + locName, versionArray[0], versionArray[1], versionArray[2], versionArray[3]); + break; + } + } + ures_close(resB); + } while((locName = uenum_next(locs,&locLen,&status))&&U_SUCCESS(status)); + + if(U_FAILURE(status)) { + log_err("Err %s testing Collation locales.\n", u_errorName(status)); + } + uenum_close(locs); +} + +static void TestResourceBundles() +{ + UErrorCode status = U_ZERO_ERROR; + loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + testTag("only_in_Root", TRUE, FALSE, FALSE); + testTag("in_Root_te", TRUE, TRUE, FALSE); + testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE); + testTag("in_Root_te_IN", TRUE, FALSE, TRUE); + testTag("only_in_te", FALSE, TRUE, FALSE); + testTag("only_in_te_IN", FALSE, FALSE, TRUE); + testTag("in_te_te_IN", FALSE, TRUE, TRUE); + testTag("nonexistent", FALSE, FALSE, FALSE); + + log_verbose("Passed:= %d Failed= %d \n", pass, fail); + +} + + +static void TestConstruction1() +{ + UResourceBundle *test1 = 0, *test2 = 0,*empty = 0; + const UChar *result1, *result2; + UErrorCode status= U_ZERO_ERROR; + UErrorCode err = U_ZERO_ERROR; + const char* locale="te_IN"; + const char* testdatapath; + + int32_t len1=0; + int32_t len2=0; + UVersionInfo versionInfo; + char versionString[256]; + char verboseOutput[256]; + + U_STRING_DECL(rootVal, "ROOT", 4); + U_STRING_DECL(te_inVal, "TE_IN", 5); + + U_STRING_INIT(rootVal, "ROOT", 4); + U_STRING_INIT(te_inVal, "TE_IN", 5); + + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + log_verbose("Testing ures_open()......\n"); + + empty = ures_open(testdatapath, "testempty", &status); + if(empty == NULL || U_FAILURE(status)) { + log_err("opening empty failed!\n"); + } + ures_close(empty); + + test1=ures_open(testdatapath, NULL, &err); + + if(U_FAILURE(err)) + { + log_err("construction of NULL did not succeed : %s \n", myErrorName(status)); + return; + } + test2=ures_open(testdatapath, locale, &err); + if(U_FAILURE(err)) + { + log_err("construction of %s did not succeed : %s \n", locale, myErrorName(status)); + return; + } + result1= tres_getString(test1, -1, "string_in_Root_te_te_IN", &len1, &err); + result2= tres_getString(test2, -1, "string_in_Root_te_te_IN", &len2, &err); + if (U_FAILURE(err) || len1==0 || len2==0) { + log_err("Something threw an error in TestConstruction(): %s\n", myErrorName(status)); + return; + } + log_verbose("for string_in_Root_te_te_IN, default.txt had %s\n", u_austrcpy(verboseOutput, result1)); + log_verbose("for string_in_Root_te_te_IN, te_IN.txt had %s\n", u_austrcpy(verboseOutput, result2)); + if(u_strcmp(result1, rootVal) !=0 || u_strcmp(result2, te_inVal) !=0 ){ + log_err("construction test failed. Run Verbose for more information"); + } + + + /* Test getVersionNumber*/ + log_verbose("Testing version number\n"); + log_verbose("for getVersionNumber : %s\n", ures_getVersionNumber(test1)); + + log_verbose("Testing version \n"); + ures_getVersion(test1, versionInfo); + u_versionToString(versionInfo, versionString); + + log_verbose("for getVersion : %s\n", versionString); + + if(strcmp(versionString, ures_getVersionNumber(test1)) != 0) { + log_err("Versions differ: %s vs %s\n", versionString, ures_getVersionNumber(test1)); + } + + ures_close(test1); + ures_close(test2); + +} + +/*****************************************************************************/ +/*****************************************************************************/ + +static UBool testTag(const char* frag, + UBool in_Root, + UBool in_te, + UBool in_te_IN) +{ + int32_t failNum = fail; + + /* Make array from input params */ + + UBool is_in[3]; + const char *NAME[] = { "ROOT", "TE", "TE_IN" }; + + /* Now try to load the desired items */ + UResourceBundle* theBundle = NULL; + char tag[99]; + char action[256]; + UErrorCode expected_status,status = U_ZERO_ERROR,expected_resource_status = U_ZERO_ERROR; + UChar* base = NULL; + UChar* expected_string = NULL; + const UChar* string = NULL; + char buf[5]; + char item_tag[10]; + int32_t i,j,row,col, len; + int32_t actual_bundle; + int32_t count = 0; + int32_t row_count=0; + int32_t column_count=0; + int32_t index = 0; + int32_t tag_count= 0; + const char* testdatapath; + char verboseOutput[256]; + UResourceBundle* array=NULL; + UResourceBundle* array2d=NULL; + UResourceBundle* tags=NULL; + UResourceBundle* arrayItem1=NULL; + + testdatapath = loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return FALSE; + } + + is_in[0] = in_Root; + is_in[1] = in_te; + is_in[2] = in_te_IN; + + strcpy(item_tag, "tag"); + + for (i=0; i<bundles_count; ++i) + { + strcpy(action,"construction for "); + strcat(action, param[i].name); + + + status = U_ZERO_ERROR; + + theBundle = ures_open(testdatapath, param[i].name, &status); + CONFIRM_ErrorCode(status,param[i].expected_constructor_status); + + if(i == 5) + actual_bundle = 0; /* ne -> default */ + else if(i == 3) + actual_bundle = 1; /* te_NE -> te */ + else if(i == 4) + actual_bundle = 2; /* te_IN_NE -> te_IN */ + else + actual_bundle = i; + + expected_resource_status = U_MISSING_RESOURCE_ERROR; + for (j=e_te_IN; j>=e_Root; --j) + { + if (is_in[j] && param[i].inherits[j]) + { + + if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */ + expected_resource_status = U_ZERO_ERROR; + else if(j == 0) + expected_resource_status = U_USING_DEFAULT_WARNING; + else + expected_resource_status = U_USING_FALLBACK_WARNING; + + log_verbose("%s[%d]::%s: in<%d:%s> inherits<%d:%s>. actual_bundle=%s\n", + param[i].name, + i, + frag, + j, + is_in[j]?"Yes":"No", + j, + param[i].inherits[j]?"Yes":"No", + param[actual_bundle].name); + + break; + } + } + + for (j=param[i].where; j>=0; --j) + { + if (is_in[j]) + { + if(base != NULL) { + free(base); + base = NULL; + } + base=(UChar*)malloc(sizeof(UChar)*(strlen(NAME[j]) + 1)); + u_uastrcpy(base,NAME[j]); + + break; + } + else { + if(base != NULL) { + free(base); + base = NULL; + } + base = (UChar*) malloc(sizeof(UChar) * 1); + *base = 0x0000; + } + } + + /*----string---------------------------------------------------------------- */ + + strcpy(tag,"string_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action, ".ures_getStringByKey(" ); + strcat(action,tag); + strcat(action, ")"); + + + status = U_ZERO_ERROR; + len=0; + + string=tres_getString(theBundle, -1, tag, &len, &status); + if(U_SUCCESS(status)) { + expected_string=(UChar*)malloc(sizeof(UChar)*(u_strlen(base) + 4)); + u_strcpy(expected_string,base); + CONFIRM_INT_EQ(len, u_strlen(expected_string)); + }else{ + expected_string = (UChar*)malloc(sizeof(UChar)*(u_strlen(kERROR) + 1)); + u_strcpy(expected_string,kERROR); + string=kERROR; + } + log_verbose("%s got %d, expected %d\n", action, status, expected_resource_status); + + CONFIRM_ErrorCode(status, expected_resource_status); + CONFIRM_EQ(string, expected_string); + + + + /*--------------array------------------------------------------------- */ + + strcpy(tag,"array_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action, ".ures_getByKey(" ); + strcat(action,tag); + strcat(action, ")"); + + len=0; + + count = kERROR_COUNT; + status = U_ZERO_ERROR; + array=ures_getByKey(theBundle, tag, array, &status); + CONFIRM_ErrorCode(status,expected_resource_status); + if (U_SUCCESS(status)) { + /*confirm the resource type is an array*/ + CONFIRM_INT_EQ(ures_getType(array), URES_ARRAY); + /*confirm the size*/ + count=ures_getSize(array); + CONFIRM_INT_GE(count,1); + for (j=0; j<count; ++j) { + UChar element[3]; + u_strcpy(expected_string, base); + u_uastrcpy(element, itoa1(j,buf)); + u_strcat(expected_string, element); + arrayItem1=ures_getNextResource(array, arrayItem1, &status); + if(U_SUCCESS(status)){ + CONFIRM_EQ(tres_getString(arrayItem1, -1, NULL, &len, &status),expected_string); + } + } + + } + else { + CONFIRM_INT_EQ(count,kERROR_COUNT); + CONFIRM_ErrorCode(status, U_MISSING_RESOURCE_ERROR); + /*CONFIRM_INT_EQ((int32_t)(unsigned long)array,(int32_t)0);*/ + count = 0; + } + + /*--------------arrayItem------------------------------------------------- */ + + strcpy(tag,"array_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action, ".ures_getStringByIndex("); + strcat(action, tag); + strcat(action, ")"); + + + for (j=0; j<10; ++j){ + index = count ? (randi(count * 3) - count) : (randi(200) - 100); + status = U_ZERO_ERROR; + string=kERROR; + array=ures_getByKey(theBundle, tag, array, &status); + if(!U_FAILURE(status)){ + UChar *t=NULL; + t=(UChar*)ures_getStringByIndex(array, index, &len, &status); + if(!U_FAILURE(status)){ + UChar element[3]; + string=t; + u_strcpy(expected_string, base); + u_uastrcpy(element, itoa1(index,buf)); + u_strcat(expected_string, element); + } else { + u_strcpy(expected_string, kERROR); + } + + } + expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR; + CONFIRM_ErrorCode(status,expected_status); + CONFIRM_EQ(string,expected_string); + + } + + + /*--------------2dArray------------------------------------------------- */ + + strcpy(tag,"array_2d_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action, ".ures_getByKey(" ); + strcat(action,tag); + strcat(action, ")"); + + + + row_count = kERROR_COUNT, column_count = kERROR_COUNT; + status = U_ZERO_ERROR; + array2d=ures_getByKey(theBundle, tag, array2d, &status); + + CONFIRM_ErrorCode(status,expected_resource_status); + if (U_SUCCESS(status)) + { + /*confirm the resource type is an 2darray*/ + CONFIRM_INT_EQ(ures_getType(array2d), URES_ARRAY); + row_count=ures_getSize(array2d); + CONFIRM_INT_GE(row_count,1); + + for(row=0; row<row_count; ++row){ + UResourceBundle *tableRow=NULL; + tableRow=ures_getByIndex(array2d, row, tableRow, &status); + CONFIRM_ErrorCode(status, expected_resource_status); + if(U_SUCCESS(status)){ + /*confirm the resourcetype of each table row is an array*/ + CONFIRM_INT_EQ(ures_getType(tableRow), URES_ARRAY); + column_count=ures_getSize(tableRow); + CONFIRM_INT_GE(column_count,1); + + for (col=0; j<column_count; ++j) { + UChar element[3]; + u_strcpy(expected_string, base); + u_uastrcpy(element, itoa1(row, buf)); + u_strcat(expected_string, element); + u_uastrcpy(element, itoa1(col, buf)); + u_strcat(expected_string, element); + arrayItem1=ures_getNextResource(tableRow, arrayItem1, &status); + if(U_SUCCESS(status)){ + const UChar *stringValue=tres_getString(arrayItem1, -1, NULL, &len, &status); + CONFIRM_EQ(stringValue, expected_string); + } + } + } + ures_close(tableRow); + } + }else{ + CONFIRM_INT_EQ(row_count,kERROR_COUNT); + CONFIRM_INT_EQ(column_count,kERROR_COUNT); + row_count=column_count=0; + } + + + /*------2dArrayItem-------------------------------------------------------------- */ + /* 2dArrayItem*/ + for (j=0; j<10; ++j) + { + row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100); + col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100); + status = U_ZERO_ERROR; + string = kERROR; + len=0; + array2d=ures_getByKey(theBundle, tag, array2d, &status); + if(U_SUCCESS(status)){ + UResourceBundle *tableRow=NULL; + tableRow=ures_getByIndex(array2d, row, tableRow, &status); + if(U_SUCCESS(status)) { + UChar *t=NULL; + t=(UChar*)ures_getStringByIndex(tableRow, col, &len, &status); + if(U_SUCCESS(status)){ + string=t; + } + } + ures_close(tableRow); + } + expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ? + expected_resource_status: U_MISSING_RESOURCE_ERROR; + CONFIRM_ErrorCode(status,expected_status); + + if (U_SUCCESS(status)){ + UChar element[3]; + u_strcpy(expected_string, base); + u_uastrcpy(element, itoa1(row, buf)); + u_strcat(expected_string, element); + u_uastrcpy(element, itoa1(col, buf)); + u_strcat(expected_string, element); + } else { + u_strcpy(expected_string,kERROR); + } + CONFIRM_EQ(string,expected_string); + + } + + + /*--------------taggedArray----------------------------------------------- */ + strcpy(tag,"tagged_array_"); + strcat(tag,frag); + + strcpy(action,param[i].name); + strcat(action,".ures_getByKey("); + strcat(action, tag); + strcat(action,")"); + + + status = U_ZERO_ERROR; + tag_count=0; + tags=ures_getByKey(theBundle, tag, tags, &status); + CONFIRM_ErrorCode(status, expected_resource_status); + if (U_SUCCESS(status)) { + UResType bundleType=ures_getType(tags); + CONFIRM_INT_EQ(bundleType, URES_TABLE); + + tag_count=ures_getSize(tags); + CONFIRM_INT_GE((int32_t)tag_count, (int32_t)0); + + for(index=0; index <tag_count; index++){ + UResourceBundle *tagelement=NULL; + const char *key=NULL; + UChar* value=NULL; + tagelement=ures_getByIndex(tags, index, tagelement, &status); + key=ures_getKey(tagelement); + value=(UChar*)ures_getNextString(tagelement, &len, &key, &status); + log_verbose("tag = %s, value = %s\n", key, u_austrcpy(verboseOutput, value)); + if(strncmp(key, "tag", 3) == 0 && u_strncmp(value, base, u_strlen(base)) == 0){ + record_pass(); + }else{ + record_fail(); + } + ures_close(tagelement); + } + }else{ + tag_count=0; + } + + /*---------taggedArrayItem----------------------------------------------*/ + count = 0; + for (index=-20; index<20; ++index) + { + + status = U_ZERO_ERROR; + string = kERROR; + strcpy(item_tag, "tag"); + strcat(item_tag, itoa1(index,buf)); + tags=ures_getByKey(theBundle, tag, tags, &status); + if(U_SUCCESS(status)){ + UResourceBundle *tagelement=NULL; + UChar *t=NULL; + tagelement=ures_getByKey(tags, item_tag, tagelement, &status); + if(!U_FAILURE(status)){ + UResType elementType=ures_getType(tagelement); + CONFIRM_INT_EQ(elementType, URES_STRING); + if(strcmp(ures_getKey(tagelement), item_tag) == 0){ + record_pass(); + }else{ + record_fail(); + } + t=(UChar*)tres_getString(tagelement, -1, NULL, &len, &status); + if(!U_FAILURE(status)){ + string=t; + } + } + if (index < 0) { + CONFIRM_ErrorCode(status,U_MISSING_RESOURCE_ERROR); + } + else{ + if (status != U_MISSING_RESOURCE_ERROR) { + UChar element[3]; + u_strcpy(expected_string, base); + u_uastrcpy(element, itoa1(index,buf)); + u_strcat(expected_string, element); + CONFIRM_EQ(string,expected_string); + count++; + } + } + ures_close(tagelement); + } + } + CONFIRM_INT_EQ(count, tag_count); + + free(expected_string); + ures_close(theBundle); + } + ures_close(array); + ures_close(array2d); + ures_close(tags); + ures_close(arrayItem1); + free(base); + return (UBool)(failNum == fail); +} + +static void record_pass() +{ + ++pass; +} + +static void record_fail() +{ + ++fail; +} + +/** + * Test to make sure that the U_USING_FALLBACK_ERROR and U_USING_DEFAULT_ERROR + * are set correctly + */ + +static void TestFallback() +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *fr_FR = NULL; + UResourceBundle *subResource = NULL; + const UChar *junk; /* ignored */ + int32_t resultLen; + + log_verbose("Opening fr_FR.."); + fr_FR = ures_open(NULL, "fr_FR", &status); + if(U_FAILURE(status)) + { + log_err("Couldn't open fr_FR - %d\n", status); + return; + } + + status = U_ZERO_ERROR; + + + /* clear it out.. just do some calls to get the gears turning */ + junk = tres_getString(fr_FR, -1, "LocaleID", &resultLen, &status); + status = U_ZERO_ERROR; + junk = tres_getString(fr_FR, -1, "LocaleString", &resultLen, &status); + status = U_ZERO_ERROR; + junk = tres_getString(fr_FR, -1, "LocaleID", &resultLen, &status); + status = U_ZERO_ERROR; + + /* OK first one. This should be a Default value. */ + subResource = ures_getByKey(fr_FR, "MeasurementSystem", NULL, &status); + if(status != U_USING_DEFAULT_WARNING) + { + log_data_err("Expected U_USING_DEFAULT_ERROR when trying to get CurrencyMap from fr_FR, got %s\n", + u_errorName(status)); + } + + status = U_ZERO_ERROR; + ures_close(subResource); + + /* and this is a Fallback, to fr */ + junk = tres_getString(fr_FR, -1, "Countries", &resultLen, &status); + if(status != U_USING_FALLBACK_WARNING) + { + log_data_err("Expected U_USING_FALLBACK_ERROR when trying to get Countries from fr_FR, got %d\n", + status); + } + + status = U_ZERO_ERROR; + + ures_close(fr_FR); + /* Temporary hack err actually should be U_USING_FALLBACK_ERROR */ + /* Test Jitterbug 552 fallback mechanism of aliased data */ + { + UErrorCode err =U_ZERO_ERROR; + UResourceBundle* myResB = ures_open(NULL,"no_NO_NY",&err); + UResourceBundle* resLocID = ures_getByKey(myResB, "Version", NULL, &err); + UResourceBundle* tResB; + const UChar* version = NULL; + static const UChar versionStr[] = { 0x0031, 0x002E, 0x0034, 0x0033, 0x0000}; + + if(err != U_ZERO_ERROR){ + log_data_err("Expected U_ZERO_ERROR when trying to test no_NO_NY aliased to nn_NO for Version err=%s\n",u_errorName(err)); + return; + } + version = tres_getString(resLocID, -1, NULL, &resultLen, &err); + if(u_strcmp(version, versionStr) != 0){ + char x[100]; + char g[100]; + u_austrcpy(x, versionStr); + u_austrcpy(g, version); + log_data_err("ures_getString(resLocID, &resultLen, &err) returned an unexpected version value. Expected '%s', but got '%s'\n", + x, g); + } + tResB = ures_getByKey(myResB, "zoneStrings", NULL, &err); + if(err != U_USING_FALLBACK_WARNING){ + log_err("Expected U_USING_FALLBACK_ERROR when trying to test no_NO_NY aliased with nn_NO_NY for zoneStrings err=%s\n",u_errorName(err)); + } + ures_close(resLocID); + ures_close(myResB); + ures_close(tResB); + + } + +} + +/* static void printUChars(UChar* uchars){ +/ int16_t i=0; +/ for(i=0; i<u_strlen(uchars); i++){ +/ log_err("%04X ", *(uchars+i)); +/ } +/ } */ + +static void TestResourceLevelAliasing(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *aliasB = NULL, *tb = NULL; + UResourceBundle *en = NULL, *uk = NULL, *testtypes = NULL; + const char* testdatapath = NULL; + const UChar *string = NULL, *sequence = NULL; + /*const uint8_t *binary = NULL, *binSequence = NULL;*/ + int32_t strLen = 0, seqLen = 0;/*, binLen = 0, binSeqLen = 0;*/ + char buffer[100]; + char *s; + + testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + aliasB = ures_open(testdatapath, "testaliases", &status); + + if(U_FAILURE(status)) + { + log_err("Could not load testaliases.res %s \n",myErrorName(status)); + return; + } + /* this should fail - circular alias */ + tb = ures_getByKey(aliasB, "aaa", tb, &status); + if(status != U_TOO_MANY_ALIASES_ERROR) { + log_err("Failed to detect circular alias\n"); + } + else { + status = U_ZERO_ERROR; + } + tb = ures_getByKey(aliasB, "aab", tb, &status); + if(status != U_TOO_MANY_ALIASES_ERROR) { + log_err("Failed to detect circular alias\n"); + } else { + status = U_ZERO_ERROR; + } + if(U_FAILURE(status) ) { + log_data_err("err loading tb resource\n"); + } else { + /* testing aliasing to a non existing resource */ + tb = ures_getByKey(aliasB, "nonexisting", tb, &status); + if(status != U_MISSING_RESOURCE_ERROR) { + log_err("Managed to find an alias to non-existing resource\n"); + } else { + status = U_ZERO_ERROR; + } + /* testing referencing/composed alias */ + uk = ures_findResource("ja/LocaleScript/2", uk, &status); + if((uk == NULL) || U_FAILURE(status)) { + log_err("Couldn't findResource('ja/LocaleScript/2') err %s\n", u_errorName(status)); + goto cleanup; + } + + sequence = tres_getString(uk, -1, NULL, &seqLen, &status); + + tb = ures_getByKey(aliasB, "referencingalias", tb, &status); + string = tres_getString(tb, -1, NULL, &strLen, &status); + + if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) { + log_err("Referencing alias didn't get the right string\n"); + } + + string = tres_getString(aliasB, -1, "referencingalias", &strLen, &status); + if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) { + log_err("Referencing alias didn't get the right string\n"); + } + + checkStatus(__LINE__, U_ZERO_ERROR, status); + tb = ures_getByKey(aliasB, "LocaleScript", tb, &status); + checkStatus(__LINE__, U_ZERO_ERROR, status); + tb = ures_getByIndex(tb, 2, tb, &status); + checkStatus(__LINE__, U_ZERO_ERROR, status); + string = tres_getString(tb, -1, NULL, &strLen, &status); + checkStatus(__LINE__, U_ZERO_ERROR, status); + + if(U_FAILURE(status)) { + log_err("%s trying to get string via separate getters\n", u_errorName(status)); + } else if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) { + log_err("Referencing alias didn't get the right string\n"); + } + + + { + UResourceBundle* ja = ures_open(U_ICUDATA_BRKITR,"ja", &status); + const UChar *got = NULL, *exp=NULL; + int32_t gotLen = 0, expLen=0; + ja = ures_getByKey(ja, "boundaries", ja, &status); + exp = tres_getString(ja, -1, "word", &expLen, &status); + + tb = ures_getByKey(aliasB, "boundaries", tb, &status); + got = tres_getString(tb, -1, "word", &gotLen, &status); + + if(U_FAILURE(status)) { + log_err("%s trying to read str boundaries\n", u_errorName(status)); + } else if(gotLen != expLen || u_strncmp(exp, got, gotLen) != 0) { + log_err("Referencing alias didn't get the right data\n"); + } + ures_close(ja); + status = U_ZERO_ERROR; + } + /* simple alias */ + testtypes = ures_open(testdatapath, "testtypes", &status); + strcpy(buffer, "menu/file/open"); + s = buffer; + uk = ures_findSubResource(testtypes, s, uk, &status); + sequence = tres_getString(uk, -1, NULL, &seqLen, &status); + + tb = ures_getByKey(aliasB, "simplealias", tb, &status); + string = tres_getString(tb, -1, NULL, &strLen, &status); + + if(U_FAILURE(status) || seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) { + log_err("Referencing alias didn't get the right string\n"); + } + + /* test indexed aliasing */ + + tb = ures_getByKey(aliasB, "zoneTests", tb, &status); + tb = ures_getByKey(tb, "zoneAlias2", tb, &status); + string = tres_getString(tb, -1, NULL, &strLen, &status); + + en = ures_findResource("en/zoneStrings/3/0", en, &status); + sequence = tres_getString(en, -1, NULL, &seqLen, &status); + + if(U_FAILURE(status) || seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) { + log_err("Referencing alias didn't get the right string\n"); + } + } + /* test getting aliased string by index */ + { + const char* keys[] = { + "KeyAlias0PST", + "KeyAlias1PacificStandardTime", + "KeyAlias2PDT", + "KeyAlias3LosAngeles" + }; + + const char* strings[] = { + "America/Los_Angeles", + "Pacific Standard Time", + "PDT", + "Los Angeles", + }; + UChar uBuffer[256]; + const UChar* result; + int32_t uBufferLen = 0, resultLen = 0; + int32_t i = 0; + const char *key = NULL; + tb = ures_getByKey(aliasB, "testGetStringByKeyAliasing", tb, &status); + if(U_FAILURE(status)) { + log_err("Couldn't get testGetStringByKeyAliasing resource\n"); + } + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + result = tres_getString(tb, -1, keys[i], &resultLen, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status)); + continue; + } + uBufferLen = u_unescape(strings[i], uBuffer, 256); + if(resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) { + log_err("Didn't get correct string while accesing alias table by key (%s)\n", keys[i]); + } + } + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + result = tres_getString(tb, i, NULL, &resultLen, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status)); + continue; + } + uBufferLen = u_unescape(strings[i], uBuffer, 256); + if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) { + log_err("Didn't get correct string while accesing alias table by index (%s)\n", strings[i]); + } + } + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + result = ures_getNextString(tb, &resultLen, &key, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status)); + continue; + } + uBufferLen = u_unescape(strings[i], uBuffer, 256); + if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) { + log_err("Didn't get correct string while iterating over alias table (%s)\n", strings[i]); + } + } + tb = ures_getByKey(aliasB, "testGetStringByIndexAliasing", tb, &status); + if(U_FAILURE(status)) { + log_err("Couldn't get testGetStringByIndexAliasing resource\n"); + } + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + result = tres_getString(tb, i, NULL, &resultLen, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status)); + continue; + } + uBufferLen = u_unescape(strings[i], uBuffer, 256); + if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) { + log_err("Didn't get correct string while accesing alias by index in an array (%s)\n", strings[i]); + } + } + for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + result = ures_getNextString(tb, &resultLen, &key, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status)); + continue; + } + uBufferLen = u_unescape(strings[i], uBuffer, 256); + if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) { + log_err("Didn't get correct string while iterating over aliases in an array (%s)\n", strings[i]); + } + } + } + tb = ures_getByKey(aliasB, "testAliasToTree", tb, &status); + if(U_FAILURE(status)){ + log_err("Fetching the resource with key \"testAliasToTree\" failed. Error: %s\n", u_errorName(status)); + } + if (strcmp(ures_getKey(tb), "collations") != 0) { + log_err("ures_getKey(aliasB) unexpectedly returned %s instead of \"collations\"\n", ures_getKey(tb)); + } +cleanup: + ures_close(aliasB); + ures_close(tb); + ures_close(en); + ures_close(uk); + ures_close(testtypes); +} + +static void TestDirectAccess(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *t = NULL, *t2 = NULL; + const char* key = NULL; + + char buffer[100]; + char *s; + /*const char* testdatapath=loadTestData(&status); + if(U_FAILURE(status)){ + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + }*/ + + t = ures_findResource("/testdata/te/zoneStrings/3/2", t, &status); + if(U_FAILURE(status)) { + log_err("Couldn't access indexed resource, error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + key = ures_getKey(t); + if(key != NULL) { + log_err("Got a strange key, expected NULL, got %s\n", key); + } + } + t = ures_findResource("en/calendar/gregorian/DateTimePatterns/3", t, &status); + if(U_FAILURE(status)) { + log_err("Couldn't access indexed resource, error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + key = ures_getKey(t); + if(key != NULL) { + log_err("Got a strange key, expected NULL, got %s\n", key); + } + } + + t = ures_findResource("ja/LocaleScript", t, &status); + if(U_FAILURE(status)) { + log_err("Couldn't access keyed resource, error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + key = ures_getKey(t); + if(strcmp(key, "LocaleScript")!=0) { + log_err("Got a strange key, expected 'LocaleScript', got %s\n", key); + } + } + + t2 = ures_open(NULL, "sr", &status); + if(U_FAILURE(status)) { + log_err("Couldn't open 'sr' resource bundle, error %s\n", u_errorName(status)); + log_data_err("No 'sr', no test - you have bigger problems than testing direct access. " + "You probably have no data! Aborting this test\n"); + } + + if(U_SUCCESS(status)) { + strcpy(buffer, "Languages/hr"); + s = buffer; + t = ures_findSubResource(t2, s, t, &status); + if(U_FAILURE(status)) { + log_err("Couldn't access keyed resource, error %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } else { + key = ures_getKey(t); + if(strcmp(key, "hr")!=0) { + log_err("Got a strange key, expected 'hr', got %s\n", key); + } + } + } + + t = ures_findResource("root/calendar/islamic-civil/DateTime", t, &status); + if(U_SUCCESS(status)) { + log_err("This resource does not exist. How did it get here?\n"); + } + status = U_ZERO_ERROR; + + /* this one will freeze */ + t = ures_findResource("root/calendar/islamic-civil/eras/abbreviated/0/mikimaus/pera", t, &status); + if(U_SUCCESS(status)) { + log_err("Second resource does not exist. How did it get here?\n"); + } + status = U_ZERO_ERROR; + + ures_close(t2); + t2 = ures_open(NULL, "he", &status); + t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "DateTime", t2, &status); + if(U_SUCCESS(status)) { + log_err("This resource does not exist. How did it get here?\n"); + } + status = U_ZERO_ERROR; + + ures_close(t2); + t2 = ures_open(NULL, "he", &status); + /* George's fix */ + t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "eras", t2, &status); + if(U_FAILURE(status)) { + log_err("Didn't get Eras. I know they are there!\n"); + } + status = U_ZERO_ERROR; + + ures_close(t2); + t2 = ures_open(NULL, "root", &status); + t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status); + t2 = ures_getByKeyWithFallback(t2, "DateTime", t2, &status); + if(U_SUCCESS(status)) { + log_err("This resource does not exist. How did it get here?\n"); + } + status = U_ZERO_ERROR; + + ures_close(t2); + ures_close(t); +} + +static void TestJB3763(void) { + /* Nasty bug prevented using parent as fill-in, since it would + * stomp the path information. + */ + UResourceBundle *t = NULL; + UErrorCode status = U_ZERO_ERROR; + t = ures_open(NULL, "sr_Latn", &status); + t = ures_getByKeyWithFallback(t, "calendar", t, &status); + t = ures_getByKeyWithFallback(t, "gregorian", t, &status); + t = ures_getByKeyWithFallback(t, "AmPmMarkers", t, &status); + if(U_FAILURE(status)) { + log_err("This resource should be available?\n"); + } + status = U_ZERO_ERROR; + + ures_close(t); + +} + +static void TestGetKeywordValues(void) { + UEnumeration *kwVals; + UBool foundStandard = FALSE; + UErrorCode status = U_ZERO_ERROR; + const char *kw; +#if !UCONFIG_NO_COLLATION + kwVals = ures_getKeywordValues( U_ICUDATA_COLL, "collations", &status); + + log_verbose("Testing getting collation keyword values:\n"); + + while((kw=uenum_next(kwVals, NULL, &status))) { + log_verbose(" %s\n", kw); + if(!strcmp(kw,"standard")) { + if(foundStandard == FALSE) { + foundStandard = TRUE; + } else { + log_err("'standard' was found twice in the keyword list.\n"); + } + } + } + if(foundStandard == FALSE) { + log_err("'standard' was not found in the keyword list.\n"); + } + uenum_close(kwVals); + if(U_FAILURE(status)) { + log_err("err %s getting collation values\n", u_errorName(status)); + } + status = U_ZERO_ERROR; +#endif + foundStandard = FALSE; + kwVals = ures_getKeywordValues( "ICUDATA", "calendar", &status); + + log_verbose("Testing getting calendar keyword values:\n"); + + while((kw=uenum_next(kwVals, NULL, &status))) { + log_verbose(" %s\n", kw); + if(!strcmp(kw,"japanese")) { + if(foundStandard == FALSE) { + foundStandard = TRUE; + } else { + log_err("'japanese' was found twice in the calendar keyword list.\n"); + } + } + } + if(foundStandard == FALSE) { + log_err("'japanese' was not found in the calendar keyword list.\n"); + } + uenum_close(kwVals); + if(U_FAILURE(status)) { + log_err("err %s getting calendar values\n", u_errorName(status)); + } +} + +static void TestGetFunctionalEquivalentOf(const char *path, const char *resName, const char *keyword, UBool truncate, const char * const testCases[]) { + int32_t i; + for(i=0;testCases[i];i+=3) { + UBool expectAvail = (testCases[i][0]=='t')?TRUE:FALSE; + UBool gotAvail = FALSE; + const char *inLocale = testCases[i+1]; + const char *expectLocale = testCases[i+2]; + char equivLocale[256]; + int32_t len; + UErrorCode status = U_ZERO_ERROR; + log_verbose("%d: %c %s\texpect %s\n",i/3, expectAvail?'t':'f', inLocale, expectLocale); + len = ures_getFunctionalEquivalent(equivLocale, 255, path, + resName, keyword, inLocale, + &gotAvail, truncate, &status); + if(U_FAILURE(status) || (len <= 0)) { + log_err("FAIL: got len %d, err %s on #%d: %c\t%s\t%s\n", + len, u_errorName(status), + i/3,expectAvail?'t':'f', inLocale, expectLocale); + } else { + log_verbose("got: %c %s\n", expectAvail?'t':'f',equivLocale); + + if((gotAvail != expectAvail) || strcmp(equivLocale, expectLocale)) { + log_err("FAIL: got avail=%c, loc=%s but expected #%d: %c\t%s\t-> loc=%s\n", + gotAvail?'t':'f', equivLocale, + i/3, + expectAvail?'t':'f', inLocale, expectLocale); + + } + } + } +} + +static void TestGetFunctionalEquivalent(void) { + static const char * const collCases[] = { + /* avail locale equiv */ + "f", "de_US_CALIFORNIA", "de", + "f", "zh_TW@collation=stroke", "zh@collation=stroke", /* alias of zh_Hant_TW */ + "t", "zh_Hant_TW@collation=stroke", "zh@collation=stroke", + "f", "de_CN@collation=pinyin", "de", + "t", "zh@collation=pinyin", "zh", + "f", "zh_CN@collation=pinyin", "zh", /* alias of zh_Hans_CN */ + "t", "zh_Hans_CN@collation=pinyin", "zh", + "f", "zh_HK@collation=pinyin", "zh", /* alias of zh_Hant_HK */ + "t", "zh_Hant_HK@collation=pinyin", "zh", + "f", "zh_HK@collation=stroke", "zh@collation=stroke", /* alias of zh_Hant_HK */ + "t", "zh_Hant_HK@collation=stroke", "zh@collation=stroke", + "f", "zh_HK", "zh@collation=stroke", /* alias of zh_Hant_HK */ + "t", "zh_Hant_HK", "zh@collation=stroke", + "f", "zh_MO", "zh@collation=stroke", /* alias of zh_Hant_MO */ + "t", "zh_Hant_MO", "zh@collation=stroke", + "f", "zh_TW_STROKE", "zh@collation=stroke", + "f", "zh_TW_STROKE@collation=big5han", "zh@collation=big5han", + "f", "de_CN@calendar=japanese", "de", + "t", "de@calendar=japanese", "de", + "f", "zh_TW@collation=big5han", "zh@collation=big5han", /* alias of zh_Hant_TW */ + "t", "zh_Hant_TW@collation=big5han", "zh@collation=big5han", + "f", "zh_TW@collation=gb2312han", "zh@collation=gb2312han", /* alias of zh_Hant_TW */ + "t", "zh_Hant_TW@collation=gb2312han", "zh@collation=gb2312han", + "f", "zh_CN@collation=big5han", "zh@collation=big5han", /* alias of zh_Hans_CN */ + "t", "zh_Hans_CN@collation=big5han", "zh@collation=big5han", + "f", "zh_CN@collation=gb2312han", "zh@collation=gb2312han", /* alias of zh_Hans_CN */ + "t", "zh_Hans_CN@collation=gb2312han", "zh@collation=gb2312han", + "t", "zh@collation=big5han", "zh@collation=big5han", + "t", "zh@collation=gb2312han", "zh@collation=gb2312han", + "t", "hi_IN@collation=direct", "hi@collation=direct", + "t", "hi@collation=standard", "hi", + "t", "hi@collation=direct", "hi@collation=direct", + "f", "hi_AU@collation=direct;currency=CHF;calendar=buddhist", "hi@collation=direct", + "f", "hi_AU@collation=standard;currency=CHF;calendar=buddhist", "hi", + "t", "de_DE@collation=pinyin", "de", /* bug 4582 tests */ + "f", "de_DE_BONN@collation=pinyin", "de", + "t", "nl", "root", + "t", "nl_NL", "root", + "f", "nl_NL_EEXT", "root", + "t", "nl@collation=stroke", "root", + "t", "nl_NL@collation=stroke", "root", + "f", "nl_NL_EEXT@collation=stroke", "root", + NULL + }; + + static const char *calCases[] = { + /* avail locale equiv */ + "t", "en_US_POSIX", "en_US@calendar=gregorian", + "f", "ja_JP_TOKYO", "ja_JP@calendar=gregorian", + "f", "ja_JP_TOKYO@calendar=japanese", "ja@calendar=japanese", + "t", "sr@calendar=gregorian", "sr@calendar=gregorian", + "t", "en", "en@calendar=gregorian", + NULL + }; + +#if !UCONFIG_NO_COLLATION + TestGetFunctionalEquivalentOf(U_ICUDATA_COLL, "collations", "collation", TRUE, collCases); +#endif + TestGetFunctionalEquivalentOf("ICUDATA", "calendar", "calendar", FALSE, calCases); + +#if !UCONFIG_NO_COLLATION + log_verbose("Testing error conditions:\n"); + { + char equivLocale[256] = "???"; + int32_t len; + UErrorCode status = U_ZERO_ERROR; + UBool gotAvail = FALSE; + + len = ures_getFunctionalEquivalent(equivLocale, 255, U_ICUDATA_COLL, + "calendar", "calendar", "ar_EG@calendar=islamic", + &gotAvail, FALSE, &status); + + if(status == U_MISSING_RESOURCE_ERROR) { + log_verbose("PASS: Got expected U_MISSING_RESOURCE_ERROR\n"); + } else { + log_err("ures_getFunctionalEquivalent returned locale %s, avail %c, err %s, but expected U_MISSING_RESOURCE_ERROR \n", + equivLocale, gotAvail?'t':'f', u_errorName(status)); + } + } +#endif +} + +static void TestXPath(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *rb = NULL, *alias = NULL; + int32_t len = 0; + const UChar* result = NULL; + const UChar expResult[] = { 0x0063, 0x006F, 0x0072, 0x0072, 0x0065, 0x0063, 0x0074, 0x0000 }; /* "correct" */ + /*const UChar expResult[] = { 0x0074, 0x0065, 0x0069, 0x006E, 0x0064, 0x0065, 0x0073, 0x0074, 0x0000 }; *//*teindest*/ + + const char *testdatapath=loadTestData(&status); + if(U_FAILURE(status)) + { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + + log_verbose("Testing ures_open()......\n"); + + rb = ures_open(testdatapath, "te_IN", &status); + if(U_FAILURE(status)) { + log_err("Could not open te_IN (%s)\n", myErrorName(status)); + return; + } + alias = ures_getByKey(rb, "rootAliasClient", alias, &status); + if(U_FAILURE(status)) { + log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status)); + ures_close(rb); + return; + } + + result = tres_getString(alias, -1, NULL, &len, &status); + if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) { + log_err("Couldn't get correct string value (%s)\n", myErrorName(status)); + } + + alias = ures_getByKey(rb, "aliasClient", alias, &status); + if(U_FAILURE(status)) { + log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status)); + ures_close(rb); + return; + } + + result = tres_getString(alias, -1, NULL, &len, &status); + if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) { + log_err("Couldn't get correct string value (%s)\n", myErrorName(status)); + } + + alias = ures_getByKey(rb, "nestedRootAliasClient", alias, &status); + if(U_FAILURE(status)) { + log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status)); + ures_close(rb); + return; + } + + result = tres_getString(alias, -1, NULL, &len, &status); + if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) { + log_err("Couldn't get correct string value (%s)\n", myErrorName(status)); + } + + ures_close(alias); + ures_close(rb); +} +static void TestCLDRStyleAliases(void) { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *rb = NULL, *alias = NULL, *a=NULL; + int32_t i, len; + char resource[256]; + const UChar *result = NULL; + UChar expected[256]; + const char *expects[7] = { "", "a41", "a12", "a03", "ar4" }; + const char *testdatapath=loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat %s \n",myErrorName(status)); + return; + } + log_verbose("Testing CLDR style aliases......\n"); + + rb = ures_open(testdatapath, "te_IN_REVISED", &status); + if(U_FAILURE(status)) { + log_err("Could not open te_IN (%s)\n", myErrorName(status)); + return; + } + alias = ures_getByKey(rb, "a", alias, &status); + if(U_FAILURE(status)) { + log_err("Couldn't find the aliased with name \"a\" resource (%s)\n", myErrorName(status)); + ures_close(rb); + return; + } + for(i = 1; i < 5 ; i++) { + resource[0]='a'; + resource[1]='0'+i; + resource[2]=0; + /* instead of sprintf(resource, "a%i", i); */ + a = ures_getByKeyWithFallback(alias, resource, a, &status); + result = tres_getString(a, -1, NULL, &len, &status); + u_charsToUChars(expects[i], expected, strlen(expects[i])+1); + if(U_FAILURE(status) || !result || u_strcmp(result, expected)) { + log_err("CLDR style aliases failed resource with name \"%s\" resource, exp %s, got %S (%s)\n", resource, expects[i], result, myErrorName(status)); + status = U_ZERO_ERROR; + } + } + + ures_close(a); + ures_close(alias); + ures_close(rb); +} + +static void TestFallbackCodes(void) { + UErrorCode status = U_ZERO_ERROR; + const char *testdatapath=loadTestData(&status); + + UResourceBundle *res = ures_open(testdatapath, "te_IN", &status); + + UResourceBundle *r = NULL, *fall = NULL; + + r = ures_getByKey(res, "tagged_array_in_Root_te_te_IN", r, &status); + + status = U_ZERO_ERROR; + fall = ures_getByKeyWithFallback(r, "tag2", fall, &status); + + if(status != U_ZERO_ERROR) { + log_err("Expected error code to be U_ZERO_ERROR, got %s\n", u_errorName(status)); + status = U_ZERO_ERROR; + } + + fall = ures_getByKeyWithFallback(r, "tag7", fall, &status); + + if(status != U_USING_FALLBACK_WARNING) { + log_err("Expected error code to be U_USING_FALLBACK_WARNING, got %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + + fall = ures_getByKeyWithFallback(r, "tag1", fall, &status); + + if(status != U_USING_DEFAULT_WARNING) { + log_err("Expected error code to be U_USING_DEFAULT_WARNING, got %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + + ures_close(fall); + ures_close(r); + ures_close(res); +} + +/* This test will crash if this doesn't work. Results don't need testing. */ +static void TestStackReuse(void) { + UResourceBundle table; + UErrorCode errorCode = U_ZERO_ERROR; + UResourceBundle *rb = ures_open(NULL, "en_US", &errorCode); + + if(U_FAILURE(errorCode)) { + log_err("Could not load en_US locale. status=%s\n",myErrorName(errorCode)); + return; + } + ures_initStackObject(&table); + ures_getByKeyWithFallback(rb, "Types", &table, &errorCode); + ures_getByKeyWithFallback(&table, "collation", &table, &errorCode); + ures_close(rb); + ures_close(&table); +} + +/* Test ures_getUTF8StringXYZ() --------------------------------------------- */ + +/* + * Replace most ures_getStringXYZ() with this function which wraps the + * desired call and also calls the UTF-8 variant and checks that it works. + */ +extern const UChar * +tres_getString(const UResourceBundle *resB, + int32_t index, const char *key, + int32_t *length, + UErrorCode *status) { + char buffer8[16]; + char *p8; + const UChar *s16; + const char *s8; + UChar32 c16, c8; + int32_t length16, length8, i16, i8; + UBool forceCopy; + + if(length == NULL) { + length = &length16; + } + if(index >= 0) { + s16 = ures_getStringByIndex(resB, index, length, status); + } else if(key != NULL) { + s16 = ures_getStringByKey(resB, key, length, status); + } else { + s16 = ures_getString(resB, length, status); + } + if(U_FAILURE(*status)) { + return s16; + } + length16 = *length; + + /* try the UTF-8 variant of ures_getStringXYZ() */ + for(forceCopy = FALSE; forceCopy <= TRUE; ++forceCopy) { + p8 = buffer8; + length8 = (int32_t)sizeof(buffer8); + if(index >= 0) { + s8 = ures_getUTF8StringByIndex(resB, index, p8, &length8, forceCopy, status); + } else if(key != NULL) { + s8 = ures_getUTF8StringByKey(resB, key, p8, &length8, forceCopy, status); + } else { + s8 = ures_getUTF8String(resB, p8, &length8, forceCopy, status); + } + if(*status == U_INVALID_CHAR_FOUND) { + /* the UTF-16 string contains an unpaired surrogate, can't test UTF-8 variant */ + return s16; + } + if(*status == U_BUFFER_OVERFLOW_ERROR) { + *status = U_ZERO_ERROR; + p8 = (char *)malloc(++length8); + if(p8 == NULL) { + return s16; + } + if(index >= 0) { + s8 = ures_getUTF8StringByIndex(resB, index, p8, &length8, forceCopy, status); + } else if(key != NULL) { + s8 = ures_getUTF8StringByKey(resB, key, p8, &length8, forceCopy, status); + } else { + s8 = ures_getUTF8String(resB, p8, &length8, forceCopy, status); + } + } + if(U_FAILURE(*status)) { + /* something unexpected happened */ + if(p8 != buffer8) { + free(p8); + } + return s16; + } + + if(forceCopy && s8 != p8) { + log_err("ures_getUTF8String(%p, %ld, '%s') did not write the string to dest\n", + resB, (long)index, key); + } + + /* verify NUL-termination */ + if((p8 != buffer8 || length8 < sizeof(buffer8)) && s8[length8] != 0) { + log_err("ures_getUTF8String(%p, %ld, '%s') did not NUL-terminate\n", + resB, (long)index, key); + } + /* verify correct string */ + i16 = i8 = 0; + while(i16 < length16 && i8 < length8) { + U16_NEXT(s16, i16, length16, c16); + U8_NEXT(s8, i8, length8, c8); + if(c16 != c8) { + log_err("ures_getUTF8String(%p, %ld, '%s') got a bad string, c16=U+%04lx!=U+%04lx=c8 before i16=%ld\n", + resB, (long)index, key, (long)c16, (long)c8, (long)i16); + } + } + /* verify correct length */ + if(i16 < length16) { + log_err("ures_getUTF8String(%p, %ld, '%s') UTF-8 string too short, length8=%ld, length16=%ld\n", + resB, (long)index, key, (long)length8, (long)length16); + } + if(i8 < length8) { + log_err("ures_getUTF8String(%p, %ld, '%s') UTF-8 string too long, length8=%ld, length16=%ld\n", + resB, (long)index, key, (long)length8, (long)length16); + } + + /* clean up */ + if(p8 != buffer8) { + free(p8); + } + } + return s16; +} + +/* + * API tests for ures_getUTF8String(). + * Most cases are handled by tres_getString(), which leaves argument checking + * to be tested here. + * Since the variants share most of their implementation, we only need to test + * one of them. + * We also need not test for checking arguments which will be checked by the + * UTF-16 ures_getStringXYZ() that are called internally. + */ +static void +TestGetUTF8String() { + UResourceBundle *res; + const char *testdatapath; + char buffer8[16]; + const char *s8; + int32_t length8; + UErrorCode status; + + status = U_ZERO_ERROR; + testdatapath = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat - %s\n", u_errorName(status)); + return; + } + + res = ures_open(testdatapath, "", &status); + if(U_FAILURE(status)) { + log_err("Unable to ures_open(testdata, \"\") - %s\n", u_errorName(status)); + return; + } + + /* one good call */ + status = U_ZERO_ERROR; + length8 = (int32_t)sizeof(buffer8); + s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", buffer8, &length8, FALSE, &status); + if(status != U_ZERO_ERROR) { + log_err("ures_getUTF8StringByKey(testdata/root string) malfunctioned - %s\n", u_errorName(status)); + } + + /* negative capacity */ + status = U_ZERO_ERROR; + length8 = -1; + s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", buffer8, &length8, FALSE, &status); + if(status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ures_getUTF8StringByKey(capacity<0) malfunctioned - %s\n", u_errorName(status)); + } + + /* capacity>0 but dest=NULL */ + status = U_ZERO_ERROR; + length8 = (int32_t)sizeof(buffer8); + s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", NULL, &length8, FALSE, &status); + if(status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ures_getUTF8StringByKey(dest=NULL capacity>0) malfunctioned - %s\n", u_errorName(status)); + } + + ures_close(res); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h new file mode 100644 index 00000000000..f6becdb979c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h @@ -0,0 +1,85 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/*************************************************************************** +* +* File CRESTST.H +* +* Modification History: +* Name Date Description +* Madhu Katragadda 05/09/2000 Ported Tests for New ResourceBundle API +* Madhu Katragadda 05/24/2000 Added new tests to test RES_BINARY for collationElements +************************************************************************************************* +*/ +#ifndef _CRESTSTN +#define _CRESTSTN +/* C TEST FOR NEW RESOURCEBUNDLE API*/ +#include "cintltst.h" + +/* + * Test wrapper for ures_getStringXYZ(), for testing other variants of + * these functions as well. + * If index>=0, calls ures_getStringByIndex(). + * If key!=NULL, calls ures_getStringByKey(). + */ +extern const UChar * +tres_getString(const UResourceBundle *resB, + int32_t index, const char *key, + int32_t *length, + UErrorCode *status); + +void addNEWResourceBundleTest(TestNode**); + +/** +*Perform several extensive tests using the subtest routine testTag +*/ +static void TestResourceBundles(void); +/** +* Test construction of ResourceBundle accessing a custom test resource-file +**/ +static void TestConstruction1(void); + +static void TestAliasConflict(void); + +static void TestFallback(void); + +static void TestBinaryCollationData(void); + +static void TestNewTypes(void); + +static void TestEmptyTypes(void); + +static void TestAPI(void); + +static void TestErrorConditions(void); + +static void TestGetVersion(void); + +static void TestGetVersionColl(void); + +static void TestEmptyBundle(void); + +static void TestDirectAccess(void); + +static void TestResourceLevelAliasing(void); + +static void TestErrorCodes(void); + +static void TestJB3763(void); + +static void TestXPath(void); + +static void TestStackReuse(void); + +/** +* extensive subtests called by TestResourceBundles +**/ +static UBool testTag(const char* frag, UBool in_Root, UBool in_te, UBool in_te_IN); + +static void record_pass(void); +static void record_fail(void); + + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c new file mode 100644 index 00000000000..befc6d4dc2d --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c @@ -0,0 +1,944 @@ +/* +******************************************************************************* +* +* Copyright (C) 2002-2007, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: cstrcase.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2002feb21 +* created by: Markus W. Scherer +* +* Test file for string casing C API functions. +*/ + +#include <string.h> +#include "unicode/utypes.h" +#include "unicode/uchar.h" +#include "unicode/ustring.h" +#include "unicode/uloc.h" +#include "unicode/ubrk.h" +#include "unicode/ucasemap.h" +#include "cmemory.h" +#include "cintltst.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +/* test string case mapping functions --------------------------------------- */ + +static void +TestCaseLower(void) { + static const UChar + + beforeLower[]= { 0x61, 0x42, 0x49, 0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff }, + lowerRoot[]= { 0x61, 0x62, 0x69, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }, + lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }; + + UChar buffer[32]; + int32_t length; + UErrorCode errorCode; + + /* lowercase with root locale and separate buffers */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, + "", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) || + uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToLower(root locale)=%ld error=%s string matches: %s\t\nlowerRoot=%s\t\nbuffer=%s\n", + length, + u_errorName(errorCode), + uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)==0 && +buffer[length]==0 ? "yes" : "no", + aescstrdup(lowerRoot,-1), + aescstrdup(buffer,-1)); + } + + /* lowercase with turkish locale and in the same buffer */ + uprv_memcpy(buffer, beforeLower, sizeof(beforeLower)); + buffer[sizeof(beforeLower)/U_SIZEOF_UCHAR]=0; + errorCode=U_ZERO_ERROR; + length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + buffer, -1, /* implicit srcLength */ + "tr", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(lowerTurkish)/U_SIZEOF_UCHAR) || + uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToLower(turkish locale)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* test preflighting */ + buffer[0]=buffer[2]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToLower(buffer, 2, /* set destCapacity=2 */ + beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, + "", + &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) || + uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)!=0 || + buffer[2]!=0xabcd + ) { + log_err("error in u_strToLower(root locale preflighting)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no"); + } + + /* test error handling */ + errorCode=U_ZERO_ERROR; + length=u_strToLower(NULL, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, + "", + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error in u_strToLower(root locale dest=NULL)=%ld error=%s\n", + length, + u_errorName(errorCode)); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToLower(buffer, -1, + beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, + "", + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strToLower(root locale destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } +} + +static void +TestCaseUpper(void) { + static const UChar + + beforeUpper[]= { 0x61, 0x42, 0x69, 0x3c2, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xd93f, 0xdfff }, + upperRoot[]= { 0x41, 0x42, 0x49, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff }, + upperTurkish[]={ 0x41, 0x42, 0x130, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff }; + + UChar buffer[32]; + int32_t length; + UErrorCode errorCode; + + /* uppercase with root locale and in the same buffer */ + uprv_memcpy(buffer, beforeUpper, sizeof(beforeUpper)); + errorCode=U_ZERO_ERROR; + length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + buffer, sizeof(beforeUpper)/U_SIZEOF_UCHAR, + "", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(upperRoot)/U_SIZEOF_UCHAR) || + uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToUpper(root locale)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* uppercase with turkish locale and separate buffers */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR, + "tr", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR) || + uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToUpper(turkish locale)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* test preflighting */ + errorCode=U_ZERO_ERROR; + length=u_strToUpper(NULL, 0, + beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR, + "tr", + &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR) + ) { + log_err("error in u_strToUpper(turkish locale pure preflighting)=%ld error=%s\n", + length, + u_errorName(errorCode)); + } + + /* test error handling */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + NULL, sizeof(beforeUpper)/U_SIZEOF_UCHAR, + "tr", + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strToUpper(turkish locale src=NULL)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeUpper, -2, + "tr", + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strToUpper(turkish locale srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } +} + +#if !UCONFIG_NO_BREAK_ITERATION + +static void +TestCaseTitle(void) { + static const UChar + + beforeTitle[]= { 0x61, 0x42, 0x20, 0x69, 0x3c2, 0x20, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xd93f, 0xdfff }, + titleWord[]= { 0x41, 0x62, 0x20, 0x49, 0x3c2, 0x20, 0x53, 0x73, 0x3c3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff }, + titleChar[]= { 0x41, 0x42, 0x20, 0x49, 0x3a3, 0x20, 0x53, 0x73, 0x3a3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff }; + + UChar buffer[32]; + UBreakIterator *titleIterChars; + int32_t length; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + titleIterChars=ubrk_open(UBRK_CHARACTER, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ubrk_open(UBRK_CHARACTER)->%s\n", u_errorName(errorCode)); + return; + } + + /* titlecase with standard break iterator and in the same buffer */ + uprv_memcpy(buffer, beforeTitle, sizeof(beforeTitle)); + errorCode=U_ZERO_ERROR; + length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + buffer, sizeof(beforeTitle)/U_SIZEOF_UCHAR, + NULL, "", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(titleWord)/U_SIZEOF_UCHAR) || + uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToTitle(standard iterator)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* titlecase with UBRK_CHARACTERS and separate buffers */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, + titleIterChars, "", + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) || + uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* test preflighting */ + errorCode=U_ZERO_ERROR; + length=u_strToTitle(NULL, 0, + beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, + titleIterChars, "", + &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) + ) { + log_err("error in u_strToTitle(UBRK_CHARACTERS pure preflighting)=%ld error=%s\n", + length, + u_errorName(errorCode)); + } + + /* test error handling */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + NULL, sizeof(beforeTitle)/U_SIZEOF_UCHAR, + titleIterChars, "", + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strToTitle(UBRK_CHARACTERS src=NULL)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + beforeTitle, -2, + titleIterChars, "", + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strToTitle(UBRK_CHARACTERS srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } + + ubrk_close(titleIterChars); +} + +#endif + +/* test case folding and case-insensitive string compare -------------------- */ + +static void +TestCaseFolding(void) { + /* + * CaseFolding.txt says about i and its cousins: + * 0049; C; 0069; # LATIN CAPITAL LETTER I + * 0049; T; 0131; # LATIN CAPITAL LETTER I + * + * 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE + * 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE + * That's all. + * See CaseFolding.txt and the Unicode Standard for how to apply the case foldings. + */ + static const UChar32 + simple[]={ + /* input, default, exclude special i */ + 0x61, 0x61, 0x61, + 0x49, 0x69, 0x131, + 0x130, 0x130, 0x69, + 0x131, 0x131, 0x131, + 0xdf, 0xdf, 0xdf, + 0xfb03, 0xfb03, 0xfb03, + 0x1040e,0x10436,0x10436, + 0x5ffff,0x5ffff,0x5ffff + }; + + static const UChar + mixed[]= { 0x61, 0x42, 0x130, 0x49, 0x131, 0x3d0, 0xdf, 0xfb03, 0xd93f, 0xdfff }, + foldedDefault[]= { 0x61, 0x62, 0x69, 0x307, 0x69, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff }, + foldedExcludeSpecialI[]={ 0x61, 0x62, 0x69, 0x131, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff }; + + UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 }; + + const UChar32 *p; + int32_t i; + + UChar buffer[32]; + int32_t length; + UErrorCode errorCode; + UBool isUnicode_3_1; + + /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */ + u_getUnicodeVersion(unicodeVersion); + isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0; + + /* test simple case folding */ + p=simple; + for(i=0; i<sizeof(simple)/12; p+=3, ++i) { + if(u_foldCase(p[0], U_FOLD_CASE_DEFAULT)!=p[1]) { + log_err("error: u_foldCase(0x%04lx, default)=0x%04lx instead of 0x%04lx\n", + p[0], u_foldCase(p[0], U_FOLD_CASE_DEFAULT), p[1]); + return; + } + + if(isUnicode_3_1 && u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I)!=p[2]) { + log_err("error: u_foldCase(0x%04lx, exclude special i)=0x%04lx instead of 0x%04lx\n", + p[0], u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I), p[2]); + return; + } + } + + /* test full string case folding with default option and separate buffers */ + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_DEFAULT, + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || + uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strFoldCase(default)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* exclude special i */ + if(isUnicode_3_1) { + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_EXCLUDE_SPECIAL_I, + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) || + uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strFoldCase(exclude special i)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + } + + /* test full string case folding with default option and in the same buffer */ + uprv_memcpy(buffer, mixed, sizeof(mixed)); + buffer[sizeof(mixed)/U_SIZEOF_UCHAR]=0; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + buffer, -1, /* implicit srcLength */ + U_FOLD_CASE_DEFAULT, + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || + uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strFoldCase(default same buffer)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + + /* test full string case folding, exclude special i, in the same buffer */ + if(isUnicode_3_1) { + uprv_memcpy(buffer, mixed, sizeof(mixed)); + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + buffer, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_EXCLUDE_SPECIAL_I, + &errorCode); + if( U_FAILURE(errorCode) || + length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) || + uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 || + buffer[length]!=0 + ) { + log_err("error in u_strFoldCase(exclude special i same buffer)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); + } + } + + /* test preflighting */ + buffer[0]=buffer[2]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, 2, /* set destCapacity=2 */ + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_DEFAULT, + &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || + uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)!=0 || + buffer[2]!=0xabcd + ) { + log_err("error in u_strFoldCase(default preflighting)=%ld error=%s string matches: %s\n", + length, + u_errorName(errorCode), + uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no"); + } + + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(NULL, 0, + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_DEFAULT, + &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) + ) { + log_err("error in u_strFoldCase(default pure preflighting)=%ld error=%s\n", + length, + u_errorName(errorCode)); + } + + /* test error handling */ + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(NULL, sizeof(buffer)/U_SIZEOF_UCHAR, + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_DEFAULT, + &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error in u_strFoldCase(default dest=NULL)=%ld error=%s\n", + length, + u_errorName(errorCode)); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, -1, + mixed, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_DEFAULT, + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strFoldCase(default destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + NULL, sizeof(mixed)/U_SIZEOF_UCHAR, + U_FOLD_CASE_EXCLUDE_SPECIAL_I, + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strFoldCase(exclude special i src=NULL)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } + + buffer[0]=0xabcd; + errorCode=U_ZERO_ERROR; + length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, + mixed, -2, + U_FOLD_CASE_EXCLUDE_SPECIAL_I, + &errorCode); + if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || + buffer[0]!=0xabcd + ) { + log_err("error in u_strFoldCase(exclude special i srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n", + length, + u_errorName(errorCode), + buffer[0]); + } +} + +static void +TestCaseCompare(void) { + static const UChar + + mixed[]= { 0x61, 0x42, 0x131, 0x3a3, 0xdf, 0xfb03, 0xd93f, 0xdfff, 0 }, + otherDefault[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 }, + otherExcludeSpecialI[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 }, + different[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 }; + + UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 }; + + int32_t result, lenMixed, lenOtherDefault, lenOtherExcludeSpecialI, lenDifferent; + UErrorCode errorCode; + UBool isUnicode_3_1; + + errorCode=U_ZERO_ERROR; + + lenMixed=u_strlen(mixed); + lenOtherDefault=u_strlen(otherDefault); + lenOtherExcludeSpecialI=u_strlen(otherExcludeSpecialI); + lenDifferent=u_strlen(different); + + /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */ + u_getUnicodeVersion(unicodeVersion); + isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0; + + /* test u_strcasecmp() */ + result=u_strcasecmp(mixed, otherDefault, U_FOLD_CASE_DEFAULT); + if(result!=0) { + log_err("error: u_strcasecmp(mixed, other, default)=%ld instead of 0\n", result); + } + result=u_strCaseCompare(mixed, -1, otherDefault, -1, U_FOLD_CASE_DEFAULT, &errorCode); + if(result!=0) { + log_err("error: u_strCaseCompare(mixed, other, default)=%ld instead of 0\n", result); + } + + /* test u_strcasecmp() - exclude special i */ + result=u_strcasecmp(mixed, otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I); + if(result!=0) { + log_err("error: u_strcasecmp(mixed, other, exclude special i)=%ld instead of 0\n", result); + } + result=u_strCaseCompare(mixed, lenMixed, otherExcludeSpecialI, lenOtherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); + if(result!=0) { + log_err("error: u_strCaseCompare(mixed, other, exclude special i)=%ld instead of 0\n", result); + } + + /* test u_strcasecmp() */ + result=u_strcasecmp(mixed, different, U_FOLD_CASE_DEFAULT); + if(result<=0) { + log_err("error: u_strcasecmp(mixed, different, default)=%ld instead of positive\n", result); + } + result=u_strCaseCompare(mixed, -1, different, lenDifferent, U_FOLD_CASE_DEFAULT, &errorCode); + if(result<=0) { + log_err("error: u_strCaseCompare(mixed, different, default)=%ld instead of positive\n", result); + } + + /* test u_strncasecmp() - stop before the sharp s (U+00df) */ + result=u_strncasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT); + if(result!=0) { + log_err("error: u_strncasecmp(mixed, different, 4, default)=%ld instead of 0\n", result); + } + result=u_strCaseCompare(mixed, 4, different, 4, U_FOLD_CASE_DEFAULT, &errorCode); + if(result!=0) { + log_err("error: u_strCaseCompare(mixed, 4, different, 4, default)=%ld instead of 0\n", result); + } + + /* test u_strncasecmp() - stop in the middle of the sharp s (U+00df) */ + result=u_strncasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT); + if(result<=0) { + log_err("error: u_strncasecmp(mixed, different, 5, default)=%ld instead of positive\n", result); + } + result=u_strCaseCompare(mixed, 5, different, 5, U_FOLD_CASE_DEFAULT, &errorCode); + if(result<=0) { + log_err("error: u_strCaseCompare(mixed, 5, different, 5, default)=%ld instead of positive\n", result); + } + + /* test u_memcasecmp() - stop before the sharp s (U+00df) */ + result=u_memcasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT); + if(result!=0) { + log_err("error: u_memcasecmp(mixed, different, 4, default)=%ld instead of 0\n", result); + } + + /* test u_memcasecmp() - stop in the middle of the sharp s (U+00df) */ + result=u_memcasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT); + if(result<=0) { + log_err("error: u_memcasecmp(mixed, different, 5, default)=%ld instead of positive\n", result); + } +} + +/* test UCaseMap ------------------------------------------------------------ */ + +/* + * API test for UCaseMap; + * test cases for actual case mappings using UCaseMap see + * intltest utility/UnicodeStringTest/StringCaseTest/TestCasing + */ +static void +TestUCaseMap(void) { + static const char + aBc[] ={ 0x61, 0x42, 0x63, 0 }, + abc[] ={ 0x61, 0x62, 0x63, 0 }, + ABCg[]={ 0x41, 0x42, 0x43, 0x67, 0 }, + defg[]={ 0x64, 0x65, 0x66, 0x67, 0 }; + char utf8Out[8]; + + UCaseMap *csm; + const char *locale; + uint32_t options; + int32_t length; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + csm=ucasemap_open("tur", 0xa5, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucasemap_open(\"tur\") failed - %s\n", u_errorName(errorCode)); + return; + } + locale=ucasemap_getLocale(csm); + if(0!=strcmp(locale, "tr")) { + log_err("ucasemap_getLocale(ucasemap_open(\"tur\"))==%s!=\"tr\"\n", locale); + } + /* overly long locale IDs get truncated to their language code to avoid unnecessary allocation */ + ucasemap_setLocale(csm, "I-kLInGOn-the-quick-brown-fox-jumps-over-the-lazy-dog", &errorCode); + locale=ucasemap_getLocale(csm); + if(0!=strcmp(locale, "i-klingon")) { + log_err("ucasemap_getLocale(ucasemap_setLocale(\"I-kLInGOn-the-quick-br...\"))==%s!=\"i-klingon\"\n", locale); + } + + errorCode=U_ZERO_ERROR; + options=ucasemap_getOptions(csm); + if(options!=0xa5) { + log_err("ucasemap_getOptions(ucasemap_open(0xa5))==0x%lx!=0xa5\n", (long)options); + } + ucasemap_setOptions(csm, 0x333333, &errorCode); + options=ucasemap_getOptions(csm); + if(options!=0x333333) { + log_err("ucasemap_getOptions(ucasemap_setOptions(0x333333))==0x%lx!=0x333333\n", (long)options); + } + + /* test case mapping API; not all permutations necessary due to shared implementation code */ + + /* NUL terminated source */ + errorCode=U_ZERO_ERROR; + length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode); + if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) { + log_err("ucasemap_utf8ToLower(aBc\\0) failed\n"); + } + + /* incoming failure code */ + errorCode=U_PARSE_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode); + if(errorCode!=U_PARSE_ERROR || 0!=strcmp(defg, utf8Out)) { + log_err("ucasemap_utf8ToLower(failure) failed\n"); + } + + /* overlapping input & output */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, aBc); + length=ucasemap_utf8ToUpper(csm, utf8Out, 2, utf8Out+1, 2, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) { + log_err("ucasemap_utf8ToUpper(overlap 1) failed\n"); + } + + /* overlap in the other direction */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, aBc); + length=ucasemap_utf8ToUpper(csm, utf8Out+1, 2, utf8Out, 2, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) { + log_err("ucasemap_utf8ToUpper(overlap 2) failed\n"); + } + + /* NULL destination */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToLower(csm, NULL, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) { + log_err("ucasemap_utf8ToLower(dest=NULL) failed\n"); + } + + /* destCapacity<0 */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToLower(csm, utf8Out, -2, aBc, -1, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) { + log_err("ucasemap_utf8ToLower(destCapacity<0) failed\n"); + } + + /* NULL source */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), NULL, -1, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) { + log_err("ucasemap_utf8ToLower(src=NULL) failed\n"); + } + + /* srcLength<-1 */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -2, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) { + log_err("ucasemap_utf8ToLower(srcLength<-1) failed\n"); + } + + /* buffer overflow */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToUpper(csm, utf8Out, 2, aBc, 3, &errorCode); + if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3 || 0!=strcmp(defg+2, utf8Out+2)) { + log_err("ucasemap_utf8ToUpper(overflow) failed\n"); + } + + /* dest not terminated (leaves g from defg alone) */ + errorCode=U_ZERO_ERROR; + strcpy(utf8Out, defg); + length=ucasemap_utf8ToUpper(csm, utf8Out, 3, aBc, 3, &errorCode); + if(errorCode!=U_STRING_NOT_TERMINATED_WARNING || length!=3 || 0!=strcmp(ABCg, utf8Out)) { + log_err("ucasemap_utf8ToUpper(overflow) failed\n"); + } + + /* C API coverage for case folding. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */ + errorCode=U_ZERO_ERROR; + utf8Out[0]=0; + length=ucasemap_utf8FoldCase(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, 3, &errorCode); + if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) { + log_err("ucasemap_utf8FoldCase(aBc) failed\n"); + } + + ucasemap_close(csm); +} + +#if !UCONFIG_NO_BREAK_ITERATION + +/* Try titlecasing with options. */ +static void +TestUCaseMapToTitle(void) { + /* "a 'CaT. A 'dOg! 'eTc." where '=U+02BB */ + /* + * Note: The sentence BreakIterator does not recognize a '.' + * as a sentence terminator if it is followed by lowercase. + * That is why the example has the '!'. + */ + static const UChar + + beforeTitle[]= { 0x61, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x54, 0x63, 0x2e }, + titleWord[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x44, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x74, 0x63, 0x2e }, + titleWordNoAdjust[]={ 0x41, 0x20, 0x2bb, 0x63, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x74, 0x63, 0x2e }, + titleSentNoLower[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x54, 0x63, 0x2e }; + + UChar buffer[32]; + UCaseMap *csm; + UBreakIterator *sentenceIter; + const UBreakIterator *iter; + int32_t length; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + csm=ucasemap_open("", 0, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucasemap_open(\"\") failed - %s\n", u_errorName(errorCode)); + return; + } + + iter=ucasemap_getBreakIterator(csm); + if(iter!=NULL) { + log_err("ucasemap_getBreakIterator() returns %p!=NULL before setting any iterator or titlecasing\n", iter); + } + + /* Use default UBreakIterator: Word breaks. */ + length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode); + if( U_FAILURE(errorCode) || + length!=LENGTHOF(titleWord) || + 0!=u_memcmp(buffer, titleWord, length) || + buffer[length]!=0 + ) { + log_err("ucasemap_toTitle(default iterator)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); + } + + iter=ucasemap_getBreakIterator(csm); + if(iter==NULL) { + log_err("ucasemap_getBreakIterator() returns NULL after titlecasing\n"); + } + + /* Try U_TITLECASE_NO_BREAK_ADJUSTMENT. */ + ucasemap_setOptions(csm, U_TITLECASE_NO_BREAK_ADJUSTMENT, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucasemap_setOptions(U_TITLECASE_NO_BREAK_ADJUSTMENT) failed - %s\n", u_errorName(errorCode)); + return; + } + + length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode); + if( U_FAILURE(errorCode) || + length!=LENGTHOF(titleWordNoAdjust) || + 0!=u_memcmp(buffer, titleWordNoAdjust, length) || + buffer[length]!=0 + ) { + log_err("ucasemap_toTitle(default iterator, no break adjustment)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); + } + + /* Set a sentence break iterator. */ + errorCode=U_ZERO_ERROR; + sentenceIter=ubrk_open(UBRK_SENTENCE, "", NULL, 0, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ubrk_open(UBRK_SENTENCE) failed - %s\n", u_errorName(errorCode)); + ucasemap_close(csm); + return; + } + ucasemap_setBreakIterator(csm, sentenceIter, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucasemap_setBreakIterator(sentence iterator) failed - %s\n", u_errorName(errorCode)); + ubrk_close(sentenceIter); + ucasemap_close(csm); + return; + } + iter=ucasemap_getBreakIterator(csm); + if(iter!=sentenceIter) { + log_err("ucasemap_getBreakIterator() returns %p!=%p after setting the iterator\n", iter, sentenceIter); + } + + ucasemap_setOptions(csm, U_TITLECASE_NO_LOWERCASE, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucasemap_setOptions(U_TITLECASE_NO_LOWERCASE) failed - %s\n", u_errorName(errorCode)); + return; + } + + /* Use the sentence break iterator with the option. Preflight first. */ + length=ucasemap_toTitle(csm, NULL, 0, beforeTitle, LENGTHOF(beforeTitle), &errorCode); + if( errorCode!=U_BUFFER_OVERFLOW_ERROR || + length!=LENGTHOF(titleSentNoLower) + ) { + log_err("ucasemap_toTitle(preflight sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + buffer[0]=0; + length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode); + if( U_FAILURE(errorCode) || + length!=LENGTHOF(titleSentNoLower) || + 0!=u_memcmp(buffer, titleSentNoLower, length) || + buffer[length]!=0 + ) { + log_err("ucasemap_toTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); + } + + /* UTF-8 C API coverage. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */ + { + char utf8BeforeTitle[64], utf8TitleSentNoLower[64], utf8[64]; + int32_t utf8BeforeTitleLength, utf8TitleSentNoLowerLength; + + errorCode=U_ZERO_ERROR; + u_strToUTF8(utf8BeforeTitle, (int32_t)sizeof(utf8BeforeTitle), &utf8BeforeTitleLength, beforeTitle, LENGTHOF(beforeTitle), &errorCode); + u_strToUTF8(utf8TitleSentNoLower, (int32_t)sizeof(utf8TitleSentNoLower), &utf8TitleSentNoLowerLength, titleSentNoLower, LENGTHOF(titleSentNoLower), &errorCode); + + length=ucasemap_utf8ToTitle(csm, utf8, (int32_t)sizeof(utf8), utf8BeforeTitle, utf8BeforeTitleLength, &errorCode); + if( U_FAILURE(errorCode) || + length!=utf8TitleSentNoLowerLength || + 0!=uprv_memcmp(utf8, utf8TitleSentNoLower, length) || + utf8[length]!=0 + ) { + log_err("ucasemap_utf8ToTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); + } + } + + ucasemap_close(csm); +} + +#endif + +void addCaseTest(TestNode** root); + +void addCaseTest(TestNode** root) { + /* cstrcase.c functions, declared in cucdtst.h */ + addTest(root, &TestCaseLower, "tsutil/cstrcase/TestCaseLower"); + addTest(root, &TestCaseUpper, "tsutil/cstrcase/TestCaseUpper"); +#if !UCONFIG_NO_BREAK_ITERATION + addTest(root, &TestCaseTitle, "tsutil/cstrcase/TestCaseTitle"); +#endif + addTest(root, &TestCaseFolding, "tsutil/cstrcase/TestCaseFolding"); + addTest(root, &TestCaseCompare, "tsutil/cstrcase/TestCaseCompare"); + addTest(root, &TestUCaseMap, "tsutil/cstrcase/TestUCaseMap"); +#if !UCONFIG_NO_BREAK_ITERATION + addTest(root, &TestUCaseMapToTitle, "tsutil/cstrcase/TestUCaseMapToTitle"); +#endif +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c new file mode 100644 index 00000000000..ea6fe5cbeaa --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c @@ -0,0 +1,286 @@ +/* +********************************************************************** +* Copyright (C) 1998-2004, International Business Machines Corporation +* and others. All Rights Reserved. +********************************************************************** +* +* File cstrtest.c +* +* Modification History: +* +* Date Name Description +* 07/13/2000 Madhu created +******************************************************************************* +*/ + +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "cstring.h" +#include "uinvchar.h" +#include "cintltst.h" +#include "cmemory.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void TestAPI(void); +void addCStringTest(TestNode** root); + +static void TestInvariant(void); + +void addCStringTest(TestNode** root) { + addTest(root, &TestAPI, "tsutil/cstrtest/TestAPI"); + addTest(root, &TestInvariant, "tsutil/cstrtest/TestInvariant"); +} + +static void TestAPI(void) +{ + int32_t intValue=0; + char src[30]="HELLO THERE", dest[30]; + static const char *const abc="abcdefghijklmnopqrstuvwxyz", *const ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *temp; + int32_t i; + + log_verbose("Testing uprv_tolower() and uprv_toupper()\n"); + for(i=0; i<=26; ++i) { + dest[i]=uprv_tolower(abc[i]); + } + if(0!=strcmp(abc, dest)) { + log_err("uprv_tolower(abc) failed\n"); + } + + for(i=0; i<=26; ++i) { + dest[i]=uprv_tolower(ABC[i]); + } + if(0!=strcmp(abc, dest)) { + log_err("uprv_tolower(ABC) failed\n"); + } + + for(i=0; i<=26; ++i) { + dest[i]=uprv_toupper(abc[i]); + } + if(0!=strcmp(ABC, dest)) { + log_err("uprv_toupper(abc) failed\n"); + } + + for(i=0; i<=26; ++i) { + dest[i]=uprv_toupper(ABC[i]); + } + if(0!=strcmp(ABC, dest)) { + log_err("uprv_toupper(ABC) failed\n"); + } + + log_verbose("Testing the API in cstring\n"); + T_CString_toLowerCase(src); + if(uprv_strcmp(src, "hello there") != 0){ + log_err("FAIL: *** T_CString_toLowerCase() failed. Expected: \"hello there\", Got: \"%s\"\n", src); + } + T_CString_toUpperCase(src); + if(uprv_strcmp(src, "HELLO THERE") != 0){ + log_err("FAIL: *** T_CString_toUpperCase() failed. Expected: \"HELLO THERE\", Got: \"%s\"\n", src); + } + + intValue=T_CString_stringToInteger("34556", 10); + if(intValue != 34556){ + log_err("FAIL: ****T_CString_stringToInteger(\"34556\", 10) failed. Expected: 34556, Got: %d\n", intValue); + } + intValue=T_CString_stringToInteger("100", 16); + if(intValue != 256){ + log_err("FAIL: ****T_CString_stringToInteger(\"100\", 16) failed. Expected: 256, Got: %d\n", intValue); + } + i = T_CString_integerToString(src, 34556, 10); + if(uprv_strcmp(src, "34556") != 0 || i != 5){ + log_err("FAIL: ****integerToString(src, 34566, 10); failed. Expected: \"34556\", Got: %s\n", src); + } + i = T_CString_integerToString(src, 431, 16); + if(uprv_stricmp(src, "1AF") != 0 || i != 3){ + log_err("FAIL: ****integerToString(src, 431, 16); failed. Expected: \"1AF\", Got: %s\n", src); + } + i = T_CString_int64ToString(src, U_INT64_MAX, 10); + if(uprv_strcmp(src, "9223372036854775807") != 0 || i != 19){ + log_err("FAIL: ****integerToString(src, 9223372036854775807, 10); failed. Got: %s\n", src); + } + i = T_CString_int64ToString(src, U_INT64_MAX, 16); + if(uprv_stricmp(src, "7FFFFFFFFFFFFFFF") != 0 || i != 16){ + log_err("FAIL: ****integerToString(src, 7FFFFFFFFFFFFFFF, 16); failed. Got: %s\n", src); + } + + uprv_strcpy(src, "this is lower case"); + if(T_CString_stricmp(src, "THIS is lower CASE") != 0){ + log_err("FAIL: *****T_CString_stricmp() failed."); + } + if((intValue=T_CString_stricmp(NULL, "first string is null") )!= -1){ + log_err("FAIL: T_CString_stricmp() where the first string is null failed. Expected: -1, returned %d\n", intValue); + } + if((intValue=T_CString_stricmp("second string is null", NULL)) != 1){ + log_err("FAIL: T_CString_stricmp() where the second string is null failed. Expected: 1, returned %d\n", intValue); + } + if((intValue=T_CString_stricmp(NULL, NULL)) != 0){ + log_err("FAIL: T_CString_stricmp(NULL, NULL) failed. Expected: 0, returned %d\n", intValue);; + } + if((intValue=T_CString_stricmp("", "")) != 0){ + log_err("FAIL: T_CString_stricmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);; + } + if((intValue=T_CString_stricmp("", "abc")) != -1){ + log_err("FAIL: T_CString_stricmp(\"\", \"abc\") failed. Expected: -1, returned %d\n", intValue); + } + if((intValue=T_CString_stricmp("abc", "")) != 1){ + log_err("FAIL: T_CString_stricmp(\"abc\", \"\") failed. Expected: 1, returned %d\n", intValue); + } + + temp=uprv_strdup("strdup"); + if(uprv_strcmp(temp, "strdup") !=0 ){ + log_err("FAIL: uprv_strdup() failed. Expected: \"strdup\", Got: %s\n", temp); + } + uprv_free((char *)temp); + + uprv_strcpy(src, "this is lower case"); + if(T_CString_strnicmp(src, "THIS", 4 ) != 0){ + log_err("FAIL: *****T_CString_strnicmp() failed."); + } + if((intValue=T_CString_strnicmp(NULL, "first string is null", 10) )!= -1){ + log_err("FAIL: T_CString_strnicmp() where the first string is null failed. Expected: -1, returned %d\n", intValue); + } + if((intValue=T_CString_strnicmp("second string is null", NULL, 10)) != 1){ + log_err("FAIL: T_CString_strnicmp() where the second string is null failed. Expected: 1, returned %d\n", intValue); + } + if((intValue=T_CString_strnicmp(NULL, NULL, 10)) != 0){ + log_err("FAIL: T_CString_strnicmp(NULL, NULL, 10) failed. Expected: 0, returned %d\n", intValue);; + } + if((intValue=T_CString_strnicmp("", "", 10)) != 0){ + log_err("FAIL: T_CString_strnicmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);; + } + if((intValue=T_CString_strnicmp("", "abc", 10)) != -1){ + log_err("FAIL: T_CString_stricmp(\"\", \"abc\", 10) failed. Expected: -1, returned %d\n", intValue); + } + if((intValue=T_CString_strnicmp("abc", "", 10)) != 1){ + log_err("FAIL: T_CString_strnicmp(\"abc\", \"\", 10) failed. Expected: 1, returned %d\n", intValue); + } + +} + +/* test invariant-character handling */ +static void +TestInvariant() { + /* all invariant graphic chars and some control codes (not \n!) */ + const char invariantChars[]= + "\t\r \"%&'()*+,-./" + "0123456789:;<=>?" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ_" + "abcdefghijklmnopqrstuvwxyz"; + + const UChar invariantUChars[]={ + 9, 0xd, 0x20, 0x22, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5f, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0 + }; + + const char variantChars[]="\n!#$@[\\]^`{|}~"; + + const UChar variantUChars[]={ + 0x0a, 0x21, 0x23, 0x24, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x7b, 0x7c, 0x7d, 0x7e, 0 + }; + + const UChar nonASCIIUChars[]={ 0x80, 0xa0, 0x900, 0xff51 }; + + UChar us[120]; + char cs[120]; + + int32_t i, length; + + /* make sure that all invariant characters convert both ways */ + length=sizeof(invariantChars); + u_charsToUChars(invariantChars, us, length); + if(u_strcmp(us, invariantUChars)!=0) { + log_err("u_charsToUChars(invariantChars) failed\n"); + } + + u_UCharsToChars(invariantUChars, cs, length); + if(strcmp(cs, invariantChars)!=0) { + log_err("u_UCharsToChars(invariantUChars) failed\n"); + } + + + /* + * make sure that variant characters convert from source code literals to Unicode + * but not back to char * + */ + length=sizeof(variantChars); + u_charsToUChars(variantChars, us, length); + if(u_strcmp(us, variantUChars)!=0) { + log_err("u_charsToUChars(variantChars) failed\n"); + } + +#ifdef NDEBUG + /* + * Test u_UCharsToChars(variantUChars) only in release mode because it will + * cause an assertion failure in debug builds. + */ + u_UCharsToChars(variantUChars, cs, length); + for(i=0; i<length; ++i) { + if(cs[i]!=0) { + log_err("u_UCharsToChars(variantUChars) converted the %d-th character to %02x instead of 00\n", i, cs[i]); + } + } +#endif + + /* + * Verify that invariant characters roundtrip from Unicode to the + * default converter and back. + */ + { + UConverter *cnv; + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + cnv=ucnv_open(NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to open the default converter\n"); + } else { + length=ucnv_fromUChars(cnv, cs, sizeof(cs), invariantUChars, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_fromUChars(invariantUChars) failed - %s\n", u_errorName(errorCode)); + } else if(length!=sizeof(invariantChars)-1 || strcmp(cs, invariantChars)!=0) { + log_err("ucnv_fromUChars(invariantUChars) failed\n"); + } + + errorCode=U_ZERO_ERROR; + length=ucnv_toUChars(cnv, us, LENGTHOF(us), invariantChars, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucnv_toUChars(invariantChars) failed - %s\n", u_errorName(errorCode)); + } else if(length!=LENGTHOF(invariantUChars)-1 || u_strcmp(us, invariantUChars)!=0) { + log_err("ucnv_toUChars(invariantChars) failed\n"); + } + + ucnv_close(cnv); + } + } + + /* API tests */ + if(!uprv_isInvariantString(invariantChars, -1)) { + log_err("uprv_isInvariantString(invariantChars) failed\n"); + } + if(!uprv_isInvariantUString(invariantUChars, -1)) { + log_err("uprv_isInvariantUString(invariantUChars) failed\n"); + } + if(!uprv_isInvariantString(invariantChars+strlen(invariantChars), 1)) { + log_err("uprv_isInvariantString(\"\\0\") failed\n"); + } + + for(i=0; i<(sizeof(variantChars)-1); ++i) { + if(uprv_isInvariantString(variantChars+i, 1)) { + log_err("uprv_isInvariantString(variantChars[%d]) failed\n", i); + } + if(uprv_isInvariantUString(variantUChars+i, 1)) { + log_err("uprv_isInvariantUString(variantUChars[%d]) failed\n", i); + } + } + + for(i=0; i<LENGTHOF(nonASCIIUChars); ++i) { + if(uprv_isInvariantUString(nonASCIIUChars+i, 1)) { + log_err("uprv_isInvariantUString(nonASCIIUChars[%d]) failed\n", i); + } + } +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c new file mode 100644 index 00000000000..c4a1767d0f9 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c @@ -0,0 +1,131 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CTURTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * CollationTurkishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "cturtst.h" +#include "unicode/ustring.h" +#include "string.h" + +static UCollator *myCollation; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {0x0073/*'s'*/, 0x0327, 0x0000}, + {0x0076/*'v'*/, 0x00E4, 0x0074/*'t'*/, 0x0000}, + {0x006f/*'o'*/, 0x006c/*'l'*/, 0x0064/*'d'*/, 0x0000}, + {0x00FC, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064/*'d'*/, 0x0000}, + {0x0068/*'h'*/, 0x011E, 0x0061/*'a'*/, 0x006c/*'l'*/, 0x0074/*'t'*/, 0x0000}, + {0x0073/*'s'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0065/*'e'*/, 0x0073/*'s'*/, 0x015E, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0131, 0x0064/*'d'*/, 0x0000}, + {0x0069/*'i'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000}, + {0x00FC, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0131, 0x0064 /*d'*/, 0x0000}, + {0x0069/*'i'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000}, +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {0x0075/*'u'*/, 0x0308, 0x0000}, + {0x0076/*'v'*/, 0x0062/*'b'*/, 0x0074/*'t'*/, 0x0000}, + {0x00D6, 0x0061/*'a'*/, 0x0079/*'y'*/, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000}, + {0x0068/*'h'*/, 0x0061/*'a'*/, 0x006c/*'l'*/, 0x0074/*'t'*/, 0x0000}, + {0x015E, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0065/*'e'*/, 0x015E, 0x0073/*'s'*/, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000}, + {0x0049/*'I'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000}, + {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000}, + {0x0049/*'I'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000}, +}; + +const static UCollationResult results[] = { + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + /* test priamry > 8 */ + UCOL_LESS, + UCOL_LESS, /*Turkish translator made a primary differnce between dotted and dotless I */ + UCOL_GREATER +}; + + + +void addTurkishCollTest(TestNode** root) +{ + + addTest(root, &TestPrimary, "tscoll/cturtst/TestPrimary"); + addTest(root, &TestTertiary, "tscoll/cturtst/TestTertiary"); + + +} + +static void TestTertiary( ) +{ + + int32_t i; + + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("tr", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing Turkish Collation with Tertiary strength\n"); + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 8 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +static void TestPrimary() +{ + + int32_t i; + + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("tr", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing Turkish Collation with Primary strength\n"); + ucol_setStrength(myCollation, UCOL_PRIMARY); + for (i = 8; i < 11; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h new file mode 100644 index 00000000000..542a484fc0c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h @@ -0,0 +1,41 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CTURTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationTurkishTest(JAPAN) is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CTRCOLLTST +#define _CTRCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 + + + /*perform test with strength PRIMARY */ +static void TestPrimary(void); + /* perform test with strength TERTIARY */ +static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c new file mode 100644 index 00000000000..f59acfef16c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c @@ -0,0 +1,356 @@ +/******************************************************************** + * Copyright (c) 1997-2007, International Business Machines + * Corporation and others. All Rights Reserved. + ********************************************************************/ + +#include <string.h> +#include "unicode/utypes.h" +#include "unicode/uscript.h" +#include "unicode/uchar.h" +#include "cintltst.h" +#include "cucdapi.h" + +#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0]) + +void TestUScriptCodeAPI(){ + int i =0; + int numErrors =0; + { + const char* testNames[]={ + /* test locale */ + "en", "en_US", "sr", "ta" , "te_IN", + "hi", "he", "ar", + /* test abbr */ + "Hani", "Hang","Hebr","Hira", + "Knda","Kana","Khmr","Lao", + "Latn",/*"Latf","Latg",*/ + "Mlym", "Mong", + + /* test names */ + "CYRILLIC","DESERET","DEVANAGARI","ETHIOPIC","GEORGIAN", + "GOTHIC", "GREEK", "GUJARATI", "COMMON", "INHERITED", + /* test lower case names */ + "malayalam", "mongolian", "myanmar", "ogham", "old-italic", + "oriya", "runic", "sinhala", "syriac","tamil", + "telugu", "thaana", "thai", "tibetan", + /* test the bounds*/ + "tagb", "arabic", + /* test bogus */ + "asfdasd", "5464", "12235", + /* test the last index */ + "zyyy", "YI", + '\0' + }; + UScriptCode expected[] ={ + /* locales should return */ + USCRIPT_LATIN, USCRIPT_LATIN, USCRIPT_CYRILLIC, USCRIPT_TAMIL, USCRIPT_TELUGU, + USCRIPT_DEVANAGARI, USCRIPT_HEBREW, USCRIPT_ARABIC, + /* abbr should return */ + USCRIPT_HAN, USCRIPT_HANGUL, USCRIPT_HEBREW, USCRIPT_HIRAGANA, + USCRIPT_KANNADA, USCRIPT_KATAKANA, USCRIPT_KHMER, USCRIPT_LAO, + USCRIPT_LATIN,/* USCRIPT_LATIN, USCRIPT_LATIN,*/ + USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN, + /* names should return */ + USCRIPT_CYRILLIC, USCRIPT_DESERET, USCRIPT_DEVANAGARI, USCRIPT_ETHIOPIC, USCRIPT_GEORGIAN, + USCRIPT_GOTHIC, USCRIPT_GREEK, USCRIPT_GUJARATI, USCRIPT_COMMON, USCRIPT_INHERITED, + /* lower case names should return */ + USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN, USCRIPT_MYANMAR, USCRIPT_OGHAM, USCRIPT_OLD_ITALIC, + USCRIPT_ORIYA, USCRIPT_RUNIC, USCRIPT_SINHALA, USCRIPT_SYRIAC, USCRIPT_TAMIL, + USCRIPT_TELUGU, USCRIPT_THAANA, USCRIPT_THAI, USCRIPT_TIBETAN, + /* bounds */ + USCRIPT_TAGBANWA, USCRIPT_ARABIC, + /* bogus names should return invalid code */ + USCRIPT_INVALID_CODE, USCRIPT_INVALID_CODE, USCRIPT_INVALID_CODE, + USCRIPT_COMMON, USCRIPT_YI, + }; + + UErrorCode err = U_ZERO_ERROR; + + const int32_t capacity = 10; + + for( ; testNames[i]!='\0'; i++){ + UScriptCode script[10]={USCRIPT_INVALID_CODE}; + uscript_getCode(testNames[i],script,capacity, &err); + if( script[0] != expected[i]){ + log_err("Error getting script code Got: %i Expected: %i for name %s\n", + script[0],expected[i],testNames[i]); + numErrors++; + } + } + if(numErrors >0 ){ + log_data_err("Errors uchar_getScriptCode() : %i \n",numErrors); + } + } + + { + UErrorCode err = U_ZERO_ERROR; + int32_t capacity=0; + int32_t j; + UScriptCode jaCode[]={USCRIPT_KATAKANA, USCRIPT_HIRAGANA, USCRIPT_HAN }; + UScriptCode script[10]={USCRIPT_INVALID_CODE}; + int32_t num = uscript_getCode("ja",script,capacity, &err); + /* preflight */ + if(err==U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + capacity = 10; + num = uscript_getCode("ja",script,capacity, &err); + if(num!=(sizeof(jaCode)/sizeof(UScriptCode))){ + log_err("Errors uscript_getScriptCode() for Japanese locale: num=%d, expected %d \n", + num, (sizeof(jaCode)/sizeof(UScriptCode))); + } + for(j=0;j<sizeof(jaCode)/sizeof(UScriptCode);j++) { + if(script[j]!=jaCode[j]) { + log_err("Japanese locale: code #%d was %d (%s) but expected %d (%s)\n", j, + script[j], uscript_getName(script[j]), + jaCode[j], uscript_getName(jaCode[j])); + + } + } + }else{ + log_data_err("Errors in uscript_getScriptCode() expected error : %s got: %s \n", + "U_BUFFER_OVERFLOW_ERROR", + u_errorName(err)); + } + + } + + { + UScriptCode testAbbr[]={ + /* names should return */ + USCRIPT_CYRILLIC, USCRIPT_DESERET, USCRIPT_DEVANAGARI, USCRIPT_ETHIOPIC, USCRIPT_GEORGIAN, + USCRIPT_GOTHIC, USCRIPT_GREEK, USCRIPT_GUJARATI, + }; + + const char* expectedNames[]={ + + /* test names */ + "Cyrillic","Deseret","Devanagari","Ethiopic","Georgian", + "Gothic", "Greek", "Gujarati", + '\0' + }; + i=0; + while(i<sizeof(testAbbr)/sizeof(UScriptCode)){ + const char* name = uscript_getName(testAbbr[i]); + if(name == NULL) { + log_data_err("Couldn't get script name\n"); + return; + } + numErrors=0; + if(strcmp(expectedNames[i],name)!=0){ + log_err("Error getting abbreviations Got: %s Expected: %s\n",name,expectedNames[i]); + numErrors++; + } + if(numErrors > 0){ + if(numErrors >0 ){ + log_err("Errors uchar_getScriptAbbr() : %i \n",numErrors); + } + } + i++; + } + + } + + { + UScriptCode testAbbr[]={ + /* abbr should return */ + USCRIPT_HAN, USCRIPT_HANGUL, USCRIPT_HEBREW, USCRIPT_HIRAGANA, + USCRIPT_KANNADA, USCRIPT_KATAKANA, USCRIPT_KHMER, USCRIPT_LAO, + USCRIPT_LATIN, + USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN, + }; + + const char* expectedAbbr[]={ + /* test abbr */ + "Hani", "Hang","Hebr","Hira", + "Knda","Kana","Khmr","Laoo", + "Latn", + "Mlym", "Mong", + '\0' + }; + i=0; + while(i<sizeof(testAbbr)/sizeof(UScriptCode)){ + const char* name = uscript_getShortName(testAbbr[i]); + numErrors=0; + if(strcmp(expectedAbbr[i],name)!=0){ + log_err("Error getting abbreviations Got: %s Expected: %s\n",name,expectedAbbr[i]); + numErrors++; + } + if(numErrors > 0){ + if(numErrors >0 ){ + log_err("Errors uchar_getScriptAbbr() : %i \n",numErrors); + } + } + i++; + } + + } + /* now test uscript_getScript() API */ + { +#define MAX_ARRAY_SIZE 23 + uint32_t codepoints[] = { + 0x0000FF9D, /* USCRIPT_KATAKANA*/ + 0x0000FFBE, /* USCRIPT_HANGUL*/ + 0x0000FFC7, /* USCRIPT_HANGUL*/ + 0x0000FFCF, /* USCRIPT_HANGUL*/ + 0x0000FFD7, /* USCRIPT_HANGUL*/ + 0x0000FFDC, /* USCRIPT_HANGUL*/ + 0x00010300, /* USCRIPT_OLD_ITALIC*/ + 0x00010330, /* USCRIPT_GOTHIC*/ + 0x0001034A, /* USCRIPT_GOTHIC*/ + 0x00010400, /* USCRIPT_DESERET*/ + 0x00010428, /* USCRIPT_DESERET*/ + 0x0001D167, /* USCRIPT_INHERITED*/ + 0x0001D17B, /* USCRIPT_INHERITED*/ + 0x0001D185, /* USCRIPT_INHERITED*/ + 0x0001D1AA, /* USCRIPT_INHERITED*/ + 0x00020000, /* USCRIPT_HAN*/ + 0x00000D02, /* USCRIPT_MALAYALAM*/ + 0x00000D00, /* USCRIPT_UNKNOWN (new Zzzz value in Unicode 5.0) */ + 0x00000000, /* USCRIPT_COMMON*/ + 0x0001D169, /* USCRIPT_INHERITED*/ + 0x0001D182, /* USCRIPT_INHERITED*/ + 0x0001D18B, /* USCRIPT_INHERITED*/ + 0x0001D1AD, /* USCRIPT_INHERITED*/ + 0x00110000, /* USCRIPT_INVALID_CODE */ + }; + + UScriptCode expected[] = { + USCRIPT_KATAKANA , + USCRIPT_HANGUL , + USCRIPT_HANGUL , + USCRIPT_HANGUL , + USCRIPT_HANGUL , + USCRIPT_HANGUL , + USCRIPT_OLD_ITALIC, + USCRIPT_GOTHIC , + USCRIPT_GOTHIC , + USCRIPT_DESERET , + USCRIPT_DESERET , + USCRIPT_INHERITED, + USCRIPT_INHERITED, + USCRIPT_INHERITED, + USCRIPT_INHERITED, + USCRIPT_HAN , + USCRIPT_MALAYALAM, + USCRIPT_UNKNOWN, + USCRIPT_COMMON, + USCRIPT_INHERITED , + USCRIPT_INHERITED , + USCRIPT_INHERITED , + USCRIPT_INHERITED , + USCRIPT_INVALID_CODE, + }; + UScriptCode code = USCRIPT_INVALID_CODE; + UErrorCode status = U_ZERO_ERROR; + UBool passed = TRUE; + + i =0; + while(i< MAX_ARRAY_SIZE){ + code = uscript_getScript(codepoints[i],&status); + if(U_SUCCESS(status)){ + if( code != expected[i] || + code != (UScriptCode)u_getIntPropertyValue(codepoints[i], UCHAR_SCRIPT) + ) { + log_err("uscript_getScript for codepoint \\U%08X failed\n",codepoints[i]); + passed = FALSE; + } + }else{ + log_err("uscript_getScript for codepoint \\U%08X failed. Error: %s\n", + codepoints[i],u_errorName(status)); + break; + } + i++; + } + + if(passed==FALSE){ + log_err("uscript_getScript failed.\n"); + } + } + { + UScriptCode code= USCRIPT_INVALID_CODE; + UErrorCode status = U_ZERO_ERROR; + code = uscript_getScript(0x001D169,&status); + if(code != USCRIPT_INHERITED){ + log_err("\\U001D169 is not contained in USCRIPT_INHERITED"); + } + } + { + UScriptCode code= USCRIPT_INVALID_CODE; + UErrorCode status = U_ZERO_ERROR; + int32_t err = 0; + + for(i = 0; i<=0x10ffff; i++){ + code = uscript_getScript(i,&status); + if(code == USCRIPT_INVALID_CODE){ + err++; + log_err("uscript_getScript for codepoint \\U%08X failed.\n", i); + } + } + if(err>0){ + log_err("uscript_getScript failed for %d codepoints\n", err); + } + } + { + for(i=0; (UScriptCode)i< USCRIPT_CODE_LIMIT; i++){ + const char* name = uscript_getName((UScriptCode)i); + if(name==NULL || strcmp(name,"")==0){ + log_err("uscript_getName failed for code %i: name is NULL or \"\"\n",i); + } + } + } + + { + /* + * These script codes were originally added to ICU pre-3.6, so that ICU would + * have all ISO 15924 script codes. ICU was then based on Unicode 4.1. + * These script codes were added with only short names because we don't + * want to invent long names ourselves. + * Unicode 5 and later encode some of these scripts and give them long names. + * Whenever this happens, the long script names here need to be updated. + */ + static const char* expectedLong[] = { + "Balinese", "Batk", "Blis", "Brah", "Cham", "Cirt", "Cyrs", "Egyd", "Egyh", "Egyp", + "Geok", "Hans", "Hant", "Hmng", "Hung", "Inds", "Java", "Kali", "Latf", "Latg", + "Lepc", "Lina", "Mand", "Maya", "Mero", "Nko", "Orkh", "Perm", "Phags_Pa", "Phoenician", + "Plrd", "Roro", "Sara", "Syre", "Syrj", "Syrn", "Teng", "Vaii", "Visp", "Cuneiform", + "Zxxx", "Unknown", + "Cari", "Jpan", "Lana", "Lyci", "Lydi", "Olck", "Rjng", "Saur", "Sgnw", "Sund", + "Moon", "Mtei", + }; + static const char* expectedShort[] = { + "Bali", "Batk", "Blis", "Brah", "Cham", "Cirt", "Cyrs", "Egyd", "Egyh", "Egyp", + "Geok", "Hans", "Hant", "Hmng", "Hung", "Inds", "Java", "Kali", "Latf", "Latg", + "Lepc", "Lina", "Mand", "Maya", "Mero", "Nkoo", "Orkh", "Perm", "Phag", "Phnx", + "Plrd", "Roro", "Sara", "Syre", "Syrj", "Syrn", "Teng", "Vaii", "Visp", "Xsux", + "Zxxx", "Zzzz", + "Cari", "Jpan", "Lana", "Lyci", "Lydi", "Olck", "Rjng", "Saur", "Sgnw", "Sund", + "Moon", "Mtei", + }; + int32_t j = 0; + for(i=USCRIPT_BALINESE; (UScriptCode)i<USCRIPT_CODE_LIMIT; i++, j++){ + const char* name = uscript_getName((UScriptCode)i); + if(name==NULL || strcmp(name,expectedLong[j])!=0){ + log_err("uscript_getName failed for code %i: %s!=%s\n", i, name, expectedLong[j]); + } + name = uscript_getShortName((UScriptCode)i); + if(name==NULL || strcmp(name,expectedShort[j])!=0){ + log_err("uscript_getShortName failed for code %i: %s!=%s\n", i, name, expectedShort[j]); + } + } + for(i=0; i<ARRAY_SIZE(expectedLong); i++){ + UScriptCode fillIn[5] = {USCRIPT_INVALID_CODE}; + UErrorCode status = U_ZERO_ERROR; + int32_t len = 0; + len = uscript_getCode(expectedShort[i], fillIn, ARRAY_SIZE(fillIn), &status); + if(U_FAILURE(status)){ + log_err("uscript_getCode failed for script name %s. Error: %s\n",expectedShort[i], u_errorName(status)); + } + if(len>1){ + log_err("uscript_getCode did not return expected number of codes for script %s. EXPECTED: 1 GOT: %i\n", expectedShort[i], len); + } + if(fillIn[0]!= (UScriptCode)(USCRIPT_BALINESE+i)){ + log_err("uscript_getCode did not return expected code for script %s. EXPECTED: %i GOT: %i\n", expectedShort[i], (USCRIPT_BALINESE+i), fillIn[0] ); + } + } + } + } diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h new file mode 100644 index 00000000000..a61b52da4f3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h @@ -0,0 +1,9 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2003-2003, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ + +void TestUScriptCodeAPI(void); + + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c new file mode 100644 index 00000000000..f132d12e6f2 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c @@ -0,0 +1,3342 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CUCDTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API, added tests for string functions +******************************************************************************** +*/ + +#include <string.h> +#include <math.h> +#include <stdlib.h> + +#include "unicode/utypes.h" +#include "unicode/uchar.h" +#include "unicode/putil.h" +#include "unicode/ustring.h" +#include "unicode/uloc.h" + +#include "cintltst.h" +#include "putilimp.h" +#include "uparse.h" +#include "ucase.h" +#include "ubidi_props.h" +#include "uprops.h" +#include "uset_imp.h" +#include "usc_impl.h" +#include "unormimp.h" +#include "udatamem.h" /* for testing ucase_openBinary() */ +#include "cucdapi.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +/* prototypes --------------------------------------------------------------- */ + +static void TestUpperLower(void); +static void TestLetterNumber(void); +static void TestMisc(void); +static void TestPOSIX(void); +static void TestControlPrint(void); +static void TestIdentifier(void); +static void TestUnicodeData(void); +static void TestCodeUnit(void); +static void TestCodePoint(void); +static void TestCharLength(void); +static void TestCharNames(void); +static void TestMirroring(void); +/* void TestUScriptCodeAPI(void);*/ /* defined in cucdapi.h */ +static void TestUScriptRunAPI(void); +static void TestAdditionalProperties(void); +static void TestNumericProperties(void); +static void TestPropertyNames(void); +static void TestPropertyValues(void); +static void TestConsistency(void); +static void TestUCase(void); +static void TestUBiDiProps(void); +static void TestCaseFolding(void); + +/* internal methods used */ +static int32_t MakeProp(char* str); +static int32_t MakeDir(char* str); + +/* helpers ------------------------------------------------------------------ */ + +static void +parseUCDFile(const char *filename, + char *fields[][2], int32_t fieldCount, + UParseLineFn *lineFn, void *context, + UErrorCode *pErrorCode) { + char path[256]; + char backupPath[256]; + + if(U_FAILURE(*pErrorCode)) { + return; + } + + /* Look inside ICU_DATA first */ + strcpy(path, u_getDataDirectory()); + strcat(path, ".." U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING); + strcat(path, filename); + + /* As a fallback, try to guess where the source data was located + * at the time ICU was built, and look there. + */ + strcpy(backupPath, ctest_dataSrcDir()); + strcat(backupPath, U_FILE_SEP_STRING); + strcat(backupPath, "unidata" U_FILE_SEP_STRING); + strcat(backupPath, filename); + + u_parseDelimitedFile(path, ';', fields, fieldCount, lineFn, context, pErrorCode); + if(*pErrorCode==U_FILE_ACCESS_ERROR) { + *pErrorCode=U_ZERO_ERROR; + u_parseDelimitedFile(backupPath, ';', fields, fieldCount, lineFn, context, pErrorCode); + } + if(U_FAILURE(*pErrorCode)) { + log_err("error parsing %s: %s\n", filename, u_errorName(*pErrorCode)); + } +} + +/* test data ---------------------------------------------------------------- */ + +static const UChar LAST_CHAR_CODE_IN_FILE = 0xFFFD; +static const char tagStrings[] = "MnMcMeNdNlNoZsZlZpCcCfCsCoCnLuLlLtLmLoPcPdPsPePoSmScSkSoPiPf"; +static const int32_t tagValues[] = + { + /* Mn */ U_NON_SPACING_MARK, + /* Mc */ U_COMBINING_SPACING_MARK, + /* Me */ U_ENCLOSING_MARK, + /* Nd */ U_DECIMAL_DIGIT_NUMBER, + /* Nl */ U_LETTER_NUMBER, + /* No */ U_OTHER_NUMBER, + /* Zs */ U_SPACE_SEPARATOR, + /* Zl */ U_LINE_SEPARATOR, + /* Zp */ U_PARAGRAPH_SEPARATOR, + /* Cc */ U_CONTROL_CHAR, + /* Cf */ U_FORMAT_CHAR, + /* Cs */ U_SURROGATE, + /* Co */ U_PRIVATE_USE_CHAR, + /* Cn */ U_UNASSIGNED, + /* Lu */ U_UPPERCASE_LETTER, + /* Ll */ U_LOWERCASE_LETTER, + /* Lt */ U_TITLECASE_LETTER, + /* Lm */ U_MODIFIER_LETTER, + /* Lo */ U_OTHER_LETTER, + /* Pc */ U_CONNECTOR_PUNCTUATION, + /* Pd */ U_DASH_PUNCTUATION, + /* Ps */ U_START_PUNCTUATION, + /* Pe */ U_END_PUNCTUATION, + /* Po */ U_OTHER_PUNCTUATION, + /* Sm */ U_MATH_SYMBOL, + /* Sc */ U_CURRENCY_SYMBOL, + /* Sk */ U_MODIFIER_SYMBOL, + /* So */ U_OTHER_SYMBOL, + /* Pi */ U_INITIAL_PUNCTUATION, + /* Pf */ U_FINAL_PUNCTUATION + }; + +static const char dirStrings[][5] = { + "L", + "R", + "EN", + "ES", + "ET", + "AN", + "CS", + "B", + "S", + "WS", + "ON", + "LRE", + "LRO", + "AL", + "RLE", + "RLO", + "PDF", + "NSM", + "BN" +}; + +void addUnicodeTest(TestNode** root); + +void addUnicodeTest(TestNode** root) +{ + addTest(root, &TestUnicodeData, "tsutil/cucdtst/TestUnicodeData"); + addTest(root, &TestCodeUnit, "tsutil/cucdtst/TestCodeUnit"); + addTest(root, &TestCodePoint, "tsutil/cucdtst/TestCodePoint"); + addTest(root, &TestCharLength, "tsutil/cucdtst/TestCharLength"); + addTest(root, &TestAdditionalProperties, "tsutil/cucdtst/TestAdditionalProperties"); + addTest(root, &TestNumericProperties, "tsutil/cucdtst/TestNumericProperties"); + addTest(root, &TestUpperLower, "tsutil/cucdtst/TestUpperLower"); + addTest(root, &TestLetterNumber, "tsutil/cucdtst/TestLetterNumber"); + addTest(root, &TestMisc, "tsutil/cucdtst/TestMisc"); + addTest(root, &TestPOSIX, "tsutil/cucdtst/TestPOSIX"); + addTest(root, &TestControlPrint, "tsutil/cucdtst/TestControlPrint"); + addTest(root, &TestIdentifier, "tsutil/cucdtst/TestIdentifier"); + addTest(root, &TestCharNames, "tsutil/cucdtst/TestCharNames"); + addTest(root, &TestMirroring, "tsutil/cucdtst/TestMirroring"); + addTest(root, &TestUScriptCodeAPI, "tsutil/cucdtst/TestUScriptCodeAPI"); + addTest(root, &TestUScriptRunAPI, "tsutil/cucdtst/TestUScriptRunAPI"); + addTest(root, &TestPropertyNames, "tsutil/cucdtst/TestPropertyNames"); + addTest(root, &TestPropertyValues, "tsutil/cucdtst/TestPropertyValues"); + addTest(root, &TestConsistency, "tsutil/cucdtst/TestConsistency"); + addTest(root, &TestUCase, "tsutil/cucdtst/TestUCase"); + addTest(root, &TestUBiDiProps, "tsutil/cucdtst/TestUBiDiProps"); + addTest(root, &TestCaseFolding, "tsutil/cucdtst/TestCaseFolding"); +} + +/*==================================================== */ +/* test u_toupper() and u_tolower() */ +/*==================================================== */ +static void TestUpperLower() +{ + const UChar upper[] = {0x41, 0x42, 0x00b2, 0x01c4, 0x01c6, 0x01c9, 0x01c8, 0x01c9, 0x000c, 0x0000}; + const UChar lower[] = {0x61, 0x62, 0x00b2, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01c9, 0x000c, 0x0000}; + U_STRING_DECL(upperTest, "abcdefg123hij.?:klmno", 21); + U_STRING_DECL(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21); + int32_t i; + + U_STRING_INIT(upperTest, "abcdefg123hij.?:klmno", 21); + U_STRING_INIT(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21); + +/* +Checks LetterLike Symbols which were previously a source of confusion +[Bertrand A. D. 02/04/98] +*/ + for (i=0x2100;i<0x2138;i++) + { + /* Unicode 5.0 adds lowercase U+214E (TURNED SMALL F) to U+2132 (TURNED CAPITAL F) */ + if(i!=0x2126 && i!=0x212a && i!=0x212b && i!=0x2132) + { + if (i != (int)u_tolower(i)) /* itself */ + log_err("Failed case conversion with itself: U+%04x\n", i); + if (i != (int)u_toupper(i)) + log_err("Failed case conversion with itself: U+%04x\n", i); + } + } + + for(i=0; i < u_strlen(upper); i++){ + if(u_tolower(upper[i]) != lower[i]){ + log_err("FAILED u_tolower() for %lx Expected %lx Got %lx\n", upper[i], lower[i], u_tolower(upper[i])); + } + } + + log_verbose("testing upper lower\n"); + for (i = 0; i < 21; i++) { + + if (u_isalpha(upperTest[i]) && !u_islower(upperTest[i])) + { + log_err("Failed isLowerCase test at %c\n", upperTest[i]); + } + else if (u_isalpha(lowerTest[i]) && !u_isupper(lowerTest[i])) + { + log_err("Failed isUpperCase test at %c\n", lowerTest[i]); + } + else if (upperTest[i] != u_tolower(lowerTest[i])) + { + log_err("Failed case conversion from %c To %c :\n", lowerTest[i], upperTest[i]); + } + else if (lowerTest[i] != u_toupper(upperTest[i])) + { + log_err("Failed case conversion : %c To %c \n", upperTest[i], lowerTest[i]); + } + else if (upperTest[i] != u_tolower(upperTest[i])) + { + log_err("Failed case conversion with itself: %c\n", upperTest[i]); + } + else if (lowerTest[i] != u_toupper(lowerTest[i])) + { + log_err("Failed case conversion with itself: %c\n", lowerTest[i]); + } + } + log_verbose("done testing upper lower\n"); + + log_verbose("testing u_istitle\n"); + { + static const UChar expected[] = { + 0x1F88, + 0x1F89, + 0x1F8A, + 0x1F8B, + 0x1F8C, + 0x1F8D, + 0x1F8E, + 0x1F8F, + 0x1F88, + 0x1F89, + 0x1F8A, + 0x1F8B, + 0x1F8C, + 0x1F8D, + 0x1F8E, + 0x1F8F, + 0x1F98, + 0x1F99, + 0x1F9A, + 0x1F9B, + 0x1F9C, + 0x1F9D, + 0x1F9E, + 0x1F9F, + 0x1F98, + 0x1F99, + 0x1F9A, + 0x1F9B, + 0x1F9C, + 0x1F9D, + 0x1F9E, + 0x1F9F, + 0x1FA8, + 0x1FA9, + 0x1FAA, + 0x1FAB, + 0x1FAC, + 0x1FAD, + 0x1FAE, + 0x1FAF, + 0x1FA8, + 0x1FA9, + 0x1FAA, + 0x1FAB, + 0x1FAC, + 0x1FAD, + 0x1FAE, + 0x1FAF, + 0x1FBC, + 0x1FBC, + 0x1FCC, + 0x1FCC, + 0x1FFC, + 0x1FFC, + }; + int32_t num = sizeof(expected)/sizeof(expected[0]); + for(i=0; i<num; i++){ + if(!u_istitle(expected[i])){ + log_err("u_istitle failed for 0x%4X. Expected TRUE, got FALSE\n",expected[i]); + } + } + + } +} + +/* compare two sets and verify that their difference or intersection is empty */ +static UBool +showADiffB(const USet *a, const USet *b, + const char *a_name, const char *b_name, + UBool expect, UBool diffIsError) { + USet *aa; + int32_t i, start, end, length; + UErrorCode errorCode; + + /* + * expect: + * TRUE -> a-b should be empty, that is, b should contain all of a + * FALSE -> a&b should be empty, that is, a should contain none of b (and vice versa) + */ + if(expect ? uset_containsAll(b, a) : uset_containsNone(a, b)) { + return TRUE; + } + + /* clone a to aa because a is const */ + aa=uset_open(1, 0); + if(aa==NULL) { + /* unusual problem - out of memory? */ + return FALSE; + } + uset_addAll(aa, a); + + /* compute the set in question */ + if(expect) { + /* a-b */ + uset_removeAll(aa, b); + } else { + /* a&b */ + uset_retainAll(aa, b); + } + + /* aa is not empty because of the initial tests above; show its contents */ + errorCode=U_ZERO_ERROR; + i=0; + for(;;) { + length=uset_getItem(aa, i, &start, &end, NULL, 0, &errorCode); + if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) { + break; /* done */ + } + if(U_FAILURE(errorCode)) { + log_err("error comparing %s with %s at difference item %d: %s\n", + a_name, b_name, i, u_errorName(errorCode)); + break; + } + if(length!=0) { + break; /* done with code points, got a string or -1 */ + } + + if(diffIsError) { + if(expect) { + log_err("error: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name); + } else { + log_err("error: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end); + } + } else { + if(expect) { + log_verbose("info: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name); + } else { + log_verbose("info: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end); + } + } + + ++i; + } + + uset_close(aa); + return FALSE; +} + +static UBool +showAMinusB(const USet *a, const USet *b, + const char *a_name, const char *b_name, + UBool diffIsError) { + return showADiffB(a, b, a_name, b_name, TRUE, diffIsError); +} + +static UBool +showAIntersectB(const USet *a, const USet *b, + const char *a_name, const char *b_name, + UBool diffIsError) { + return showADiffB(a, b, a_name, b_name, FALSE, diffIsError); +} + +static UBool +compareUSets(const USet *a, const USet *b, + const char *a_name, const char *b_name, + UBool diffIsError) { + /* + * Use an arithmetic & not a logical && so that both branches + * are always taken and all differences are shown. + */ + return + showAMinusB(a, b, a_name, b_name, diffIsError) & + showAMinusB(b, a, b_name, a_name, diffIsError); +} + +/* test isLetter(u_isapha()) and isDigit(u_isdigit()) */ +static void TestLetterNumber() +{ + UChar i = 0x0000; + + log_verbose("Testing for isalpha\n"); + for (i = 0x0041; i < 0x005B; i++) { + if (!u_isalpha(i)) + { + log_err("Failed isLetter test at %.4X\n", i); + } + } + for (i = 0x0660; i < 0x066A; i++) { + if (u_isalpha(i)) + { + log_err("Failed isLetter test with numbers at %.4X\n", i); + } + } + + log_verbose("Testing for isdigit\n"); + for (i = 0x0660; i < 0x066A; i++) { + if (!u_isdigit(i)) + { + log_verbose("Failed isNumber test at %.4X\n", i); + } + } + + log_verbose("Testing for isalnum\n"); + for (i = 0x0041; i < 0x005B; i++) { + if (!u_isalnum(i)) + { + log_err("Failed isAlNum test at %.4X\n", i); + } + } + for (i = 0x0660; i < 0x066A; i++) { + if (!u_isalnum(i)) + { + log_err("Failed isAlNum test at %.4X\n", i); + } + } + + { + /* + * The following checks work only starting from Unicode 4.0. + * Check the version number here. + */ + static UVersionInfo u401={ 4, 0, 1, 0 }; + UVersionInfo version; + u_getUnicodeVersion(version); + if(version[0]<4 || 0==memcmp(version, u401, 4)) { + return; + } + } + + { + /* + * Sanity check: + * Verify that exactly the digit characters have decimal digit values. + * This assumption is used in the implementation of u_digit() + * (which checks nt=de) + * compared with the parallel java.lang.Character.digit() + * (which checks Nd). + * + * This was not true in Unicode 3.2 and earlier. + * Unicode 4.0 fixed discrepancies. + * Unicode 4.0.1 re-introduced problems in this area due to an + * unintentionally incomplete last-minute change. + */ + U_STRING_DECL(digitsPattern, "[:Nd:]", 6); + U_STRING_DECL(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24); + + USet *digits, *decimalValues; + UErrorCode errorCode; + + U_STRING_INIT(digitsPattern, "[:Nd:]", 6); + U_STRING_INIT(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24); + errorCode=U_ZERO_ERROR; + digits=uset_openPattern(digitsPattern, 6, &errorCode); + decimalValues=uset_openPattern(decimalValuesPattern, 24, &errorCode); + + if(U_SUCCESS(errorCode)) { + compareUSets(digits, decimalValues, "[:Nd:]", "[:Numeric_Type=Decimal:]", TRUE); + } + + uset_close(digits); + uset_close(decimalValues); + } +} + +/* Tests for isDefined(u_isdefined)(, isBaseForm(u_isbase()), isSpaceChar(u_isspace()), isWhiteSpace(), u_CharDigitValue() */ +static void TestMisc() +{ + static const UChar sampleSpaces[] = {0x0020, 0x00a0, 0x2000, 0x2001, 0x2005}; + static const UChar sampleNonSpaces[] = {0x61, 0x62, 0x63, 0x64, 0x74}; + static const UChar sampleUndefined[] = {0xfff1, 0xfff7, 0xfa6b }; + static const UChar sampleDefined[] = {0x523E, 0x4f88, 0xfffd}; + static const UChar sampleBase[] = {0x0061, 0x0031, 0x03d2}; + static const UChar sampleNonBase[] = {0x002B, 0x0020, 0x203B}; +/* static const UChar sampleChars[] = {0x000a, 0x0045, 0x4e00, 0xDC00, 0xFFE8, 0xFFF0};*/ + static const UChar sampleDigits[]= {0x0030, 0x0662, 0x0F23, 0x0ED5}; + static const UChar sampleNonDigits[] = {0x0010, 0x0041, 0x0122, 0x68FE}; + static const UChar sampleWhiteSpaces[] = {0x2008, 0x2009, 0x200a, 0x001c, 0x000c}; + static const UChar sampleNonWhiteSpaces[] = {0x61, 0x62, 0x3c, 0x28, 0x3f}; + + + static const int32_t sampleDigitValues[] = {0, 2, 3, 5}; + + uint32_t mask; + + int32_t i; + char icuVersion[U_MAX_VERSION_STRING_LENGTH]; + UVersionInfo realVersion; + + memset(icuVersion, 0, U_MAX_VERSION_STRING_LENGTH); + + log_verbose("Testing for isspace and nonspaces\n"); + for (i = 0; i < 5; i++) { + if (!(u_isspace(sampleSpaces[i])) || + (u_isspace(sampleNonSpaces[i]))) + { + log_err("Space char test error : %d or %d \n", (int32_t)sampleSpaces[i], (int32_t)sampleNonSpaces[i]); + } + if (!(u_isJavaSpaceChar(sampleSpaces[i])) || + (u_isJavaSpaceChar(sampleNonSpaces[i]))) + { + log_err("u_isJavaSpaceChar() test error : %d or %d \n", (int32_t)sampleSpaces[i], (int32_t)sampleNonSpaces[i]); + } + } + + log_verbose("Testing for isspace and nonspaces\n"); + for (i = 0; i < 5; i++) { + if (!(u_isWhitespace(sampleWhiteSpaces[i])) || + (u_isWhitespace(sampleNonWhiteSpaces[i]))) + { + log_err("White Space char test error : %lx or %lx \n", sampleWhiteSpaces[i], sampleNonWhiteSpaces[i]); + } + } + + log_verbose("Testing for isdefined\n"); + for (i = 0; i < 3; i++) { + if ((u_isdefined(sampleUndefined[i])) || + !(u_isdefined(sampleDefined[i]))) + { + log_err("Undefined char test error : U+%04x or U+%04x\n", (int32_t)sampleUndefined[i], (int32_t)sampleDefined[i]); + } + } + + log_verbose("Testing for isbase\n"); + for (i = 0; i < 3; i++) { + if ((u_isbase(sampleNonBase[i])) || + !(u_isbase(sampleBase[i]))) + { + log_err("Non-baseform char test error : U+%04x or U+%04x",(int32_t)sampleNonBase[i], (int32_t)sampleBase[i]); + } + } + + log_verbose("Testing for isdigit \n"); + for (i = 0; i < 4; i++) { + if ((u_isdigit(sampleDigits[i]) && + (u_charDigitValue(sampleDigits[i])!= sampleDigitValues[i])) || + (u_isdigit(sampleNonDigits[i]))) { + log_err("Digit char test error : %lx or %lx\n", sampleDigits[i], sampleNonDigits[i]); + } + } + + /* Tests the ICU version #*/ + u_getVersion(realVersion); + u_versionToString(realVersion, icuVersion); + if (strncmp(icuVersion, U_ICU_VERSION, uprv_min((int32_t)strlen(icuVersion), (int32_t)strlen(U_ICU_VERSION))) != 0) + { + log_err("ICU version test failed. Header says=%s, got=%s \n", U_ICU_VERSION, icuVersion); + } +#if defined(ICU_VERSION) + /* test only happens where we have configure.in with VERSION - sanity check. */ + if(strcmp(U_ICU_VERSION, ICU_VERSION)) + { + log_err("ICU version mismatch: Header says %s, build environment says %s.\n", U_ICU_VERSION, ICU_VERSION); + } +#endif + + /* test U_GC_... */ + if( + U_GET_GC_MASK(0x41)!=U_GC_LU_MASK || + U_GET_GC_MASK(0x662)!=U_GC_ND_MASK || + U_GET_GC_MASK(0xa0)!=U_GC_ZS_MASK || + U_GET_GC_MASK(0x28)!=U_GC_PS_MASK || + U_GET_GC_MASK(0x2044)!=U_GC_SM_MASK || + U_GET_GC_MASK(0xe0063)!=U_GC_CF_MASK + ) { + log_err("error: U_GET_GC_MASK does not work properly\n"); + } + + mask=0; + mask=(mask&~U_GC_CN_MASK)|U_GC_CN_MASK; + + mask=(mask&~U_GC_LU_MASK)|U_GC_LU_MASK; + mask=(mask&~U_GC_LL_MASK)|U_GC_LL_MASK; + mask=(mask&~U_GC_LT_MASK)|U_GC_LT_MASK; + mask=(mask&~U_GC_LM_MASK)|U_GC_LM_MASK; + mask=(mask&~U_GC_LO_MASK)|U_GC_LO_MASK; + + mask=(mask&~U_GC_MN_MASK)|U_GC_MN_MASK; + mask=(mask&~U_GC_ME_MASK)|U_GC_ME_MASK; + mask=(mask&~U_GC_MC_MASK)|U_GC_MC_MASK; + + mask=(mask&~U_GC_ND_MASK)|U_GC_ND_MASK; + mask=(mask&~U_GC_NL_MASK)|U_GC_NL_MASK; + mask=(mask&~U_GC_NO_MASK)|U_GC_NO_MASK; + + mask=(mask&~U_GC_ZS_MASK)|U_GC_ZS_MASK; + mask=(mask&~U_GC_ZL_MASK)|U_GC_ZL_MASK; + mask=(mask&~U_GC_ZP_MASK)|U_GC_ZP_MASK; + + mask=(mask&~U_GC_CC_MASK)|U_GC_CC_MASK; + mask=(mask&~U_GC_CF_MASK)|U_GC_CF_MASK; + mask=(mask&~U_GC_CO_MASK)|U_GC_CO_MASK; + mask=(mask&~U_GC_CS_MASK)|U_GC_CS_MASK; + + mask=(mask&~U_GC_PD_MASK)|U_GC_PD_MASK; + mask=(mask&~U_GC_PS_MASK)|U_GC_PS_MASK; + mask=(mask&~U_GC_PE_MASK)|U_GC_PE_MASK; + mask=(mask&~U_GC_PC_MASK)|U_GC_PC_MASK; + mask=(mask&~U_GC_PO_MASK)|U_GC_PO_MASK; + + mask=(mask&~U_GC_SM_MASK)|U_GC_SM_MASK; + mask=(mask&~U_GC_SC_MASK)|U_GC_SC_MASK; + mask=(mask&~U_GC_SK_MASK)|U_GC_SK_MASK; + mask=(mask&~U_GC_SO_MASK)|U_GC_SO_MASK; + + mask=(mask&~U_GC_PI_MASK)|U_GC_PI_MASK; + mask=(mask&~U_GC_PF_MASK)|U_GC_PF_MASK; + + if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) { + log_err("error: problems with U_GC_XX_MASK constants\n"); + } + + mask=0; + mask=(mask&~U_GC_C_MASK)|U_GC_C_MASK; + mask=(mask&~U_GC_L_MASK)|U_GC_L_MASK; + mask=(mask&~U_GC_M_MASK)|U_GC_M_MASK; + mask=(mask&~U_GC_N_MASK)|U_GC_N_MASK; + mask=(mask&~U_GC_Z_MASK)|U_GC_Z_MASK; + mask=(mask&~U_GC_P_MASK)|U_GC_P_MASK; + mask=(mask&~U_GC_S_MASK)|U_GC_S_MASK; + + if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) { + log_err("error: problems with U_GC_Y_MASK constants\n"); + } + { + static const UChar32 digit[10]={ 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039 }; + for(i=0; i<10; i++){ + if(digit[i]!=u_forDigit(i,10)){ + log_err("u_forDigit failed for %i. Expected: 0x%4X Got: 0x%4X\n",i,digit[i],u_forDigit(i,10)); + } + } + } + + /* test u_digit() */ + { + static const struct { + UChar32 c; + int8_t radix, value; + } data[]={ + /* base 16 */ + { 0x0031, 16, 1 }, + { 0x0038, 16, 8 }, + { 0x0043, 16, 12 }, + { 0x0066, 16, 15 }, + { 0x00e4, 16, -1 }, + { 0x0662, 16, 2 }, + { 0x06f5, 16, 5 }, + { 0xff13, 16, 3 }, + { 0xff41, 16, 10 }, + + /* base 8 */ + { 0x0031, 8, 1 }, + { 0x0038, 8, -1 }, + { 0x0043, 8, -1 }, + { 0x0066, 8, -1 }, + { 0x00e4, 8, -1 }, + { 0x0662, 8, 2 }, + { 0x06f5, 8, 5 }, + { 0xff13, 8, 3 }, + { 0xff41, 8, -1 }, + + /* base 36 */ + { 0x5a, 36, 35 }, + { 0x7a, 36, 35 }, + { 0xff3a, 36, 35 }, + { 0xff5a, 36, 35 }, + + /* wrong radix values */ + { 0x0031, 1, -1 }, + { 0xff3a, 37, -1 } + }; + + for(i=0; i<LENGTHOF(data); ++i) { + if(u_digit(data[i].c, data[i].radix)!=data[i].value) { + log_err("u_digit(U+%04x, %d)=%d expected %d\n", + data[i].c, + data[i].radix, + u_digit(data[i].c, data[i].radix), + data[i].value); + } + } + } +} + +/* test C/POSIX-style functions --------------------------------------------- */ + +/* bit flags */ +#define ISAL 1 +#define ISLO 2 +#define ISUP 4 + +#define ISDI 8 +#define ISXD 0x10 + +#define ISAN 0x20 + +#define ISPU 0x40 +#define ISGR 0x80 +#define ISPR 0x100 + +#define ISSP 0x200 +#define ISBL 0x400 +#define ISCN 0x800 + +/* C/POSIX-style functions, in the same order as the bit flags */ +typedef UBool U_EXPORT2 IsPOSIXClass(UChar32 c); + +static const struct { + IsPOSIXClass *fn; + const char *name; +} posixClasses[]={ + { u_isalpha, "isalpha" }, + { u_islower, "islower" }, + { u_isupper, "isupper" }, + { u_isdigit, "isdigit" }, + { u_isxdigit, "isxdigit" }, + { u_isalnum, "isalnum" }, + { u_ispunct, "ispunct" }, + { u_isgraph, "isgraph" }, + { u_isprint, "isprint" }, + { u_isspace, "isspace" }, + { u_isblank, "isblank" }, + { u_iscntrl, "iscntrl" } +}; + +static const struct { + UChar32 c; + uint32_t posixResults; +} posixData[]={ + { 0x0008, ISCN }, /* backspace */ + { 0x0009, ISSP|ISBL|ISCN }, /* TAB */ + { 0x000a, ISSP| ISCN }, /* LF */ + { 0x000c, ISSP| ISCN }, /* FF */ + { 0x000d, ISSP| ISCN }, /* CR */ + { 0x0020, ISPR|ISSP|ISBL }, /* space */ + { 0x0021, ISPU|ISGR|ISPR }, /* ! */ + { 0x0033, ISDI|ISXD|ISAN| ISGR|ISPR }, /* 3 */ + { 0x0040, ISPU|ISGR|ISPR }, /* @ */ + { 0x0041, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* A */ + { 0x007a, ISAL|ISLO| ISAN| ISGR|ISPR }, /* z */ + { 0x007b, ISPU|ISGR|ISPR }, /* { */ + { 0x0085, ISSP| ISCN }, /* NEL */ + { 0x00a0, ISPR|ISSP|ISBL }, /* NBSP */ + { 0x00a4, ISGR|ISPR }, /* currency sign */ + { 0x00e4, ISAL|ISLO| ISAN| ISGR|ISPR }, /* a-umlaut */ + { 0x0300, ISGR|ISPR }, /* combining grave */ + { 0x0600, ISCN }, /* arabic number sign */ + { 0x0627, ISAL| ISAN| ISGR|ISPR }, /* alef */ + { 0x0663, ISDI|ISXD|ISAN| ISGR|ISPR }, /* arabic 3 */ + { 0x2002, ISPR|ISSP|ISBL }, /* en space */ + { 0x2007, ISPR|ISSP|ISBL }, /* figure space */ + { 0x2009, ISPR|ISSP|ISBL }, /* thin space */ + { 0x200b, ISCN }, /* ZWSP */ + /*{ 0x200b, ISPR|ISSP },*/ /* ZWSP */ /* ZWSP became a control char in 4.0.1*/ + { 0x200e, ISCN }, /* LRM */ + { 0x2028, ISPR|ISSP| ISCN }, /* LS */ + { 0x2029, ISPR|ISSP| ISCN }, /* PS */ + { 0x20ac, ISGR|ISPR }, /* Euro */ + { 0xff15, ISDI|ISXD|ISAN| ISGR|ISPR }, /* fullwidth 5 */ + { 0xff25, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* fullwidth E */ + { 0xff35, ISAL| ISUP| ISAN| ISGR|ISPR }, /* fullwidth U */ + { 0xff45, ISAL|ISLO| ISXD|ISAN| ISGR|ISPR }, /* fullwidth e */ + { 0xff55, ISAL|ISLO| ISAN| ISGR|ISPR } /* fullwidth u */ +}; + +static void +TestPOSIX() { + uint32_t mask; + int32_t cl, i; + UBool expect; + + mask=1; + for(cl=0; cl<12; ++cl) { + for(i=0; i<LENGTHOF(posixData); ++i) { + expect=(UBool)((posixData[i].posixResults&mask)!=0); + if(posixClasses[cl].fn(posixData[i].c)!=expect) { + log_err("u_%s(U+%04x)=%s is wrong\n", + posixClasses[cl].name, posixData[i].c, expect ? "FALSE" : "TRUE"); + } + } + mask<<=1; + } +} + +/* Tests for isControl(u_iscntrl()) and isPrintable(u_isprint()) */ +static void TestControlPrint() +{ + const UChar sampleControl[] = {0x1b, 0x97, 0x82, 0x2028, 0x2029, 0x200c, 0x202b}; + const UChar sampleNonControl[] = {0x61, 0x0031, 0x00e2}; + const UChar samplePrintable[] = {0x0042, 0x005f, 0x2014}; + const UChar sampleNonPrintable[] = {0x200c, 0x009f, 0x001b}; + UChar32 c; + int i; + + log_verbose("Testing for iscontrol\n"); + for (i = 0; i < LENGTHOF(sampleControl); i++) { + if (!u_iscntrl(sampleControl[i])) + { + log_err("Control char test error : U+%04x should be control but is not\n", (int32_t)sampleControl[i]); + } + } + + log_verbose("Testing for !iscontrol\n"); + for (i = 0; i < LENGTHOF(sampleNonControl); i++) { + if (u_iscntrl(sampleNonControl[i])) + { + log_err("Control char test error : U+%04x should not be control but is\n", (int32_t)sampleNonControl[i]); + } + } + + log_verbose("testing for isprintable\n"); + for (i = 0; i < 3; i++) { + if (!u_isprint(samplePrintable[i])) + { + log_err("Printable char test error : U+%04x should be printable but is not\n", (int32_t)samplePrintable[i]); + } + if (u_isprint(sampleNonPrintable[i])) + { + log_err("Printable char test error : U+%04x should not be printable but is\n", (int32_t)sampleNonPrintable[i]); + } + } + + /* test all ISO 8 controls */ + for(c=0; c<=0x9f; ++c) { + if(c==0x20) { + /* skip ASCII graphic characters and continue with DEL */ + c=0x7f; + } + if(!u_iscntrl(c)) { + log_err("error: u_iscntrl(ISO 8 control U+%04x)=FALSE\n", c); + } + if(!u_isISOControl(c)) { + log_err("error: u_isISOControl(ISO 8 control U+%04x)=FALSE\n", c); + } + if(u_isprint(c)) { + log_err("error: u_isprint(ISO 8 control U+%04x)=TRUE\n", c); + } + } + + /* test all Latin-1 graphic characters */ + for(c=0x20; c<=0xff; ++c) { + if(c==0x7f) { + c=0xa0; + } else if(c==0xad) { + /* Unicode 4 changes 00AD Soft Hyphen to Cf (and it is in fact not printable) */ + ++c; + } + if(!u_isprint(c)) { + log_err("error: u_isprint(Latin-1 graphic character U+%04x)=FALSE\n", c); + } + } +} + +/* u_isJavaIDStart, u_isJavaIDPart, u_isIDStart(), u_isIDPart(), u_isIDIgnorable()*/ +static void TestIdentifier() +{ + const UChar sampleJavaIDStart[] = {0x0071, 0x00e4, 0x005f}; + const UChar sampleNonJavaIDStart[] = {0x0020, 0x2030, 0x0082}; + const UChar sampleJavaIDPart[] = {0x005f, 0x0032, 0x0045}; + const UChar sampleNonJavaIDPart[] = {0x2030, 0x2020, 0x0020}; + const UChar sampleUnicodeIDStart[] = {0x0250, 0x00e2, 0x0061}; + const UChar sampleNonUnicodeIDStart[] = {0x2000, 0x000a, 0x2019}; + const UChar sampleUnicodeIDPart[] = {0x005f, 0x0032, 0x0045}; + const UChar sampleNonUnicodeIDPart[] = {0x2030, 0x00a3, 0x0020}; + const UChar sampleIDIgnore[] = {0x0006, 0x0010, 0x206b}; + const UChar sampleNonIDIgnore[] = {0x0075, 0x00a3, 0x0061}; + + int i; + + log_verbose("Testing sampleJavaID start \n"); + for (i = 0; i < 3; i++) { + if (!(u_isJavaIDStart(sampleJavaIDStart[i])) || + (u_isJavaIDStart(sampleNonJavaIDStart[i]))) + log_err("Java ID Start char test error : %lx or %lx\n", + sampleJavaIDStart[i], sampleNonJavaIDStart[i]); + } + + log_verbose("Testing sampleJavaID part \n"); + for (i = 0; i < 3; i++) { + if (!(u_isJavaIDPart(sampleJavaIDPart[i])) || + (u_isJavaIDPart(sampleNonJavaIDPart[i]))) + log_err("Java ID Part char test error : %lx or %lx\n", + sampleJavaIDPart[i], sampleNonJavaIDPart[i]); + } + + log_verbose("Testing sampleUnicodeID start \n"); + for (i = 0; i < 3; i++) { + /* T_test_logln_ustr((int32_t)i); */ + if (!(u_isIDStart(sampleUnicodeIDStart[i])) || + (u_isIDStart(sampleNonUnicodeIDStart[i]))) + { + log_err("Unicode ID Start char test error : %lx or %lx\n", sampleUnicodeIDStart[i], + sampleNonUnicodeIDStart[i]); + } + } + + log_verbose("Testing sample unicode ID part \n"); + for (i = 2; i < 3; i++) { /* nos *** starts with 2 instead of 0, until clarified */ + /* T_test_logln_ustr((int32_t)i); */ + if (!(u_isIDPart(sampleUnicodeIDPart[i])) || + (u_isIDPart(sampleNonUnicodeIDPart[i]))) + { + log_err("Unicode ID Part char test error : %lx or %lx", sampleUnicodeIDPart[i], sampleNonUnicodeIDPart[i]); + } + } + + log_verbose("Testing sampleId ignore\n"); + for (i = 0; i < 3; i++) { + /*T_test_logln_ustr((int32_t)i); */ + if (!(u_isIDIgnorable(sampleIDIgnore[i])) || + (u_isIDIgnorable(sampleNonIDIgnore[i]))) + { + log_err("ID ignorable char test error : U+%04x or U+%04x\n", sampleIDIgnore[i], sampleNonIDIgnore[i]); + } + } +} + +/* for each line of UnicodeData.txt, check some of the properties */ +/* + * ### TODO + * This test fails incorrectly if the First or Last code point of a repetitive area + * is overridden, which is allowed and is encouraged for the PUAs. + * Currently, this means that both area First/Last and override lines are + * tested against the properties from the API, + * and the area boundary will not match and cause an error. + * + * This function should detect area boundaries and skip them for the test of individual + * code points' properties. + * Then it should check that the areas contain all the same properties except where overridden. + * For this, it would have had to set a flag for which code points were listed explicitly. + */ +static void U_CALLCONV +unicodeDataLineFn(void *context, + char *fields[][2], int32_t fieldCount, + UErrorCode *pErrorCode) +{ + char buffer[100]; + char *end; + uint32_t value; + UChar32 c; + int32_t i; + int8_t type; + + /* get the character code, field 0 */ + c=strtoul(fields[0][0], &end, 16); + if(end<=fields[0][0] || end!=fields[0][1]) { + log_err("error: syntax error in field 0 at %s\n", fields[0][0]); + return; + } + if((uint32_t)c>=UCHAR_MAX_VALUE + 1) { + log_err("error in UnicodeData.txt: code point %lu out of range\n", c); + return; + } + + /* get general category, field 2 */ + *fields[2][1]=0; + type = (int8_t)tagValues[MakeProp(fields[2][0])]; + if(u_charType(c)!=type) { + log_err("error: u_charType(U+%04lx)==%u instead of %u\n", c, u_charType(c), type); + } + if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) { + log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c); + } + + /* get canonical combining class, field 3 */ + value=strtoul(fields[3][0], &end, 10); + if(end<=fields[3][0] || end!=fields[3][1]) { + log_err("error: syntax error in field 3 at code 0x%lx\n", c); + return; + } + if(value>255) { + log_err("error in UnicodeData.txt: combining class %lu out of range\n", value); + return; + } +#if !UCONFIG_NO_NORMALIZATION + if(value!=u_getCombiningClass(c) || value!=(uint32_t)u_getIntPropertyValue(c, UCHAR_CANONICAL_COMBINING_CLASS)) { + log_err("error: u_getCombiningClass(U+%04lx)==%hu instead of %lu\n", c, u_getCombiningClass(c), value); + } +#endif + + /* get BiDi category, field 4 */ + *fields[4][1]=0; + i=MakeDir(fields[4][0]); + if(i!=u_charDirection(c) || i!=u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)) { + log_err("error: u_charDirection(U+%04lx)==%u instead of %u (%s)\n", c, u_charDirection(c), MakeDir(fields[4][0]), fields[4][0]); + } + + /* get ISO Comment, field 11 */ + *fields[11][1]=0; + i=u_getISOComment(c, buffer, sizeof(buffer), pErrorCode); + if(U_FAILURE(*pErrorCode) || 0!=strcmp(fields[11][0], buffer)) { + log_err("error: u_getISOComment(U+%04lx) wrong (%s): \"%s\" should be \"%s\"\n", + c, u_errorName(*pErrorCode), + U_FAILURE(*pErrorCode) ? buffer : "[error]", + fields[11][0]); + } + + /* get uppercase mapping, field 12 */ + if(fields[12][0]!=fields[12][1]) { + value=strtoul(fields[12][0], &end, 16); + if(end!=fields[12][1]) { + log_err("error: syntax error in field 12 at code 0x%lx\n", c); + return; + } + if((UChar32)value!=u_toupper(c)) { + log_err("error: u_toupper(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_toupper(c), value); + } + } else { + /* no case mapping: the API must map the code point to itself */ + if(c!=u_toupper(c)) { + log_err("error: U+%04lx does not have an uppercase mapping but u_toupper()==U+%04lx\n", c, u_toupper(c)); + } + } + + /* get lowercase mapping, field 13 */ + if(fields[13][0]!=fields[13][1]) { + value=strtoul(fields[13][0], &end, 16); + if(end!=fields[13][1]) { + log_err("error: syntax error in field 13 at code 0x%lx\n", c); + return; + } + if((UChar32)value!=u_tolower(c)) { + log_err("error: u_tolower(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_tolower(c), value); + } + } else { + /* no case mapping: the API must map the code point to itself */ + if(c!=u_tolower(c)) { + log_err("error: U+%04lx does not have a lowercase mapping but u_tolower()==U+%04lx\n", c, u_tolower(c)); + } + } + + /* get titlecase mapping, field 14 */ + if(fields[14][0]!=fields[14][1]) { + value=strtoul(fields[14][0], &end, 16); + if(end!=fields[14][1]) { + log_err("error: syntax error in field 14 at code 0x%lx\n", c); + return; + } + if((UChar32)value!=u_totitle(c)) { + log_err("error: u_totitle(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_totitle(c), value); + } + } else { + /* no case mapping: the API must map the code point to itself */ + if(c!=u_totitle(c)) { + log_err("error: U+%04lx does not have a titlecase mapping but u_totitle()==U+%04lx\n", c, u_totitle(c)); + } + } +} + +static UBool U_CALLCONV +enumTypeRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) { + static const UChar32 test[][2]={ + {0x41, U_UPPERCASE_LETTER}, + {0x308, U_NON_SPACING_MARK}, + {0xfffe, U_GENERAL_OTHER_TYPES}, + {0xe0041, U_FORMAT_CHAR}, + {0xeffff, U_UNASSIGNED} + }; + + int32_t i, count; + + if(0!=strcmp((const char *)context, "a1")) { + log_err("error: u_enumCharTypes() passes on an incorrect context pointer\n"); + return FALSE; + } + + count=LENGTHOF(test); + for(i=0; i<count; ++i) { + if(start<=test[i][0] && test[i][0]<limit) { + if(type!=(UCharCategory)test[i][1]) { + log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld instead of U+%04lx with %ld\n", + start, limit, (long)type, test[i][0], test[i][1]); + } + /* stop at the range that includes the last test code point (increases code coverage for enumeration) */ + return i==(count-1) ? FALSE : TRUE; + } + } + + if(start>test[count-1][0]) { + log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld after it should have stopped\n", + start, limit, (long)type); + return FALSE; + } + + return TRUE; +} + +static UBool U_CALLCONV +enumDefaultsRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) { + /* default Bidi classes for unassigned code points */ + static const int32_t defaultBidi[][2]={ /* { limit, class } */ + { 0x0590, U_LEFT_TO_RIGHT }, + { 0x0600, U_RIGHT_TO_LEFT }, + { 0x07C0, U_RIGHT_TO_LEFT_ARABIC }, + { 0x0900, U_RIGHT_TO_LEFT }, + { 0xFB1D, U_LEFT_TO_RIGHT }, + { 0xFB50, U_RIGHT_TO_LEFT }, + { 0xFE00, U_RIGHT_TO_LEFT_ARABIC }, + { 0xFE70, U_LEFT_TO_RIGHT }, + { 0xFF00, U_RIGHT_TO_LEFT_ARABIC }, + { 0x10800, U_LEFT_TO_RIGHT }, + { 0x11000, U_RIGHT_TO_LEFT }, + { 0x110000, U_LEFT_TO_RIGHT } + }; + + UChar32 c; + int32_t i; + UCharDirection shouldBeDir; + + /* + * LineBreak.txt specifies: + * # - Assigned characters that are not listed explicitly are given the value + * # "AL". + * # - Unassigned characters are given the value "XX". + * + * PUA characters are listed explicitly with "XX". + * Verify that no assigned character has "XX". + */ + if(type!=U_UNASSIGNED && type!=U_PRIVATE_USE_CHAR) { + c=start; + while(c<limit) { + if(0==u_getIntPropertyValue(c, UCHAR_LINE_BREAK)) { + log_err("error UCHAR_LINE_BREAK(assigned U+%04lx)=XX\n", c); + } + ++c; + } + } + + /* + * Verify default Bidi classes. + * For recent Unicode versions, see UCD.html. + * + * For older Unicode versions: + * See table 3-7 "Bidirectional Character Types" in UAX #9. + * http://www.unicode.org/reports/tr9/ + * + * See also DerivedBidiClass.txt for Cn code points! + * + * Unicode 4.0.1/Public Review Issue #28 (http://www.unicode.org/review/resolved-pri.html) + * changed some default values. + * In particular, non-characters and unassigned Default Ignorable Code Points + * change from L to BN. + * + * UCD.html version 4.0.1 does not yet reflect these changes. + */ + if(type==U_UNASSIGNED || type==U_PRIVATE_USE_CHAR) { + /* enumerate the intersections of defaultBidi ranges with [start..limit[ */ + c=start; + for(i=0; i<LENGTHOF(defaultBidi) && c<limit; ++i) { + if((int32_t)c<defaultBidi[i][0]) { + while(c<limit && (int32_t)c<defaultBidi[i][0]) { + if(U_IS_UNICODE_NONCHAR(c) || u_hasBinaryProperty(c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT)) { + shouldBeDir=U_BOUNDARY_NEUTRAL; + } else { + shouldBeDir=(UCharDirection)defaultBidi[i][1]; + } + + if( u_charDirection(c)!=shouldBeDir || + u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)!=shouldBeDir + ) { + log_err("error: u_charDirection(unassigned/PUA U+%04lx)=%s should be %s\n", + c, dirStrings[u_charDirection(c)], dirStrings[shouldBeDir]); + } + ++c; + } + } + } + } + + return TRUE; +} + +/* tests for several properties */ +static void TestUnicodeData() +{ + UVersionInfo expectVersionArray; + UVersionInfo versionArray; + char *fields[15][2]; + UErrorCode errorCode; + UChar32 c; + int8_t type; + + u_versionFromString(expectVersionArray, U_UNICODE_VERSION); + u_getUnicodeVersion(versionArray); + if(memcmp(versionArray, expectVersionArray, U_MAX_VERSION_LENGTH) != 0) + { + log_err("Testing u_getUnicodeVersion() - expected " U_UNICODE_VERSION " got %d.%d.%d.%d\n", + versionArray[0], versionArray[1], versionArray[2], versionArray[3]); + } + +#if defined(ICU_UNICODE_VERSION) + /* test only happens where we have configure.in with UNICODE_VERSION - sanity check. */ + if(strcmp(U_UNICODE_VERSION, ICU_UNICODE_VERSION)) + { + log_err("Testing configure.in's ICU_UNICODE_VERSION - expected " U_UNICODE_VERSION " got " ICU_UNICODE_VERSION "\n"); + } +#endif + + if (ublock_getCode((UChar)0x0041) != UBLOCK_BASIC_LATIN || u_getIntPropertyValue(0x41, UCHAR_BLOCK)!=(int32_t)UBLOCK_BASIC_LATIN) { + log_err("ublock_getCode(U+0041) property failed! Expected : %i Got: %i \n", UBLOCK_BASIC_LATIN,ublock_getCode((UChar)0x0041)); + } + + errorCode=U_ZERO_ERROR; + parseUCDFile("UnicodeData.txt", fields, 15, unicodeDataLineFn, NULL, &errorCode); + if(U_FAILURE(errorCode)) { + return; /* if we couldn't parse UnicodeData.txt, we should return */ + } + + /* sanity check on repeated properties */ + for(c=0xfffe; c<=0x10ffff;) { + type=u_charType(c); + if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) { + log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c); + } + if(type!=U_UNASSIGNED) { + log_err("error: u_charType(U+%04lx)!=U_UNASSIGNED (returns %d)\n", c, u_charType(c)); + } + if((c&0xffff)==0xfffe) { + ++c; + } else { + c+=0xffff; + } + } + + /* test that PUA is not "unassigned" */ + for(c=0xe000; c<=0x10fffd;) { + type=u_charType(c); + if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) { + log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c); + } + if(type==U_UNASSIGNED) { + log_err("error: u_charType(U+%04lx)==U_UNASSIGNED\n", c); + } else if(type!=U_PRIVATE_USE_CHAR) { + log_verbose("PUA override: u_charType(U+%04lx)=%d\n", c, type); + } + if(c==0xf8ff) { + c=0xf0000; + } else if(c==0xffffd) { + c=0x100000; + } else { + ++c; + } + } + + /* test u_enumCharTypes() */ + u_enumCharTypes(enumTypeRange, "a1"); + + /* check default properties */ + u_enumCharTypes(enumDefaultsRange, NULL); +} + +static void TestCodeUnit(){ + const UChar codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0}; + + int32_t i; + + for(i=0; i<(int32_t)(sizeof(codeunit)/sizeof(codeunit[0])); i++){ + UChar c=codeunit[i]; + if(i<4){ + if(!(UTF_IS_SINGLE(c)) || (UTF_IS_LEAD(c)) || (UTF_IS_TRAIL(c)) ||(UTF_IS_SURROGATE(c))){ + log_err("ERROR: U+%04x is a single", c); + } + + } + if(i >= 4 && i< 8){ + if(!(UTF_IS_LEAD(c)) || UTF_IS_SINGLE(c) || UTF_IS_TRAIL(c) || !(UTF_IS_SURROGATE(c))){ + log_err("ERROR: U+%04x is a first surrogate", c); + } + } + if(i >= 8 && i< 12){ + if(!(UTF_IS_TRAIL(c)) || UTF_IS_SINGLE(c) || UTF_IS_LEAD(c) || !(UTF_IS_SURROGATE(c))){ + log_err("ERROR: U+%04x is a second surrogate", c); + } + } + } + +} + +static void TestCodePoint(){ + const UChar32 codePoint[]={ + /*surrogate, notvalid(codepoint), not a UnicodeChar, not Error */ + 0xd800, + 0xdbff, + 0xdc00, + 0xdfff, + 0xdc04, + 0xd821, + /*not a surrogate, valid, isUnicodeChar , not Error*/ + 0x20ac, + 0xd7ff, + 0xe000, + 0xe123, + 0x0061, + 0xe065, + 0x20402, + 0x24506, + 0x23456, + 0x20402, + 0x10402, + 0x23456, + /*not a surrogate, not valid, isUnicodeChar, isError */ + 0x0015, + 0x009f, + /*not a surrogate, not valid, not isUnicodeChar, isError */ + 0xffff, + 0xfffe, + }; + int32_t i; + for(i=0; i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0])); i++){ + UChar32 c=codePoint[i]; + if(i<6){ + if(!UTF_IS_SURROGATE(c) || !U_IS_SURROGATE(c) || !U16_IS_SURROGATE(c)){ + log_err("ERROR: isSurrogate() failed for U+%04x\n", c); + } + if(UTF_IS_VALID(c)){ + log_err("ERROR: isValid() failed for U+%04x\n", c); + } + if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){ + log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c); + } + if(UTF_IS_ERROR(c)){ + log_err("ERROR: isError() failed for U+%04x\n", c); + } + }else if(i >=6 && i<18){ + if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){ + log_err("ERROR: isSurrogate() failed for U+%04x\n", c); + } + if(!UTF_IS_VALID(c)){ + log_err("ERROR: isValid() failed for U+%04x\n", c); + } + if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){ + log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c); + } + if(UTF_IS_ERROR(c)){ + log_err("ERROR: isError() failed for U+%04x\n", c); + } + }else if(i >=18 && i<20){ + if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){ + log_err("ERROR: isSurrogate() failed for U+%04x\n", c); + } + if(UTF_IS_VALID(c)){ + log_err("ERROR: isValid() failed for U+%04x\n", c); + } + if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){ + log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c); + } + if(!UTF_IS_ERROR(c)){ + log_err("ERROR: isError() failed for U+%04x\n", c); + } + } + else if(i >=18 && i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0]))){ + if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){ + log_err("ERROR: isSurrogate() failed for U+%04x\n", c); + } + if(UTF_IS_VALID(c)){ + log_err("ERROR: isValid() failed for U+%04x\n", c); + } + if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){ + log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c); + } + if(!UTF_IS_ERROR(c)){ + log_err("ERROR: isError() failed for U+%04x\n", c); + } + } + } + + if( + !U_IS_BMP(0) || !U_IS_BMP(0x61) || !U_IS_BMP(0x20ac) || + !U_IS_BMP(0xd9da) || !U_IS_BMP(0xdfed) || !U_IS_BMP(0xffff) || + U_IS_BMP(U_SENTINEL) || U_IS_BMP(0x10000) || U_IS_BMP(0x50005) || + U_IS_BMP(0x10ffff) || U_IS_BMP(0x110000) || U_IS_BMP(0x7fffffff) + ) { + log_err("error with U_IS_BMP()\n"); + } + + if( + U_IS_SUPPLEMENTARY(0) || U_IS_SUPPLEMENTARY(0x61) || U_IS_SUPPLEMENTARY(0x20ac) || + U_IS_SUPPLEMENTARY(0xd9da) || U_IS_SUPPLEMENTARY(0xdfed) || U_IS_SUPPLEMENTARY(0xffff) || + U_IS_SUPPLEMENTARY(U_SENTINEL) || !U_IS_SUPPLEMENTARY(0x10000) || !U_IS_SUPPLEMENTARY(0x50005) || + !U_IS_SUPPLEMENTARY(0x10ffff) || U_IS_SUPPLEMENTARY(0x110000) || U_IS_SUPPLEMENTARY(0x7fffffff) + ) { + log_err("error with U_IS_SUPPLEMENTARY()\n"); + } +} + +static void TestCharLength() +{ + const int32_t codepoint[]={ + 1, 0x0061, + 1, 0xe065, + 1, 0x20ac, + 2, 0x20402, + 2, 0x23456, + 2, 0x24506, + 2, 0x20402, + 2, 0x10402, + 1, 0xd7ff, + 1, 0xe000 + }; + + int32_t i; + UBool multiple; + for(i=0; i<(int32_t)(sizeof(codepoint)/sizeof(codepoint[0])); i=(int16_t)(i+2)){ + UChar32 c=codepoint[i+1]; + if(UTF_CHAR_LENGTH(c) != codepoint[i] || U16_LENGTH(c) != codepoint[i]){ + log_err("The no: of code units for U+%04x:- Expected: %d Got: %d\n", c, codepoint[i], UTF_CHAR_LENGTH(c)); + } + multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE); + if(UTF_NEED_MULTIPLE_UCHAR(c) != multiple){ + log_err("ERROR: Unicode::needMultipleUChar() failed for U+%04x\n", c); + } + } +} + +/*internal functions ----*/ +static int32_t MakeProp(char* str) +{ + int32_t result = 0; + char* matchPosition =0; + + matchPosition = strstr(tagStrings, str); + if (matchPosition == 0) + { + log_err("unrecognized type letter "); + log_err(str); + } + else + result = (int32_t)((matchPosition - tagStrings) / 2); + return result; +} + +static int32_t MakeDir(char* str) +{ + int32_t pos = 0; + for (pos = 0; pos < 19; pos++) { + if (strcmp(str, dirStrings[pos]) == 0) { + return pos; + } + } + return -1; +} + +/* test u_charName() -------------------------------------------------------- */ + +static const struct { + uint32_t code; + const char *name, *oldName, *extName; +} names[]={ + {0x0061, "LATIN SMALL LETTER A", "", "LATIN SMALL LETTER A"}, + {0x0284, "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK", "LATIN SMALL LETTER DOTLESS J BAR HOOK", "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK" }, + {0x3401, "CJK UNIFIED IDEOGRAPH-3401", "", "CJK UNIFIED IDEOGRAPH-3401" }, + {0x7fed, "CJK UNIFIED IDEOGRAPH-7FED", "", "CJK UNIFIED IDEOGRAPH-7FED" }, + {0xac00, "HANGUL SYLLABLE GA", "", "HANGUL SYLLABLE GA" }, + {0xd7a3, "HANGUL SYLLABLE HIH", "", "HANGUL SYLLABLE HIH" }, + {0xd800, "", "", "<lead surrogate-D800>" }, + {0xdc00, "", "", "<trail surrogate-DC00>" }, + {0xff08, "FULLWIDTH LEFT PARENTHESIS", "FULLWIDTH OPENING PARENTHESIS", "FULLWIDTH LEFT PARENTHESIS" }, + {0xffe5, "FULLWIDTH YEN SIGN", "", "FULLWIDTH YEN SIGN" }, + {0xffff, "", "", "<noncharacter-FFFF>" }, + {0x23456, "CJK UNIFIED IDEOGRAPH-23456", "", "CJK UNIFIED IDEOGRAPH-23456" } +}; + +static UBool +enumCharNamesFn(void *context, + UChar32 code, UCharNameChoice nameChoice, + const char *name, int32_t length) { + int32_t *pCount=(int32_t *)context; + int i; + + if(length<=0 || length!=(int32_t)strlen(name)) { + /* should not be called with an empty string or invalid length */ + log_err("u_enumCharName(0x%lx)=%s but length=%ld\n", name, length); + return TRUE; + } + + ++*pCount; + for(i=0; i<sizeof(names)/sizeof(names[0]); ++i) { + if(code==(UChar32)names[i].code) { + switch (nameChoice) { + case U_EXTENDED_CHAR_NAME: + if(0!=strcmp(name, names[i].extName)) { + log_err("u_enumCharName(0x%lx - Extended)=%s instead of %s\n", code, name, names[i].extName); + } + break; + case U_UNICODE_CHAR_NAME: + if(0!=strcmp(name, names[i].name)) { + log_err("u_enumCharName(0x%lx)=%s instead of %s\n", code, name, names[i].name); + } + break; + case U_UNICODE_10_CHAR_NAME: + if(names[i].oldName[0]==0 || 0!=strcmp(name, names[i].oldName)) { + log_err("u_enumCharName(0x%lx - 1.0)=%s instead of %s\n", code, name, names[i].oldName); + } + break; + case U_CHAR_NAME_CHOICE_COUNT: + break; + } + break; + } + } + return TRUE; +} + +struct enumExtCharNamesContext { + uint32_t length; + int32_t last; +}; + +static UBool +enumExtCharNamesFn(void *context, + UChar32 code, UCharNameChoice nameChoice, + const char *name, int32_t length) { + struct enumExtCharNamesContext *ecncp = (struct enumExtCharNamesContext *) context; + + if (ecncp->last != (int32_t) code - 1) { + if (ecncp->last < 0) { + log_err("u_enumCharName(0x%lx - Ext) after u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x%lx - Ext)\n", code, ecncp->last, ecncp->last + 1); + } else { + log_err("u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x0 - Ext)\n", code); + } + } + ecncp->last = (int32_t) code; + + if (!*name) { + log_err("u_enumCharName(0x%lx - Ext) should not be an empty string\n", code); + } + + return enumCharNamesFn(&ecncp->length, code, nameChoice, name, length); +} + +/** + * This can be made more efficient by moving it into putil.c and having + * it directly access the ebcdic translation tables. + * TODO: If we get this method in putil.c, then delete it from here. + */ +static UChar +u_charToUChar(char c) { + UChar uc; + u_charsToUChars(&c, &uc, 1); + return uc; +} + +static void +TestCharNames() { + static char name[80]; + UErrorCode errorCode=U_ZERO_ERROR; + struct enumExtCharNamesContext extContext; + int32_t length; + UChar32 c; + int32_t i; + + log_verbose("Testing uprv_getMaxCharNameLength()\n"); + length=uprv_getMaxCharNameLength(); + if(length==0) { + /* no names data available */ + return; + } + if(length<83) { /* Unicode 3.2 max char name length */ + log_err("uprv_getMaxCharNameLength()=%d is too short"); + } + /* ### TODO same tests for max ISO comment length as for max name length */ + + log_verbose("Testing u_charName()\n"); + for(i=0; i<(int32_t)(sizeof(names)/sizeof(names[0])); ++i) { + /* modern Unicode character name */ + length=u_charName(names[i].code, U_UNICODE_CHAR_NAME, name, sizeof(name), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("u_charName(0x%lx) error %s\n", names[i].code, u_errorName(errorCode)); + return; + } + if(length<0 || 0!=strcmp(name, names[i].name) || length!=(uint16_t)strlen(name)) { + log_err("u_charName(0x%lx) gets: %s (length %ld) instead of: %s\n", names[i].code, name, length, names[i].name); + } + + /* find the modern name */ + if (*names[i].name) { + c=u_charFromName(U_UNICODE_CHAR_NAME, names[i].name, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("u_charFromName(%s) error %s\n", names[i].name, u_errorName(errorCode)); + return; + } + if(c!=(UChar32)names[i].code) { + log_err("u_charFromName(%s) gets 0x%lx instead of 0x%lx\n", names[i].name, c, names[i].code); + } + } + + /* Unicode 1.0 character name */ + length=u_charName(names[i].code, U_UNICODE_10_CHAR_NAME, name, sizeof(name), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("u_charName(0x%lx - 1.0) error %s\n", names[i].code, u_errorName(errorCode)); + return; + } + if(length<0 || (length>0 && 0!=strcmp(name, names[i].oldName)) || length!=(uint16_t)strlen(name)) { + log_err("u_charName(0x%lx - 1.0) gets %s length %ld instead of nothing or %s\n", names[i].code, name, length, names[i].oldName); + } + + /* find the Unicode 1.0 name if it is stored (length>0 means that we could read it) */ + if(names[i].oldName[0]!=0 /* && length>0 */) { + c=u_charFromName(U_UNICODE_10_CHAR_NAME, names[i].oldName, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("u_charFromName(%s - 1.0) error %s\n", names[i].oldName, u_errorName(errorCode)); + return; + } + if(c!=(UChar32)names[i].code) { + log_err("u_charFromName(%s - 1.0) gets 0x%lx instead of 0x%lx\n", names[i].oldName, c, names[i].code); + } + } + } + + /* test u_enumCharNames() */ + length=0; + errorCode=U_ZERO_ERROR; + u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumCharNamesFn, &length, U_UNICODE_CHAR_NAME, &errorCode); + if(U_FAILURE(errorCode) || length<94140) { + log_err("u_enumCharNames(%ld..%lx) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE, u_errorName(errorCode), length); + } + + extContext.length = 0; + extContext.last = -1; + errorCode=U_ZERO_ERROR; + u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumExtCharNamesFn, &extContext, U_EXTENDED_CHAR_NAME, &errorCode); + if(U_FAILURE(errorCode) || extContext.length<UCHAR_MAX_VALUE + 1) { + log_err("u_enumCharNames(%ld..0x%lx - Extended) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, u_errorName(errorCode), extContext.length); + } + + /* test that u_charFromName() uppercases the input name, i.e., works with mixed-case names (new in 2.0) */ + if(0x61!=u_charFromName(U_UNICODE_CHAR_NAME, "LATin smALl letTER A", &errorCode)) { + log_err("u_charFromName(U_UNICODE_CHAR_NAME, \"LATin smALl letTER A\") did not find U+0061 (%s)\n", u_errorName(errorCode)); + } + + /* Test getCharNameCharacters */ + if(!QUICK) { + enum { BUFSIZE = 256 }; + UErrorCode ec = U_ZERO_ERROR; + char buf[BUFSIZE]; + int32_t maxLength; + UChar32 cp; + UChar pat[BUFSIZE], dumbPat[BUFSIZE]; + int32_t l1, l2; + UBool map[256]; + UBool ok; + + USet* set = uset_open(1, 0); /* empty set */ + USet* dumb = uset_open(1, 0); /* empty set */ + + /* + * uprv_getCharNameCharacters() will likely return more lowercase + * letters than actual character names contain because + * it includes all the characters in lowercased names of + * general categories, for the full possible set of extended names. + */ + { + USetAdder sa={ + NULL, + uset_add, + uset_addRange, + uset_addString, + NULL /* don't need remove() */ + }; + sa.set=set; + uprv_getCharNameCharacters(&sa); + } + + /* build set the dumb (but sure-fire) way */ + for (i=0; i<256; ++i) { + map[i] = FALSE; + } + + maxLength=0; + for (cp=0; cp<0x110000; ++cp) { + int32_t len = u_charName(cp, U_EXTENDED_CHAR_NAME, + buf, BUFSIZE, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: u_charName failed when it shouldn't\n"); + uset_close(set); + uset_close(dumb); + return; + } + if(len>maxLength) { + maxLength=len; + } + + for (i=0; i<len; ++i) { + if (!map[(uint8_t) buf[i]]) { + uset_add(dumb, (UChar32)u_charToUChar(buf[i])); + map[(uint8_t) buf[i]] = TRUE; + } + } + + /* test for leading/trailing whitespace */ + if(buf[0]==' ' || buf[0]=='\t' || buf[len-1]==' ' || buf[len-1]=='\t') { + log_err("u_charName(U+%04x) returns a name with leading or trailing whitespace\n", cp); + } + } + + if(map[(uint8_t)'\t']) { + log_err("u_charName() returned a name with a TAB for some code point\n", cp); + } + + length=uprv_getMaxCharNameLength(); + if(length!=maxLength) { + log_err("uprv_getMaxCharNameLength()=%d differs from the maximum length %d of all extended names\n", + length, maxLength); + } + + /* compare the sets. Where is my uset_equals?!! */ + ok=TRUE; + for(i=0; i<256; ++i) { + if(uset_contains(set, i)!=uset_contains(dumb, i)) { + if(0x61<=i && i<=0x7a /* a-z */ && uset_contains(set, i) && !uset_contains(dumb, i)) { + /* ignore lowercase a-z that are in set but not in dumb */ + ok=TRUE; + } else { + ok=FALSE; + break; + } + } + } + + l1 = uset_toPattern(set, pat, BUFSIZE, TRUE, &ec); + l2 = uset_toPattern(dumb, dumbPat, BUFSIZE, TRUE, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: uset_toPattern failed when it shouldn't\n"); + uset_close(set); + uset_close(dumb); + return; + } + + if (l1 >= BUFSIZE) { + l1 = BUFSIZE-1; + pat[l1] = 0; + } + if (l2 >= BUFSIZE) { + l2 = BUFSIZE-1; + dumbPat[l2] = 0; + } + + if (!ok) { + log_err("FAIL: uprv_getCharNameCharacters() returned %s, expected %s (too many lowercase a-z are ok)\n", + aescstrdup(pat, l1), aescstrdup(dumbPat, l2)); + } else if(VERBOSITY) { + log_verbose("Ok: uprv_getCharNameCharacters() returned %s\n", aescstrdup(pat, l1)); + } + + uset_close(set); + uset_close(dumb); + } + + /* ### TODO: test error cases and other interesting things */ +} + +/* test u_isMirrored() and u_charMirror() ----------------------------------- */ + +static void +TestMirroring() { + USet *set; + UErrorCode errorCode; + + UChar32 start, end, c2, c3; + int32_t i; + + U_STRING_DECL(mirroredPattern, "[:Bidi_Mirrored:]", 17); + + U_STRING_INIT(mirroredPattern, "[:Bidi_Mirrored:]", 17); + + log_verbose("Testing u_isMirrored()\n"); + if(!(u_isMirrored(0x28) && u_isMirrored(0xbb) && u_isMirrored(0x2045) && u_isMirrored(0x232a) && + !u_isMirrored(0x27) && !u_isMirrored(0x61) && !u_isMirrored(0x284) && !u_isMirrored(0x3400) + ) + ) { + log_err("u_isMirrored() does not work correctly\n"); + } + + log_verbose("Testing u_charMirror()\n"); + if(!(u_charMirror(0x3c)==0x3e && u_charMirror(0x5d)==0x5b && u_charMirror(0x208d)==0x208e && u_charMirror(0x3017)==0x3016 && + u_charMirror(0xbb)==0xab && u_charMirror(0x2215)==0x29F5 && u_charMirror(0x29F5)==0x2215 && /* large delta between the code points */ + u_charMirror(0x2e)==0x2e && u_charMirror(0x6f3)==0x6f3 && u_charMirror(0x301c)==0x301c && u_charMirror(0xa4ab)==0xa4ab && + /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */ + u_charMirror(0x2018)==0x2018 && u_charMirror(0x201b)==0x201b && u_charMirror(0x301d)==0x301d + ) + ) { + log_err("u_charMirror() does not work correctly\n"); + } + + /* verify that Bidi_Mirroring_Glyph roundtrips */ + errorCode=U_ZERO_ERROR; + set=uset_openPattern(mirroredPattern, 17, &errorCode); + + if (U_FAILURE(errorCode)) { + log_data_err("uset_openPattern(mirroredPattern, 17, &errorCode) failed!"); + } else { + for(i=0; 0==uset_getItem(set, i, &start, &end, NULL, 0, &errorCode); ++i) { + do { + c2=u_charMirror(start); + c3=u_charMirror(c2); + if(c3!=start) { + log_err("u_charMirror() does not roundtrip: U+%04lx->U+%04lx->U+%04lx\n", (long)start, (long)c2, (long)c3); + } + } while(++start<=end); + } + } + + uset_close(set); +} + + +struct RunTestData +{ + const char *runText; + UScriptCode runCode; +}; + +typedef struct RunTestData RunTestData; + +static void +CheckScriptRuns(UScriptRun *scriptRun, int32_t *runStarts, const RunTestData *testData, int32_t nRuns, + const char *prefix) +{ + int32_t run, runStart, runLimit; + UScriptCode runCode; + + /* iterate over all the runs */ + run = 0; + while (uscript_nextRun(scriptRun, &runStart, &runLimit, &runCode)) { + if (runStart != runStarts[run]) { + log_err("%s: incorrect start offset for run %d: expected %d, got %d\n", + prefix, run, runStarts[run], runStart); + } + + if (runLimit != runStarts[run + 1]) { + log_err("%s: incorrect limit offset for run %d: expected %d, got %d\n", + prefix, run, runStarts[run + 1], runLimit); + } + + if (runCode != testData[run].runCode) { + log_err("%s: incorrect script for run %d: expected \"%s\", got \"%s\"\n", + prefix, run, uscript_getName(testData[run].runCode), uscript_getName(runCode)); + } + + run += 1; + + /* stop when we've seen all the runs we expect to see */ + if (run >= nRuns) { + break; + } + } + + /* Complain if we didn't see then number of runs we expected */ + if (run != nRuns) { + log_err("%s: incorrect number of runs: expected %d, got %d\n", prefix, run, nRuns); + } +} + +static void +TestUScriptRunAPI() +{ + static const RunTestData testData1[] = { + {"\\u0020\\u0946\\u0939\\u093F\\u0928\\u094D\\u0926\\u0940\\u0020", USCRIPT_DEVANAGARI}, + {"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629\\u0020", USCRIPT_ARABIC}, + {"\\u0420\\u0443\\u0441\\u0441\\u043A\\u0438\\u0439\\u0020", USCRIPT_CYRILLIC}, + {"English (", USCRIPT_LATIN}, + {"\\u0E44\\u0E17\\u0E22", USCRIPT_THAI}, + {") ", USCRIPT_LATIN}, + {"\\u6F22\\u5B75", USCRIPT_HAN}, + {"\\u3068\\u3072\\u3089\\u304C\\u306A\\u3068", USCRIPT_HIRAGANA}, + {"\\u30AB\\u30BF\\u30AB\\u30CA", USCRIPT_KATAKANA}, + {"\\U00010400\\U00010401\\U00010402\\U00010403", USCRIPT_DESERET} + }; + + static const RunTestData testData2[] = { + {"((((((((((abc))))))))))", USCRIPT_LATIN} + }; + + static const struct { + const RunTestData *testData; + int32_t nRuns; + } testDataEntries[] = { + {testData1, LENGTHOF(testData1)}, + {testData2, LENGTHOF(testData2)} + }; + + static const int32_t nTestEntries = LENGTHOF(testDataEntries); + int32_t testEntry; + + for (testEntry = 0; testEntry < nTestEntries; testEntry += 1) { + UChar testString[1024]; + int32_t runStarts[256]; + int32_t nTestRuns = testDataEntries[testEntry].nRuns; + const RunTestData *testData = testDataEntries[testEntry].testData; + + int32_t run, stringLimit; + UScriptRun *scriptRun = NULL; + UErrorCode err; + + /* + * Fill in the test string and the runStarts array. + */ + stringLimit = 0; + for (run = 0; run < nTestRuns; run += 1) { + runStarts[run] = stringLimit; + stringLimit += u_unescape(testData[run].runText, &testString[stringLimit], 1024 - stringLimit); + /*stringLimit -= 1;*/ + } + + /* The limit of the last run */ + runStarts[nTestRuns] = stringLimit; + + /* + * Make sure that calling uscript_OpenRun with a NULL text pointer + * and a non-zero text length returns the correct error. + */ + err = U_ZERO_ERROR; + scriptRun = uscript_openRun(NULL, stringLimit, &err); + + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("uscript_openRun(NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err)); + } + + if (scriptRun != NULL) { + log_err("uscript_openRun(NULL, stringLimit, &err) returned a non-NULL result.\n"); + uscript_closeRun(scriptRun); + } + + /* + * Make sure that calling uscript_OpenRun with a non-NULL text pointer + * and a zero text length returns the correct error. + */ + err = U_ZERO_ERROR; + scriptRun = uscript_openRun(testString, 0, &err); + + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("uscript_openRun(testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err)); + } + + if (scriptRun != NULL) { + log_err("uscript_openRun(testString, 0, &err) returned a non-NULL result.\n"); + uscript_closeRun(scriptRun); + } + + /* + * Make sure that calling uscript_openRun with a NULL text pointer + * and a zero text length doesn't return an error. + */ + err = U_ZERO_ERROR; + scriptRun = uscript_openRun(NULL, 0, &err); + + if (U_FAILURE(err)) { + log_err("Got error %s from uscript_openRun(NULL, 0, &err)\n", u_errorName(err)); + } + + /* Make sure that the empty iterator doesn't find any runs */ + if (uscript_nextRun(scriptRun, NULL, NULL, NULL)) { + log_err("uscript_nextRun(...) returned TRUE for an empty iterator.\n"); + } + + /* + * Make sure that calling uscript_setRunText with a NULL text pointer + * and a non-zero text length returns the correct error. + */ + err = U_ZERO_ERROR; + uscript_setRunText(scriptRun, NULL, stringLimit, &err); + + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("uscript_setRunText(scriptRun, NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err)); + } + + /* + * Make sure that calling uscript_OpenRun with a non-NULL text pointer + * and a zero text length returns the correct error. + */ + err = U_ZERO_ERROR; + uscript_setRunText(scriptRun, testString, 0, &err); + + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("uscript_setRunText(scriptRun, testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err)); + } + + /* + * Now call uscript_setRunText on the empty iterator + * and make sure that it works. + */ + err = U_ZERO_ERROR; + uscript_setRunText(scriptRun, testString, stringLimit, &err); + + if (U_FAILURE(err)) { + log_err("Got error %s from uscript_setRunText(...)\n", u_errorName(err)); + } else { + CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_setRunText"); + } + + uscript_closeRun(scriptRun); + + /* + * Now open an interator over the testString + * using uscript_openRun and make sure that it works + */ + scriptRun = uscript_openRun(testString, stringLimit, &err); + + if (U_FAILURE(err)) { + log_err("Got error %s from uscript_openRun(...)\n", u_errorName(err)); + } else { + CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_openRun"); + } + + /* Now reset the iterator, and make sure + * that it still works. + */ + uscript_resetRun(scriptRun); + + CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_resetRun"); + + /* Close the iterator */ + uscript_closeRun(scriptRun); + } +} + +/* test additional, non-core properties */ +static void +TestAdditionalProperties() { + /* test data for u_charAge() */ + static const struct { + UChar32 c; + UVersionInfo version; + } charAges[]={ + {0x41, { 1, 1, 0, 0 }}, + {0xffff, { 1, 1, 0, 0 }}, + {0x20ab, { 2, 0, 0, 0 }}, + {0x2fffe, { 2, 0, 0, 0 }}, + {0x20ac, { 2, 1, 0, 0 }}, + {0xfb1d, { 3, 0, 0, 0 }}, + {0x3f4, { 3, 1, 0, 0 }}, + {0x10300, { 3, 1, 0, 0 }}, + {0x220, { 3, 2, 0, 0 }}, + {0xff60, { 3, 2, 0, 0 }} + }; + + /* test data for u_hasBinaryProperty() */ + static const int32_t + props[][3]={ /* code point, property, value */ + { 0x0627, UCHAR_ALPHABETIC, TRUE }, + { 0x1034a, UCHAR_ALPHABETIC, TRUE }, + { 0x2028, UCHAR_ALPHABETIC, FALSE }, + + { 0x0066, UCHAR_ASCII_HEX_DIGIT, TRUE }, + { 0x0067, UCHAR_ASCII_HEX_DIGIT, FALSE }, + + { 0x202c, UCHAR_BIDI_CONTROL, TRUE }, + { 0x202f, UCHAR_BIDI_CONTROL, FALSE }, + + { 0x003c, UCHAR_BIDI_MIRRORED, TRUE }, + { 0x003d, UCHAR_BIDI_MIRRORED, FALSE }, + + /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */ + { 0x2018, UCHAR_BIDI_MIRRORED, FALSE }, + { 0x201d, UCHAR_BIDI_MIRRORED, FALSE }, + { 0x201f, UCHAR_BIDI_MIRRORED, FALSE }, + { 0x301e, UCHAR_BIDI_MIRRORED, FALSE }, + + { 0x058a, UCHAR_DASH, TRUE }, + { 0x007e, UCHAR_DASH, FALSE }, + + { 0x0c4d, UCHAR_DIACRITIC, TRUE }, + { 0x3000, UCHAR_DIACRITIC, FALSE }, + + { 0x0e46, UCHAR_EXTENDER, TRUE }, + { 0x0020, UCHAR_EXTENDER, FALSE }, + +#if !UCONFIG_NO_NORMALIZATION + { 0xfb1d, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE }, + { 0x1d15f, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE }, + { 0xfb1e, UCHAR_FULL_COMPOSITION_EXCLUSION, FALSE }, + + { 0x110a, UCHAR_NFD_INERT, TRUE }, /* Jamo L */ + { 0x0308, UCHAR_NFD_INERT, FALSE }, + + { 0x1164, UCHAR_NFKD_INERT, TRUE }, /* Jamo V */ + { 0x1d79d, UCHAR_NFKD_INERT, FALSE }, /* math compat version of xi */ + + { 0x0021, UCHAR_NFC_INERT, TRUE }, /* ! */ + { 0x0061, UCHAR_NFC_INERT, FALSE }, /* a */ + { 0x00e4, UCHAR_NFC_INERT, FALSE }, /* a-umlaut */ + { 0x0102, UCHAR_NFC_INERT, FALSE }, /* a-breve */ + { 0xac1c, UCHAR_NFC_INERT, FALSE }, /* Hangul LV */ + { 0xac1d, UCHAR_NFC_INERT, TRUE }, /* Hangul LVT */ + + { 0x1d79d, UCHAR_NFKC_INERT, FALSE }, /* math compat version of xi */ + { 0x2a6d6, UCHAR_NFKC_INERT, TRUE }, /* Han, last of CJK ext. B */ + + { 0x00e4, UCHAR_SEGMENT_STARTER, TRUE }, + { 0x0308, UCHAR_SEGMENT_STARTER, FALSE }, + { 0x110a, UCHAR_SEGMENT_STARTER, TRUE }, /* Jamo L */ + { 0x1164, UCHAR_SEGMENT_STARTER, FALSE },/* Jamo V */ + { 0xac1c, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LV */ + { 0xac1d, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LVT */ +#endif + + { 0x0044, UCHAR_HEX_DIGIT, TRUE }, + { 0xff46, UCHAR_HEX_DIGIT, TRUE }, + { 0x0047, UCHAR_HEX_DIGIT, FALSE }, + + { 0x30fb, UCHAR_HYPHEN, TRUE }, + { 0xfe58, UCHAR_HYPHEN, FALSE }, + + { 0x2172, UCHAR_ID_CONTINUE, TRUE }, + { 0x0307, UCHAR_ID_CONTINUE, TRUE }, + { 0x005c, UCHAR_ID_CONTINUE, FALSE }, + + { 0x2172, UCHAR_ID_START, TRUE }, + { 0x007a, UCHAR_ID_START, TRUE }, + { 0x0039, UCHAR_ID_START, FALSE }, + + { 0x4db5, UCHAR_IDEOGRAPHIC, TRUE }, + { 0x2f999, UCHAR_IDEOGRAPHIC, TRUE }, + { 0x2f99, UCHAR_IDEOGRAPHIC, FALSE }, + + { 0x200c, UCHAR_JOIN_CONTROL, TRUE }, + { 0x2029, UCHAR_JOIN_CONTROL, FALSE }, + + { 0x1d7bc, UCHAR_LOWERCASE, TRUE }, + { 0x0345, UCHAR_LOWERCASE, TRUE }, + { 0x0030, UCHAR_LOWERCASE, FALSE }, + + { 0x1d7a9, UCHAR_MATH, TRUE }, + { 0x2135, UCHAR_MATH, TRUE }, + { 0x0062, UCHAR_MATH, FALSE }, + + { 0xfde1, UCHAR_NONCHARACTER_CODE_POINT, TRUE }, + { 0x10ffff, UCHAR_NONCHARACTER_CODE_POINT, TRUE }, + { 0x10fffd, UCHAR_NONCHARACTER_CODE_POINT, FALSE }, + + { 0x0022, UCHAR_QUOTATION_MARK, TRUE }, + { 0xff62, UCHAR_QUOTATION_MARK, TRUE }, + { 0xd840, UCHAR_QUOTATION_MARK, FALSE }, + + { 0x061f, UCHAR_TERMINAL_PUNCTUATION, TRUE }, + { 0xe003f, UCHAR_TERMINAL_PUNCTUATION, FALSE }, + + { 0x1d44a, UCHAR_UPPERCASE, TRUE }, + { 0x2162, UCHAR_UPPERCASE, TRUE }, + { 0x0345, UCHAR_UPPERCASE, FALSE }, + + { 0x0020, UCHAR_WHITE_SPACE, TRUE }, + { 0x202f, UCHAR_WHITE_SPACE, TRUE }, + { 0x3001, UCHAR_WHITE_SPACE, FALSE }, + + { 0x0711, UCHAR_XID_CONTINUE, TRUE }, + { 0x1d1aa, UCHAR_XID_CONTINUE, TRUE }, + { 0x007c, UCHAR_XID_CONTINUE, FALSE }, + + { 0x16ee, UCHAR_XID_START, TRUE }, + { 0x23456, UCHAR_XID_START, TRUE }, + { 0x1d1aa, UCHAR_XID_START, FALSE }, + + /* + * Version break: + * The following properties are only supported starting with the + * Unicode version indicated in the second field. + */ + { -1, 0x320, 0 }, + + { 0x180c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE }, + { 0xfe02, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE }, + { 0x1801, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, FALSE }, + + { 0x0341, UCHAR_DEPRECATED, TRUE }, + { 0xe0041, UCHAR_DEPRECATED, FALSE }, + + { 0x00a0, UCHAR_GRAPHEME_BASE, TRUE }, + { 0x0a4d, UCHAR_GRAPHEME_BASE, FALSE }, + { 0xff9f, UCHAR_GRAPHEME_BASE, TRUE }, /* changed from Unicode 3.2 to 4 */ + + { 0x0300, UCHAR_GRAPHEME_EXTEND, TRUE }, + { 0xff9f, UCHAR_GRAPHEME_EXTEND, FALSE }, /* changed from Unicode 3.2 to 4 */ + { 0x0603, UCHAR_GRAPHEME_EXTEND, FALSE }, + + { 0x0a4d, UCHAR_GRAPHEME_LINK, TRUE }, + { 0xff9f, UCHAR_GRAPHEME_LINK, FALSE }, + + { 0x2ff7, UCHAR_IDS_BINARY_OPERATOR, TRUE }, + { 0x2ff3, UCHAR_IDS_BINARY_OPERATOR, FALSE }, + + { 0x2ff3, UCHAR_IDS_TRINARY_OPERATOR, TRUE }, + { 0x2f03, UCHAR_IDS_TRINARY_OPERATOR, FALSE }, + + { 0x0ec1, UCHAR_LOGICAL_ORDER_EXCEPTION, TRUE }, + { 0xdcba, UCHAR_LOGICAL_ORDER_EXCEPTION, FALSE }, + + { 0x2e9b, UCHAR_RADICAL, TRUE }, + { 0x4e00, UCHAR_RADICAL, FALSE }, + + { 0x012f, UCHAR_SOFT_DOTTED, TRUE }, + { 0x0049, UCHAR_SOFT_DOTTED, FALSE }, + + { 0xfa11, UCHAR_UNIFIED_IDEOGRAPH, TRUE }, + { 0xfa12, UCHAR_UNIFIED_IDEOGRAPH, FALSE }, + + { -1, 0x401, 0 }, /* version break for Unicode 4.0.1 */ + + { 0x002e, UCHAR_S_TERM, TRUE }, + { 0x0061, UCHAR_S_TERM, FALSE }, + + { 0x180c, UCHAR_VARIATION_SELECTOR, TRUE }, + { 0xfe03, UCHAR_VARIATION_SELECTOR, TRUE }, + { 0xe01ef, UCHAR_VARIATION_SELECTOR, TRUE }, + { 0xe0200, UCHAR_VARIATION_SELECTOR, FALSE }, + + /* enum/integer type properties */ + + /* UCHAR_BIDI_CLASS tested for assigned characters in TestUnicodeData() */ + /* test default Bidi classes for unassigned code points */ + { 0x0590, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x05cf, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x05ed, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x07f2, UCHAR_BIDI_CLASS, U_DIR_NON_SPACING_MARK }, /* Nko, new in Unicode 5.0 */ + { 0x07fe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, /* unassigned R */ + { 0x08ba, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0xfb37, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0xfb42, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x10806, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x10909, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + { 0x10fe4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, + + { 0x0606, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0x061c, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0x063f, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0x070e, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0x0775, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0xfbc2, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0xfd90, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + { 0xfefe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC }, + + { 0x02AF, UCHAR_BLOCK, UBLOCK_IPA_EXTENSIONS }, + { 0x0C4E, UCHAR_BLOCK, UBLOCK_TELUGU }, + { 0x155A, UCHAR_BLOCK, UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS }, + { 0x1717, UCHAR_BLOCK, UBLOCK_TAGALOG }, + { 0x1900, UCHAR_BLOCK, UBLOCK_LIMBU }, + { 0x1AFF, UCHAR_BLOCK, UBLOCK_NO_BLOCK }, + { 0x3040, UCHAR_BLOCK, UBLOCK_HIRAGANA }, + { 0x1D0FF, UCHAR_BLOCK, UBLOCK_BYZANTINE_MUSICAL_SYMBOLS }, + { 0x50000, UCHAR_BLOCK, UBLOCK_NO_BLOCK }, + { 0xEFFFF, UCHAR_BLOCK, UBLOCK_NO_BLOCK }, + { 0x10D0FF, UCHAR_BLOCK, UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B }, + + /* UCHAR_CANONICAL_COMBINING_CLASS tested for assigned characters in TestUnicodeData() */ + { 0xd7d7, UCHAR_CANONICAL_COMBINING_CLASS, 0 }, + + { 0x00A0, UCHAR_DECOMPOSITION_TYPE, U_DT_NOBREAK }, + { 0x00A8, UCHAR_DECOMPOSITION_TYPE, U_DT_COMPAT }, + { 0x00bf, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE }, + { 0x00c0, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL }, + { 0x1E9B, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL }, + { 0xBCDE, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL }, + { 0xFB5D, UCHAR_DECOMPOSITION_TYPE, U_DT_MEDIAL }, + { 0x1D736, UCHAR_DECOMPOSITION_TYPE, U_DT_FONT }, + { 0xe0033, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE }, + + { 0x0009, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL }, + { 0x0020, UCHAR_EAST_ASIAN_WIDTH, U_EA_NARROW }, + { 0x00B1, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS }, + { 0x20A9, UCHAR_EAST_ASIAN_WIDTH, U_EA_HALFWIDTH }, + { 0x2FFB, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0x3000, UCHAR_EAST_ASIAN_WIDTH, U_EA_FULLWIDTH }, + { 0x35bb, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0x58bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0xD7A3, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0xEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS }, + { 0x1D198, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL }, + { 0x20000, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0x2F8C7, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, + { 0x3a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, /* plane 3 got default W values in Unicode 4 */ + { 0x5a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL }, + { 0xFEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS }, + { 0x10EEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS }, + + /* UCHAR_GENERAL_CATEGORY tested for assigned characters in TestUnicodeData() */ + { 0xd7d7, UCHAR_GENERAL_CATEGORY, 0 }, + + { 0x0444, UCHAR_JOINING_GROUP, U_JG_NO_JOINING_GROUP }, + { 0x0639, UCHAR_JOINING_GROUP, U_JG_AIN }, + { 0x072A, UCHAR_JOINING_GROUP, U_JG_DALATH_RISH }, + { 0x0647, UCHAR_JOINING_GROUP, U_JG_HEH }, + { 0x06C1, UCHAR_JOINING_GROUP, U_JG_HEH_GOAL }, + { 0x06C3, UCHAR_JOINING_GROUP, U_JG_HAMZA_ON_HEH_GOAL }, + + { 0x200C, UCHAR_JOINING_TYPE, U_JT_NON_JOINING }, + { 0x200D, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING }, + { 0x0639, UCHAR_JOINING_TYPE, U_JT_DUAL_JOINING }, + { 0x0640, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING }, + { 0x06C3, UCHAR_JOINING_TYPE, U_JT_RIGHT_JOINING }, + { 0x0300, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT }, + { 0x070F, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT }, + { 0xe0033, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT }, + + /* TestUnicodeData() verifies that no assigned character has "XX" (unknown) */ + { 0xe7e7, UCHAR_LINE_BREAK, U_LB_UNKNOWN }, + { 0x10fffd, UCHAR_LINE_BREAK, U_LB_UNKNOWN }, + { 0x0028, UCHAR_LINE_BREAK, U_LB_OPEN_PUNCTUATION }, + { 0x232A, UCHAR_LINE_BREAK, U_LB_CLOSE_PUNCTUATION }, + { 0x3401, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC }, + { 0x4e02, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC }, + { 0x20004, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC }, + { 0xf905, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC }, + { 0xdb7e, UCHAR_LINE_BREAK, U_LB_SURROGATE }, + { 0xdbfd, UCHAR_LINE_BREAK, U_LB_SURROGATE }, + { 0xdffc, UCHAR_LINE_BREAK, U_LB_SURROGATE }, + { 0x2762, UCHAR_LINE_BREAK, U_LB_EXCLAMATION }, + { 0x002F, UCHAR_LINE_BREAK, U_LB_BREAK_SYMBOLS }, + { 0x1D49C, UCHAR_LINE_BREAK, U_LB_ALPHABETIC }, + { 0x1731, UCHAR_LINE_BREAK, U_LB_ALPHABETIC }, + + /* UCHAR_NUMERIC_TYPE tested in TestNumericProperties() */ + + /* UCHAR_SCRIPT tested in TestUScriptCodeAPI() */ + + { 0x1100, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, + { 0x1111, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, + { 0x1159, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, + { 0x115f, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO }, + + { 0x1160, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, + { 0x1161, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, + { 0x1172, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, + { 0x11a2, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO }, + + { 0x11a8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, + { 0x11b8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, + { 0x11c8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, + { 0x11f9, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO }, + + { 0x115a, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + { 0x115e, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + { 0x11a3, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + { 0x11a7, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + { 0x11fa, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + { 0x11ff, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + + { 0xac00, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE }, + { 0xac1c, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE }, + { 0xc5ec, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE }, + { 0xd788, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE }, + + { 0xac01, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE }, + { 0xac1b, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE }, + { 0xac1d, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE }, + { 0xc5ee, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE }, + { 0xd7a3, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE }, + + { 0xd7a4, UCHAR_HANGUL_SYLLABLE_TYPE, 0 }, + + { -1, 0x410, 0 }, /* version break for Unicode 4.1 */ + + { 0x00d7, UCHAR_PATTERN_SYNTAX, TRUE }, + { 0xfe45, UCHAR_PATTERN_SYNTAX, TRUE }, + { 0x0061, UCHAR_PATTERN_SYNTAX, FALSE }, + + { 0x0020, UCHAR_PATTERN_WHITE_SPACE, TRUE }, + { 0x0085, UCHAR_PATTERN_WHITE_SPACE, TRUE }, + { 0x200f, UCHAR_PATTERN_WHITE_SPACE, TRUE }, + { 0x00a0, UCHAR_PATTERN_WHITE_SPACE, FALSE }, + { 0x3000, UCHAR_PATTERN_WHITE_SPACE, FALSE }, + + { 0x1d200, UCHAR_BLOCK, UBLOCK_ANCIENT_GREEK_MUSICAL_NOTATION }, + { 0x2c8e, UCHAR_BLOCK, UBLOCK_COPTIC }, + { 0xfe17, UCHAR_BLOCK, UBLOCK_VERTICAL_FORMS }, + + { 0x1a00, UCHAR_SCRIPT, USCRIPT_BUGINESE }, + { 0x2cea, UCHAR_SCRIPT, USCRIPT_COPTIC }, + { 0xa82b, UCHAR_SCRIPT, USCRIPT_SYLOTI_NAGRI }, + { 0x103d0, UCHAR_SCRIPT, USCRIPT_OLD_PERSIAN }, + + { 0xcc28, UCHAR_LINE_BREAK, U_LB_H2 }, + { 0xcc29, UCHAR_LINE_BREAK, U_LB_H3 }, + { 0xac03, UCHAR_LINE_BREAK, U_LB_H3 }, + { 0x115f, UCHAR_LINE_BREAK, U_LB_JL }, + { 0x11aa, UCHAR_LINE_BREAK, U_LB_JT }, + { 0x11a1, UCHAR_LINE_BREAK, U_LB_JV }, + + { 0xb2c9, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_LVT }, + { 0x036f, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_EXTEND }, + { 0x0000, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_CONTROL }, + { 0x1160, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_V }, + + { 0x05f4, UCHAR_WORD_BREAK, U_WB_MIDLETTER }, + { 0x4ef0, UCHAR_WORD_BREAK, U_WB_OTHER }, + { 0x19d9, UCHAR_WORD_BREAK, U_WB_NUMERIC }, + { 0x2044, UCHAR_WORD_BREAK, U_WB_MIDNUM }, + + { 0xfffd, UCHAR_SENTENCE_BREAK, U_SB_OTHER }, + { 0x1ffc, UCHAR_SENTENCE_BREAK, U_SB_UPPER }, + { 0xff63, UCHAR_SENTENCE_BREAK, U_SB_CLOSE }, + { 0x2028, UCHAR_SENTENCE_BREAK, U_SB_SEP }, + + /* undefined UProperty values */ + { 0x61, 0x4a7, 0 }, + { 0x234bc, 0x15ed, 0 } + }; + + UVersionInfo version; + UChar32 c; + int32_t i, result, uVersion; + UProperty which; + + /* what is our Unicode version? */ + u_getUnicodeVersion(version); + uVersion=((int32_t)version[0]<<8)|(version[1]<<4)|version[2]; /* major/minor/update version numbers */ + + u_charAge(0x20, version); + if(version[0]==0) { + /* no additional properties available */ + log_err("TestAdditionalProperties: no additional properties available, not tested\n"); + return; + } + + /* test u_charAge() */ + for(i=0; i<sizeof(charAges)/sizeof(charAges[0]); ++i) { + u_charAge(charAges[i].c, version); + if(0!=memcmp(version, charAges[i].version, sizeof(UVersionInfo))) { + log_err("error: u_charAge(U+%04lx)={ %u, %u, %u, %u } instead of { %u, %u, %u, %u }\n", + charAges[i].c, + version[0], version[1], version[2], version[3], + charAges[i].version[0], charAges[i].version[1], charAges[i].version[2], charAges[i].version[3]); + } + } + + if( u_getIntPropertyMinValue(UCHAR_DASH)!=0 || + u_getIntPropertyMinValue(UCHAR_BIDI_CLASS)!=0 || + u_getIntPropertyMinValue(UCHAR_BLOCK)!=0 || /* j2478 */ + u_getIntPropertyMinValue(UCHAR_SCRIPT)!=0 || /*JB#2410*/ + u_getIntPropertyMinValue(0x2345)!=0 + ) { + log_err("error: u_getIntPropertyMinValue() wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_DASH)!=1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_DASH) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE)!=1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE) wrong\n"); + } + if( u_getIntPropertyMaxValue((UProperty)(UCHAR_BINARY_LIMIT-1))!=1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_BINARY_LIMIT-1) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)!=(int32_t)U_CHAR_DIRECTION_COUNT-1 ) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_BLOCK)!=(int32_t)UBLOCK_COUNT-1 ) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_BLOCK) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_LINE_BREAK)!=(int32_t)U_LB_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_LINE_BREAK) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_SCRIPT)!=(int32_t)USCRIPT_CODE_LIMIT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_SCRIPT) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE)!=(int32_t)U_NT_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY)!=(int32_t)U_CHAR_CATEGORY_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE)!=(int32_t)U_HST_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK)!=(int32_t)U_GCB_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK)!=(int32_t)U_SB_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK) wrong\n"); + } + if(u_getIntPropertyMaxValue(UCHAR_WORD_BREAK)!=(int32_t)U_WB_COUNT-1) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_WORD_BREAK) wrong\n"); + } + /*JB#2410*/ + if( u_getIntPropertyMaxValue(0x2345)!=-1) { + log_err("error: u_getIntPropertyMaxValue(0x2345) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) != (int32_t) (U_DT_COUNT - 1)) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) != (int32_t) (U_JG_COUNT -1)) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) != (int32_t) (U_JT_COUNT -1)) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) wrong\n"); + } + if( u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) != (int32_t) (U_EA_COUNT -1)) { + log_err("error: u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) wrong\n"); + } + + /* test u_hasBinaryProperty() and u_getIntPropertyValue() */ + for(i=0; i<sizeof(props)/sizeof(props[0]); ++i) { + if(props[i][0]<0) { + /* Unicode version break */ + if(uVersion<props[i][1]) { + break; /* do not test properties that are not yet supported */ + } else { + continue; /* skip this row */ + } + } + + c=(UChar32)props[i][0]; + which=(UProperty)props[i][1]; + + if(which<UCHAR_INT_START) { + result=u_hasBinaryProperty(c, which); + if(result!=props[i][2]) { + log_err("error: u_hasBinaryProperty(U+%04lx, %d)=%d is wrong (props[%d])\n", + c, which, result, i); + } + } + + result=u_getIntPropertyValue(c, which); + if(result!=props[i][2]) { + log_err("error: u_getIntPropertyValue(U+%04lx, 0x1000+%d)=%d is wrong, should be %d (props[%d])\n", + c, (int32_t)which-0x1000, result, props[i][2], i); + } + + /* test separate functions, too */ + switch((UProperty)props[i][1]) { + case UCHAR_ALPHABETIC: + if(u_isUAlphabetic((UChar32)props[i][0])!=(UBool)props[i][2]) { + log_err("error: u_isUAlphabetic(U+%04lx)=%d is wrong (props[%d])\n", + props[i][0], result, i); + } + break; + case UCHAR_LOWERCASE: + if(u_isULowercase((UChar32)props[i][0])!=(UBool)props[i][2]) { + log_err("error: u_isULowercase(U+%04lx)=%d is wrong (props[%d])\n", + props[i][0], result, i); + } + break; + case UCHAR_UPPERCASE: + if(u_isUUppercase((UChar32)props[i][0])!=(UBool)props[i][2]) { + log_err("error: u_isUUppercase(U+%04lx)=%d is wrong (props[%d])\n", + props[i][0], result, i); + } + break; + case UCHAR_WHITE_SPACE: + if(u_isUWhiteSpace((UChar32)props[i][0])!=(UBool)props[i][2]) { + log_err("error: u_isUWhiteSpace(U+%04lx)=%d is wrong (props[%d])\n", + props[i][0], result, i); + } + break; + default: + break; + } + } +} + +static void +TestNumericProperties(void) { + /* see UnicodeData.txt, DerivedNumericValues.txt */ + static const struct { + UChar32 c; + int32_t type; + double numValue; + } values[]={ + { 0x0F33, U_NT_NUMERIC, -1./2. }, + { 0x0C66, U_NT_DECIMAL, 0 }, + { 0x96f6, U_NT_NUMERIC, 0 }, + { 0x2159, U_NT_NUMERIC, 1./6. }, + { 0x00BD, U_NT_NUMERIC, 1./2. }, + { 0x0031, U_NT_DECIMAL, 1. }, + { 0x4e00, U_NT_NUMERIC, 1. }, + { 0x58f1, U_NT_NUMERIC, 1. }, + { 0x10320, U_NT_NUMERIC, 1. }, + { 0x0F2B, U_NT_NUMERIC, 3./2. }, + { 0x00B2, U_NT_DIGIT, 2. }, + { 0x5f10, U_NT_NUMERIC, 2. }, + { 0x1813, U_NT_DECIMAL, 3. }, + { 0x5f0e, U_NT_NUMERIC, 3. }, + { 0x2173, U_NT_NUMERIC, 4. }, + { 0x8086, U_NT_NUMERIC, 4. }, + { 0x278E, U_NT_DIGIT, 5. }, + { 0x1D7F2, U_NT_DECIMAL, 6. }, + { 0x247A, U_NT_DIGIT, 7. }, + { 0x7396, U_NT_NUMERIC, 9. }, + { 0x1372, U_NT_NUMERIC, 10. }, + { 0x216B, U_NT_NUMERIC, 12. }, + { 0x16EE, U_NT_NUMERIC, 17. }, + { 0x249A, U_NT_NUMERIC, 19. }, + { 0x303A, U_NT_NUMERIC, 30. }, + { 0x5345, U_NT_NUMERIC, 30. }, + { 0x32B2, U_NT_NUMERIC, 37. }, + { 0x1375, U_NT_NUMERIC, 40. }, + { 0x10323, U_NT_NUMERIC, 50. }, + { 0x0BF1, U_NT_NUMERIC, 100. }, + { 0x964c, U_NT_NUMERIC, 100. }, + { 0x217E, U_NT_NUMERIC, 500. }, + { 0x2180, U_NT_NUMERIC, 1000. }, + { 0x4edf, U_NT_NUMERIC, 1000. }, + { 0x2181, U_NT_NUMERIC, 5000. }, + { 0x137C, U_NT_NUMERIC, 10000. }, + { 0x4e07, U_NT_NUMERIC, 10000. }, + { 0x4ebf, U_NT_NUMERIC, 100000000. }, + { 0x5146, U_NT_NUMERIC, 1000000000000. }, + { 0x61, U_NT_NONE, U_NO_NUMERIC_VALUE }, + { 0x3000, U_NT_NONE, U_NO_NUMERIC_VALUE }, + { 0xfffe, U_NT_NONE, U_NO_NUMERIC_VALUE }, + { 0x10301, U_NT_NONE, U_NO_NUMERIC_VALUE }, + { 0xe0033, U_NT_NONE, U_NO_NUMERIC_VALUE }, + { 0x10ffff, U_NT_NONE, U_NO_NUMERIC_VALUE } + }; + + double nv; + UChar32 c; + int32_t i, type; + + for(i=0; i<LENGTHOF(values); ++i) { + c=values[i].c; + type=u_getIntPropertyValue(c, UCHAR_NUMERIC_TYPE); + nv=u_getNumericValue(c); + + if(type!=values[i].type) { + log_err("UCHAR_NUMERIC_TYPE(U+%04lx)=%d should be %d\n", c, type, values[i].type); + } + if(0.000001 <= fabs(nv - values[i].numValue)) { + log_err("u_getNumericValue(U+%04lx)=%g should be %g\n", c, nv, values[i].numValue); + } + } +} + +/** + * Test the property names and property value names API. + */ +static void +TestPropertyNames(void) { + int32_t p, v, choice=0, rev; + UBool atLeastSomething = FALSE; + + for (p=0; ; ++p) { + UProperty propEnum = (UProperty)p; + UBool sawProp = FALSE; + if(p > 10 && !atLeastSomething) { + log_data_err("Never got anything after 10 tries.\nYour data is probably fried. Quitting this test\n", p, choice); + return; + } + + for (choice=0; ; ++choice) { + const char* name = u_getPropertyName(propEnum, (UPropertyNameChoice)choice); + if (name) { + if (!sawProp) + log_verbose("prop 0x%04x+%2d:", p&~0xfff, p&0xfff); + log_verbose("%d=\"%s\"", choice, name); + sawProp = TRUE; + atLeastSomething = TRUE; + + /* test reverse mapping */ + rev = u_getPropertyEnum(name); + if (rev != p) { + log_err("Property round-trip failure: %d -> %s -> %d\n", + p, name, rev); + } + } + if (!name && choice>0) break; + } + if (sawProp) { + /* looks like a valid property; check the values */ + const char* pname = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME); + int32_t max = 0; + if (p == UCHAR_CANONICAL_COMBINING_CLASS) { + max = 255; + } else if (p == UCHAR_GENERAL_CATEGORY_MASK) { + /* it's far too slow to iterate all the way up to + the real max, U_GC_P_MASK */ + max = U_GC_NL_MASK; + } else if (p == UCHAR_BLOCK) { + /* UBlockCodes, unlike other values, start at 1 */ + max = 1; + } + log_verbose("\n"); + for (v=-1; ; ++v) { + UBool sawValue = FALSE; + for (choice=0; ; ++choice) { + const char* vname = u_getPropertyValueName(propEnum, v, (UPropertyNameChoice)choice); + if (vname) { + if (!sawValue) log_verbose(" %s, value %d:", pname, v); + log_verbose("%d=\"%s\"", choice, vname); + sawValue = TRUE; + + /* test reverse mapping */ + rev = u_getPropertyValueEnum(p, vname); + if (rev != v) { + log_err("Value round-trip failure (%s): %d -> %s -> %d\n", + pname, v, vname, rev); + } + } + if (!vname && choice>0) break; + } + if (sawValue) { + log_verbose("\n"); + } + if (!sawValue && v>=max) break; + } + } + if (!sawProp) { + if (p>=UCHAR_STRING_LIMIT) { + break; + } else if (p>=UCHAR_DOUBLE_LIMIT) { + p = UCHAR_STRING_START - 1; + } else if (p>=UCHAR_MASK_LIMIT) { + p = UCHAR_DOUBLE_START - 1; + } else if (p>=UCHAR_INT_LIMIT) { + p = UCHAR_MASK_START - 1; + } else if (p>=UCHAR_BINARY_LIMIT) { + p = UCHAR_INT_START - 1; + } + } + } +} + +/** + * Test the property values API. See JB#2410. + */ +static void +TestPropertyValues(void) { + int32_t i, p, min, max; + UErrorCode ec; + + /* Min should be 0 for everything. */ + /* Until JB#2478 is fixed, the one exception is UCHAR_BLOCK. */ + for (p=UCHAR_INT_START; p<UCHAR_INT_LIMIT; ++p) { + UProperty propEnum = (UProperty)p; + min = u_getIntPropertyMinValue(propEnum); + if (min != 0) { + if (p == UCHAR_BLOCK) { + /* This is okay...for now. See JB#2487. + TODO Update this for JB#2487. */ + } else { + const char* name; + name = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME); + if (name == NULL) + name = "<ERROR>"; + log_err("FAIL: u_getIntPropertyMinValue(%s) = %d, exp. 0\n", + name, min); + } + } + } + + if( u_getIntPropertyMinValue(UCHAR_GENERAL_CATEGORY_MASK)!=0 || + u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY_MASK)!=-1) { + log_err("error: u_getIntPropertyMin/MaxValue(UCHAR_GENERAL_CATEGORY_MASK) is wrong\n"); + } + + /* Max should be -1 for invalid properties. */ + max = u_getIntPropertyMaxValue(UCHAR_INVALID_CODE); + if (max != -1) { + log_err("FAIL: u_getIntPropertyMaxValue(-1) = %d, exp. -1\n", + max); + } + + /* Script should return USCRIPT_INVALID_CODE for an invalid code point. */ + for (i=0; i<2; ++i) { + int32_t script; + const char* desc; + ec = U_ZERO_ERROR; + switch (i) { + case 0: + script = uscript_getScript(-1, &ec); + desc = "uscript_getScript(-1)"; + break; + case 1: + script = u_getIntPropertyValue(-1, UCHAR_SCRIPT); + desc = "u_getIntPropertyValue(-1, UCHAR_SCRIPT)"; + break; + default: + log_err("Internal test error. Too many scripts\n"); + return; + } + /* We don't explicitly test ec. It should be U_FAILURE but it + isn't documented as such. */ + if (script != (int32_t)USCRIPT_INVALID_CODE) { + log_err("FAIL: %s = %d, exp. 0\n", + desc, script); + } + } +} + +/* add characters from a serialized set to a normal one */ +static void +_setAddSerialized(USet *set, const USerializedSet *sset) { + UChar32 start, end; + int32_t i, count; + + count=uset_getSerializedRangeCount(sset); + for(i=0; i<count; ++i) { + uset_getSerializedRange(sset, i, &start, &end); + uset_addRange(set, start, end); + } +} + +/* various tests for consistency of UCD data and API behavior */ +static void +TestConsistency() { +#if !UCONFIG_NO_NORMALIZATION + UChar buffer16[300]; +#endif + char buffer[300]; + USet *set1, *set2, *set3, *set4; + UErrorCode errorCode; + +#if !UCONFIG_NO_NORMALIZATION + USerializedSet sset; +#endif + UChar32 start, end; + int32_t i, length; + + U_STRING_DECL(hyphenPattern, "[:Hyphen:]", 10); + U_STRING_DECL(dashPattern, "[:Dash:]", 8); + U_STRING_DECL(lowerPattern, "[:Lowercase:]", 13); + U_STRING_DECL(formatPattern, "[:Cf:]", 6); + U_STRING_DECL(alphaPattern, "[:Alphabetic:]", 14); + + U_STRING_DECL(mathBlocksPattern, + "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]", + 1+32+46+46+45+43+1+1); /* +1 for NUL */ + U_STRING_DECL(mathPattern, "[:Math:]", 8); + U_STRING_DECL(unassignedPattern, "[:Cn:]", 6); + U_STRING_DECL(unknownPattern, "[:sc=Unknown:]", 14); + U_STRING_DECL(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20); + + U_STRING_INIT(hyphenPattern, "[:Hyphen:]", 10); + U_STRING_INIT(dashPattern, "[:Dash:]", 8); + U_STRING_INIT(lowerPattern, "[:Lowercase:]", 13); + U_STRING_INIT(formatPattern, "[:Cf:]", 6); + U_STRING_INIT(alphaPattern, "[:Alphabetic:]", 14); + + U_STRING_INIT(mathBlocksPattern, + "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]", + 1+32+46+46+45+43+1+1); /* +1 for NUL */ + U_STRING_INIT(mathPattern, "[:Math:]", 8); + U_STRING_INIT(unassignedPattern, "[:Cn:]", 6); + U_STRING_INIT(unknownPattern, "[:sc=Unknown:]", 14); + U_STRING_INIT(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20); + + /* + * It used to be that UCD.html and its precursors said + * "Those dashes used to mark connections between pieces of words, + * plus the Katakana middle dot." + * + * Unicode 4 changed 00AD Soft Hyphen to Cf and removed it from Dash + * but not from Hyphen. + * UTC 94 (2003mar) decided to leave it that way and to changed UCD.html. + * Therefore, do not show errors when testing the Hyphen property. + */ + log_verbose("Starting with Unicode 4, inconsistencies with [:Hyphen:] are\n" + "known to the UTC and not considered errors.\n"); + + errorCode=U_ZERO_ERROR; + set1=uset_openPattern(hyphenPattern, 10, &errorCode); + set2=uset_openPattern(dashPattern, 8, &errorCode); + if(U_SUCCESS(errorCode)) { + /* remove the Katakana middle dot(s) from set1 */ + uset_remove(set1, 0x30fb); + uset_remove(set1, 0xff65); /* halfwidth variant */ + showAMinusB(set1, set2, "[:Hyphen:]", "[:Dash:]", FALSE); + } else { + log_err("error opening [:Hyphen:] or [:Dash:] - %s\n", u_errorName(errorCode)); + } + + /* check that Cf is neither Hyphen nor Dash nor Alphabetic */ + set3=uset_openPattern(formatPattern, 6, &errorCode); + set4=uset_openPattern(alphaPattern, 14, &errorCode); + if(U_SUCCESS(errorCode)) { + showAIntersectB(set3, set1, "[:Cf:]", "[:Hyphen:]", FALSE); + showAIntersectB(set3, set2, "[:Cf:]", "[:Dash:]", TRUE); + showAIntersectB(set3, set4, "[:Cf:]", "[:Alphabetic:]", TRUE); + } else { + log_err("error opening [:Cf:] or [:Alpbabetic:] - %s\n", u_errorName(errorCode)); + } + + uset_close(set1); + uset_close(set2); + uset_close(set3); + uset_close(set4); + + /* + * Check that each lowercase character has "small" in its name + * and not "capital". + * There are some such characters, some of which seem odd. + * Use the verbose flag to see these notices. + */ + errorCode=U_ZERO_ERROR; + set1=uset_openPattern(lowerPattern, 13, &errorCode); + if(U_SUCCESS(errorCode)) { + for(i=0;; ++i) { + length=uset_getItem(set1, i, &start, &end, NULL, 0, &errorCode); + if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) { + break; /* done */ + } + if(U_FAILURE(errorCode)) { + log_err("error iterating over [:Lowercase:] at item %d: %s\n", + i, u_errorName(errorCode)); + break; + } + if(length!=0) { + break; /* done with code points, got a string or -1 */ + } + + while(start<=end) { + length=u_charName(start, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error getting the name of U+%04x - %s\n", start, u_errorName(errorCode)); + errorCode=U_ZERO_ERROR; + continue; + } + if( (strstr(buffer, "SMALL")==NULL || strstr(buffer, "CAPITAL")!=NULL) && + strstr(buffer, "SMALL CAPITAL")==NULL + ) { + log_verbose("info: [:Lowercase:] contains U+%04x whose name does not suggest lowercase: %s\n", start, buffer); + } + ++start; + } + } + } else { + log_err("error opening [:Lowercase:] - %s\n", u_errorName(errorCode)); + } + uset_close(set1); + +#if !UCONFIG_NO_NORMALIZATION + + /* + * Test for an example that unorm_getCanonStartSet() delivers + * all characters that compose from the input one, + * even in multiple steps. + * For example, the set for "I" (0049) should contain both + * I-diaeresis (00CF) and I-diaeresis-acute (1E2E). + * In general, the set for the middle such character should be a subset + * of the set for the first. + */ + set1=uset_open(1, 0); + set2=uset_open(1, 0); + + if (unorm_getCanonStartSet(0x49, &sset)) { + _setAddSerialized(set1, &sset); + + /* enumerate all characters that are plausible to be latin letters */ + for(start=0xa0; start<0x2000; ++start) { + if(unorm_getDecomposition(start, FALSE, buffer16, LENGTHOF(buffer16))>1 && buffer16[0]==0x49) { + uset_add(set2, start); + } + } + + compareUSets(set1, set2, + "[canon start set of 0049]", "[all c with canon decomp with 0049]", + TRUE); + } else { + log_err("error calling unorm_getCanonStartSet()\n"); + } + + uset_close(set1); + uset_close(set2); + +#endif + + /* verify that all assigned characters in Math blocks are exactly Math characters */ + errorCode=U_ZERO_ERROR; + set1=uset_openPattern(mathBlocksPattern, -1, &errorCode); + set2=uset_openPattern(mathPattern, 8, &errorCode); + set3=uset_openPattern(unassignedPattern, 6, &errorCode); + if(U_SUCCESS(errorCode)) { + uset_retainAll(set2, set1); /* [math blocks]&[:Math:] */ + uset_complement(set3); /* assigned characters */ + uset_retainAll(set1, set3); /* [math blocks]&[assigned] */ + compareUSets(set1, set2, + "[assigned Math block chars]", "[math blocks]&[:Math:]", + TRUE); + } else { + log_err("error opening [math blocks] or [:Math:] or [:Cn:] - %s\n", u_errorName(errorCode)); + } + uset_close(set1); + uset_close(set2); + uset_close(set3); + + /* new in Unicode 5.0: exactly all unassigned+PUA+surrogate code points have script=Unknown */ + errorCode=U_ZERO_ERROR; + set1=uset_openPattern(unknownPattern, 14, &errorCode); + set2=uset_openPattern(reservedPattern, 20, &errorCode); + if(U_SUCCESS(errorCode)) { + compareUSets(set1, set2, + "[:sc=Unknown:]", "[[:Cn:][:Co:][:Cs:]]", + TRUE); + } else { + log_err("error opening [:sc=Unknown:] or [[:Cn:][:Co:][:Cs:]] - %s\n", u_errorName(errorCode)); + } + uset_close(set1); + uset_close(set2); +} + +/* + * Starting with ICU4C 3.4, the core Unicode properties files + * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu) + * are hardcoded in the common DLL and therefore not included + * in the data package any more. + * Test requiring these files are disabled so that + * we need not jump through hoops (like adding snapshots of these files + * to testdata). + * See Jitterbug 4497. + */ +#define HARDCODED_DATA_4497 1 + +/* API coverage for ucase.c */ +static void TestUCase() { +#if !HARDCODED_DATA_4497 + UDataMemory *pData; + UCaseProps *csp; +#endif + const UCaseProps *ccsp; + UErrorCode errorCode; + +#if !HARDCODED_DATA_4497 + /* coverage for ucase_openBinary() */ + errorCode=U_ZERO_ERROR; + pData=udata_open(NULL, UCASE_DATA_TYPE, UCASE_DATA_NAME, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("unable to open " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n", + u_errorName(errorCode)); + return; + } + + csp=ucase_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucase_openBinary() fails for the contents of " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n", + u_errorName(errorCode)); + udata_close(pData); + return; + } + + if(UCASE_LOWER!=ucase_getType(csp, 0xdf)) { /* verify islower(sharp s) */ + log_err("ucase_openBinary() does not seem to return working UCaseProps\n"); + } + + ucase_close(csp); + udata_close(pData); +#endif + + /* coverage for ucase_getDummy() */ + errorCode=U_ZERO_ERROR; + ccsp=ucase_getDummy(&errorCode); + if(ucase_tolower(ccsp, 0x41)!=0x41) { + log_err("ucase_tolower(dummy, A)!=A\n"); + } +} + +/* API coverage for ubidi_props.c */ +static void TestUBiDiProps() { +#if !HARDCODED_DATA_4497 + UDataMemory *pData; + UBiDiProps *bdp; +#endif + const UBiDiProps *cbdp; + UErrorCode errorCode; + +#if !HARDCODED_DATA_4497 + /* coverage for ubidi_openBinary() */ + errorCode=U_ZERO_ERROR; + pData=udata_open(NULL, UBIDI_DATA_TYPE, UBIDI_DATA_NAME, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("unable to open " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n", + u_errorName(errorCode)); + return; + } + + bdp=ubidi_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ubidi_openBinary() fails for the contents of " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n", + u_errorName(errorCode)); + udata_close(pData); + return; + } + + if(0x2215!=ubidi_getMirror(bdp, 0x29F5)) { /* verify some data */ + log_err("ubidi_openBinary() does not seem to return working UBiDiProps\n"); + } + + ubidi_closeProps(bdp); + udata_close(pData); +#endif + + /* coverage for ubidi_getDummy() */ + errorCode=U_ZERO_ERROR; + cbdp=ubidi_getDummy(&errorCode); + if(ubidi_getClass(cbdp, 0x20)!=0) { + log_err("ubidi_getClass(dummy, space)!=0\n"); + } +} + +/* test case folding, compare return values with CaseFolding.txt ------------ */ + +/* bit set for which case foldings for a character have been tested already */ +enum { + CF_SIMPLE=1, + CF_FULL=2, + CF_TURKIC=4, + CF_ALL=7 +}; + +static void +testFold(UChar32 c, int which, + UChar32 simple, UChar32 turkic, + const UChar *full, int32_t fullLength, + const UChar *turkicFull, int32_t turkicFullLength) { + UChar s[2], t[32]; + UChar32 c2; + int32_t length, length2; + + UErrorCode errorCode=U_ZERO_ERROR; + + length=0; + U16_APPEND_UNSAFE(s, length, c); + + if((which&CF_SIMPLE)!=0 && (c2=u_foldCase(c, 0))!=simple) { + log_err("u_foldCase(U+%04lx, default)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple); + } + if((which&CF_FULL)!=0) { + length2=u_strFoldCase(t, LENGTHOF(t), s, length, 0, &errorCode); + if(length2!=fullLength || 0!=u_memcmp(t, full, fullLength)) { + log_err("u_strFoldCase(U+%04lx, default) does not fold properly\n", (long)c); + } + } + if((which&CF_TURKIC)!=0) { + if((c2=u_foldCase(c, U_FOLD_CASE_EXCLUDE_SPECIAL_I))!=turkic) { + log_err("u_foldCase(U+%04lx, turkic)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple); + } + + length2=u_strFoldCase(t, LENGTHOF(t), s, length, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); + if(length2!=turkicFullLength || 0!=u_memcmp(t, turkicFull, length2)) { + log_err("u_strFoldCase(U+%04lx, turkic) does not fold properly\n", (long)c); + } + } +} + +/* test that c case-folds to itself */ +static void +testFoldToSelf(UChar32 c, int which) { + UChar s[2]; + int32_t length; + + length=0; + U16_APPEND_UNSAFE(s, length, c); + testFold(c, which, c, c, s, length, s, length); +} + +struct CaseFoldingData { + USet *notSeen; + UChar32 prev, prevSimple; + UChar prevFull[32]; + int32_t prevFullLength; + int which; +}; +typedef struct CaseFoldingData CaseFoldingData; + +static void U_CALLCONV +caseFoldingLineFn(void *context, + char *fields[][2], int32_t fieldCount, + UErrorCode *pErrorCode) { + CaseFoldingData *pData=(CaseFoldingData *)context; + char *end; + UChar full[32]; + UChar32 c, prev, simple; + int32_t count; + int which; + char status; + + /* get code point */ + c=(UChar32)strtoul(u_skipWhitespace(fields[0][0]), &end, 16); + end=(char *)u_skipWhitespace(end); + if(end<=fields[0][0] || end!=fields[0][1]) { + log_err("syntax error in CaseFolding.txt field 0 at %s\n", fields[0][0]); + *pErrorCode=U_PARSE_ERROR; + return; + } + + /* get the status of this mapping */ + status=*u_skipWhitespace(fields[1][0]); + if(status!='C' && status!='S' && status!='F' && status!='T') { + log_err("unrecognized status field in CaseFolding.txt at %s\n", fields[0][0]); + *pErrorCode=U_PARSE_ERROR; + return; + } + + /* get the mapping */ + count=u_parseString(fields[2][0], full, 32, (uint32_t *)&simple, pErrorCode); + if(U_FAILURE(*pErrorCode)) { + log_err("error parsing CaseFolding.txt mapping at %s\n", fields[0][0]); + return; + } + + /* there is a simple mapping only if there is exactly one code point (count is in UChars) */ + if(count==0 || count>2 || (count==2 && U16_IS_SINGLE(full[1]))) { + simple=c; + } + + if(c!=(prev=pData->prev)) { + /* + * Test remaining mappings for the previous code point. + * If a turkic folding was not mentioned, then it should fold the same + * as the regular simple case folding. + */ + UChar s[2]; + int32_t length; + + length=0; + U16_APPEND_UNSAFE(s, length, prev); + testFold(prev, (~pData->which)&CF_ALL, + prev, pData->prevSimple, + s, length, + pData->prevFull, pData->prevFullLength); + pData->prev=pData->prevSimple=c; + length=0; + U16_APPEND_UNSAFE(pData->prevFull, length, c); + pData->prevFullLength=length; + pData->which=0; + } + + /* + * Turn the status into a bit set of case foldings to test. + * Remember non-Turkic case foldings as defaults for Turkic mode. + */ + switch(status) { + case 'C': + which=CF_SIMPLE|CF_FULL; + pData->prevSimple=simple; + u_memcpy(pData->prevFull, full, count); + pData->prevFullLength=count; + break; + case 'S': + which=CF_SIMPLE; + pData->prevSimple=simple; + break; + case 'F': + which=CF_FULL; + u_memcpy(pData->prevFull, full, count); + pData->prevFullLength=count; + break; + case 'T': + which=CF_TURKIC; + break; + default: + which=0; + break; /* won't happen because of test above */ + } + + testFold(c, which, simple, simple, full, count, full, count); + + /* remember which case foldings of c have been tested */ + pData->which|=which; + + /* remove c from the set of ones not mentioned in CaseFolding.txt */ + uset_remove(pData->notSeen, c); +} + +static void +TestCaseFolding() { + CaseFoldingData data={ NULL }; + char *fields[3][2]; + UErrorCode errorCode; + + static char *lastLine= (char *)"10FFFF; C; 10FFFF;"; + + errorCode=U_ZERO_ERROR; + /* test BMP & plane 1 - nothing interesting above */ + data.notSeen=uset_open(0, 0x1ffff); + data.prevFullLength=1; /* length of full case folding of U+0000 */ + + parseUCDFile("CaseFolding.txt", fields, 3, caseFoldingLineFn, &data, &errorCode); + if(U_SUCCESS(errorCode)) { + int32_t i, start, end; + + /* add a pseudo-last line to finish testing of the actual last one */ + fields[0][0]=lastLine; + fields[0][1]=lastLine+6; + fields[1][0]=lastLine+7; + fields[1][1]=lastLine+9; + fields[2][0]=lastLine+10; + fields[2][1]=lastLine+17; + caseFoldingLineFn(&data, fields, 3, &errorCode); + + /* verify that all code points that are not mentioned in CaseFolding.txt fold to themselves */ + for(i=0; + 0==uset_getItem(data.notSeen, i, &start, &end, NULL, 0, &errorCode) && + U_SUCCESS(errorCode); + ++i + ) { + do { + testFoldToSelf(start, CF_ALL); + } while(++start<=end); + } + } + + uset_close(data.notSeen); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c new file mode 100644 index 00000000000..adce0854037 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c @@ -0,0 +1,243 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2005-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#include "unicode/unum.h" +#include "unicode/ucurr.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "cstring.h" + +static void expectInList(const char *isoCurrency, uint32_t currencyType, UBool isExpected) { + UErrorCode status = U_ZERO_ERROR; + const char *foundCurrency = NULL; + const char *currentCurrency; + UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status); + if (U_FAILURE(status)) { + log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status)); + return; + } + + while ((currentCurrency = uenum_next(en, NULL, &status)) != NULL) { + if (strcmp(isoCurrency, currentCurrency) == 0) { + foundCurrency = currentCurrency; + break; + } + } + + if ((foundCurrency != NULL) != isExpected) { + log_err("Error: could not find %s as expected. isExpected = %s type=0x%X\n", + isoCurrency, isExpected ? "TRUE" : "FALSE", currencyType); + } + uenum_close(en); +} + +static void TestEnumList(void) { + expectInList("ADP", UCURR_ALL, TRUE); /* First in list */ + expectInList("ZWD", UCURR_ALL, TRUE); /* Last in list */ + + expectInList("USD", UCURR_ALL, TRUE); + expectInList("USD", UCURR_COMMON, TRUE); + expectInList("USD", UCURR_UNCOMMON, FALSE); + expectInList("USD", UCURR_DEPRECATED, FALSE); + expectInList("USD", UCURR_NON_DEPRECATED, TRUE); + expectInList("USD", UCURR_COMMON|UCURR_DEPRECATED, FALSE); + expectInList("USD", UCURR_COMMON|UCURR_NON_DEPRECATED, TRUE); + expectInList("USD", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE); + expectInList("USD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE); + + expectInList("USN", UCURR_ALL, TRUE); + expectInList("USN", UCURR_COMMON, FALSE); + expectInList("USN", UCURR_UNCOMMON, TRUE); + expectInList("USN", UCURR_DEPRECATED, FALSE); + expectInList("USN", UCURR_NON_DEPRECATED, TRUE); + expectInList("USN", UCURR_COMMON|UCURR_DEPRECATED, FALSE); + expectInList("USN", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE); + expectInList("USN", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE); + expectInList("USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, TRUE); + + expectInList("DEM", UCURR_ALL, TRUE); + expectInList("DEM", UCURR_COMMON, TRUE); + expectInList("DEM", UCURR_UNCOMMON, FALSE); + expectInList("DEM", UCURR_DEPRECATED, TRUE); + expectInList("DEM", UCURR_NON_DEPRECATED, FALSE); + expectInList("DEM", UCURR_COMMON|UCURR_DEPRECATED, TRUE); + expectInList("DEM", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE); + expectInList("DEM", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE); + expectInList("DEM", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE); + + expectInList("XEU", UCURR_ALL, TRUE); + expectInList("XEU", UCURR_COMMON, FALSE); + expectInList("XEU", UCURR_UNCOMMON, TRUE); + expectInList("XEU", UCURR_DEPRECATED, TRUE); + expectInList("XEU", UCURR_NON_DEPRECATED, FALSE); + expectInList("XEU", UCURR_COMMON|UCURR_DEPRECATED, FALSE); + expectInList("XEU", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE); + expectInList("XEU", UCURR_UNCOMMON|UCURR_DEPRECATED, TRUE); + expectInList("XEU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE); + +} + +static void TestEnumListReset(void) { + UErrorCode status = U_ZERO_ERROR; + const char *currency1; + const char *currency2; + UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &status); + if (U_FAILURE(status)) { + log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status)); + return; + } + + currency1 = uenum_next(en, NULL, &status); + uenum_reset(en, &status); + currency2 = uenum_next(en, NULL, &status); + if (U_FAILURE(status)) { + log_err("Error: uenum_next or uenum_reset returned %s\n", myErrorName(status)); + return; + } + /* The first item's pointer in the list should be the same between resets. */ + if (currency1 != currency2) { + log_err("Error: reset doesn't work %s != %s\n", currency1, currency2); + } + uenum_close(en); +} + +static int32_t checkItemCount(uint32_t currencyType) { + UErrorCode status = U_ZERO_ERROR; + int32_t originalCount, count; + UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status); + int32_t expectedLen = 3, len; + if (U_FAILURE(status)) { + log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status)); + return -1; + } + + originalCount = uenum_count(en, &status); + for (count=0;;count++) { + const char *str = uenum_next(en, &len, &status); + if (str == NULL || len != expectedLen || strlen(str) != expectedLen) { + break; + } + } + + if (originalCount != count) { + log_err("Error: uenum_count returned the wrong value (type = 0x%X). Got: %d Expected %d\n", + currencyType, count, originalCount); + } + if (U_FAILURE(status)) { + log_err("Error: uenum_next got an error: %s\n", u_errorName(status)); + } + uenum_close(en); + return count; +} + +static void TestEnumListCount(void) { + checkItemCount(UCURR_ALL); + checkItemCount(UCURR_COMMON); + checkItemCount(UCURR_UNCOMMON); + checkItemCount(UCURR_DEPRECATED); + checkItemCount(UCURR_NON_DEPRECATED); + checkItemCount(UCURR_COMMON|UCURR_DEPRECATED); + checkItemCount(UCURR_COMMON|UCURR_NON_DEPRECATED); + checkItemCount(UCURR_UNCOMMON|UCURR_DEPRECATED); + checkItemCount(UCURR_UNCOMMON|UCURR_NON_DEPRECATED); + + if (checkItemCount(UCURR_DEPRECATED|UCURR_NON_DEPRECATED) != 0) { + log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n"); + } + if (checkItemCount(UCURR_COMMON|UCURR_UNCOMMON) != 0) { + log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n"); + } +} + +static void TestFractionDigitOverride(void) { + UErrorCode status = U_ZERO_ERROR; + UNumberFormat *fmt = unum_open(UNUM_CURRENCY, NULL, 0, "hu_HU", NULL, &status); + UChar buffer[256]; + UChar expectedBuf[256]; + const char expectedFirst[] = "123,46 Ft"; + const char expectedSecond[] = "123 Ft"; + const char expectedThird[] = "123,456 Ft"; + if (U_FAILURE(status)) { + log_err("Error: unum_open returned %s\n", myErrorName(status)); + return; + } + /* Make sure that you can format normal fraction digits. */ + unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status); + u_charsToUChars(expectedFirst, expectedBuf, strlen(expectedFirst)+1); + if (u_strcmp(buffer, expectedBuf) != 0) { + log_err("Error: unum_formatDouble didn't return %s\n", expectedFirst); + } + /* Make sure that you can format no fraction digits. */ + unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 0); + unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status); + u_charsToUChars(expectedSecond, expectedBuf, strlen(expectedSecond)+1); + if (u_strcmp(buffer, expectedBuf) != 0) { + log_err("Error: unum_formatDouble didn't return %s\n", expectedSecond); + } + /* Make sure that you can format more fraction digits. */ + unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 3); + unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status); + u_charsToUChars(expectedThird, expectedBuf, strlen(expectedThird)+1); + if (u_strcmp(buffer, expectedBuf) != 0) { + log_err("Error: unum_formatDouble didn't return %s\n", expectedThird); + } + unum_close(fmt); +} + +static void TestPrefixSuffix(void) { + int32_t pos; + UErrorCode status; + double result1 = 0.0, result2 = 0.0; + UNumberFormat* parser; + UChar buffer[4]; + static const UChar TEST_NUMBER[] = {0x0024,0x0031,0x0032,0x002E,0x0030,0x0030,0}; /* $12.00 */ + static const UChar NEG_PREFIX[] = {0x005B,0}; /* "[" */ + static const UChar NEG_SUFFIX[] = {0x005D,0}; /* "]" */ + + + status = U_ZERO_ERROR; + parser = unum_open(UNUM_CURRENCY, NULL, -1, "en_US", NULL, &status); + if (U_FAILURE(status)) { + log_err("Error: unum_open returned %s\n", u_errorName(status)); + return; + } + + pos = 0; + status = U_ZERO_ERROR; + result1 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status); + + unum_setTextAttribute(parser, UNUM_NEGATIVE_SUFFIX, NEG_SUFFIX, -1, &status); + unum_setTextAttribute(parser, UNUM_NEGATIVE_PREFIX, NEG_PREFIX, -1, &status); + if (U_FAILURE(status)) { + log_err("Error: unum_setTextAttribute returned %s\n", u_errorName(status)); + return; + } + + pos = 0; + result2 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status); + if (result1 != result2 || U_FAILURE(status)) { + log_err("Error: unum_parseDoubleCurrency didn't return the same value for same string %f %f %s\n", + result1, result2, u_errorName(status)); + } + unum_close(parser); +} + +void addCurrencyTest(TestNode** root); + +#define TESTCASE(x) addTest(root, &x, "tsformat/currtest/" #x) + +void addCurrencyTest(TestNode** root) +{ + TESTCASE(TestEnumList); + TESTCASE(TestEnumListReset); + TESTCASE(TestEnumListCount); + TESTCASE(TestFractionDigitOverride); + TESTCASE(TestPrefixSuffix); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c new file mode 100644 index 00000000000..90cc00ae5c4 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c @@ -0,0 +1,1185 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2001-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File custrtrn.C +* +* Modification History: +* Name Description +* Ram String transformations test +********************************************************************************* +*/ +/****************************************************************************/ + + +#include <stdlib.h> +#include <stdio.h> +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/ures.h" +#include "ustr_imp.h" +#include "cintltst.h" +#include "cmemory.h" +#include "cstring.h" +#include "cwchar.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +void addUCharTransformTest(TestNode** root); + +static void Test_UChar_UTF32_API(void); +static void Test_UChar_UTF8_API(void); +static void Test_FromUTF8Lenient(void); +static void Test_UChar_WCHART_API(void); +static void Test_widestrs(void); +static void Test_WCHART_LongString(void); + +void +addUCharTransformTest(TestNode** root) +{ + addTest(root, &Test_UChar_UTF32_API, "custrtrn/Test_UChar_UTF32_API"); + addTest(root, &Test_UChar_UTF8_API, "custrtrn/Test_UChar_UTF8_API"); + addTest(root, &Test_FromUTF8Lenient, "custrtrn/Test_FromUTF8Lenient"); + addTest(root, &Test_UChar_WCHART_API, "custrtrn/Test_UChar_WCHART_API"); + addTest(root, &Test_widestrs, "custrtrn/Test_widestrs"); + addTest(root, &Test_WCHART_LongString, "custrtrn/Test_WCHART_LongString"); +} + +static const UChar32 src32[]={ + 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A, + 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A, + 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A, + 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A, + 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A, + 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A, + 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A, + 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A, + 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A, + 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A, + 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A, + 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A, + 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A, + 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A, + /* test non-BMP code points */ + 0x0002A699, + 0x0002A69C, 0x0002A69D, 0x0002A69E, 0x0002A69F, 0x0002A6A0, 0x0002A6A5, 0x0002A6A6, 0x0002A6A7, 0x0002A6A8, 0x0002A6AB, + 0x0002A6AC, 0x0002A6AD, 0x0002A6AE, 0x0002A6AF, 0x0002A6B0, 0x0002A6B1, 0x0002A6B3, 0x0002A6B5, 0x0002A6B6, 0x0002A6B7, + 0x0002A6B8, 0x0002A6B9, 0x0002A6BA, 0x0002A6BB, 0x0002A6BC, 0x0002A6BD, 0x0002A6BE, 0x0002A6BF, 0x0002A6C0, 0x0002A6C1, + 0x0002A6C2, 0x0002A6C3, 0x0002A6C4, 0x0002A6C8, 0x0002A6CA, 0x0002A6CB, 0x0002A6CD, 0x0002A6CE, 0x0002A6CF, 0x0002A6D0, + 0x0002A6D1, 0x0002A6D2, 0x0002A6D3, 0x0002A6D4, 0x0002A6D5, + + 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A, + 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A, + 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A, + 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,0x0000 +}; + +static const UChar src16[] = { + 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A, + 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A, + 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A, + 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A, + 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A, + 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A, + 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A, + 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A, + 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A, + 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A, + 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A, + 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A, + 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A, + 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A, + + /* test non-BMP code points */ + 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F, + 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8, + 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF, + 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6, + 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB, + 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0, + 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8, + 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF, + 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4, + 0xD869, 0xDED5, + + 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A, + 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A, + 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A, + 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,0x0000 +}; + + +static void Test_UChar_UTF32_API(void){ + + UErrorCode err = U_ZERO_ERROR; + UChar uTemp[1]; + UChar32 u32Temp[1]; + UChar* uTarget=uTemp; + const UChar32* u32Src = src32; + int32_t u32SrcLen = sizeof(src32)/4; + int32_t uTargetLength = 0; + int32_t uDestLen=0; + const UChar* uSrc = src16; + int32_t uSrcLen = sizeof(src16)/2; + UChar32* u32Target = u32Temp; + uint32_t u32TargetLength =0; + int32_t u32DestLen =0; + UBool failed = FALSE; + int i= 0; + { + /* preflight */ + u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + u32Target = (UChar32*) malloc (sizeof(uint32_t) * (u32DestLen+1)); + u32TargetLength = u32DestLen+1; + + u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err); + } + else { + log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR"); + } + failed = FALSE; + /*for(i=0; i< u32DestLen; i++){ + printf("0x%08X, ",uTarget[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + for(i=0; i< u32SrcLen; i++){ + if(u32Target[i] != src32[i]){ + log_verbose("u_strToUTF32() failed expected: \\U%08X got: \\U%08X at index: %i \n", src32[i], u32Target[i],i); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF32() failed \n"); + } + + /* preflight */ + u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1)); + uTargetLength = uDestLen+1; + u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err); + + } + /*for(i=0; i< uDestLen; i++){ + printf("0x%04X, ",uTarget[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + + for(i=0; i< uDestLen; i++){ + if(uTarget[i] != src16[i]){ + log_verbose("u_strFromUTF32() failed expected: \\U%08X got: \\U%08X at index: %i \n", src16[i] ,uTarget[i],i); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF32() failed \n"); + } + + free(u32Target); + free(uTarget); + } + { + u32SrcLen = -1; + uTargetLength = 0; + uSrcLen =-1; + u32TargetLength=0; + failed = FALSE; + + /* preflight */ + u_strToUTF32(NULL,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + u32Target = (UChar32*) malloc (sizeof(uint32_t) * (u32DestLen+1)); + u32TargetLength = u32DestLen+1; + + u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err); + } + else { + log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR"); + } + failed = FALSE; + + for(i=0; i< u32SrcLen; i++){ + if(u32Target[i] != src32[i]){ + log_verbose("u_strToUTF32() failed expected: \\U%08X got: \\U%08X \n", src32[i], u32Target[i]); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF32() failed \n"); + } + + /* preflight */ + u_strFromUTF32(NULL,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1)); + uTargetLength = uDestLen+1; + u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err); + + } + + for(i=0; i< uDestLen; i++){ + if(uTarget[i] != src16[i]){ + log_verbose("u_strFromUTF32() failed expected: \\U%08X got: \\U%08X \n", src16[i] ,uTarget[i]); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF32() failed \n"); + } + + free(u32Target); + free(uTarget); + } +} + + +static void Test_UChar_UTF8_API(void){ + + UErrorCode err = U_ZERO_ERROR; + UChar uTemp[1]; + char u8Temp[1]; + UChar* uTarget=uTemp; + const char* u8Src; + int32_t u8SrcLen = 0; + int32_t uTargetLength = 0; + int32_t uDestLen=0; + const UChar* uSrc = src16; + int32_t uSrcLen = sizeof(src16)/2; + char* u8Target = u8Temp; + int32_t u8TargetLength =0; + int32_t u8DestLen =0; + UBool failed = FALSE; + int i= 0; + int32_t numSubstitutions; + + { + /* preflight */ + u8Temp[0] = 0x12; + u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR && u8Temp[0] == 0x12){ + err = U_ZERO_ERROR; + u8Target = (char*) malloc (sizeof(uint8_t) * (u8DestLen+1)); + u8TargetLength = u8DestLen; + + u8Target[u8TargetLength] = (char)0xfe; + u8DestLen = -1; + u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err); + if(U_FAILURE(err) || u8DestLen != u8TargetLength || u8Target[u8TargetLength] != (char)0xfe){ + log_err("u_strToUTF8 failed after preflight. Error: %s\n", u_errorName(err)); + return; + } + + } + else { + log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR"); + } + failed = FALSE; + /*for(i=0; i< u8DestLen; i++){ + printf("0x%04X, ",u8Target[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + /*for(i=0; i< u8DestLen; i++){ + if(u8Target[i] != src8[i]){ + log_verbose("u_strToUTF8() failed expected: \\U%08X got: \\U%08X \n", src8[i], u8Target[i]); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF8() failed \n"); + }*/ + u8Src = u8Target; + u8SrcLen = u8DestLen; + + /* preflight */ + uTemp[0] = 0x1234; + u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR && uTemp[0] == 0x1234){ + err = U_ZERO_ERROR; + uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1)); + uTargetLength = uDestLen; + + uTarget[uTargetLength] = 0xfff0; + uDestLen = -1; + u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err); + } + else { + log_err("error: u_strFromUTF8(preflight) should have gotten U_BUFFER_OVERFLOW_ERROR\n"); + } + /*for(i=0; i< uDestLen; i++){ + printf("0x%04X, ",uTarget[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + + if(U_FAILURE(err) || uDestLen != uTargetLength || uTarget[uTargetLength] != 0xfff0) { + failed = TRUE; + } + for(i=0; i< uSrcLen; i++){ + if(uTarget[i] != src16[i]){ + log_verbose("u_strFromUTF8() failed expected: \\u%04X got: \\u%04X at index: %i \n", src16[i] ,uTarget[i],i); + failed =TRUE; + } + } + if(failed){ + log_err("error: u_strFromUTF8(after preflighting) failed\n"); + } + + free(u8Target); + free(uTarget); + } + { + u8SrcLen = -1; + uTargetLength = 0; + uSrcLen =-1; + u8TargetLength=0; + failed = FALSE; + /* preflight */ + u_strToUTF8(NULL,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + u8Target = (char*) malloc (sizeof(uint8_t) * (u8DestLen+1)); + u8TargetLength = u8DestLen; + + u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err); + + } + else { + log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR"); + } + failed = FALSE; + /*for(i=0; i< u8DestLen; i++){ + printf("0x%04X, ",u8Target[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + /*for(i=0; i< u8DestLen; i++){ + if(u8Target[i] != src8[i]){ + log_verbose("u_strToUTF8() failed expected: \\U%08X got: \\U%08X \n", src8[i], u8Target[i]); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF8() failed \n"); + }*/ + u8Src = u8Target; + u8SrcLen = u8DestLen; + + /* preflight */ + u_strFromUTF8(NULL,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err); + if(err == U_BUFFER_OVERFLOW_ERROR){ + err = U_ZERO_ERROR; + uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1)); + uTargetLength = uDestLen; + + u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err); + } + else { + log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR"); + } + /*for(i=0; i< uDestLen; i++){ + printf("0x%04X, ",uTarget[i]); + if(i%10==0){ + printf("\n"); + } + }*/ + + for(i=0; i< uSrcLen; i++){ + if(uTarget[i] != src16[i]){ + log_verbose("u_strFromUTF8() failed expected: \\u%04X got: \\u%04X at index: %i \n", src16[i] ,uTarget[i],i); + failed =TRUE; + } + } + if(failed){ + log_err("u_strToUTF8() failed \n"); + } + + free(u8Target); + free(uTarget); + } + + /* test UTF-8 with single surrogates - illegal in Unicode 3.2 */ + { + static const UChar + withLead16[]={ 0x1800, 0xd89a, 0x0061 }, + withTrail16[]={ 0x1800, 0xdcba, 0x0061, 0 }, + withTrail16SubFFFD[]={ 0x1800, 0xfffd, 0x0061, 0 }, /* sub==U+FFFD */ + withTrail16Sub50005[]={ 0x1800, 0xd900, 0xdc05, 0x0061, 0 }; /* sub==U+50005 */ + static const uint8_t + withLead8[]={ 0xe1, 0xa0, 0x80, 0xed, 0xa2, 0x9a, 0x61 }, + withTrail8[]={ 0xe1, 0xa0, 0x80, 0xed, 0xb2, 0xba, 0x61, 0 }, + withTrail8Sub1A[]={ 0xe1, 0xa0, 0x80, 0x1a, 0x61, 0 }, /* sub==U+001A */ + withTrail8SubFFFD[]={ 0xe1, 0xa0, 0x80, 0xef, 0xbf, 0xbd, 0x61, 0 }; /* sub==U+FFFD */ + UChar out16[10]; + char out8[10]; + + if( + (err=U_ZERO_ERROR, u_strToUTF8(out8, LENGTHOF(out8), NULL, withLead16, LENGTHOF(withLead16), &err), err!=U_INVALID_CHAR_FOUND) || + (err=U_ZERO_ERROR, u_strToUTF8(out8, LENGTHOF(out8), NULL, withTrail16, -1, &err), err!=U_INVALID_CHAR_FOUND) || + (err=U_ZERO_ERROR, u_strFromUTF8(out16, LENGTHOF(out16), NULL, (const char *)withLead8, LENGTHOF(withLead8), &err), err!=U_INVALID_CHAR_FOUND) || + (err=U_ZERO_ERROR, u_strFromUTF8(out16, LENGTHOF(out16), NULL, (const char *)withTrail8, -1, &err), err!=U_INVALID_CHAR_FOUND) + ) { + log_err("error: u_strTo/FromUTF8(string with single surrogate) fails to report error\n"); + } + + /* test error handling with substitution characters */ + + /* from UTF-8 with length */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out16[0]=0x55aa; + uDestLen=0; + u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen, + (const char *)withTrail8, uprv_strlen((const char *)withTrail8), + 0x50005, &numSubstitutions, + &err); + if(U_FAILURE(err) || uDestLen!=u_strlen(withTrail16Sub50005) || + 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen+1) || + numSubstitutions!=1) { + log_err("error: u_strFromUTF8WithSub(length) failed\n"); + } + + /* from UTF-8 with NUL termination */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out16[0]=0x55aa; + uDestLen=0; + u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen, + (const char *)withTrail8, -1, + 0xfffd, &numSubstitutions, + &err); + if(U_FAILURE(err) || uDestLen!=u_strlen(withTrail16SubFFFD) || + 0!=u_memcmp(withTrail16SubFFFD, out16, uDestLen+1) || + numSubstitutions!=1) { + log_err("error: u_strFromUTF8WithSub(NUL termination) failed\n"); + } + + /* preflight from UTF-8 with NUL termination */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out16[0]=0x55aa; + uDestLen=0; + u_strFromUTF8WithSub(out16, 1, &uDestLen, + (const char *)withTrail8, -1, + 0x50005, &numSubstitutions, + &err); + if(err!=U_BUFFER_OVERFLOW_ERROR || uDestLen!=u_strlen(withTrail16Sub50005) || numSubstitutions!=1) { + log_err("error: u_strFromUTF8WithSub(preflight/NUL termination) failed\n"); + } + + /* to UTF-8 with length */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out8[0]=(char)0xf5; + u8DestLen=0; + u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen, + withTrail16, u_strlen(withTrail16), + 0xfffd, &numSubstitutions, + &err); + if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) || + 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen+1) || + numSubstitutions!=1) { + log_err("error: u_strToUTF8WithSub(length) failed\n"); + } + + /* to UTF-8 with NUL termination */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out8[0]=(char)0xf5; + u8DestLen=0; + u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen, + withTrail16, -1, + 0x1a, &numSubstitutions, + &err); + if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8Sub1A) || + 0!=uprv_memcmp((const char *)withTrail8Sub1A, out8, u8DestLen+1) || + numSubstitutions!=1) { + log_err("error: u_strToUTF8WithSub(NUL termination) failed\n"); + } + + /* preflight to UTF-8 with NUL termination */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out8[0]=(char)0xf5; + u8DestLen=0; + u_strToUTF8WithSub(out8, 1, &u8DestLen, + withTrail16, -1, + 0xfffd, &numSubstitutions, + &err); + if(err!=U_BUFFER_OVERFLOW_ERROR || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) || + numSubstitutions!=1) { + log_err("error: u_strToUTF8WithSub(preflight/NUL termination) failed\n"); + } + + /* test that numSubstitutions==0 if there are no substitutions */ + + /* from UTF-8 with length (just first 3 bytes which are valid) */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out16[0]=0x55aa; + uDestLen=0; + u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen, + (const char *)withTrail8, 3, + 0x50005, &numSubstitutions, + &err); + if(U_FAILURE(err) || uDestLen!=1 || + 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen) || + numSubstitutions!=0) { + log_err("error: u_strFromUTF8WithSub(no subs) failed\n"); + } + + /* to UTF-8 with length (just first UChar which is valid) */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out8[0]=(char)0xf5; + u8DestLen=0; + u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen, + withTrail16, 1, + 0xfffd, &numSubstitutions, + &err); + if(U_FAILURE(err) || u8DestLen!=3 || + 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen) || + numSubstitutions!=0) { + log_err("error: u_strToUTF8WithSub(no subs) failed\n"); + } + + /* test that numSubstitutions==0 if subchar==U_SENTINEL (no subchar) */ + + /* from UTF-8 with length (just first 3 bytes which are valid) */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out16[0]=0x55aa; + uDestLen=0; + u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen, + (const char *)withTrail8, 3, + U_SENTINEL, &numSubstitutions, + &err); + if(U_FAILURE(err) || uDestLen!=1 || + 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen) || + numSubstitutions!=0) { + log_err("error: u_strFromUTF8WithSub(no subchar) failed\n"); + } + + /* to UTF-8 with length (just first UChar which is valid) */ + err=U_ZERO_ERROR; + numSubstitutions=-1; + out8[0]=(char)0xf5; + u8DestLen=0; + u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen, + withTrail16, 1, + U_SENTINEL, &numSubstitutions, + &err); + if(U_FAILURE(err) || u8DestLen!=3 || + 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen) || + numSubstitutions!=0) { + log_err("error: u_strToUTF8WithSub(no subchar) failed\n"); + } + } +} + +/* compare if two strings are equal, but match 0xfffd in the second string with anything in the first */ +static UBool +equalAnyFFFD(const UChar *s, const UChar *t, int32_t length) { + UChar c1, c2; + + while(length>0) { + c1=*s++; + c2=*t++; + if(c1!=c2 && c2!=0xfffd) { + return FALSE; + } + --length; + } + return TRUE; +} + +/* test u_strFromUTF8Lenient() */ +static void +Test_FromUTF8Lenient(void) { + /* + * Multiple input strings, each NUL-terminated. + * Terminate with a string starting with 0xff. + */ + static const uint8_t bytes[]={ + /* well-formed UTF-8 */ + 0x61, 0xc3, 0x9f, 0xe0, 0xa0, 0x80, 0xf0, 0xa0, 0x80, 0x80, + 0x62, 0xc3, 0xa0, 0xe0, 0xa0, 0x81, 0xf0, 0xa0, 0x80, 0x81, 0, + + /* various malformed sequences */ + 0xc3, 0xc3, 0x9f, 0xc3, 0xa0, 0xe0, 0x80, 0x8a, 0xf0, 0x41, 0x42, 0x43, 0, + + /* truncated input */ + 0xc3, 0, + 0xe0, 0, + 0xe0, 0xa0, 0, + 0xf0, 0, + 0xf0, 0x90, 0, + 0xf0, 0x90, 0x80, 0, + + /* non-ASCII characters in the last few bytes */ + 0x61, 0xc3, 0x9f, 0xe0, 0xa0, 0x80, 0, + 0x61, 0xe0, 0xa0, 0x80, 0xc3, 0x9f, 0, + + /* empty string */ + 0, + + /* finish */ + 0xff, 0 + }; + + /* Multiple output strings, each NUL-terminated. 0xfffd matches anything. */ + static const UChar uchars[]={ + 0x61, 0xdf, 0x800, 0xd840, 0xdc00, + 0x62, 0xe0, 0x801, 0xd840, 0xdc01, 0, + + 0xfffd, 0x9f, 0xe0, 0xa, 0xfffd, 0xfffd, 0, + + 0xfffd, 0, + 0xfffd, 0, + 0xfffd, 0, + 0xfffd, 0, + 0xfffd, 0, + 0xfffd, 0, + + 0x61, 0xdf, 0x800, 0, + 0x61, 0x800, 0xdf, 0, + + 0, + + 0 + }; + + UChar dest[64]; + const char *pb; + const UChar *pu, *pDest; + int32_t srcLength, destLength0, destLength; + int number; + UErrorCode errorCode; + + /* verify checking for some illegal arguments */ + dest[0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, 1, &destLength, NULL, -1, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || dest[0]!=0x1234) { + log_err("u_strFromUTF8Lenient(src=NULL) failed\n"); + } + + dest[0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(NULL, 1, &destLength, (const char *)bytes, -1, &errorCode); + if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { + log_err("u_strFromUTF8Lenient(dest=NULL[1]) failed\n"); + } + + dest[0]=0x1234; + destLength=-1; + errorCode=U_MEMORY_ALLOCATION_ERROR; + pDest=u_strFromUTF8Lenient(dest, 1, &destLength, (const char *)bytes, -1, &errorCode); + if(errorCode!=U_MEMORY_ALLOCATION_ERROR || dest[0]!=0x1234) { + log_err("u_strFromUTF8Lenient(U_MEMORY_ALLOCATION_ERROR) failed\n"); + } + + dest[0]=0x1234; + destLength=-1; + errorCode=U_MEMORY_ALLOCATION_ERROR; + pDest=u_strFromUTF8Lenient(dest, 1, &destLength, (const char *)bytes, -1, NULL); + if(dest[0]!=0x1234) { + log_err("u_strFromUTF8Lenient(pErrorCode=NULL) failed\n"); + } + + /* test normal behavior */ + number=0; /* string number for log_err() */ + + for(pb=(const char *)bytes, pu=uchars; + *pb!=(char)0xff; + pb+=srcLength+1, pu+=destLength0+1, ++number + ) { + srcLength=uprv_strlen(pb); + destLength0=u_strlen(pu); + + /* preflighting with NUL-termination */ + dest[0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(NULL, 0, &destLength, pb, -1, &errorCode); + if (errorCode!= (destLength0==0 ? U_STRING_NOT_TERMINATED_WARNING : U_BUFFER_OVERFLOW_ERROR) || + pDest!=NULL || dest[0]!=0x1234 || destLength!=destLength0 + ) { + log_err("u_strFromUTF8Lenient(%d preflighting with NUL-termination) failed\n", number); + } + + /* preflighting/some capacity with NUL-termination */ + if(srcLength>0) { + dest[destLength0-1]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, destLength0-1, &destLength, pb, -1, &errorCode); + if (errorCode!=U_BUFFER_OVERFLOW_ERROR || + dest[destLength0-1]!=0x1234 || destLength!=destLength0 + ) { + log_err("u_strFromUTF8Lenient(%d preflighting/some capacity with NUL-termination) failed\n", number); + } + } + + /* conversion with NUL-termination, much capacity */ + dest[0]=dest[destLength0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, LENGTHOF(dest), &destLength, pb, -1, &errorCode); + if (errorCode!=U_ZERO_ERROR || + pDest!=dest || dest[destLength0]!=0 || + destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength) + ) { + log_err("u_strFromUTF8Lenient(%d conversion with NUL-termination, much capacity) failed\n", number); + } + + /* conversion with NUL-termination, exact capacity */ + dest[0]=dest[destLength0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, destLength0, &destLength, pb, -1, &errorCode); + if (errorCode!=U_STRING_NOT_TERMINATED_WARNING || + pDest!=dest || dest[destLength0]!=0x1234 || + destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength) + ) { + log_err("u_strFromUTF8Lenient(%d conversion with NUL-termination, exact capacity) failed\n", number); + } + + /* preflighting with length */ + dest[0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(NULL, 0, &destLength, pb, srcLength, &errorCode); + if (errorCode!= (destLength0==0 ? U_STRING_NOT_TERMINATED_WARNING : U_BUFFER_OVERFLOW_ERROR) || + pDest!=NULL || dest[0]!=0x1234 || destLength!=srcLength + ) { + log_err("u_strFromUTF8Lenient(%d preflighting with length) failed\n", number); + } + + /* preflighting/some capacity with length */ + if(srcLength>0) { + dest[srcLength-1]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, srcLength-1, &destLength, pb, srcLength, &errorCode); + if (errorCode!=U_BUFFER_OVERFLOW_ERROR || + dest[srcLength-1]!=0x1234 || destLength!=srcLength + ) { + log_err("u_strFromUTF8Lenient(%d preflighting/some capacity with length) failed\n", number); + } + } + + /* conversion with length, much capacity */ + dest[0]=dest[destLength0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, LENGTHOF(dest), &destLength, pb, srcLength, &errorCode); + if (errorCode!=U_ZERO_ERROR || + pDest!=dest || dest[destLength0]!=0 || + destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength) + ) { + log_err("u_strFromUTF8Lenient(%d conversion with length, much capacity) failed\n", number); + } + + /* conversion with length, srcLength capacity */ + dest[0]=dest[srcLength]=dest[destLength0]=0x1234; + destLength=-1; + errorCode=U_ZERO_ERROR; + pDest=u_strFromUTF8Lenient(dest, srcLength, &destLength, pb, srcLength, &errorCode); + if(srcLength==destLength0) { + if (errorCode!=U_STRING_NOT_TERMINATED_WARNING || + pDest!=dest || dest[destLength0]!=0x1234 || + destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength) + ) { + log_err("u_strFromUTF8Lenient(%d conversion with length, srcLength capacity/not terminated) failed\n", number); + } + } else { + if (errorCode!=U_ZERO_ERROR || + pDest!=dest || dest[destLength0]!=0 || + destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength) + ) { + log_err("u_strFromUTF8Lenient(%d conversion with length, srcLength capacity/terminated) failed\n", number); + } + } + } +} + +static const uint16_t src16j[] = { + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x0000, + /* Test only ASCII */ + +}; +static const uint16_t src16WithNulls[] = { + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0000, + 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, 0x0000, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0000, + 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, 0x0000, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0000, + 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, 0x0000, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0000, + 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, 0x0000, + /* test only ASCII */ + /* + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, + 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, + 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, + 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, + 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, + 0x0054, 0x0000 */ + +}; +static void Test_UChar_WCHART_API(void){ +#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) + UErrorCode err = U_ZERO_ERROR; + const UChar* uSrc = src16j; + int32_t uSrcLen = sizeof(src16j)/2; + wchar_t* wDest = NULL; + int32_t wDestLen = 0; + int32_t reqLen= 0 ; + UBool failed = FALSE; + UChar* uDest = NULL; + int32_t uDestLen = 0; + int i =0; + { + /* Bad UErrorCode arguments. Make sure that the API doesn't crash, and that Purify doesn't complain. */ + if (u_strFromWCS(NULL,0,NULL,NULL,0,NULL) != NULL) { + log_err("u_strFromWCS() should return NULL with a bad argument\n"); + } + if (u_strToWCS(NULL,0,NULL,NULL,0,NULL) != NULL) { + log_err("u_strToWCS() should return NULL with a bad argument\n"); + } + + /* Bad UErrorCode arguments. */ + err = U_ZERO_ERROR; + u_strFromWCS(NULL,0,NULL,NULL,0,&err); + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("u_strFromWCS() didn't fail as expected with bad arguments. Error: %s \n", u_errorName(err)); + } + err = U_ZERO_ERROR; + u_strToWCS(NULL,0,NULL,NULL,0,&err); + if (err != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("u_strToWCS() didn't fail as expected with bad arguments. Error: %s \n", u_errorName(err)); + } + err = U_ZERO_ERROR; + + /* pre-flight*/ + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err); + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err=U_ZERO_ERROR; + wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1)); + wDestLen = reqLen+1; + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err); + } + + /* pre-flight */ + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err); + + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err =U_ZERO_ERROR; + uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1)); + uDestLen = reqLen + 1; + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err); + }else if(U_FAILURE(err)){ + + log_err("u_strFromWCS() failed. Error: %s \n", u_errorName(err)); + return; + } + + for(i=0; i< uSrcLen; i++){ + if(uDest[i] != src16j[i]){ + log_verbose("u_str*WCS() failed for unterminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i); + failed =TRUE; + } + } + + if(U_FAILURE(err)){ + failed = TRUE; + } + if(failed){ + log_err("u_strToWCS() failed \n"); + } + free(wDest); + free(uDest); + + + /* test with embeded nulls */ + uSrc = src16WithNulls; + uSrcLen = sizeof(src16WithNulls)/2; + wDestLen =0; + uDestLen =0; + wDest = NULL; + uDest = NULL; + /* pre-flight*/ + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err); + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err=U_ZERO_ERROR; + wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1)); + wDestLen = reqLen+1; + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err); + } + + /* pre-flight */ + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err); + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err =U_ZERO_ERROR; + uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1)); + uDestLen = reqLen + 1; + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err); + } + + + for(i=0; i< uSrcLen; i++){ + if(uDest[i] != src16WithNulls[i]){ + log_verbose("u_str*WCS() failed for string with nulls expected: \\u%04X got: \\u%04X at index: %i \n", src16WithNulls[i] ,uDest[i],i); + failed =TRUE; + } + } + + if(U_FAILURE(err)){ + failed = TRUE; + } + if(failed){ + log_err("u_strToWCS() failed \n"); + } + free(wDest); + free(uDest); + + } + + { + + uSrc = src16j; + uSrcLen = sizeof(src16j)/2; + wDestLen =0; + uDestLen =0; + wDest = NULL; + uDest = NULL; + wDestLen = 0; + /* pre-flight*/ + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&err); + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err=U_ZERO_ERROR; + wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1)); + wDestLen = reqLen+1; + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&err); + } + uDestLen = 0; + /* pre-flight */ + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&err); + + if(err == U_BUFFER_OVERFLOW_ERROR){ + err =U_ZERO_ERROR; + uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1)); + uDestLen = reqLen + 1; + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&err); + } + + + for(i=0; i< uSrcLen; i++){ + if(uDest[i] != src16j[i]){ + log_verbose("u_str*WCS() failed for null terminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i); + failed =TRUE; + } + } + + if(U_FAILURE(err)){ + failed = TRUE; + } + if(failed){ + log_err("u_strToWCS() failed \n"); + } + free(wDest); + free(uDest); + } + + /* + * Test u_terminateWChars(). + * All u_terminateXYZ() use the same implementation macro; + * we test this function to improve API coverage. + */ + { + wchar_t buffer[10]; + + err=U_ZERO_ERROR; + buffer[3]=0x20ac; + wDestLen=u_terminateWChars(buffer, LENGTHOF(buffer), 3, &err); + if(err!=U_ZERO_ERROR || wDestLen!=3 || buffer[3]!=0) { + log_err("u_terminateWChars(buffer, all, 3, zero) failed: %s length %d [3]==U+%04x\n", + u_errorName(err), wDestLen, buffer[3]); + } + + err=U_ZERO_ERROR; + buffer[3]=0x20ac; + wDestLen=u_terminateWChars(buffer, 3, 3, &err); + if(err!=U_STRING_NOT_TERMINATED_WARNING || wDestLen!=3 || buffer[3]!=0x20ac) { + log_err("u_terminateWChars(buffer, 3, 3, zero) failed: %s length %d [3]==U+%04x\n", + u_errorName(err), wDestLen, buffer[3]); + } + + err=U_STRING_NOT_TERMINATED_WARNING; + buffer[3]=0x20ac; + wDestLen=u_terminateWChars(buffer, LENGTHOF(buffer), 3, &err); + if(err!=U_ZERO_ERROR || wDestLen!=3 || buffer[3]!=0) { + log_err("u_terminateWChars(buffer, all, 3, not-terminated) failed: %s length %d [3]==U+%04x\n", + u_errorName(err), wDestLen, buffer[3]); + } + + err=U_ZERO_ERROR; + buffer[3]=0x20ac; + wDestLen=u_terminateWChars(buffer, 2, 3, &err); + if(err!=U_BUFFER_OVERFLOW_ERROR || wDestLen!=3 || buffer[3]!=0x20ac) { + log_err("u_terminateWChars(buffer, 2, 3, zero) failed: %s length %d [3]==U+%04x\n", + u_errorName(err), wDestLen, buffer[3]); + } + } +#else + log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32"); +#endif +} + +static void Test_widestrs() +{ +#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) + wchar_t ws[100]; + UChar rts[100]; + int32_t wcap = sizeof(ws) / sizeof(*ws); + int32_t wl; + int32_t rtcap = sizeof(rts) / sizeof(*rts); + int32_t rtl; + wchar_t *wcs; + UChar *cp; + const char *errname; + UChar ustr[] = {'h', 'e', 'l', 'l', 'o', 0}; + int32_t ul = sizeof(ustr)/sizeof(*ustr) -1; + char astr[100]; + + UErrorCode err; + + err = U_ZERO_ERROR; + wcs = u_strToWCS(ws, wcap, &wl, ustr, ul, &err); + if (U_FAILURE(err)) { + errname = u_errorName(err); + log_err("test_widestrs: u_strToWCS error: %s!\n",errname); + } + if(ul!=wl){ + log_err("u_strToWCS: ustr = %s, ul = %d, ws = %S, wl = %d!\n", u_austrcpy(astr, ustr), ul, ws, wl); + } + err = U_ZERO_ERROR; + wl = (int32_t)uprv_wcslen(wcs); + cp = u_strFromWCS(rts, rtcap, &rtl, wcs, wl, &err); + if (U_FAILURE(err)) { + errname = u_errorName(err); + fprintf(stderr, "test_widestrs: ucnv_wcstombs error: %s!\n",errname); + } + if(wl != rtl){ + log_err("u_strFromWCS: wcs = %S, wl = %d,rts = %s, rtl = %d!\n", wcs, wl, u_austrcpy(astr, rts), rtl); + } +#else + log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32"); +#endif +} + +static void +Test_WCHART_LongString(){ +#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) + UErrorCode status = U_ZERO_ERROR; + const char* testdatapath=loadTestData(&status); + UResourceBundle *theBundle = ures_open(testdatapath, "testtypes", &status); + int32_t strLen =0; + const UChar* str = ures_getStringByKey(theBundle, "testinclude",&strLen,&status); + const UChar* uSrc = str; + int32_t uSrcLen = strLen; + int32_t wDestLen =0, reqLen=0, i=0; + int32_t uDestLen =0; + wchar_t* wDest = NULL; + UChar* uDest = NULL; + UBool failed = FALSE; + + if(U_FAILURE(status)){ + log_err("Could not get testinclude resource from testtypes bundle. Error: %s\n",u_errorName(status)); + return; + } + + /* pre-flight*/ + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&status); + + if(status == U_BUFFER_OVERFLOW_ERROR){ + status=U_ZERO_ERROR; + wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1)); + wDestLen = reqLen+1; + u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&status); + } + uDestLen = 0; + /* pre-flight */ + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&status); + + if(status == U_BUFFER_OVERFLOW_ERROR){ + status =U_ZERO_ERROR; + uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1)); + uDestLen = reqLen + 1; + u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&status); + } + + + for(i=0; i< uSrcLen; i++){ + if(uDest[i] != str[i]){ + log_verbose("u_str*WCS() failed for null terminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i); + failed =TRUE; + } + } + + if(U_FAILURE(status)){ + failed = TRUE; + } + if(failed){ + log_err("u_strToWCS() failed \n"); + } + free(wDest); + free(uDest); + /* close the bundle */ + ures_close(theBundle); +#else + log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32"); +#endif +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c new file mode 100644 index 00000000000..76cae0be6d7 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c @@ -0,0 +1,1817 @@ +/* +****************************************************************************** +* +* Copyright (C) 2002-2006, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* file name: custrtst.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2002oct09 +* created by: Markus W. Scherer +* +* Tests of ustring.h Unicode string API functions. +*/ + +#include "unicode/ustring.h" +#include "unicode/ucnv.h" +#include "unicode/uiter.h" +#include "cintltst.h" +#include <string.h> + +#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) + +/* get the sign of an integer */ +#define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1) + +/* test setup --------------------------------------------------------------- */ + +static void setUpDataTable(void); +static void TestStringCopy(void); +static void TestStringFunctions(void); +static void TestStringSearching(void); +static void TestSurrogateSearching(void); +static void TestUnescape(void); +static void TestCountChar32(void); +static void TestUCharIterator(void); +static void TestUNormIterator(void); +static void TestBadUNormIterator(void); + +void addUStringTest(TestNode** root); + +void addUStringTest(TestNode** root) +{ + addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy"); + addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions"); + addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching"); + addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearching"); + addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape"); + addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32"); + addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator"); + addTest(root, &TestUNormIterator, "tsutil/custrtst/TestUNormIterator"); + addTest(root, &TestBadUNormIterator, "tsutil/custrtst/TestBadUNormIterator"); +} + +/* test data for TestStringFunctions ---------------------------------------- */ + +UChar*** dataTable = NULL; + +static const char* raw[3][4] = { + + /* First String */ + { "English_", "French_", "Croatian_", "English_"}, + /* Second String */ + { "United States", "France", "Croatia", "Unites States"}, + + /* Concatenated string */ + { "English_United States", "French_France", "Croatian_Croatia", "English_United States"} +}; + +static void setUpDataTable() +{ + int32_t i,j; + if(dataTable == NULL) { + dataTable = (UChar***)calloc(sizeof(UChar**),3); + + for (i = 0; i < 3; i++) { + dataTable[i] = (UChar**)calloc(sizeof(UChar*),4); + for (j = 0; j < 4; j++){ + dataTable[i][j] = (UChar*) malloc(sizeof(UChar)*(strlen(raw[i][j])+1)); + u_uastrcpy(dataTable[i][j],raw[i][j]); + } + } + } +} + +static void cleanUpDataTable() +{ + int32_t i,j; + if(dataTable != NULL) { + for (i=0; i<3; i++) { + for(j = 0; j<4; j++) { + free(dataTable[i][j]); + } + free(dataTable[i]); + } + free(dataTable); + } + dataTable = NULL; +} + +/*Tests for u_strcat(),u_strcmp(), u_strlen(), u_strcpy(),u_strncat(),u_strncmp(),u_strncpy, u_uastrcpy(),u_austrcpy(), u_uastrncpy(); */ +static void TestStringFunctions() +{ + int32_t i,j,k; + UChar temp[512]; + UChar nullTemp[512]; + char test[512]; + char tempOut[512]; + + setUpDataTable(); + + log_verbose("Testing u_strlen()\n"); + if( u_strlen(dataTable[0][0])!= u_strlen(dataTable[0][3]) || u_strlen(dataTable[0][0]) == u_strlen(dataTable[0][2])) + log_err("There is an error in u_strlen()"); + + log_verbose("Testing u_memcpy() and u_memcmp()\n"); + + for(i=0;i<3;++i) + { + for(j=0;j<4;++j) + { + log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j])); + temp[0] = 0; + temp[7] = 0xA4; /* Mark the end */ + u_memcpy(temp,dataTable[i][j], 7); + + if(temp[7] != 0xA4) + log_err("an error occured in u_memcpy()\n"); + if(u_memcmp(temp, dataTable[i][j], 7)!=0) + log_err("an error occured in u_memcpy() or u_memcmp()\n"); + } + } + if(u_memcmp(dataTable[0][0], dataTable[1][1], 7)==0) + log_err("an error occured in u_memcmp()\n"); + + log_verbose("Testing u_memset()\n"); + nullTemp[0] = 0; + nullTemp[7] = 0; + u_memset(nullTemp, 0xa4, 7); + for (i = 0; i < 7; i++) { + if(nullTemp[i] != 0xa4) { + log_err("an error occured in u_memset()\n"); + } + } + if(nullTemp[7] != 0) { + log_err("u_memset() went too far\n"); + } + + u_memset(nullTemp, 0, 7); + nullTemp[7] = 0xa4; + temp[7] = 0; + u_memcpy(temp,nullTemp, 7); + if(u_memcmp(temp, nullTemp, 7)!=0 || temp[7]!=0) + log_err("an error occured in u_memcpy() or u_memcmp()\n"); + + + log_verbose("Testing u_memmove()\n"); + for (i = 0; i < 7; i++) { + temp[i] = (UChar)i; + } + u_memmove(temp + 1, temp, 7); + if(temp[0] != 0) { + log_err("an error occured in u_memmove()\n"); + } + for (i = 1; i <= 7; i++) { + if(temp[i] != (i - 1)) { + log_err("an error occured in u_memmove()\n"); + } + } + + log_verbose("Testing u_strcpy() and u_strcmp()\n"); + + for(i=0;i<3;++i) + { + for(j=0;j<4;++j) + { + log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j])); + temp[0] = 0; + u_strcpy(temp,dataTable[i][j]); + + if(u_strcmp(temp,dataTable[i][j])!=0) + log_err("something threw an error in u_strcpy() or u_strcmp()\n"); + } + } + if(u_strcmp(dataTable[0][0], dataTable[1][1])==0) + log_err("an error occured in u_memcmp()\n"); + + log_verbose("testing u_strcat()\n"); + i=0; + for(j=0; j<2;++j) + { + u_uastrcpy(temp, ""); + u_strcpy(temp,dataTable[i][j]); + u_strcat(temp,dataTable[i+1][j]); + if(u_strcmp(temp,dataTable[i+2][j])!=0) + log_err("something threw an error in u_strcat()\n"); + + } + log_verbose("Testing u_strncmp()\n"); + for(i=0,j=0;j<4; ++j) + { + k=u_strlen(dataTable[i][j]); + if(u_strncmp(dataTable[i][j],dataTable[i+2][j],k)!=0) + log_err("Something threw an error in u_strncmp\n"); + } + if(u_strncmp(dataTable[0][0], dataTable[1][1], 7)==0) + log_err("an error occured in u_memcmp()\n"); + + + log_verbose("Testing u_strncat\n"); + for(i=0,j=0;j<4; ++j) + { + k=u_strlen(dataTable[i][j]); + + u_uastrcpy(temp,""); + + if(u_strcmp(u_strncat(temp,dataTable[i+2][j],k),dataTable[i][j])!=0) + log_err("something threw an error in u_strncat or u_uastrcpy()\n"); + + } + + log_verbose("Testing u_strncpy() and u_uastrcpy()\n"); + for(i=2,j=0;j<4; ++j) + { + k=u_strlen(dataTable[i][j]); + u_strncpy(temp, dataTable[i][j],k); + temp[k] = 0xa4; + + if(u_strncmp(temp, dataTable[i][j],k)!=0) + log_err("something threw an error in u_strncpy()\n"); + + if(temp[k] != 0xa4) + log_err("something threw an error in u_strncpy()\n"); + + u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1); + u_uastrncpy(temp, raw[i][j], k-1); + if(u_strncmp(temp, dataTable[i][j],k-1)!=0) + log_err("something threw an error in u_uastrncpy(k-1)\n"); + + if(temp[k-1] != 0x3F) + log_err("something threw an error in u_uastrncpy(k-1)\n"); + + u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1); + u_uastrncpy(temp, raw[i][j], k+1); + if(u_strcmp(temp, dataTable[i][j])!=0) + log_err("something threw an error in u_uastrncpy(k+1)\n"); + + if(temp[k] != 0) + log_err("something threw an error in u_uastrncpy(k+1)\n"); + + u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1); + u_uastrncpy(temp, raw[i][j], k); + if(u_strncmp(temp, dataTable[i][j], k)!=0) + log_err("something threw an error in u_uastrncpy(k)\n"); + + if(temp[k] != 0x3F) + log_err("something threw an error in u_uastrncpy(k)\n"); + } + + log_verbose("Testing u_strchr() and u_memchr()\n"); + + for(i=2,j=0;j<4;j++) + { + UChar saveVal = dataTable[i][j][0]; + UChar *findPtr = u_strchr(dataTable[i][j], 0x005F); + int32_t dataSize = (int32_t)(u_strlen(dataTable[i][j]) + 1); + + log_verbose("%s ", u_austrcpy(tempOut, findPtr)); + + if (findPtr == NULL || *findPtr != 0x005F) { + log_err("u_strchr can't find '_' in the string\n"); + } + + findPtr = u_strchr32(dataTable[i][j], 0x005F); + if (findPtr == NULL || *findPtr != 0x005F) { + log_err("u_strchr32 can't find '_' in the string\n"); + } + + findPtr = u_strchr(dataTable[i][j], 0); + if (findPtr != (&(dataTable[i][j][dataSize - 1]))) { + log_err("u_strchr can't find NULL in the string\n"); + } + + findPtr = u_strchr32(dataTable[i][j], 0); + if (findPtr != (&(dataTable[i][j][dataSize - 1]))) { + log_err("u_strchr32 can't find NULL in the string\n"); + } + + findPtr = u_memchr(dataTable[i][j], 0, dataSize); + if (findPtr != (&(dataTable[i][j][dataSize - 1]))) { + log_err("u_memchr can't find NULL in the string\n"); + } + + findPtr = u_memchr32(dataTable[i][j], 0, dataSize); + if (findPtr != (&(dataTable[i][j][dataSize - 1]))) { + log_err("u_memchr32 can't find NULL in the string\n"); + } + + dataTable[i][j][0] = 0; + /* Make sure we skip over the NULL termination */ + findPtr = u_memchr(dataTable[i][j], 0x005F, dataSize); + if (findPtr == NULL || *findPtr != 0x005F) { + log_err("u_memchr can't find '_' in the string\n"); + } + + findPtr = u_memchr32(dataTable[i][j], 0x005F, dataSize); + if (findPtr == NULL || *findPtr != 0x005F) { + log_err("u_memchr32 can't find '_' in the string\n"); + } + findPtr = u_memchr32(dataTable[i][j], 0xFFFD, dataSize); + if (findPtr != NULL) { + log_err("Should have found NULL when the character is not there.\n"); + } + dataTable[i][j][0] = saveVal; /* Put it back for the other tests */ + } + + /* + * test that u_strchr32() + * does not find surrogate code points when they are part of matched pairs + * (= part of supplementary code points) + * Jitterbug 1542 + */ + { + static const UChar s[]={ + /* 0 1 2 3 4 5 6 7 8 9 */ + 0x0061, 0xd841, 0xdc02, 0xd841, 0x0062, 0xdc02, 0xd841, 0xdc02, 0x0063, 0 + }; + + if(u_strchr32(s, 0xd841)!=(s+3) || u_strchr32(s, 0xdc02)!=(s+5)) { + log_err("error: u_strchr32(surrogate) finds a partial supplementary code point\n"); + } + if(u_memchr32(s, 0xd841, 9)!=(s+3) || u_memchr32(s, 0xdc02, 9)!=(s+5)) { + log_err("error: u_memchr32(surrogate) finds a partial supplementary code point\n"); + } + } + + log_verbose("Testing u_austrcpy()"); + u_austrcpy(test,dataTable[0][0]); + if(strcmp(test,raw[0][0])!=0) + log_err("There is an error in u_austrcpy()"); + + + log_verbose("Testing u_strtok_r()"); + { + const char tokString[] = " , 1 2 3 AHHHHH! 5.5 6 7 , 8\n"; + const char *tokens[] = {",", "1", "2", "3", "AHHHHH!", "5.5", "6", "7", "8\n"}; + UChar delimBuf[sizeof(test)]; + UChar currTokenBuf[sizeof(tokString)]; + UChar *state; + uint32_t currToken = 0; + UChar *ptr; + + u_uastrcpy(temp, tokString); + u_uastrcpy(delimBuf, " "); + + ptr = u_strtok_r(temp, delimBuf, &state); + u_uastrcpy(delimBuf, " ,"); + while (ptr != NULL) { + u_uastrcpy(currTokenBuf, tokens[currToken]); + if (u_strcmp(ptr, currTokenBuf) != 0) { + log_err("u_strtok_r mismatch at %d. Got: %s, Expected: %s\n", currToken, ptr, tokens[currToken]); + } + ptr = u_strtok_r(NULL, delimBuf, &state); + currToken++; + } + + if (currToken != sizeof(tokens)/sizeof(tokens[0])) { + log_err("Didn't get correct number of tokens\n"); + } + state = delimBuf; /* Give it an "invalid" saveState */ + u_uastrcpy(currTokenBuf, ""); + if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) { + log_err("Didn't get NULL for empty string\n"); + } + if (state != NULL) { + log_err("State should be NULL for empty string\n"); + } + state = delimBuf; /* Give it an "invalid" saveState */ + u_uastrcpy(currTokenBuf, ", ,"); + if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) { + log_err("Didn't get NULL for a string of delimiters\n"); + } + if (state != NULL) { + log_err("State should be NULL for a string of delimiters\n"); + } + + state = delimBuf; /* Give it an "invalid" saveState */ + u_uastrcpy(currTokenBuf, "q, ,"); + if (u_strtok_r(currTokenBuf, delimBuf, &state) == NULL) { + log_err("Got NULL for a string that does not begin with delimiters\n"); + } + if (u_strtok_r(NULL, delimBuf, &state) != NULL) { + log_err("Didn't get NULL for a string that ends in delimiters\n"); + } + if (state != NULL) { + log_err("State should be NULL for empty string\n"); + } + + state = delimBuf; /* Give it an "invalid" saveState */ + u_uastrcpy(currTokenBuf, tokString); + u_uastrcpy(temp, tokString); + u_uastrcpy(delimBuf, "q"); /* Give it a delimiter that it can't find. */ + ptr = u_strtok_r(currTokenBuf, delimBuf, &state); + if (ptr == NULL || u_strcmp(ptr, temp) != 0) { + log_err("Should have recieved the same string when there are no delimiters\n"); + } + if (u_strtok_r(NULL, delimBuf, &state) != NULL) { + log_err("Should not have found another token in a one token string\n"); + } + } + + /* test u_strcmpCodePointOrder() */ + { + /* these strings are in ascending order */ + static const UChar strings[][4]={ + { 0x61, 0 }, /* U+0061 */ + { 0x20ac, 0xd801, 0 }, /* U+20ac U+d801 */ + { 0x20ac, 0xd800, 0xdc00, 0 }, /* U+20ac U+10000 */ + { 0xd800, 0 }, /* U+d800 */ + { 0xd800, 0xff61, 0 }, /* U+d800 U+ff61 */ + { 0xdfff, 0 }, /* U+dfff */ + { 0xff61, 0xdfff, 0 }, /* U+ff61 U+dfff */ + { 0xff61, 0xd800, 0xdc02, 0 }, /* U+ff61 U+10002 */ + { 0xd800, 0xdc02, 0 }, /* U+10002 */ + { 0xd84d, 0xdc56, 0 } /* U+23456 */ + }; + + UCharIterator iter1, iter2; + int32_t len1, len2, r1, r2; + + for(i=0; i<(sizeof(strings)/sizeof(strings[0])-1); ++i) { + if(u_strcmpCodePointOrder(strings[i], strings[i+1])>=0) { + log_err("error: u_strcmpCodePointOrder() fails for string %d and the following one\n", i); + } + if(u_strncmpCodePointOrder(strings[i], strings[i+1], 10)>=0) { + log_err("error: u_strncmpCodePointOrder() fails for string %d and the following one\n", i); + } + + /* There are at least 2 UChars in each string - verify that strncmp()==memcmp(). */ + if(u_strncmpCodePointOrder(strings[i], strings[i+1], 2)!=u_memcmpCodePointOrder(strings[i], strings[i+1], 2)) { + log_err("error: u_strncmpCodePointOrder(2)!=u_memcmpCodePointOrder(2) for string %d and the following one\n", i); + } + + /* test u_strCompare(TRUE) */ + len1=u_strlen(strings[i]); + len2=u_strlen(strings[i+1]); + if( u_strCompare(strings[i], -1, strings[i+1], -1, TRUE)>=0 || + u_strCompare(strings[i], -1, strings[i+1], len2, TRUE)>=0 || + u_strCompare(strings[i], len1, strings[i+1], -1, TRUE)>=0 || + u_strCompare(strings[i], len1, strings[i+1], len2, TRUE)>=0 + ) { + log_err("error: u_strCompare(code point order) fails for string %d and the following one\n", i); + } + + /* test u_strCompare(FALSE) */ + r1=u_strCompare(strings[i], -1, strings[i+1], -1, FALSE); + r2=u_strcmp(strings[i], strings[i+1]); + if(_SIGN(r1)!=_SIGN(r2)) { + log_err("error: u_strCompare(code unit order)!=u_strcmp() for string %d and the following one\n", i); + } + + /* test u_strCompareIter() */ + uiter_setString(&iter1, strings[i], len1); + uiter_setString(&iter2, strings[i+1], len2); + if(u_strCompareIter(&iter1, &iter2, TRUE)>=0) { + log_err("error: u_strCompareIter(code point order) fails for string %d and the following one\n", i); + } + r1=u_strCompareIter(&iter1, &iter2, FALSE); + if(_SIGN(r1)!=_SIGN(u_strcmp(strings[i], strings[i+1]))) { + log_err("error: u_strCompareIter(code unit order)!=u_strcmp() for string %d and the following one\n", i); + } + } + } + + cleanUpDataTable(); +} + +static void TestStringSearching() +{ + const UChar testString[] = {0x0061, 0x0062, 0x0063, 0x0064, 0x0064, 0x0061, 0}; + const UChar testSurrogateString[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0x0063, 0x0064, 0x0064, 0xdbff, 0xdfff, 0xdb00, 0xdf00, 0x0061, 0}; + const UChar surrMatchSet1[] = {0xdbff, 0xdfff, 0}; + const UChar surrMatchSet2[] = {0x0061, 0x0062, 0xdbff, 0xdfff, 0}; + const UChar surrMatchSet3[] = {0xdb00, 0xdf00, 0xdbff, 0xdfff, 0}; + const UChar surrMatchSet4[] = {0x0000}; + const UChar surrMatchSetBad[] = {0xdbff, 0x0061, 0}; + const UChar surrMatchSetBad2[] = {0x0061, 0xdbff, 0}; + const UChar surrMatchSetBad3[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0}; /* has partial surrogate */ + const UChar + empty[] = { 0 }, + a[] = { 0x61, 0 }, + ab[] = { 0x61, 0x62, 0 }, + ba[] = { 0x62, 0x61, 0 }, + abcd[] = { 0x61, 0x62, 0x63, 0x64, 0 }, + cd[] = { 0x63, 0x64, 0 }, + dc[] = { 0x64, 0x63, 0 }, + cdh[] = { 0x63, 0x64, 0x68, 0 }, + f[] = { 0x66, 0 }, + fg[] = { 0x66, 0x67, 0 }, + gf[] = { 0x67, 0x66, 0 }; + + log_verbose("Testing u_strpbrk()"); + + if (u_strpbrk(testString, a) != &testString[0]) { + log_err("u_strpbrk couldn't find first letter a.\n"); + } + if (u_strpbrk(testString, dc) != &testString[2]) { + log_err("u_strpbrk couldn't find d or c.\n"); + } + if (u_strpbrk(testString, cd) != &testString[2]) { + log_err("u_strpbrk couldn't find c or d.\n"); + } + if (u_strpbrk(testString, cdh) != &testString[2]) { + log_err("u_strpbrk couldn't find c, d or h.\n"); + } + if (u_strpbrk(testString, f) != NULL) { + log_err("u_strpbrk didn't return NULL for \"f\".\n"); + } + if (u_strpbrk(testString, fg) != NULL) { + log_err("u_strpbrk didn't return NULL for \"fg\".\n"); + } + if (u_strpbrk(testString, gf) != NULL) { + log_err("u_strpbrk didn't return NULL for \"gf\".\n"); + } + if (u_strpbrk(testString, empty) != NULL) { + log_err("u_strpbrk didn't return NULL for \"\".\n"); + } + + log_verbose("Testing u_strpbrk() with surrogates"); + + if (u_strpbrk(testSurrogateString, a) != &testSurrogateString[1]) { + log_err("u_strpbrk couldn't find first letter a.\n"); + } + if (u_strpbrk(testSurrogateString, dc) != &testSurrogateString[5]) { + log_err("u_strpbrk couldn't find d or c.\n"); + } + if (u_strpbrk(testSurrogateString, cd) != &testSurrogateString[5]) { + log_err("u_strpbrk couldn't find c or d.\n"); + } + if (u_strpbrk(testSurrogateString, cdh) != &testSurrogateString[5]) { + log_err("u_strpbrk couldn't find c, d or h.\n"); + } + if (u_strpbrk(testSurrogateString, f) != NULL) { + log_err("u_strpbrk didn't return NULL for \"f\".\n"); + } + if (u_strpbrk(testSurrogateString, fg) != NULL) { + log_err("u_strpbrk didn't return NULL for \"fg\".\n"); + } + if (u_strpbrk(testSurrogateString, gf) != NULL) { + log_err("u_strpbrk didn't return NULL for \"gf\".\n"); + } + if (u_strpbrk(testSurrogateString, surrMatchSet1) != &testSurrogateString[3]) { + log_err("u_strpbrk couldn't find \"0xdbff, 0xdfff\".\n"); + } + if (u_strpbrk(testSurrogateString, surrMatchSet2) != &testSurrogateString[1]) { + log_err("u_strpbrk couldn't find \"0xdbff, a, b, 0xdbff, 0xdfff\".\n"); + } + if (u_strpbrk(testSurrogateString, surrMatchSet3) != &testSurrogateString[3]) { + log_err("u_strpbrk couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n"); + } + if (u_strpbrk(testSurrogateString, surrMatchSet4) != NULL) { + log_err("u_strpbrk should have returned NULL for empty string.\n"); + } + if (u_strpbrk(testSurrogateString, surrMatchSetBad) != &testSurrogateString[0]) { + log_err("u_strpbrk should have found bad surrogate.\n"); + } + + log_verbose("Testing u_strcspn()"); + + if (u_strcspn(testString, a) != 0) { + log_err("u_strcspn couldn't find first letter a.\n"); + } + if (u_strcspn(testString, dc) != 2) { + log_err("u_strcspn couldn't find d or c.\n"); + } + if (u_strcspn(testString, cd) != 2) { + log_err("u_strcspn couldn't find c or d.\n"); + } + if (u_strcspn(testString, cdh) != 2) { + log_err("u_strcspn couldn't find c, d or h.\n"); + } + if (u_strcspn(testString, f) != u_strlen(testString)) { + log_err("u_strcspn didn't return NULL for \"f\".\n"); + } + if (u_strcspn(testString, fg) != u_strlen(testString)) { + log_err("u_strcspn didn't return NULL for \"fg\".\n"); + } + if (u_strcspn(testString, gf) != u_strlen(testString)) { + log_err("u_strcspn didn't return NULL for \"gf\".\n"); + } + + log_verbose("Testing u_strcspn() with surrogates"); + + if (u_strcspn(testSurrogateString, a) != 1) { + log_err("u_strcspn couldn't find first letter a.\n"); + } + if (u_strcspn(testSurrogateString, dc) != 5) { + log_err("u_strcspn couldn't find d or c.\n"); + } + if (u_strcspn(testSurrogateString, cd) != 5) { + log_err("u_strcspn couldn't find c or d.\n"); + } + if (u_strcspn(testSurrogateString, cdh) != 5) { + log_err("u_strcspn couldn't find c, d or h.\n"); + } + if (u_strcspn(testSurrogateString, f) != u_strlen(testSurrogateString)) { + log_err("u_strcspn didn't return NULL for \"f\".\n"); + } + if (u_strcspn(testSurrogateString, fg) != u_strlen(testSurrogateString)) { + log_err("u_strcspn didn't return NULL for \"fg\".\n"); + } + if (u_strcspn(testSurrogateString, gf) != u_strlen(testSurrogateString)) { + log_err("u_strcspn didn't return NULL for \"gf\".\n"); + } + if (u_strcspn(testSurrogateString, surrMatchSet1) != 3) { + log_err("u_strcspn couldn't find \"0xdbff, 0xdfff\".\n"); + } + if (u_strcspn(testSurrogateString, surrMatchSet2) != 1) { + log_err("u_strcspn couldn't find \"a, b, 0xdbff, 0xdfff\".\n"); + } + if (u_strcspn(testSurrogateString, surrMatchSet3) != 3) { + log_err("u_strcspn couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n"); + } + if (u_strcspn(testSurrogateString, surrMatchSet4) != u_strlen(testSurrogateString)) { + log_err("u_strcspn should have returned strlen for empty string.\n"); + } + + + log_verbose("Testing u_strspn()"); + + if (u_strspn(testString, a) != 1) { + log_err("u_strspn couldn't skip first letter a.\n"); + } + if (u_strspn(testString, ab) != 2) { + log_err("u_strspn couldn't skip a or b.\n"); + } + if (u_strspn(testString, ba) != 2) { + log_err("u_strspn couldn't skip a or b.\n"); + } + if (u_strspn(testString, f) != 0) { + log_err("u_strspn didn't return 0 for \"f\".\n"); + } + if (u_strspn(testString, dc) != 0) { + log_err("u_strspn couldn't find first letter a (skip d or c).\n"); + } + if (u_strspn(testString, abcd) != u_strlen(testString)) { + log_err("u_strspn couldn't skip over the whole string.\n"); + } + if (u_strspn(testString, empty) != 0) { + log_err("u_strspn should have returned 0 for empty string.\n"); + } + + log_verbose("Testing u_strspn() with surrogates"); + if (u_strspn(testSurrogateString, surrMatchSetBad) != 2) { + log_err("u_strspn couldn't skip 0xdbff or a.\n"); + } + if (u_strspn(testSurrogateString, surrMatchSetBad2) != 2) { + log_err("u_strspn couldn't skip 0xdbff or a.\n"); + } + if (u_strspn(testSurrogateString, f) != 0) { + log_err("u_strspn couldn't skip d or c (skip first letter).\n"); + } + if (u_strspn(testSurrogateString, dc) != 0) { + log_err("u_strspn couldn't skip d or c (skip first letter).\n"); + } + if (u_strspn(testSurrogateString, cd) != 0) { + log_err("u_strspn couldn't skip d or c (skip first letter).\n"); + } + if (u_strspn(testSurrogateString, testSurrogateString) != u_strlen(testSurrogateString)) { + log_err("u_strspn couldn't skip whole string.\n"); + } + if (u_strspn(testSurrogateString, surrMatchSet1) != 0) { + log_err("u_strspn couldn't skip \"0xdbff, 0xdfff\" (get first letter).\n"); + } + if (u_strspn(testSurrogateString, surrMatchSetBad3) != 5) { + log_err("u_strspn couldn't skip \"0xdbff, a, b, 0xdbff, 0xdfff\".\n"); + } + if (u_strspn(testSurrogateString, surrMatchSet4) != 0) { + log_err("u_strspn should have returned 0 for empty string.\n"); + } +} + +/* + * All binary Unicode string searches should behave the same for equivalent input. + * See Jitterbug 2145. + * There are some new functions, too - just test them all. + */ +static void +TestSurrogateSearching() { + static const UChar s[]={ + /* 0 1 2 3 4 5 6 7 8 9 10 11 */ + 0x61, 0xd801, 0xdc02, 0x61, 0xdc02, 0x61, 0xd801, 0x61, 0xd801, 0xdc02, 0x61, 0 + }, sub_a[]={ + 0x61, 0 + }, sub_b[]={ + 0x62, 0 + }, sub_lead[]={ + 0xd801, 0 + }, sub_trail[]={ + 0xdc02, 0 + }, sub_supp[]={ + 0xd801, 0xdc02, 0 + }, sub_supp2[]={ + 0xd801, 0xdc03, 0 + }, sub_a_lead[]={ + 0x61, 0xd801, 0 + }, sub_trail_a[]={ + 0xdc02, 0x61, 0 + }, sub_aba[]={ + 0x61, 0x62, 0x61, 0 + }; + static const UChar a=0x61, b=0x62, lead=0xd801, trail=0xdc02, nul=0; + static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456; + + const UChar *first, *last; + + /* search for NUL code point: find end of string */ + first=s+u_strlen(s); + + if( + first!=u_strchr(s, nul) || + first!=u_strchr32(s, nul) || + first!=u_memchr(s, nul, LENGTHOF(s)) || + first!=u_memchr32(s, nul, LENGTHOF(s)) || + first!=u_strrchr(s, nul) || + first!=u_strrchr32(s, nul) || + first!=u_memrchr(s, nul, LENGTHOF(s)) || + first!=u_memrchr32(s, nul, LENGTHOF(s)) + ) { + log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find the terminator of s\n"); + } + + /* search for empty substring: find beginning of string */ + if( + s!=u_strstr(s, &nul) || + s!=u_strFindFirst(s, -1, &nul, -1) || + s!=u_strFindFirst(s, -1, &nul, 0) || + s!=u_strFindFirst(s, LENGTHOF(s), &nul, -1) || + s!=u_strFindFirst(s, LENGTHOF(s), &nul, 0) || + s!=u_strrstr(s, &nul) || + s!=u_strFindLast(s, -1, &nul, -1) || + s!=u_strFindLast(s, -1, &nul, 0) || + s!=u_strFindLast(s, LENGTHOF(s), &nul, -1) || + s!=u_strFindLast(s, LENGTHOF(s), &nul, 0) + ) { + log_err("error: one of the u_str[str etc](s, \"\") does not find s itself\n"); + } + + /* find 'a' in s[1..10[ */ + first=s+3; + last=s+7; + if( + first!=u_strchr(s+1, a) || + first!=u_strchr32(s+1, a) || + first!=u_memchr(s+1, a, 9) || + first!=u_memchr32(s+1, a, 9) || + first!=u_strstr(s+1, sub_a) || + first!=u_strFindFirst(s+1, -1, sub_a, -1) || + first!=u_strFindFirst(s+1, -1, &a, 1) || + first!=u_strFindFirst(s+1, 9, sub_a, -1) || + first!=u_strFindFirst(s+1, 9, &a, 1) || + (s+10)!=u_strrchr(s+1, a) || + (s+10)!=u_strrchr32(s+1, a) || + last!=u_memrchr(s+1, a, 9) || + last!=u_memrchr32(s+1, a, 9) || + (s+10)!=u_strrstr(s+1, sub_a) || + (s+10)!=u_strFindLast(s+1, -1, sub_a, -1) || + (s+10)!=u_strFindLast(s+1, -1, &a, 1) || + last!=u_strFindLast(s+1, 9, sub_a, -1) || + last!=u_strFindLast(s+1, 9, &a, 1) + ) { + log_err("error: one of the u_str[chr etc]('a') does not find the correct place\n"); + } + + /* do not find 'b' in s[1..10[ */ + if( + NULL!=u_strchr(s+1, b) || + NULL!=u_strchr32(s+1, b) || + NULL!=u_memchr(s+1, b, 9) || + NULL!=u_memchr32(s+1, b, 9) || + NULL!=u_strstr(s+1, sub_b) || + NULL!=u_strFindFirst(s+1, -1, sub_b, -1) || + NULL!=u_strFindFirst(s+1, -1, &b, 1) || + NULL!=u_strFindFirst(s+1, 9, sub_b, -1) || + NULL!=u_strFindFirst(s+1, 9, &b, 1) || + NULL!=u_strrchr(s+1, b) || + NULL!=u_strrchr32(s+1, b) || + NULL!=u_memrchr(s+1, b, 9) || + NULL!=u_memrchr32(s+1, b, 9) || + NULL!=u_strrstr(s+1, sub_b) || + NULL!=u_strFindLast(s+1, -1, sub_b, -1) || + NULL!=u_strFindLast(s+1, -1, &b, 1) || + NULL!=u_strFindLast(s+1, 9, sub_b, -1) || + NULL!=u_strFindLast(s+1, 9, &b, 1) + ) { + log_err("error: one of the u_str[chr etc]('b') incorrectly finds something\n"); + } + + /* do not find a non-code point in s[1..10[ */ + if( + NULL!=u_strchr32(s+1, ill) || + NULL!=u_memchr32(s+1, ill, 9) || + NULL!=u_strrchr32(s+1, ill) || + NULL!=u_memrchr32(s+1, ill, 9) + ) { + log_err("error: one of the u_str[chr etc](illegal code point) incorrectly finds something\n"); + } + + /* find U+d801 in s[1..10[ */ + first=s+6; + if( + first!=u_strchr(s+1, lead) || + first!=u_strchr32(s+1, lead) || + first!=u_memchr(s+1, lead, 9) || + first!=u_memchr32(s+1, lead, 9) || + first!=u_strstr(s+1, sub_lead) || + first!=u_strFindFirst(s+1, -1, sub_lead, -1) || + first!=u_strFindFirst(s+1, -1, &lead, 1) || + first!=u_strFindFirst(s+1, 9, sub_lead, -1) || + first!=u_strFindFirst(s+1, 9, &lead, 1) || + first!=u_strrchr(s+1, lead) || + first!=u_strrchr32(s+1, lead) || + first!=u_memrchr(s+1, lead, 9) || + first!=u_memrchr32(s+1, lead, 9) || + first!=u_strrstr(s+1, sub_lead) || + first!=u_strFindLast(s+1, -1, sub_lead, -1) || + first!=u_strFindLast(s+1, -1, &lead, 1) || + first!=u_strFindLast(s+1, 9, sub_lead, -1) || + first!=u_strFindLast(s+1, 9, &lead, 1) + ) { + log_err("error: one of the u_str[chr etc](U+d801) does not find the correct place\n"); + } + + /* find U+dc02 in s[1..10[ */ + first=s+4; + if( + first!=u_strchr(s+1, trail) || + first!=u_strchr32(s+1, trail) || + first!=u_memchr(s+1, trail, 9) || + first!=u_memchr32(s+1, trail, 9) || + first!=u_strstr(s+1, sub_trail) || + first!=u_strFindFirst(s+1, -1, sub_trail, -1) || + first!=u_strFindFirst(s+1, -1, &trail, 1) || + first!=u_strFindFirst(s+1, 9, sub_trail, -1) || + first!=u_strFindFirst(s+1, 9, &trail, 1) || + first!=u_strrchr(s+1, trail) || + first!=u_strrchr32(s+1, trail) || + first!=u_memrchr(s+1, trail, 9) || + first!=u_memrchr32(s+1, trail, 9) || + first!=u_strrstr(s+1, sub_trail) || + first!=u_strFindLast(s+1, -1, sub_trail, -1) || + first!=u_strFindLast(s+1, -1, &trail, 1) || + first!=u_strFindLast(s+1, 9, sub_trail, -1) || + first!=u_strFindLast(s+1, 9, &trail, 1) + ) { + log_err("error: one of the u_str[chr etc](U+dc02) does not find the correct place\n"); + } + + /* find U+10402 in s[1..10[ */ + first=s+1; + last=s+8; + if( + first!=u_strchr32(s+1, supp) || + first!=u_memchr32(s+1, supp, 9) || + first!=u_strstr(s+1, sub_supp) || + first!=u_strFindFirst(s+1, -1, sub_supp, -1) || + first!=u_strFindFirst(s+1, -1, sub_supp, 2) || + first!=u_strFindFirst(s+1, 9, sub_supp, -1) || + first!=u_strFindFirst(s+1, 9, sub_supp, 2) || + last!=u_strrchr32(s+1, supp) || + last!=u_memrchr32(s+1, supp, 9) || + last!=u_strrstr(s+1, sub_supp) || + last!=u_strFindLast(s+1, -1, sub_supp, -1) || + last!=u_strFindLast(s+1, -1, sub_supp, 2) || + last!=u_strFindLast(s+1, 9, sub_supp, -1) || + last!=u_strFindLast(s+1, 9, sub_supp, 2) + ) { + log_err("error: one of the u_str[chr etc](U+10402) does not find the correct place\n"); + } + + /* do not find U+10402 in a single UChar */ + if( + NULL!=u_memchr32(s+1, supp, 1) || + NULL!=u_strFindFirst(s+1, 1, sub_supp, -1) || + NULL!=u_strFindFirst(s+1, 1, sub_supp, 2) || + NULL!=u_memrchr32(s+1, supp, 1) || + NULL!=u_strFindLast(s+1, 1, sub_supp, -1) || + NULL!=u_strFindLast(s+1, 1, sub_supp, 2) || + NULL!=u_memrchr32(s+2, supp, 1) || + NULL!=u_strFindLast(s+2, 1, sub_supp, -1) || + NULL!=u_strFindLast(s+2, 1, sub_supp, 2) + ) { + log_err("error: one of the u_str[chr etc](U+10402) incorrectly finds a supplementary c.p. in a single UChar\n"); + } + + /* do not find U+10403 in s[1..10[ */ + if( + NULL!=u_strchr32(s+1, supp2) || + NULL!=u_memchr32(s+1, supp2, 9) || + NULL!=u_strstr(s+1, sub_supp2) || + NULL!=u_strFindFirst(s+1, -1, sub_supp2, -1) || + NULL!=u_strFindFirst(s+1, -1, sub_supp2, 2) || + NULL!=u_strFindFirst(s+1, 9, sub_supp2, -1) || + NULL!=u_strFindFirst(s+1, 9, sub_supp2, 2) || + NULL!=u_strrchr32(s+1, supp2) || + NULL!=u_memrchr32(s+1, supp2, 9) || + NULL!=u_strrstr(s+1, sub_supp2) || + NULL!=u_strFindLast(s+1, -1, sub_supp2, -1) || + NULL!=u_strFindLast(s+1, -1, sub_supp2, 2) || + NULL!=u_strFindLast(s+1, 9, sub_supp2, -1) || + NULL!=u_strFindLast(s+1, 9, sub_supp2, 2) + ) { + log_err("error: one of the u_str[chr etc](U+10403) incorrectly finds something\n"); + } + + /* find <0061 d801> in s[1..10[ */ + first=s+5; + if( + first!=u_strstr(s+1, sub_a_lead) || + first!=u_strFindFirst(s+1, -1, sub_a_lead, -1) || + first!=u_strFindFirst(s+1, -1, sub_a_lead, 2) || + first!=u_strFindFirst(s+1, 9, sub_a_lead, -1) || + first!=u_strFindFirst(s+1, 9, sub_a_lead, 2) || + first!=u_strrstr(s+1, sub_a_lead) || + first!=u_strFindLast(s+1, -1, sub_a_lead, -1) || + first!=u_strFindLast(s+1, -1, sub_a_lead, 2) || + first!=u_strFindLast(s+1, 9, sub_a_lead, -1) || + first!=u_strFindLast(s+1, 9, sub_a_lead, 2) + ) { + log_err("error: one of the u_str[str etc](<0061 d801>) does not find the correct place\n"); + } + + /* find <dc02 0061> in s[1..10[ */ + first=s+4; + if( + first!=u_strstr(s+1, sub_trail_a) || + first!=u_strFindFirst(s+1, -1, sub_trail_a, -1) || + first!=u_strFindFirst(s+1, -1, sub_trail_a, 2) || + first!=u_strFindFirst(s+1, 9, sub_trail_a, -1) || + first!=u_strFindFirst(s+1, 9, sub_trail_a, 2) || + first!=u_strrstr(s+1, sub_trail_a) || + first!=u_strFindLast(s+1, -1, sub_trail_a, -1) || + first!=u_strFindLast(s+1, -1, sub_trail_a, 2) || + first!=u_strFindLast(s+1, 9, sub_trail_a, -1) || + first!=u_strFindLast(s+1, 9, sub_trail_a, 2) + ) { + log_err("error: one of the u_str[str etc](<dc02 0061>) does not find the correct place\n"); + } + + /* do not find "aba" in s[1..10[ */ + if( + NULL!=u_strstr(s+1, sub_aba) || + NULL!=u_strFindFirst(s+1, -1, sub_aba, -1) || + NULL!=u_strFindFirst(s+1, -1, sub_aba, 3) || + NULL!=u_strFindFirst(s+1, 9, sub_aba, -1) || + NULL!=u_strFindFirst(s+1, 9, sub_aba, 3) || + NULL!=u_strrstr(s+1, sub_aba) || + NULL!=u_strFindLast(s+1, -1, sub_aba, -1) || + NULL!=u_strFindLast(s+1, -1, sub_aba, 3) || + NULL!=u_strFindLast(s+1, 9, sub_aba, -1) || + NULL!=u_strFindLast(s+1, 9, sub_aba, 3) + ) { + log_err("error: one of the u_str[str etc](\"aba\") incorrectly finds something\n"); + } +} + +static void TestStringCopy() +{ + UChar temp[40]; + UChar *result=0; + UChar subString[5]; + UChar uchars[]={0x61, 0x62, 0x63, 0x00}; + char charOut[40]; + char chars[]="abc"; /* needs default codepage */ + + log_verbose("Testing u_uastrncpy() and u_uastrcpy()"); + + u_uastrcpy(temp, "abc"); + if(u_strcmp(temp, uchars) != 0) { + log_err("There is an error in u_uastrcpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp)); + } + + temp[0] = 0xFB; /* load garbage into it */ + temp[1] = 0xFB; + temp[2] = 0xFB; + temp[3] = 0xFB; + + u_uastrncpy(temp, "abcabcabc", 3); + if(u_strncmp(uchars, temp, 3) != 0){ + log_err("There is an error in u_uastrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp)); + } + if(temp[3] != 0xFB) { + log_err("u_uastrncpy wrote past it's bounds. Expected undisturbed byte at 3\n"); + } + + charOut[0] = (char)0x7B; /* load garbage into it */ + charOut[1] = (char)0x7B; + charOut[2] = (char)0x7B; + charOut[3] = (char)0x7B; + + temp[0] = 0x0061; + temp[1] = 0x0062; + temp[2] = 0x0063; + temp[3] = 0x0061; + temp[4] = 0x0062; + temp[5] = 0x0063; + temp[6] = 0x0000; + + u_austrncpy(charOut, temp, 3); + if(strncmp(chars, charOut, 3) != 0){ + log_err("There is an error in u_austrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp)); + } + if(charOut[3] != (char)0x7B) { + log_err("u_austrncpy wrote past it's bounds. Expected undisturbed byte at 3\n"); + } + + /*Testing u_strchr()*/ + log_verbose("Testing u_strchr\n"); + temp[0]=0x42; + temp[1]=0x62; + temp[2]=0x62; + temp[3]=0x63; + temp[4]=0xd841; + temp[5]=0xd841; + temp[6]=0xdc02; + temp[7]=0; + result=u_strchr(temp, (UChar)0x62); + if(result != temp+1){ + log_err("There is an error in u_strchr() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + /*Testing u_strstr()*/ + log_verbose("Testing u_strstr\n"); + subString[0]=0x62; + subString[1]=0x63; + subString[2]=0; + result=u_strstr(temp, subString); + if(result != temp+2){ + log_err("There is an error in u_strstr() Expected match at position 2 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_strstr(temp, subString+2); /* subString+2 is an empty string */ + if(result != temp){ + log_err("There is an error in u_strstr() Expected match at position 0 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_strstr(subString, temp); + if(result != NULL){ + log_err("There is an error in u_strstr() Expected NULL \"not found\" Got non-NULL \"found\" result\n"); + } + + /*Testing u_strchr32*/ + log_verbose("Testing u_strchr32\n"); + result=u_strchr32(temp, (UChar32)0x62); + if(result != temp+1){ + log_err("There is an error in u_strchr32() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_strchr32(temp, (UChar32)0xfb); + if(result != NULL){ + log_err("There is an error in u_strchr32() Expected NULL \"not found\" Got non-NULL \"found\" result\n"); + } + result=u_strchr32(temp, (UChar32)0x20402); + if(result != temp+5){ + log_err("There is an error in u_strchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + + temp[7]=0xfc00; + result=u_memchr32(temp, (UChar32)0x20402, 7); + if(result != temp+5){ + log_err("There is an error in u_memchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_memchr32(temp, (UChar32)0x20402, 6); + if(result != NULL){ + log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_memchr32(temp, (UChar32)0x20402, 1); + if(result != NULL){ + log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result); + } + result=u_memchr32(temp, (UChar32)0xfc00, 8); + if(result != temp+7){ + log_err("There is an error in u_memchr32() Expected match at position 7 Got %ld (pointer 0x%lx)\n", result-temp, result); + } +} + +/* test u_unescape() and u_unescapeAt() ------------------------------------- */ + +static void +TestUnescape() { + static UChar buffer[200]; + + static const char* input = + "Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\e\\cC\\n \\x1b\\x{263a}"; + + static const UChar expect[]={ + 0x53, 0x63, 0x68, 0xf6, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x3a, 0x20, + 0x20ac, 0x20, 0x31, 0x31, 0x32, 0x34, 0x30, 0x2e, 0x0c, + 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x73, 0x20, + 0x5a, 0x65, 0x69, 0x63, 0x68, 0x65, 0x6e, 0x3a, 0x20, 0xdbc8, 0xdf45, 0x1b, 0x03, 0x0a, 0x20, 0x1b, 0x263A, 0 + }; + static const int32_t explength = sizeof(expect)/sizeof(expect[0])-1; + int32_t length; + + /* test u_unescape() */ + length=u_unescape(input, buffer, sizeof(buffer)/sizeof(buffer[0])); + if(length!=explength || u_strcmp(buffer, expect)!=0) { + log_err("failure in u_unescape(): length %d!=%d and/or incorrect result string\n", length, + explength); + } + + /* try preflighting */ + length=u_unescape(input, NULL, sizeof(buffer)/sizeof(buffer[0])); + if(length!=explength || u_strcmp(buffer, expect)!=0) { + log_err("failure in u_unescape(preflighting): length %d!=%d\n", length, explength); + } + + /* ### TODO: test u_unescapeAt() */ +} + +/* test code point counting functions --------------------------------------- */ + +/* reference implementation of u_strHasMoreChar32Than() */ +static int32_t +_refStrHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) { + int32_t count=u_countChar32(s, length); + return count>number; +} + +/* compare the real function against the reference */ +static void +_testStrHasMoreChar32Than(const UChar *s, int32_t i, int32_t length, int32_t number) { + if(u_strHasMoreChar32Than(s, length, number)!=_refStrHasMoreChar32Than(s, length, number)) { + log_err("u_strHasMoreChar32Than(s+%d, %d, %d)=%hd is wrong\n", + i, length, number, u_strHasMoreChar32Than(s, length, number)); + } +} + +static void +TestCountChar32() { + static const UChar string[]={ + 0x61, 0x62, 0xd800, 0xdc00, + 0xd801, 0xdc01, 0x63, 0xd802, + 0x64, 0xdc03, 0x65, 0x66, + 0xd804, 0xdc04, 0xd805, 0xdc05, + 0x67 + }; + UChar buffer[100]; + int32_t i, length, number; + + /* test u_strHasMoreChar32Than() with length>=0 */ + length=LENGTHOF(string); + while(length>=0) { + for(i=0; i<=length; ++i) { + for(number=-1; number<=((length-i)+2); ++number) { + _testStrHasMoreChar32Than(string+i, i, length-i, number); + } + } + --length; + } + + /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */ + length=LENGTHOF(string); + u_memcpy(buffer, string, length); + while(length>=0) { + buffer[length]=0; + for(i=0; i<=length; ++i) { + for(number=-1; number<=((length-i)+2); ++number) { + _testStrHasMoreChar32Than(string+i, i, -1, number); + } + } + --length; + } + + /* test u_strHasMoreChar32Than() with NULL string (bad input) */ + for(length=-1; length<=1; ++length) { + for(i=0; i<=length; ++i) { + for(number=-2; number<=2; ++number) { + _testStrHasMoreChar32Than(NULL, 0, length, number); + } + } + } +} + +/* UCharIterator ------------------------------------------------------------ */ + +/* + * Compare results from two iterators, should be same. + * Assume that the text is not empty and that + * iteration start==0 and iteration limit==length. + */ +static void +compareIterators(UCharIterator *iter1, const char *n1, + UCharIterator *iter2, const char *n2) { + int32_t i, pos1, pos2, middle, length; + UChar32 c1, c2; + + /* compare lengths */ + length=iter1->getIndex(iter1, UITER_LENGTH); + pos2=iter2->getIndex(iter2, UITER_LENGTH); + if(length!=pos2) { + log_err("%s->getIndex(length)=%d != %d=%s->getIndex(length)\n", n1, length, pos2, n2); + return; + } + + /* set into the middle */ + middle=length/2; + + pos1=iter1->move(iter1, middle, UITER_ZERO); + if(pos1!=middle) { + log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n1, middle, pos1); + return; + } + + pos2=iter2->move(iter2, middle, UITER_ZERO); + if(pos2!=middle) { + log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n2, middle, pos2); + return; + } + + /* test current() */ + c1=iter1->current(iter1); + c2=iter2->current(iter2); + if(c1!=c2) { + log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle); + return; + } + + /* move forward 3 UChars */ + for(i=0; i<3; ++i) { + c1=iter1->next(iter1); + c2=iter2->next(iter2); + if(c1!=c2) { + log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } + + /* move backward 5 UChars */ + for(i=0; i<5; ++i) { + c1=iter1->previous(iter1); + c2=iter2->previous(iter2); + if(c1!=c2) { + log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } + + /* iterate forward from the beginning */ + pos1=iter1->move(iter1, 0, UITER_START); + if(pos1<0) { + log_err("%s->move(start) failed\n", n1); + return; + } + if(!iter1->hasNext(iter1)) { + log_err("%s->hasNext() at the start returns FALSE\n", n1); + return; + } + + pos2=iter2->move(iter2, 0, UITER_START); + if(pos2<0) { + log_err("%s->move(start) failed\n", n2); + return; + } + if(!iter2->hasNext(iter2)) { + log_err("%s->hasNext() at the start returns FALSE\n", n2); + return; + } + + do { + c1=iter1->next(iter1); + c2=iter2->next(iter2); + if(c1!=c2) { + log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } while(c1>=0); + + if(iter1->hasNext(iter1)) { + log_err("%s->hasNext() at the end returns TRUE\n", n1); + return; + } + if(iter2->hasNext(iter2)) { + log_err("%s->hasNext() at the end returns TRUE\n", n2); + return; + } + + /* back to the middle */ + pos1=iter1->move(iter1, middle, UITER_ZERO); + if(pos1!=middle) { + log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n1, middle, pos1); + return; + } + + pos2=iter2->move(iter2, middle, UITER_ZERO); + if(pos2!=middle) { + log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n2, middle, pos2); + return; + } + + /* move to index 1 */ + pos1=iter1->move(iter1, 1, UITER_ZERO); + if(pos1!=1) { + log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n1, middle, pos1); + return; + } + + pos2=iter2->move(iter2, 1, UITER_ZERO); + if(pos2!=1) { + log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n2, middle, pos2); + return; + } + + /* iterate backward from the end */ + pos1=iter1->move(iter1, 0, UITER_LIMIT); + if(pos1<0) { + log_err("%s->move(limit) failed\n", n1); + return; + } + if(!iter1->hasPrevious(iter1)) { + log_err("%s->hasPrevious() at the end returns FALSE\n", n1); + return; + } + + pos2=iter2->move(iter2, 0, UITER_LIMIT); + if(pos2<0) { + log_err("%s->move(limit) failed\n", n2); + return; + } + if(!iter2->hasPrevious(iter2)) { + log_err("%s->hasPrevious() at the end returns FALSE\n", n2); + return; + } + + do { + c1=iter1->previous(iter1); + c2=iter2->previous(iter2); + if(c1!=c2) { + log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } while(c1>=0); + + if(iter1->hasPrevious(iter1)) { + log_err("%s->hasPrevious() at the start returns TRUE\n", n1); + return; + } + if(iter2->hasPrevious(iter2)) { + log_err("%s->hasPrevious() at the start returns TRUE\n", n2); + return; + } +} + +/* + * Test the iterator's getState() and setState() functions. + * iter1 and iter2 must be set up for the same iterator type and the same string + * but may be physically different structs (different addresses). + * + * Assume that the text is not empty and that + * iteration start==0 and iteration limit==length. + * It must be 2<=middle<=length-2. + */ +static void +testIteratorState(UCharIterator *iter1, UCharIterator *iter2, const char *n, int32_t middle) { + UChar32 u[4]; + + UErrorCode errorCode; + UChar32 c; + uint32_t state; + int32_t i, j; + + /* get four UChars from the middle of the string */ + iter1->move(iter1, middle-2, UITER_ZERO); + for(i=0; i<4; ++i) { + c=iter1->next(iter1); + if(c<0) { + /* the test violates the assumptions, see comment above */ + log_err("test error: %s[%d]=%d\n", n, middle-2+i, c); + return; + } + u[i]=c; + } + + /* move to the middle and get the state */ + iter1->move(iter1, -2, UITER_CURRENT); + state=uiter_getState(iter1); + + /* set the state into the second iterator and compare the results */ + errorCode=U_ZERO_ERROR; + uiter_setState(iter2, state, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("%s->setState(0x%x) failed: %s\n", n, state, u_errorName(errorCode)); + return; + } + + c=iter2->current(iter2); + if(c!=u[2]) { + log_err("%s->current(at %d)=U+%04x!=U+%04x\n", n, middle, c, u[2]); + } + + c=iter2->previous(iter2); + if(c!=u[1]) { + log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-1, c, u[1]); + } + + iter2->move(iter2, 2, UITER_CURRENT); + c=iter2->next(iter2); + if(c!=u[3]) { + log_err("%s->next(at %d)=U+%04x!=U+%04x\n", n, middle+1, c, u[3]); + } + + iter2->move(iter2, -3, UITER_CURRENT); + c=iter2->previous(iter2); + if(c!=u[0]) { + log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-2, c, u[0]); + } + + /* move the second iterator back to the middle */ + iter2->move(iter2, 1, UITER_CURRENT); + iter2->next(iter2); + + /* check that both are in the middle */ + i=iter1->getIndex(iter1, UITER_CURRENT); + j=iter2->getIndex(iter2, UITER_CURRENT); + if(i!=middle) { + log_err("%s->getIndex(current)=%d!=%d as expected\n", n, i, middle); + } + if(i!=j) { + log_err("%s->getIndex(current)=%d!=%d after setState()\n", n, j, i); + } + + /* compare lengths */ + i=iter1->getIndex(iter1, UITER_LENGTH); + j=iter2->getIndex(iter2, UITER_LENGTH); + if(i!=j) { + log_err("%s->getIndex(length)=%d!=%d before/after setState()\n", n, i, j); + } +} + +static void +TestUCharIterator() { + static const UChar text[]={ + 0x61, 0x62, 0x63, 0xd801, 0xdffd, 0x78, 0x79, 0x7a, 0 + }; + char bytes[40]; + + UCharIterator iter, iter1, iter2; + UConverter *cnv; + UErrorCode errorCode; + int32_t length; + + /* simple API/code coverage - test NOOP UCharIterator */ + uiter_setString(&iter, NULL, 0); + if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!=-1 || + iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT)!=0 || + iter.hasNext(&iter) || iter.hasPrevious(&iter) + ) { + log_err("NOOP UCharIterator behaves unexpectedly\n"); + } + + /* test get/set state */ + length=LENGTHOF(text)-1; + uiter_setString(&iter1, text, -1); + uiter_setString(&iter2, text, length); + testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2); + testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1); + + /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */ + errorCode=U_ZERO_ERROR; + u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode)); + return; + } + + uiter_setString(&iter1, text, -1); + uiter_setUTF8(&iter2, bytes, length); + compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator"); + + /* try again with length=-1 */ + uiter_setUTF8(&iter2, bytes, -1); + compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1"); + + /* test get/set state */ + length=LENGTHOF(text)-1; + uiter_setUTF8(&iter1, bytes, -1); + testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2); + testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1); + + /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */ + errorCode=U_ZERO_ERROR; + cnv=ucnv_open("UTF-16BE", &errorCode); + length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode); + ucnv_close(cnv); + if(U_FAILURE(errorCode)) { + log_err("ucnv_fromUChars(UTF-16BE) failed, %s\n", u_errorName(errorCode)); + return; + } + + /* terminate with a _pair_ of 0 bytes - a UChar NUL in UTF-16BE (length is known to be ok) */ + bytes[length]=bytes[length+1]=0; + + uiter_setString(&iter1, text, -1); + uiter_setUTF16BE(&iter2, bytes, length); + compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator"); + + /* try again with length=-1 */ + uiter_setUTF16BE(&iter2, bytes, -1); + compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1"); + + /* try again after moving the bytes up one, and with length=-1 */ + memmove(bytes+1, bytes, length+2); + uiter_setUTF16BE(&iter2, bytes+1, -1); + compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1"); + + /* ### TODO test other iterators: CharacterIterator, Replaceable */ +} + +#if UCONFIG_NO_COLLATION + +static void +TestUNormIterator() { + /* test nothing */ +} + +static void +TestBadUNormIterator(void) { + /* test nothing, as well */ +} + +#else + +#include "unicode/unorm.h" +#include "unorm_it.h" + +/* + * Compare results from two iterators, should be same. + * Assume that the text is not empty and that + * iteration start==0 and iteration limit==length. + * + * Modified version of compareIterators() but does not assume that indexes + * are available. + */ +static void +compareIterNoIndexes(UCharIterator *iter1, const char *n1, + UCharIterator *iter2, const char *n2, + int32_t middle) { + uint32_t state; + int32_t i; + UChar32 c1, c2; + UErrorCode errorCode; + + /* code coverage for unorm_it.c/unormIteratorGetIndex() */ + if( + iter2->getIndex(iter2, UITER_START)!=0 || + iter2->getIndex(iter2, UITER_LENGTH)!=UITER_UNKNOWN_INDEX + ) { + log_err("UNormIterator.getIndex() failed\n"); + } + + /* set into the middle */ + iter1->move(iter1, middle, UITER_ZERO); + iter2->move(iter2, middle, UITER_ZERO); + + /* test current() */ + c1=iter1->current(iter1); + c2=iter2->current(iter2); + if(c1!=c2) { + log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle); + return; + } + + /* move forward 3 UChars */ + for(i=0; i<3; ++i) { + c1=iter1->next(iter1); + c2=iter2->next(iter2); + if(c1!=c2) { + log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } + + /* move backward 5 UChars */ + for(i=0; i<5; ++i) { + c1=iter1->previous(iter1); + c2=iter2->previous(iter2); + if(c1!=c2) { + log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } + + /* iterate forward from the beginning */ + iter1->move(iter1, 0, UITER_START); + if(!iter1->hasNext(iter1)) { + log_err("%s->hasNext() at the start returns FALSE\n", n1); + return; + } + + iter2->move(iter2, 0, UITER_START); + if(!iter2->hasNext(iter2)) { + log_err("%s->hasNext() at the start returns FALSE\n", n2); + return; + } + + do { + c1=iter1->next(iter1); + c2=iter2->next(iter2); + if(c1!=c2) { + log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } while(c1>=0); + + if(iter1->hasNext(iter1)) { + log_err("%s->hasNext() at the end returns TRUE\n", n1); + return; + } + if(iter2->hasNext(iter2)) { + log_err("%s->hasNext() at the end returns TRUE\n", n2); + return; + } + + /* iterate backward */ + do { + c1=iter1->previous(iter1); + c2=iter2->previous(iter2); + if(c1!=c2) { + log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } while(c1>=0); + + /* back to the middle */ + iter1->move(iter1, middle, UITER_ZERO); + iter2->move(iter2, middle, UITER_ZERO); + + /* try get/set state */ + while((state=uiter_getState(iter2))==UITER_NO_STATE) { + if(!iter2->hasNext(iter2)) { + log_err("%s has no known state from middle=%d to the end\n", n2, middle); + return; + } + iter2->next(iter2); + } + + errorCode=U_ZERO_ERROR; + + c2=iter2->current(iter2); + iter2->move(iter2, 0, UITER_ZERO); + uiter_setState(iter2, state, &errorCode); + c1=iter2->current(iter2); + if(U_FAILURE(errorCode) || c1!=c2) { + log_err("%s->current() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1); + return; + } + + c2=iter2->previous(iter2); + iter2->move(iter2, 0, UITER_ZERO); + uiter_setState(iter2, state, &errorCode); + c1=iter2->previous(iter2); + if(U_FAILURE(errorCode) || c1!=c2) { + log_err("%s->previous() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1); + return; + } + + /* iterate backward from the end */ + iter1->move(iter1, 0, UITER_LIMIT); + if(!iter1->hasPrevious(iter1)) { + log_err("%s->hasPrevious() at the end returns FALSE\n", n1); + return; + } + + iter2->move(iter2, 0, UITER_LIMIT); + if(!iter2->hasPrevious(iter2)) { + log_err("%s->hasPrevious() at the end returns FALSE\n", n2); + return; + } + + do { + c1=iter1->previous(iter1); + c2=iter2->previous(iter2); + if(c1!=c2) { + log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); + return; + } + } while(c1>=0); + + if(iter1->hasPrevious(iter1)) { + log_err("%s->hasPrevious() at the start returns TRUE\n", n1); + return; + } + if(iter2->hasPrevious(iter2)) { + log_err("%s->hasPrevious() at the start returns TRUE\n", n2); + return; + } +} + +/* n2 must have a digit 1 at the end, will be incremented with the normalization mode */ +static void +testUNormIteratorWithText(const UChar *text, int32_t textLength, int32_t middle, + const char *name1, const char *n2) { + UChar buffer[600]; + char name2[40]; + + UCharIterator iter1, iter2, *iter; + UNormIterator *uni; + + UNormalizationMode mode; + UErrorCode errorCode; + int32_t length; + + /* open a normalizing iterator */ + errorCode=U_ZERO_ERROR; + uni=unorm_openIter(NULL, 0, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unorm_openIter() fails: %s\n", u_errorName(errorCode)); + return; + } + + /* set iterator 2 to the original text */ + uiter_setString(&iter2, text, textLength); + + strcpy(name2, n2); + + /* test the normalizing iterator for each mode */ + for(mode=UNORM_NONE; mode<UNORM_MODE_COUNT; ++mode) { + length=unorm_normalize(text, textLength, mode, 0, buffer, LENGTHOF(buffer), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unorm_normalize(mode %d) failed: %s\n", mode, u_errorName(errorCode)); + break; + } + + /* set iterator 1 to the normalized text */ + uiter_setString(&iter1, buffer, length); + + /* set the normalizing iterator to use iter2 */ + iter=unorm_setIter(uni, &iter2, mode, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unorm_setIter(mode %d) failed: %s\n", mode, u_errorName(errorCode)); + break; + } + + compareIterNoIndexes(&iter1, name1, iter, name2, middle); + ++name2[strlen(name2)-1]; + } + + unorm_closeIter(uni); +} + +static void +TestUNormIterator() { + static const UChar text[]={ /* must contain <00C5 0327> see u_strchr() below */ + 0x61, /* 'a' */ + 0xe4, 0x61, 0x308, /* variations of 'a'+umlaut */ + 0xc5, 0x327, 0x41, 0x30a, 0x327, 0x41, 0x327, 0x30a, /* variations of 'A'+ring+cedilla */ + 0xfb03, 0xfb00, 0x69, 0x66, 0x66, 0x69, 0x66, 0xfb01 /* variations of 'ffi' */ + }; + static const UChar surrogateText[]={ + 0x6e, 0xd900, 0x6a, 0xdc00, 0xd900, 0xdc00, 0x61 + }; + + UChar longText[600]; + int32_t i, middle, length; + + length=LENGTHOF(text); + testUNormIteratorWithText(text, length, length/2, "UCharIter", "UNormIter1"); + testUNormIteratorWithText(text, length, length, "UCharIterEnd", "UNormIterEnd1"); + + /* test again, this time with an insane string to cause internal buffer overflows */ + middle=(int32_t)(u_strchr(text, 0x327)-text); /* see comment at text[] */ + memcpy(longText, text, middle*U_SIZEOF_UCHAR); + for(i=0; i<150; ++i) { + longText[middle+i]=0x30a; /* insert many rings between 'A-ring' and cedilla */ + } + memcpy(longText+middle+i, text+middle, (LENGTHOF(text)-middle)*U_SIZEOF_UCHAR); + length=LENGTHOF(text)+i; + + /* append another copy of this string for more overflows */ + memcpy(longText+length, longText, length*U_SIZEOF_UCHAR); + length*=2; + + /* the first test of the following two starts at length/4, inside the sea of combining rings */ + testUNormIteratorWithText(longText, length, length/4, "UCharIterLong", "UNormIterLong1"); + testUNormIteratorWithText(longText, length, length, "UCharIterLongEnd", "UNormIterLongEnd1"); + + length=LENGTHOF(surrogateText); + testUNormIteratorWithText(surrogateText, length, length/4, "UCharIterSurr", "UNormIterSurr1"); + testUNormIteratorWithText(surrogateText, length, length, "UCharIterSurrEnd", "UNormIterSurrEnd1"); +} + +static void +TestBadUNormIterator(void) { +#if !UCONFIG_NO_NORMALIZATION + UErrorCode status = U_ILLEGAL_ESCAPE_SEQUENCE; + UNormIterator *uni; + + unorm_setIter(NULL, NULL, UNORM_NONE, &status); + if (status != U_ILLEGAL_ESCAPE_SEQUENCE) { + log_err("unorm_setIter changed the error code to: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + unorm_setIter(NULL, NULL, UNORM_NONE, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("unorm_setIter didn't react correctly to bad arguments: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + uni=unorm_openIter(NULL, 0, &status); + if(U_FAILURE(status)) { + log_err("unorm_openIter() fails: %s\n", u_errorName(status)); + return; + } + unorm_setIter(uni, NULL, UNORM_NONE, &status); + unorm_closeIter(uni); +#endif +} + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c new file mode 100644 index 00000000000..2bb339c6d96 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c @@ -0,0 +1,48 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File CUTILTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda Creation +********************************************************************************* +*/ +#include "cintltst.h" + +void addLocaleTest(TestNode**); +void addCLDRTest(TestNode**); +void addUnicodeTest(TestNode**); +void addUStringTest(TestNode**); +void addCaseTest(TestNode**); +void addResourceBundleTest(TestNode**); +void addNEWResourceBundleTest(TestNode**); +void addHashtableTest(TestNode** root); +void addCStringTest(TestNode** root); +void addTrieTest(TestNode** root); +void addEnumerationTest(TestNode** root); +void addPosixTest(TestNode** root); +void addSortTest(TestNode** root); + +void addUtility(TestNode** root); + +void addUtility(TestNode** root) +{ + addCStringTest(root); + addTrieTest(root); + addLocaleTest(root); + addCLDRTest(root); + addUnicodeTest(root); + addUStringTest(root); + addCaseTest(root); + addResourceBundleTest(root); + addNEWResourceBundleTest(root); + addHashtableTest(root); + addEnumerationTest(root); + addPosixTest(root); + addSortTest(root); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c new file mode 100644 index 00000000000..1c48eca45aa --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c @@ -0,0 +1,357 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2003, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File encoll.C +* +* Modification History: +* Name Description +* Madhu Katragadda Ported for C API +*********************************************************************************/ +/** + * CollationEnglishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#include <stdlib.h> +#include <string.h> + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "unicode/uloc.h" +#include "cintltst.h" +#include "encoll.h" +#include "ccolltst.h" +#include "callcoll.h" +#include "unicode/ustring.h" + +static UCollator *myCollation = NULL; +const static UChar testSourceCases[][MAX_TOKEN_LEN] = { + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0020 /* ' ' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0048 /* 'H' */, (UChar)0x0065 /* 'e' */, (UChar)0x006C /* 'l' */, (UChar)0x006C /* 'l' */, (UChar)0x006F /* 'o' */, 0}, + {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0}, + {0x00C4, (UChar)0x0042 /* 'B' */, 0x0308, (UChar)0x0043 /* 'C' */, 0x0308, 0}, + {(UChar)0x0061 /* 'a' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x0072 /* 'r' */, 0}, + {(UChar)0x0072 /* 'r' */, (UChar)0x006F /* 'o' */, (UChar)0x006C /* 'l' */, (UChar)0x0065 /* 'e' */, (UChar)0x0073 /* 's' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0041 /* 'A' */, 0}, + {(UChar)0x0041 /* 'A' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0074 /* 't' */, (UChar)0x0063 /* 'c' */, (UChar)0x006F /* 'o' */, (UChar)0x006D /* 'm' */, (UChar)0x0070 /* 'p' */, (UChar)0x0061 /* 'a' */, (UChar)0x0072 /* 'r' */, (UChar)0x0065 /* 'e' */, (UChar)0x0070 /* 'p' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0069 /* 'i' */, (UChar)0x006E /* 'n' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0041 /* 'A' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00E6, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x0048 /* 'H' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0074 /* 't' */, (UChar)0x0068 /* 'h' */, (UChar)0x0069 /* 'i' */, 0x0302, (UChar)0x0073 /* 's' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, 0x00E6, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, 0x00E6, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0} +}; + +const static UChar testTargetCases[][MAX_TOKEN_LEN] = { + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, 0}, + {(UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x006C /* 'l' */, (UChar)0x006C /* 'l' */, (UChar)0x006F /* 'o' */, 0}, + {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0}, + {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, (UChar)0x0073 /* 's' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, (UChar)0x0073 /* 's' */, 0}, + {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x0072 /* 'r' */, 0}, + {0x00C4, (UChar)0x0042 /* 'B' */, 0x0308, (UChar)0x0043 /* 'C' */, 0x0308, 0}, + {(UChar)0x0041 /* 'A' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0072 /* 'r' */, (UChar)0x006F /* 'o' */, 0x0302, (UChar)0x006C /* 'l' */, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0041 /* 'A' */, 0x00E1, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0041 /* 'A' */, 0x00E1, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0054 /* 'T' */, (UChar)0x0043 /* 'C' */, (UChar)0x006F /* 'o' */, (UChar)0x006D /* 'm' */, (UChar)0x0070 /* 'p' */, (UChar)0x0061 /* 'a' */, (UChar)0x0072 /* 'r' */, (UChar)0x0065 /* 'e' */, (UChar)0x0050 /* 'P' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0069 /* 'i' */, (UChar)0x006E /* 'n' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0042 /* 'B' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0026 /* '&' */, (UChar)0x0062 /* 'b' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0023 /* '#' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x003D /* '=' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0064 /* 'd' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0043 /* 'C' */, (UChar)0x0048 /* 'H' */, (UChar)0x0063 /* 'c' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0074 /* 't' */, (UChar)0x0068 /* 'h' */, 0x00EE, (UChar)0x0073 /* 's' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0064 /* 'd' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, 0x00C6, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0064 /* 'd' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, 0x00C6, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0064 /* 'd' */, 0}, + {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0}, + {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0} +}; + +const static UCollationResult results[] = { + UCOL_LESS, + UCOL_LESS, /*UCOL_GREATER,*/ + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_EQUAL, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, /*UCOL_GREATER,*/ /* 10 */ + UCOL_GREATER, + UCOL_LESS, + UCOL_EQUAL, + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, /* 20 */ + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + UCOL_GREATER, + UCOL_GREATER, + /* Test Tertiary > 26 */ + UCOL_LESS, + UCOL_LESS, + UCOL_GREATER, + UCOL_LESS, /* 30 */ + UCOL_GREATER, + UCOL_EQUAL, + UCOL_GREATER, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS, + /* test identical > 36 */ + UCOL_EQUAL, + UCOL_EQUAL, + /* test primary > 38 */ + UCOL_EQUAL, + UCOL_EQUAL, /* 40 */ + UCOL_LESS, + UCOL_EQUAL, + UCOL_EQUAL, + /* test secondary > 43 */ + UCOL_LESS, + UCOL_LESS, + UCOL_EQUAL, + UCOL_LESS, + UCOL_LESS, + UCOL_LESS /* 49 */ +}; + +const static UChar testBugs[][MAX_TOKEN_LEN] = { + {(UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0041 /* 'A' */, 0}, + {(UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0045 /* 'E' */, 0}, + {0x00e9, 0}, + {0x00e8, 0}, + {0x00ea, 0}, + {0x00eb, 0}, + {(UChar)0x0065 /* 'e' */, (UChar)0x0061 /* 'a' */, 0}, + {(UChar)0x0078 /* 'x' */, 0} + +}; + +/* 0x0300 is grave, 0x0301 is acute + the order of elements in this array must be different than the order in CollationFrenchTest */ +const static UChar testAcute[][MAX_TOKEN_LEN] = { + {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0}, + {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0} +}; + +static const UChar testMore[][MAX_TOKEN_LEN] = { + {(UChar)0x0061 /* 'a' */, (UChar)0x0065 /* 'e' */, 0}, + { 0x00E6, 0}, + { 0x00C6, 0}, + {(UChar)0x0061 /* 'a' */, (UChar)0x0066 /* 'f' */, 0}, + {(UChar)0x006F /* 'o' */, (UChar)0x0065 /* 'e' */, 0}, + { 0x0153, 0}, + { 0x0152, 0}, + {(UChar)0x006F /* 'o' */, (UChar)0x0066 /* 'f' */, 0}, +}; + + +void addEnglishCollTest(TestNode** root) +{ + + addTest(root, &TestPrimary, "tscoll/encoll/TestPrimary"); + addTest(root, &TestSecondary, "tscoll/encoll/TestSecondary"); + addTest(root, &TestTertiary, "tscoll/encoll/TestTertiary"); + +} + +static void TestTertiary( ) +{ + int32_t testMoreSize; + UCollationResult expected=UCOL_EQUAL; + int32_t i,j; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("en_US", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + log_verbose("Testing English Collation with Tertiary strength\n"); + + ucol_setStrength(myCollation, UCOL_TERTIARY); + for (i = 0; i < 38 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + + + j = 0; + for (i = 0; i < 10; i++) + { + for (j = i+1; j < 10; j++) + { + doTest(myCollation, testBugs[i], testBugs[j], UCOL_LESS); + } + } + /*test more interesting cases */ + testMoreSize = sizeof(testMore) / sizeof(testMore[0]); + for (i = 0; i < testMoreSize; i++) + { + for (j = 0; j < testMoreSize; j++) + { + if (i < j) expected = UCOL_LESS; + if (i == j) expected = UCOL_EQUAL; + if (i > j) expected = UCOL_GREATER; + doTest(myCollation, testMore[i], testMore[j], expected ); + } + } + ucol_close(myCollation); +} + +static void TestPrimary() +{ + + int32_t i; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("en_US", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + ucol_setStrength(myCollation, UCOL_PRIMARY); + log_verbose("Testing English Collation with Primary strength\n"); + for (i = 38; i < 43 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + ucol_close(myCollation); +} + +static void TestSecondary() +{ + UCollationResult expected=UCOL_EQUAL; + int32_t i,j, testAcuteSize; + UErrorCode status = U_ZERO_ERROR; + myCollation = ucol_open("en_US", &status); + if(U_FAILURE(status)){ + log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status)); + return; + } + ucol_setStrength(myCollation, UCOL_SECONDARY); + log_verbose("Testing English Collation with Secondary strength\n"); + for (i = 43; i < 49 ; i++) + { + doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]); + } + + + /*test acute and grave ordering (compare to french collation) */ + testAcuteSize = sizeof(testAcute) / sizeof(testAcute[0]); + for (i = 0; i < testAcuteSize; i++) + { + for (j = 0; j < testAcuteSize; j++) + { + if (i < j) expected = UCOL_LESS; + if (i == j) expected = UCOL_EQUAL; + if (i > j) expected = UCOL_GREATER; + doTest(myCollation, testAcute[i], testAcute[j], expected ); + } + } +ucol_close(myCollation); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h new file mode 100644 index 00000000000..1102885a213 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h @@ -0,0 +1,44 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File encoll.H +* +* Modification History: +* Name Description +* Madhu Katragadda Converted to C +*********************************************************************************/ +/** + * CollationEnglishTest is a third level test class. This tests the locale + * specific primary, secondary and tertiary rules. For example, the ignorable + * character '-' in string "black-bird". The en_US locale uses the default + * collation rules as its sorting sequence. + */ + +#ifndef _CENCOLLTST +#define _CENCOLLTST + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "cintltst.h" + +#define MAX_TOKEN_LEN 16 + + /* performs test with strength PRIMARY */ +static void TestPrimary(void); + + /* perform test with strength SECONDARY */ +static void TestSecondary(void); + + /* perform test with strength TERTIARY */ +static void TestTertiary(void); + + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c b/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c new file mode 100644 index 00000000000..8e29d4c6815 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c @@ -0,0 +1,188 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1999-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/ctest.h" +#include "unicode/ucnv.h" + +void TestEuroRegression(void); +void addTestEuroRegression(TestNode** root); + +#if !UCONFIG_NO_LEGACY_CONVERSION +void addTestEuroRegression(TestNode** root) +{ + addTest(root, &TestEuroRegression, "tsconv/eurocreg/TestEuroRegression"); +} + +/* + * The table below lists codepages that are supposed to have roundtrip mappings for + * the U+20AC Euro sign. + * + * Changes made 2000nov28 and marked as such are due to the following: + * + * After updating all ibm-*.ucm files with precise fallback indicators (|0, |1, |3), + * some of these codepages failed the Euro regression test. + * This means that the actuall mappings changed when only the preciseness of fallback + * mappings should have changed. + * My (Markus) suspicion is that some files got Euro sign mappings added manually, + * changing their contents compared to the NLTC (IBM Toronto codepage database) definition. + * Such changes are highly undesirable because they effectively define new codepages. + * Codepage mapping files with "ibm-*.ucm" should always exactly match the files + * from the IBM codepage database. + * (If there are several mappings with the same number, then we choose the + * default mappings with Private-Use Area assignments.) + * + * Also, in the past, some aliases were set such that e.g. cp850 became an alias for ibm-858. + * This followed the practice of OS/2 that uses the old codepage number 850 for the new + * codepage 858, with the main difference being the additional Euro sign. + * However, we have documented that the "cp" prefix should be used for Microsoft-compatible + * codepages, and Microsoft Windows 2000's codepage 850 does not contain a Euro sign mapping. + * Therefore, cp850 must not support the Euro sign. + * In these cases, I have changed the codepage name here to point to a newer codepage with the + * Euro sign, using its new name. + * I could not find such "updates" for codepages 1362 and 1363 - we might want to supply them later. + */ + +static const char convertersToCheck[][15] = { + "cp1250", + "cp1251", + "cp1252", + "cp1254", + "cp1255", + "cp1256", + "cp1257", + "cp1258", + "ibm1140", + "ibm1142", + "ibm1143", + "ibm1144", + "ibm1145", + "ibm1146", + "ibm1147", + "ibm1148", + "ibm1149", + "ibm1153", + "ibm1154", + "ibm1155", + "ibm1156", + "ibm1157", + "ibm1158", + /*"ibm-1159",*/ /* removed 2003Apr17 */ + "ibm12712", + "ibm16804", + "ibm-1160", + "ibm-1162", + "ibm-1164", + + "ibm-858", /* was "cp850" changed 2000nov28 */ + /* duplicate "cp850" removed 2000nov28 */ + /*"ibm-9049",*/ /* was "cp857" changed 2002nov25 */ + "ibm-12712", /* was "cp424" changed 2000nov28 */ + "ibm-4899", /* was "cp803" changed 2000nov28 */ + "ibm-867", /* was "cp862" changed 2002nov25 */ + "cp1258", + "windows-950", + "cp1253", + /* "cp819", + "cp13488",*/ + "ibm-4971", + /*"ibm-9061",*/ /* was "cp869" changed 2002nov25 */ + /* "cp813",*/ + /*"ibm-9044",*/ /* was "cp852" changed 2002nov25 */ + /*"ibm-872",*/ /* was "cp855" changed 2002nov25 */ + /*"ibm-808",*/ /* was "cp866" changed 2002nov25 */ +/* "cp1131", + "cp1125",*/ + "ibm-902", /* was "cp922" changed 2003jan08 */ + "ibm-901", /* was "cp921" changed 2003jan09 */ + /*"ibm-17248",*/ /* was "cp864" changed 2002nov25 */ + /*"cp1008", + "cp1046",*/ + /* "cp9066", + "cp1129",*/ + "ibm-5123", /* was "cp1027" changed 2003jan08 */ + /* "cp300",*/ + /* "cp4930",*/ + "ibm-1364", + /* "cp1362" removed 2000nov28 */ + "cp1363", + /* "cp1114", removed 2002jul3 + "cp947", removed 2002jul3 */ + "gb18030", + ""}; + +UBool isEuroAware(UConverter*); + +void TestEuroRegression() +{ + int32_t i=0; + + do + { + UErrorCode err = U_ZERO_ERROR; + UConverter* myConv = ucnv_open(convertersToCheck[i], &err); + if (U_FAILURE(err)&&convertersToCheck[i][0]) + log_data_err("%s \tMISSING [%s]\n", convertersToCheck[i], u_errorName(err)); + else + { + if (isEuroAware(myConv)) + log_verbose("%s \tsupports euro\n", convertersToCheck[i]); + else + log_err("%s \tDOES NOT support euro\n", convertersToCheck[i]); + ucnv_close(myConv); + } + } while (convertersToCheck[++i][0]); +} + +UBool isEuroAware(UConverter* myConv) +{ + static const UChar euroString[2] = { 0x20AC, 0x0000 }; + char target[20]; + UChar euroBack[2]; + int32_t targetSize, euroBackSize; + UErrorCode err = U_ZERO_ERROR; + /*const char* myName = ucnv_getName(myConv, &err);*/ + + targetSize = ucnv_fromUChars(myConv, + target, + sizeof(target), + euroString, + -1, + &err); + if (U_FAILURE(err)) + { + log_err("Failure Occured in ucnv_fromUChars euro roundtrip test\n"); + return FALSE; + } + euroBackSize = ucnv_toUChars(myConv, + euroBack, + 2, + target, + targetSize, + &err); + if (U_FAILURE(err)) + { + log_err("Failure Occured in ucnv_toUChars euro roundtrip test\n"); + return FALSE; + } + if (u_strcmp(euroString, euroBack)) + { + /* log_err("%s FAILED Euro rountrip\n", myName);*/ + return FALSE; + } + else + { + /* log_verbose("%s PASSED Euro rountrip\n", myName);*/ + return TRUE; + } + +} +#else +void addTestEuroRegression(TestNode** root) +{ + /* test nothing... */ +} +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c new file mode 100644 index 00000000000..02cf1576cd3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c @@ -0,0 +1,530 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2003-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File hpmufn.c +* +*/ + +#include "unicode/utypes.h" +#include "unicode/putil.h" +#include "unicode/uclean.h" +#include "unicode/uchar.h" +#include "unicode/ures.h" +#include "cintltst.h" +#include "umutex.h" +#include "unicode/utrace.h" +#include <stdlib.h> +#include <string.h> + +/** + * This should align the memory properly on any machine. + */ +typedef union { + long t1; + double t2; + void *t3; +} ctest_AlignedMemory; + +static void TestHeapFunctions(void); +static void TestMutexFunctions(void); +static void TestIncDecFunctions(void); + +void addHeapMutexTest(TestNode **root); + + +void +addHeapMutexTest(TestNode** root) +{ + addTest(root, &TestHeapFunctions, "hpmufn/TestHeapFunctions" ); + addTest(root, &TestMutexFunctions, "hpmufn/TestMutexFunctions" ); + addTest(root, &TestIncDecFunctions, "hpmufn/TestIncDecFunctions"); +} + +static int32_t gMutexFailures = 0; + +#define TEST_STATUS(status, expected) \ +if (status != expected) { \ +log_err("FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \ + __FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailures++; } + + +#define TEST_ASSERT(expr) \ +if (!(expr)) { \ + log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \ + gMutexFailures++; \ +} + + +/* These tests do cleanup and reinitialize ICU in the course of their operation. + * The ICU data directory must be preserved across these operations. + * Here is a helper function to assist with that. + */ +static char *safeGetICUDataDirectory() { + const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */ + char *retStr = NULL; + if (dataDir != NULL) { + retStr = (char *)malloc(strlen(dataDir)+1); + strcpy(retStr, dataDir); + } + return retStr; +} + + + +/* + * Test Heap Functions. + * Implemented on top of the standard malloc heap. + * All blocks increased in size by 8 to 16 bytes, and the poiner returned to ICU is + * offset up by 8 to 16, which should cause a good heap corruption if one of our "blocks" + * ends up being freed directly, without coming through us. + * Allocations are counted, to check that ICU actually does call back to us. + */ +int gBlockCount = 0; +const void *gContext; + +static void * U_CALLCONV myMemAlloc(const void *context, size_t size) { + char *retPtr = (char *)malloc(size+sizeof(ctest_AlignedMemory)); + if (retPtr != NULL) { + retPtr += sizeof(ctest_AlignedMemory); + } + gBlockCount ++; + return retPtr; +} + +static void U_CALLCONV myMemFree(const void *context, void *mem) { + char *freePtr = (char *)mem; + if (freePtr != NULL) { + freePtr -= sizeof(ctest_AlignedMemory); + } + free(freePtr); +} + + + +static void * U_CALLCONV myMemRealloc(const void *context, void *mem, size_t size) { + char *p = (char *)mem; + char *retPtr; + + if (p!=NULL) { + p -= sizeof(ctest_AlignedMemory); + } + retPtr = realloc(p, size+sizeof(ctest_AlignedMemory)); + if (retPtr != NULL) { + p += sizeof(ctest_AlignedMemory); + } + return retPtr; +} + + +static void TestHeapFunctions() { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *rb = NULL; + char *icuDataDir; + UVersionInfo unicodeVersion = {0,0,0,0}; + + UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */ + UTraceExit *traceExitFunc; /* and restore them across calls to */ + UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */ + const void *traceContext; + int32_t traceLevel; + + icuDataDir = safeGetICUDataDirectory(); /* save icu data dir, so we can put it back + * after doing u_cleanup(). */ + + utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc); + traceLevel = utrace_getLevel(); + + /* Verify that ICU can be cleaned up and reinitialized successfully. + * Failure here usually means that some ICU service didn't clean up successfully, + * probably because some earlier test accidently left something open. */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + status = U_ZERO_ERROR; + u_setDataDirectory(icuDataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + if (U_FAILURE(status)) { + return; + } + + /* Can not set memory functions if ICU is already initialized */ + u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Un-initialize ICU */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + + /* Can not set memory functions with NULL values */ + status = U_ZERO_ERROR; + u_setMemoryFunctions(&gContext, NULL, myMemRealloc, myMemFree, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setMemoryFunctions(&gContext, myMemAlloc, NULL, myMemFree, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, NULL, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + + /* u_setMemoryFunctions() should work with null or non-null context pointer */ + status = U_ZERO_ERROR; + u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status); + TEST_STATUS(status, U_ZERO_ERROR); + u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status); + TEST_STATUS(status, U_ZERO_ERROR); + + + /* After reinitializing ICU, we should not be able to set the memory funcs again. */ + status = U_ZERO_ERROR; + u_setDataDirectory(icuDataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Doing ICU operations should cause allocations to come through our test heap */ + gBlockCount = 0; + status = U_ZERO_ERROR; + rb = ures_open(NULL, "es", &status); + TEST_STATUS(status, U_ZERO_ERROR); + if (gBlockCount == 0) { + log_err("Heap functions are not being called from ICU.\n"); + } + ures_close(rb); + + /* Cleanup should put the heap back to its default implementation. */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + u_setDataDirectory(icuDataDir); + u_getUnicodeVersion(unicodeVersion); + if (unicodeVersion[0] <= 0) { + log_err("Properties doesn't reinitialize without u_init.\n"); + } + status = U_ZERO_ERROR; + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + + /* ICU operations should no longer cause allocations to come through our test heap */ + gBlockCount = 0; + status = U_ZERO_ERROR; + rb = ures_open(NULL, "fr", &status); + TEST_STATUS(status, U_ZERO_ERROR); + if (gBlockCount != 0) { + log_err("Heap functions did not reset after u_cleanup.\n"); + } + ures_close(rb); + free(icuDataDir); +} + + +/* + * Test u_setMutexFunctions() + */ + +int gTotalMutexesInitialized = 0; /* Total number of mutexes created */ +int gTotalMutexesActive = 0; /* Total mutexes created, but not destroyed */ +int gAccumulatedLocks = 0; +const void *gMutexContext; + +typedef struct DummyMutex { + int fLockCount; + int fMagic; +} DummyMutex; + + +static void U_CALLCONV myMutexInit(const void *context, UMTX *mutex, UErrorCode *status) { + DummyMutex *theMutex; + + TEST_STATUS(*status, U_ZERO_ERROR); + theMutex = (DummyMutex *)malloc(sizeof(DummyMutex)); + theMutex->fLockCount = 0; + theMutex->fMagic = 123456; + gTotalMutexesInitialized++; + gTotalMutexesActive++; + gMutexContext = context; + *mutex = theMutex; +} + + +static void U_CALLCONV myMutexDestroy(const void *context, UMTX *mutex) { + DummyMutex *This = *(DummyMutex **)mutex; + + gTotalMutexesActive--; + TEST_ASSERT(This->fLockCount == 0); + TEST_ASSERT(This->fMagic == 123456); + This->fMagic = 0; + This->fLockCount = 0; + free(This); +} + +static void U_CALLCONV myMutexLock(const void *context, UMTX *mutex) { + DummyMutex *This = *(DummyMutex **)mutex; + + TEST_ASSERT(This->fMagic == 123456); + This->fLockCount++; + gAccumulatedLocks++; +} + +static void U_CALLCONV myMutexUnlock(const void *context, UMTX *mutex) { + DummyMutex *This = *(DummyMutex **)mutex; + + TEST_ASSERT(This->fMagic == 123456); + This->fLockCount--; + TEST_ASSERT(This->fLockCount >= 0); +} + + + +static void TestMutexFunctions() { + UErrorCode status = U_ZERO_ERROR; + UResourceBundle *rb = NULL; + char *icuDataDir; + + UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */ + UTraceExit *traceExitFunc; /* and restore them across calls to */ + UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */ + const void *traceContext; + int32_t traceLevel; + + gMutexFailures = 0; + + /* Save initial ICU state so that it can be restored later. + * u_cleanup(), which is called in this test, resets ICU's state. + */ + icuDataDir = safeGetICUDataDirectory(); + utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc); + traceLevel = utrace_getLevel(); + + /* Verify that ICU can be cleaned up and reinitialized successfully. + * Failure here usually means that some ICU service didn't clean up successfully, + * probably because some earlier test accidently left something open. */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + status = U_ZERO_ERROR; + u_setDataDirectory(icuDataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + if (U_FAILURE(status)) { + return; + } + + /* Can not set mutex functions if ICU is already initialized */ + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Un-initialize ICU */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + + /* Can not set Mutex functions with NULL values */ + status = U_ZERO_ERROR; + u_setMutexFunctions(&gContext, NULL, myMutexDestroy, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setMutexFunctions(&gContext, myMutexInit, NULL, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, NULL, myMutexUnlock, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, NULL, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + + /* u_setMutexFunctions() should work with null or non-null context pointer */ + status = U_ZERO_ERROR; + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_ZERO_ERROR); + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_ZERO_ERROR); + + + /* After reinitializing ICU, we should not be able to set the mutex funcs again. */ + status = U_ZERO_ERROR; + u_setDataDirectory(icuDataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Doing ICU operations should cause allocations to come through our test mutexes */ + gBlockCount = 0; + status = U_ZERO_ERROR; + rb = ures_open(NULL, "es", &status); + TEST_STATUS(status, U_ZERO_ERROR); + TEST_ASSERT(gTotalMutexesInitialized > 0); + TEST_ASSERT(gTotalMutexesActive > 0); + + ures_close(rb); + + /* Cleanup should destroy all of the mutexes. */ + u_cleanup(); + u_setDataDirectory(icuDataDir); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + status = U_ZERO_ERROR; + TEST_ASSERT(gTotalMutexesInitialized > 0); + TEST_ASSERT(gTotalMutexesActive == 0); + + + /* Additional ICU operations should no longer use our dummy test mutexes */ + gTotalMutexesInitialized = 0; + gTotalMutexesActive = 0; + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + + status = U_ZERO_ERROR; + rb = ures_open(NULL, "fr", &status); + TEST_STATUS(status, U_ZERO_ERROR); + TEST_ASSERT(gTotalMutexesInitialized == 0); + TEST_ASSERT(gTotalMutexesActive == 0); + + ures_close(rb); + free(icuDataDir); + + if(gMutexFailures) { + log_info("Note: these failures may be caused by ICU failing to initialize/uninitialize properly.\n"); + log_verbose("Check for prior tests which may not have closed all open resources. See the internal function ures_flushCache()\n"); + } +} + + + + +/* + * Test Atomic Increment & Decrement Functions + */ + +int gIncCount = 0; +int gDecCount = 0; +const void *gIncDecContext; +const void *gExpectedContext = &gIncDecContext; + + +static int32_t U_CALLCONV myIncFunc(const void *context, int32_t *p) { + int32_t retVal; + TEST_ASSERT(context == gExpectedContext); + gIncCount++; + retVal = ++(*p); + return retVal; +} + +static int32_t U_CALLCONV myDecFunc(const void *context, int32_t *p) { + int32_t retVal; + TEST_ASSERT(context == gExpectedContext); + gDecCount++; + retVal = --(*p); + return retVal; +} + + + + +static void TestIncDecFunctions() { + UErrorCode status = U_ZERO_ERROR; + int32_t t = 1; /* random value to make sure that Inc/dec works */ + char *dataDir; + + UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */ + UTraceExit *traceExitFunc; /* and restore them across calls to */ + UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */ + const void *traceContext; + int32_t traceLevel; + + /* Save ICU's data dir and tracing functions so that they can be resored + after cleanup and reinit. */ + dataDir = safeGetICUDataDirectory(); + utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc); + traceLevel = utrace_getLevel(); + + /* Verify that ICU can be cleaned up and reinitialized successfully. + * Failure here usually means that some ICU service didn't clean up successfully, + * probably because some earlier test accidently left something open. */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + status = U_ZERO_ERROR; + u_setDataDirectory(dataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + if (U_FAILURE(status)) { + return; + } + + /* Can not set mutex functions if ICU is already initialized */ + u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Clean up ICU */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + + /* Can not set functions with NULL values */ + status = U_ZERO_ERROR; + u_setAtomicIncDecFunctions(&gIncDecContext, NULL, myDecFunc, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + status = U_ZERO_ERROR; + u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, NULL, &status); + TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); + + /* u_setIncDecFunctions() should work with null or non-null context pointer */ + status = U_ZERO_ERROR; + gExpectedContext = NULL; + u_setAtomicIncDecFunctions(NULL, myIncFunc, myDecFunc, &status); + TEST_STATUS(status, U_ZERO_ERROR); + gExpectedContext = &gIncDecContext; + u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status); + TEST_STATUS(status, U_ZERO_ERROR); + + + /* After reinitializing ICU, we should not be able to set the inc/dec funcs again. */ + status = U_ZERO_ERROR; + u_setDataDirectory(dataDir); + u_init(&status); + TEST_STATUS(status, U_ZERO_ERROR); + gExpectedContext = &gIncDecContext; + u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status); + TEST_STATUS(status, U_INVALID_STATE_ERROR); + + /* Doing ICU operations should cause our functions to be called */ + gIncCount = 0; + gDecCount = 0; + umtx_atomic_inc(&t); + TEST_ASSERT(t == 2); + umtx_atomic_dec(&t); + TEST_ASSERT(t == 1); + TEST_ASSERT(gIncCount > 0); + TEST_ASSERT(gDecCount > 0); + + + /* Cleanup should cancel use of our inc/dec functions. */ + /* Additional ICU operations should not use them */ + u_cleanup(); + utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc); + utrace_setLevel(traceLevel); + gIncCount = 0; + gDecCount = 0; + status = U_ZERO_ERROR; + u_setDataDirectory(dataDir); + u_init(&status); + TEST_ASSERT(gIncCount == 0); + TEST_ASSERT(gDecCount == 0); + + status = U_ZERO_ERROR; + umtx_atomic_inc(&t); + umtx_atomic_dec(&t); + TEST_STATUS(status, U_ZERO_ERROR); + TEST_ASSERT(gIncCount == 0); + TEST_ASSERT(gDecCount == 0); + + free(dataDir); +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c new file mode 100644 index 00000000000..6196523087a --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c @@ -0,0 +1,885 @@ +/* + ******************************************************************************* + * + * Copyright (C) 2003-2007, International Business Machines + * Corporation and others. All Rights Reserved. + * + ******************************************************************************* + * file name: idnatest.c + * encoding: US-ASCII + * tab size: 8 (not used) + * indentation:4 + * + * created on: 2003jul11 + * created by: Ram Viswanadha + */ +#include <stdlib.h> +#include <string.h> +#include "unicode/utypes.h" + +#if !UCONFIG_NO_IDNA + +#include "unicode/ustring.h" +#include "unicode/uidna.h" +#include "cintltst.h" + + + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) +#define MAX_DEST_SIZE 1000 + +static void TestToUnicode(void); +static void TestToASCII(void); +static void TestIDNToUnicode(void); +static void TestIDNToASCII(void); +static void TestCompare(void); +static void TestUnicode32Norm(void); +static void TestJB4490(void); +static void TestJB4475(void); +static void TestLength(void); +static void TestJB5273(void); +void addIDNATest(TestNode** root); + + +typedef int32_t +(U_EXPORT2 *TestFunc) ( const UChar *src, int32_t srcLength, + UChar *dest, int32_t destCapacity, + int32_t options, UParseError *parseError, + UErrorCode *status); +typedef int32_t +(U_EXPORT2 *CompareFunc) (const UChar *s1, int32_t s1Len, + const UChar *s2, int32_t s2Len, + int32_t options, + UErrorCode *status); + + +void +addIDNATest(TestNode** root) +{ + addTest(root, &TestToUnicode, "idna/TestToUnicode"); + addTest(root, &TestToASCII, "idna/TestToASCII"); + addTest(root, &TestIDNToUnicode, "idna/TestIDNToUnicode"); + addTest(root, &TestIDNToASCII, "idna/TestIDNToASCII"); + addTest(root, &TestCompare, "idna/TestCompare"); + addTest(root, &TestUnicode32Norm,"idna/TestUnicode32Norm"); + addTest(root, &TestJB4490, "idna/TestJB4490"); + addTest(root, &TestJB4475, "idna/TestJB4475"); + addTest(root, &TestLength, "idna/TestLength"); + addTest(root, &TestJB5273, "idna/TestJB5273"); +} + +static void +testAPI(const UChar* src, const UChar* expected, const char* testName, + UBool useSTD3ASCIIRules,UErrorCode expectedStatus, + UBool doCompare, UBool testUnassigned, TestFunc func){ + + UErrorCode status = U_ZERO_ERROR; + UChar destStack[MAX_DEST_SIZE]; + int32_t destLen = 0; + UChar* dest = NULL; + int32_t expectedLen = (expected != NULL) ? u_strlen(expected) : 0; + int32_t options = (useSTD3ASCIIRules == TRUE) ? UIDNA_USE_STD3_RULES : UIDNA_DEFAULT; + UParseError parseError; + int32_t tSrcLen = 0; + UChar* tSrc = NULL; + + if(src != NULL){ + tSrcLen = u_strlen(src); + tSrc =(UChar*) malloc( U_SIZEOF_UCHAR * tSrcLen ); + memcpy(tSrc,src,tSrcLen * U_SIZEOF_UCHAR); + } + + /* test null-terminated source and return value of number of UChars required */ + + destLen = func(src,-1,NULL,0,options, &parseError , &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code */ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,-1,dest,destLen+1,options, &parseError, &status); + /* TODO : compare output with expected */ + if(U_SUCCESS(status) && expectedStatus != U_IDNA_STD3_ASCII_RULES_ERROR&& (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for null terminated source.\n" ); + } + }else{ + log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName); + } + } + + if(status != expectedStatus){ + log_err( "Did not get the expected error for %s null terminated source failed. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + free(tSrc); + return; + } + if(testUnassigned ){ + status = U_ZERO_ERROR; + destLen = func(src,-1,NULL,0,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code */ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,-1,dest,destLen+1,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status); + /* TODO : compare output with expected */ + if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for %s null terminated source with both options set.\n",testName); + + } + }else{ + log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName); + } + } + /*testing query string*/ + if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){ + log_err( "Did not get the expected error for %s null terminated source with options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + } + } + + status = U_ZERO_ERROR; + + /* test source with lengthand return value of number of UChars required*/ + destLen = func(tSrc, tSrcLen, NULL,0,options, &parseError, &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code */ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,u_strlen(src),dest,destLen+1,options, &parseError, &status); + /* TODO : compare output with expected */ + if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for %s with source length.\n",testName); + } + }else{ + log_err( "%s with source length failed. Requires destCapacity > 300\n",testName); + } + } + + if(status != expectedStatus){ + log_err( "Did not get the expected error for %s with source length. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + } + if(testUnassigned){ + status = U_ZERO_ERROR; + + destLen = func(tSrc,tSrcLen,NULL,0,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status); + + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code */ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,u_strlen(src),dest,destLen+1,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status); + /* TODO : compare output with expected */ + if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for %s with source length and both options set.\n",testName); + } + }else{ + log_err( "%s with source length failed. Requires destCapacity > 300\n",testName); + } + } + /*testing query string*/ + if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){ + log_err( "Did not get the expected error for %s with source length and options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + } + } + + status = U_ZERO_ERROR; + destLen = func(src,-1,NULL,0,options | UIDNA_USE_STD3_RULES, &parseError, &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code*/ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,-1,dest,destLen+1,options | UIDNA_USE_STD3_RULES, &parseError, &status); + /* TODO : compare output with expected*/ + if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for %s null terminated source with both options set.\n",testName); + + } + }else{ + log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName); + } + } + /*testing query string*/ + if(status != expectedStatus){ + log_err( "Did not get the expected error for %s null terminated source with options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + } + + status = U_ZERO_ERROR; + + destLen = func(tSrc,tSrcLen,NULL,0,options | UIDNA_USE_STD3_RULES, &parseError, &status); + + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; /* reset error code*/ + if(destLen+1 < MAX_DEST_SIZE){ + dest = destStack; + destLen = func(src,u_strlen(src),dest,destLen+1,options | UIDNA_USE_STD3_RULES, &parseError, &status); + /* TODO : compare output with expected*/ + if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){ + log_err("Did not get the expected result for %s with source length and both options set.\n",testName); + } + }else{ + log_err( "%s with source length failed. Requires destCapacity > 300\n",testName); + } + } + /*testing query string*/ + if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){ + log_err( "Did not get the expected error for %s with source length and options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status)); + } + free(tSrc); +} + +static const UChar unicodeIn[][41] ={ + { + 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644, + 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F, 0x0000 + }, + { + 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587, + 0x0000 + }, + { + 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 0x0074, + 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 0x00ED, 0x010D, + 0x0065, 0x0073, 0x006B, 0x0079, 0x0000 + }, + { + 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 0x05D8, + 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 0x05DD, 0x05E2, + 0x05D1, 0x05E8, 0x05D9, 0x05EA, 0x0000 + }, + { + 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 0x094D, + 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 0x0928, 0x0939, + 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 0x0915, 0x0924, 0x0947, + 0x0939, 0x0948, 0x0902, 0x0000 + }, + { + 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 0x3092, + 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 0x306E, 0x304B, + 0x0000 + }, +/* + { + 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774, + 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C, 0xB2E4, 0xBA74, + 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 0xAE4C, 0x0000 + }, +*/ + { + 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 0x043E, + 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 0x043E, 0x0440, + 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 0x0441, 0x0441, 0x043A, + 0x0438, 0x0000 + }, + { + 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 0x0070, + 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 0x006D, 0x0070, + 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 0x0065, 0x0068, 0x0061, + 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 0x006E, 0x0045, 0x0073, 0x0070, + 0x0061, 0x00F1, 0x006F, 0x006C, 0x0000 + }, + { + 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587, + 0x0000 + }, + { + 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 0x006B, + 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 0x0063, 0x0068, + 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 0x1EBF, 0x006E, 0x0067, + 0x0056, 0x0069, 0x1EC7, 0x0074, 0x0000 + }, + { + 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F, 0x0000 + }, + { + 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 0x0074, + 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 0x002D, 0x004D, + 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053, 0x0000 + }, + { + 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 0x006F, + 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 0x0079, 0x002D, + 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 0x6240, 0x0000 + }, + { + 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032, 0x0000 + }, + { + 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 0x3059, + 0x308B, 0x0035, 0x79D2, 0x524D, 0x0000 + }, + { + 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0, + 0x0000 + }, + { + 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067, 0x0000 + }, + /* test non-BMP code points */ + { + 0xD800, 0xDF00, 0xD800, 0xDF01, 0xD800, 0xDF02, 0xD800, 0xDF03, 0xD800, 0xDF05, + 0xD800, 0xDF06, 0xD800, 0xDF07, 0xD800, 0xDF09, 0xD800, 0xDF0A, 0xD800, 0xDF0B, + 0x0000 + }, + { + 0xD800, 0xDF0D, 0xD800, 0xDF0C, 0xD800, 0xDF1E, 0xD800, 0xDF0F, 0xD800, 0xDF16, + 0xD800, 0xDF15, 0xD800, 0xDF14, 0xD800, 0xDF12, 0xD800, 0xDF10, 0xD800, 0xDF20, + 0xD800, 0xDF21, + 0x0000 + }, + /* Greek */ + { + 0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac + }, + /* Maltese */ + { + 0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127, + 0x0127, 0x0061 + }, + /* Russian */ + { + 0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435, + 0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432, + 0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443, + 0x0441, 0x0441, 0x043a, 0x0438 + }, + { + 0x0054,0x0045,0x0053,0x0054 + } +}; + +static const char * const asciiIn[] = { + "xn--egbpdaj6bu4bxfgehfvwxn", + "xn--ihqwcrb4cv8a8dqg056pqjye", + "xn--Proprostnemluvesky-uyb24dma41a", + "xn--4dbcagdahymbxekheh6e0a7fei0b", + "xn--i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", + "xn--n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", +/* "xn--989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c",*/ + "xn--b1abfaaepdrnnbgefbaDotcwatmq2g4l", + "xn--PorqunopuedensimplementehablarenEspaol-fmd56a", + "xn--ihqwctvzc91f659drss3x8bo0yb", + "xn--TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g", + "xn--3B-ww4c5e180e575a65lsy2b", + "xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n", + "xn--Hello-Another-Way--fc4qua05auwb3674vfr0b", + "xn--2-u9tlzr9756bt3uc0v", + "xn--MajiKoi5-783gue6qz075azm5e", + "xn--de-jg4avhby1noc0d", + "xn--d9juau41awczczp", + "XN--097CCDEKGHQJK", + "XN--db8CBHEJLGH4E0AL", + "xn--hxargifdar", /* Greek */ + "xn--bonusaa-5bb1da", /* Maltese */ + "xn--b1abfaaepdrnnbgefbadotcwatmq2g4l", /* Russian (Cyrillic)*/ + "TEST" + +}; + +static const char * const domainNames[] = { + "slip129-37-118-146.nc.us.ibm.net", + "saratoga.pe.utexas.edu", + "dial-120-45.ots.utexas.edu", + "woo-085.dorms.waller.net", + "hd30-049.hil.compuserve.com", + "pem203-31.pe.ttu.edu", + "56K-227.MaxTNT3.pdq.net", + "dial-36-2.ots.utexas.edu", + "slip129-37-23-152.ga.us.ibm.net", + "ts45ip119.cadvision.com", + "sdn-ts-004txaustP05.dialsprint.net", + "bar-tnt1s66.erols.com", + "101.st-louis-15.mo.dial-access.att.net", + "h92-245.Arco.COM", + "dial-13-2.ots.utexas.edu", + "net-redynet29.datamarkets.com.ar", + "ccs-shiva28.reacciun.net.ve", + "7.houston-11.tx.dial-access.att.net", + "ingw129-37-120-26.mo.us.ibm.net", + "dialup6.austintx.com", + "dns2.tpao.gov.tr", + "slip129-37-119-194.nc.us.ibm.net", + "cs7.dillons.co.uk.203.119.193.in-addr.arpa", + "swprd1.innovplace.saskatoon.sk.ca", + "bikini.bologna.maraut.it", + "node91.subnet159-198-79.baxter.com", + "cust19.max5.new-york.ny.ms.uu.net", + "balexander.slip.andrew.cmu.edu", + "pool029.max2.denver.co.dynip.alter.net", + "cust49.max9.new-york.ny.ms.uu.net", + "s61.abq-dialin2.hollyberry.com", + "\\u0917\\u0928\\u0947\\u0936.sanjose.ibm.com", /*':'(0x003a) produces U_IDNA_STD3_ASCII_RULES_ERROR*/ + "www.xn--vea.com", + /* "www.\\u00E0\\u00B3\\u00AF.com",//' ' (0x0020) produces U_IDNA_STD3_ASCII_RULES_ERROR*/ + "www.\\u00C2\\u00A4.com", + "www.\\u00C2\\u00A3.com", + /* "\\u0025", //'%' (0x0025) produces U_IDNA_STD3_ASCII_RULES_ERROR*/ + /* "\\u005C\\u005C", //'\' (0x005C) produces U_IDNA_STD3_ASCII_RULES_ERROR*/ + /*"@",*/ + /*"\\u002F",*/ + /*"www.\\u0021.com",*/ + /*"www.\\u0024.com",*/ + /*"\\u003f",*/ + /* These yeild U_IDNA_PROHIBITED_ERROR*/ + /*"\\u00CF\\u0082.com",*/ + /*"\\u00CE\\u00B2\\u00C3\\u009Fss.com",*/ + /*"\\u00E2\\u0098\\u00BA.com",*/ + "\\u00C3\\u00BC.com" + +}; + +static void +TestToASCII(){ + + int32_t i; + UChar buf[MAX_DEST_SIZE]; + const char* testName = "uidna_toASCII"; + TestFunc func = uidna_toASCII; + for(i=0;i< (int32_t)(sizeof(unicodeIn)/sizeof(unicodeIn[0])); i++){ + u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1); + testAPI(unicodeIn[i], buf,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func); + + } +} + +static void +TestToUnicode(){ + + int32_t i; + UChar buf[MAX_DEST_SIZE]; + const char* testName = "uidna_toUnicode"; + TestFunc func = uidna_toUnicode; + for(i=0;i< (int32_t)(sizeof(asciiIn)/sizeof(asciiIn[0])); i++){ + u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1); + testAPI(buf,unicodeIn[i],testName,FALSE,U_ZERO_ERROR, TRUE, TRUE, func); + } +} + + +static void +TestIDNToUnicode(){ + int32_t i; + UChar buf[MAX_DEST_SIZE]; + UChar expected[MAX_DEST_SIZE]; + UErrorCode status = U_ZERO_ERROR; + int32_t bufLen = 0; + UParseError parseError; + const char* testName="uidna_IDNToUnicode"; + TestFunc func = uidna_IDNToUnicode; + for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){ + bufLen = (int32_t)strlen(domainNames[i]); + bufLen = u_unescape(domainNames[i],buf, bufLen+1); + func(buf,bufLen,expected,MAX_DEST_SIZE, UIDNA_ALLOW_UNASSIGNED, &parseError,&status); + if(U_FAILURE(status)){ + log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName, i, u_errorName(status)); + break; + } + testAPI(buf,expected,testName,FALSE,U_ZERO_ERROR, TRUE, TRUE, func); + /*test toUnicode with all labels in the string*/ + testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func); + if(U_FAILURE(status)){ + log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status)); + break; + } + } + +} + +static void +TestIDNToASCII(){ + int32_t i; + UChar buf[MAX_DEST_SIZE]; + UChar expected[MAX_DEST_SIZE]; + UErrorCode status = U_ZERO_ERROR; + int32_t bufLen = 0; + UParseError parseError; + const char* testName="udina_IDNToASCII"; + TestFunc func=uidna_IDNToASCII; + + for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){ + bufLen = (int32_t)strlen(domainNames[i]); + bufLen = u_unescape(domainNames[i],buf, bufLen+1); + func(buf,bufLen,expected,MAX_DEST_SIZE, UIDNA_ALLOW_UNASSIGNED, &parseError,&status); + if(U_FAILURE(status)){ + log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status)); + break; + } + testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func); + /*test toASCII with all labels in the string*/ + testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, FALSE, TRUE, func); + if(U_FAILURE(status)){ + log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status)); + break; + } + } + + +} + + +static void +testCompareWithSrc(const UChar* s1, int32_t s1Len, + const UChar* s2, int32_t s2Len, + const char* testName, CompareFunc func, + UBool isEqual){ + + UErrorCode status = U_ZERO_ERROR; + int32_t retVal = func(s1,-1,s2,-1,UIDNA_DEFAULT,&status); + + if(isEqual==TRUE && retVal !=0){ + log_err("Did not get the expected result for %s with null termniated strings.\n",testName); + } + if(U_FAILURE(status)){ + log_err( "%s null terminated source failed. Error: %s\n", testName,u_errorName(status)); + } + + status = U_ZERO_ERROR; + retVal = func(s1,-1,s2,-1,UIDNA_ALLOW_UNASSIGNED,&status); + + if(isEqual==TRUE && retVal !=0){ + log_err("Did not get the expected result for %s with null termniated strings with options set.\n", testName); + } + if(U_FAILURE(status)){ + log_err( "%s null terminated source and options set failed. Error: %s\n",testName, u_errorName(status)); + } + + status = U_ZERO_ERROR; + retVal = func(s1,s1Len,s2,s2Len,UIDNA_DEFAULT,&status); + + if(isEqual==TRUE && retVal !=0){ + log_err("Did not get the expected result for %s with string length.\n",testName); + } + if(U_FAILURE(status)){ + log_err( "%s with string length. Error: %s\n",testName, u_errorName(status)); + } + + status = U_ZERO_ERROR; + retVal = func(s1,s1Len,s2,s2Len,UIDNA_ALLOW_UNASSIGNED,&status); + + if(isEqual==TRUE && retVal !=0){ + log_err("Did not get the expected result for %s with string length and options set.\n",testName); + } + if(U_FAILURE(status)){ + log_err( "%s with string length and options set. Error: %s\n", u_errorName(status), testName); + } +} + + +static void +TestCompare(){ + int32_t i; + + const char* testName ="uidna_compare"; + CompareFunc func = uidna_compare; + + UChar www[] = {0x0057, 0x0057, 0x0057, 0x002E, 0x0000}; + UChar com[] = {0x002E, 0x0043, 0x004F, 0x004D, 0x0000}; + UChar buf[MAX_DEST_SIZE]={0x0057, 0x0057, 0x0057, 0x002E, 0x0000}; + UChar source[MAX_DEST_SIZE]={0}, + uni0[MAX_DEST_SIZE]={0}, + uni1[MAX_DEST_SIZE]={0}, + ascii0[MAX_DEST_SIZE]={0}, + ascii1[MAX_DEST_SIZE]={0}, + temp[MAX_DEST_SIZE] ={0}; + + + u_strcat(uni0,unicodeIn[0]); + u_strcat(uni0,com); + + u_strcat(uni1,unicodeIn[1]); + u_strcat(uni1,com); + + u_charsToUChars(asciiIn[0], temp, (int32_t)strlen(asciiIn[0])); + u_strcat(ascii0,temp); + u_strcat(ascii0,com); + + memset(temp, 0, U_SIZEOF_UCHAR * MAX_DEST_SIZE); + + u_charsToUChars(asciiIn[1], temp, (int32_t)strlen(asciiIn[1])); + u_strcat(ascii1,temp); + u_strcat(ascii1,com); + + /* prepend www. */ + u_strcat(source, www); + + for(i=0;i< (int32_t)(sizeof(unicodeIn)/sizeof(unicodeIn[0])); i++){ + UChar* src; + int32_t srcLen; + + memset(buf+4, 0, (MAX_DEST_SIZE-4) * U_SIZEOF_UCHAR); + + u_charsToUChars(asciiIn[i],buf+4, (int32_t)strlen(asciiIn[i])); + u_strcat(buf,com); + + + /* for every entry in unicodeIn array + prepend www. and append .com*/ + source[4]=0; + u_strncat(source,unicodeIn[i], u_strlen(unicodeIn[i])); + u_strcat(source,com); + + /* a) compare it with itself*/ + src = source; + srcLen = u_strlen(src); + + testCompareWithSrc(src,srcLen,src,srcLen,testName, func, TRUE); + + /* b) compare it with asciiIn equivalent */ + testCompareWithSrc(src,srcLen,buf,u_strlen(buf),testName, func,TRUE); + + /* c) compare it with unicodeIn not equivalent*/ + if(i==0){ + testCompareWithSrc(src,srcLen,uni1,u_strlen(uni1),testName, func,FALSE); + }else{ + testCompareWithSrc(src,srcLen,uni0,u_strlen(uni0),testName, func,FALSE); + } + /* d) compare it with asciiIn not equivalent */ + if(i==0){ + testCompareWithSrc(src,srcLen,ascii1,u_strlen(ascii1),testName, func,FALSE); + }else{ + testCompareWithSrc(src,srcLen,ascii0,u_strlen(ascii0),testName, func,FALSE); + } + + } +} + +static void TestUnicode32Norm() { + /* + * test Unicode 3.2 normalization, before Public Review Issue #29 + * see cnormtst.c TestComposition() + */ + static const UChar strings[][8]={ + { 0x1100, 0x0300, 0x1161, 0x0327 }, + { 0x0b47, 0x0300, 0x0b3e, 0x0327 } + }; + + UChar ascii[20], unicode[20]; + int32_t i, length; + UErrorCode errorCode; + + for(i=0; i<LENGTHOF(strings); ++i) { + errorCode=U_ZERO_ERROR; + length=uidna_toASCII(strings[i], -1, ascii, LENGTHOF(ascii), 0, NULL, &errorCode); + length=uidna_toUnicode(ascii, length, unicode, LENGTHOF(unicode), 0, NULL, &errorCode); + if(u_strncmp(ascii, unicode, length)!=0) { + log_err("Did not get the correct output\n"); + } + } +} + +static void TestJB4490(){ + static const UChar data[][50]= { + {0x00F5,0x00dE,0x00dF,0x00dD, 0x0000}, + {0xFB00,0xFB01} + }; + UChar output1[40] = {0}; + UChar output2[40] = {0}; + int32_t i; + for(i=0; i< sizeof(data)/sizeof(data[0]); i++){ + const UChar* src1 = data[i]; + int32_t src1Len = u_strlen(src1); + UChar* dest1 = output1; + int32_t dest1Len = 40; + UErrorCode status = U_ZERO_ERROR; + UParseError ps; + UChar* src2 = NULL; + int32_t src2Len = 0; + UChar* dest2 = output2; + int32_t dest2Len = 40; + dest1Len = uidna_toASCII(src1, src1Len, dest1, dest1Len,UIDNA_DEFAULT, &ps, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status)); + } + src2 = dest1; + src2Len = dest1Len; + dest2Len = uidna_toUnicode(src2, src2Len, dest2, dest2Len, UIDNA_DEFAULT, &ps, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status)); + } + } +} + +static void TestJB4475(){ + + static const UChar input[][10] = { + {0x0054,0x0045,0x0053,0x0054,0x0000},/* TEST */ + {0x0074,0x0065,0x0073,0x0074,0x0000} /* test */ + }; + int i; + UChar output[40] = {0}; + for(i=0; i< sizeof(input)/sizeof(input[0]); i++){ + const UChar* src = input[i]; + int32_t srcLen = u_strlen(src); + UChar* dest = output; + int32_t destLen = 40; + UErrorCode status = U_ZERO_ERROR; + UParseError ps; + + destLen = uidna_toASCII(src, srcLen, dest, destLen,UIDNA_DEFAULT, &ps, &status); + if(U_FAILURE(status)){ + log_err("uidna_toASCII failed with error %s.\n", u_errorName(status)); + } + if(u_strncmp(input[i], dest, srcLen)!=0){ + log_err("uidna_toASCII did not return the expected output.\n"); + } + } +} + +static void TestLength(){ + { + static const char* cl = "my_very_very_very_very_very_very_very_very_very_very_very_very_very_long_and_incredibly_uncreative_domain_label"; + UChar ul[128] = {'\0'}; + UChar dest[256] = {'\0'}; + /* this unicode string is longer than MAX_LABEL_BUFFER_SIZE and produces an + IDNA prepared string (including xn--)that is exactly 63 bytes long */ + UChar ul1[] = { 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774, + 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0x00AD, 0x034F, 0x1806, 0x180B, + 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, + 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, + 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0xD574, 0xD55C, 0xB2E4, 0xBA74, + 0xC138, 0x0041, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, + 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, + 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, + 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, + 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, + 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, + 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, + 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, + 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, + 0xFE0F, 0xFEFF, 0x0000 + }; + + int32_t len1 = LENGTHOF(ul1)-1/*remove the null termination*/; + int32_t destLen = LENGTHOF(dest); + UErrorCode status = U_ZERO_ERROR; + UParseError ps; + int32_t len = (int32_t)strlen(cl); + u_charsToUChars(cl, ul, len+1); + destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_ZERO_ERROR){ + log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = -1; + destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_ZERO_ERROR){ + log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = (int32_t)strlen(cl); + destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_LABEL_TOO_LONG_ERROR){ + log_err("uidna_toASCII failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = -1; + destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_LABEL_TOO_LONG_ERROR){ + log_err("uidna_toASCII failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_ZERO_ERROR){ + log_err("uidna_toASCII failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len1 = -1; + destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_ZERO_ERROR){ + log_err("uidna_toASCII failed with error %s.\n", u_errorName(status)); + } + } + { + static const char* cl = "my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.ibm.com"; + UChar ul[400] = {'\0'}; + UChar dest[400] = {'\0'}; + int32_t destLen = LENGTHOF(dest); + UErrorCode status = U_ZERO_ERROR; + UParseError ps; + int32_t len = (int32_t)strlen(cl); + u_charsToUChars(cl, ul, len+1); + + destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_IDNToUnicode failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = -1; + destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_IDNToUnicode failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = (int32_t)strlen(cl); + destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_IDNToASCII failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + destLen = LENGTHOF(dest); + len = -1; + destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_IDNToASCII failed with error %s.\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + uidna_compare(ul, len, ul, len, UIDNA_DEFAULT, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_compare failed with error %s.\n", u_errorName(status)); + } + uidna_compare(ul, -1, ul, -1, UIDNA_DEFAULT, &status); + if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){ + log_err("uidna_compare failed with error %s.\n", u_errorName(status)); + } + } +} +static void TestJB5273(){ + static const char INVALID_DOMAIN_NAME[] = "xn--m\\u00FCller.de"; + UChar invalid_idn[25] = {'\0'}; + int32_t len = u_unescape(INVALID_DOMAIN_NAME, invalid_idn, strlen(INVALID_DOMAIN_NAME)); + UChar output[50] = {'\0'}; + UErrorCode status = U_ZERO_ERROR; + UParseError prsError; + int32_t outLen = uidna_toUnicode(invalid_idn, len, output, 50, UIDNA_DEFAULT, &prsError, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + outLen = uidna_toUnicode(invalid_idn, len, output, 50, UIDNA_USE_STD3_RULES, &prsError, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status)); + } + + status = U_ZERO_ERROR; + outLen = uidna_IDNToUnicode(invalid_idn, len, output, 50, UIDNA_DEFAULT, &prsError, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status)); + } + status = U_ZERO_ERROR; + outLen = uidna_IDNToUnicode(invalid_idn, len, output, 50, UIDNA_USE_STD3_RULES, &prsError, &status); + if(U_FAILURE(status)){ + log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status)); + } +} +#endif + +/* + * Hey, Emacs, please set the following: + * + * Local Variables: + * indent-tabs-mode: nil + * End: + * + */ + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c new file mode 100644 index 00000000000..d82d37b9e6d --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c @@ -0,0 +1,3354 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +******************************************************************************** +* File NCCBTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda 7/21/1999 Testing error callback routines +******************************************************************************** +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "cstring.h" +#include "unicode/uloc.h" +#include "unicode/ucnv.h" +#include "unicode/ucnv_err.h" +#include "cintltst.h" +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "nccbtst.h" +#include "unicode/ucnv_cb.h" +#define NEW_MAX_BUFFER 999 + +#define nct_min(x,y) ((x<y) ? x : y) +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0])) + +static int32_t gInBufferSize = 0; +static int32_t gOutBufferSize = 0; +static char gNuConvTestName[1024]; + +static void printSeq(const uint8_t* a, int len) +{ + int i=0; + log_verbose("\n{"); + while (i<len) + log_verbose("0x%02X, ", a[i++]); + log_verbose("}\n"); +} + +static void printUSeq(const UChar* a, int len) +{ + int i=0; + log_verbose("{"); + while (i<len) + log_verbose(" 0x%04x, ", a[i++]); + log_verbose("}\n"); +} + +static void printSeqErr(const uint8_t* a, int len) +{ + int i=0; + fprintf(stderr, "{"); + while (i<len) + fprintf(stderr, " 0x%02x, ", a[i++]); + fprintf(stderr, "}\n"); +} + +static void printUSeqErr(const UChar* a, int len) +{ + int i=0; + fprintf(stderr, "{"); + while (i<len) + fprintf(stderr, "0x%04x, ", a[i++]); + fprintf(stderr,"}\n"); +} + +static void setNuConvTestName(const char *codepage, const char *direction) +{ + sprintf(gNuConvTestName, "[testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]", + codepage, + direction, + (int)gInBufferSize, + (int)gOutBufferSize); +} + + +static void TestCallBackFailure(void); + +void addTestConvertErrorCallBack(TestNode** root); + +void addTestConvertErrorCallBack(TestNode** root) +{ + addTest(root, &TestSkipCallBack, "tsconv/nccbtst/TestSkipCallBack"); + addTest(root, &TestStopCallBack, "tsconv/nccbtst/TestStopCallBack"); + addTest(root, &TestSubCallBack, "tsconv/nccbtst/TestSubCallBack"); + addTest(root, &TestSubWithValueCallBack, "tsconv/nccbtst/TestSubWithValueCallBack"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestLegalAndOtherCallBack, "tsconv/nccbtst/TestLegalAndOtherCallBack"); + addTest(root, &TestSingleByteCallBack, "tsconv/nccbtst/TestSingleByteCallBack"); +#endif + + addTest(root, &TestCallBackFailure, "tsconv/nccbtst/TestCallBackFailure"); +} + +static void TestSkipCallBack() +{ + TestSkip(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestSkip(1,NEW_MAX_BUFFER); + TestSkip(1,1); + TestSkip(NEW_MAX_BUFFER, 1); +} + +static void TestStopCallBack() +{ + TestStop(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestStop(1,NEW_MAX_BUFFER); + TestStop(1,1); + TestStop(NEW_MAX_BUFFER, 1); +} + +static void TestSubCallBack() +{ + TestSub(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestSub(1,NEW_MAX_BUFFER); + TestSub(1,1); + TestSub(NEW_MAX_BUFFER, 1); + +#if !UCONFIG_NO_LEGACY_CONVERSION + TestEBCDIC_STATEFUL_Sub(1, 1); + TestEBCDIC_STATEFUL_Sub(1, NEW_MAX_BUFFER); + TestEBCDIC_STATEFUL_Sub(NEW_MAX_BUFFER, 1); + TestEBCDIC_STATEFUL_Sub(NEW_MAX_BUFFER, NEW_MAX_BUFFER); +#endif +} + +static void TestSubWithValueCallBack() +{ + TestSubWithValue(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestSubWithValue(1,NEW_MAX_BUFFER); + TestSubWithValue(1,1); + TestSubWithValue(NEW_MAX_BUFFER, 1); +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestLegalAndOtherCallBack() +{ + TestLegalAndOthers(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestLegalAndOthers(1,NEW_MAX_BUFFER); + TestLegalAndOthers(1,1); + TestLegalAndOthers(NEW_MAX_BUFFER, 1); +} + +static void TestSingleByteCallBack() +{ + TestSingleByte(NEW_MAX_BUFFER, NEW_MAX_BUFFER); + TestSingleByte(1,NEW_MAX_BUFFER); + TestSingleByte(1,1); + TestSingleByte(NEW_MAX_BUFFER, 1); +} +#endif + +static void TestSkip(int32_t inputsize, int32_t outputsize) +{ + static const uint8_t expskipIBM_949[]= { + 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xc8, 0xd3 }; + + static const uint8_t expskipIBM_943[] = { + 0x9f, 0xaf, 0x9f, 0xb1, 0x89, 0x59 }; + + static const uint8_t expskipIBM_930[] = { + 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x46, 0x6b, 0x0f }; + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + /*From Unicode*/ + log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_SKIP \n"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + { + static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 }; + static const UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 }; + + static const int32_t toIBM949Offsskip [] = { 0, 1, 1, 2, 2, 4, 4 }; + static const int32_t toIBM943Offsskip [] = { 0, 0, 1, 1, 3, 3 }; + + if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expskipIBM_949, sizeof(expskipIBM_949), "ibm-949", + UCNV_FROM_U_CALLBACK_SKIP, toIBM949Offsskip, NULL, 0 )) + log_err("u-> ibm-949 with skip did not match.\n"); + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expskipIBM_943, sizeof(expskipIBM_943), "ibm-943", + UCNV_FROM_U_CALLBACK_SKIP, toIBM943Offsskip, NULL, 0 )) + log_err("u-> ibm-943 with skip did not match.\n"); + } + + { + static const UChar fromU[] = { 0x61, 0xff5e, 0x62, 0x6d63, 0xff5e, 0x6d64, 0x63, 0xff5e, 0x6d66 }; + static const uint8_t fromUBytes[] = { 0x62, 0x63, 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x0f, 0x64, 0x0e, 0x46, 0x6b, 0x0f }; + static const int32_t fromUOffsets[] = { 0, 2, 3, 3, 3, 5, 5, 6, 6, 8, 8, 8, 8 }; + + /* test ibm-930 (EBCDIC_STATEFUL) with fallbacks that are not taken to check correct state transitions */ + if(!testConvertFromUnicode(fromU, sizeof(fromU)/U_SIZEOF_UCHAR, + fromUBytes, sizeof(fromUBytes), + "ibm-930", + UCNV_FROM_U_CALLBACK_SKIP, fromUOffsets, + NULL, 0) + ) { + log_err("u->ibm-930 with skip with untaken fallbacks did not match.\n"); + } + } +#endif + + { + static const UChar usasciiFromU[] = { 0x61, 0x80, 0x4e00, 0x31, 0xd800, 0xdfff, 0x39 }; + static const uint8_t usasciiFromUBytes[] = { 0x61, 0x31, 0x39 }; + static const int32_t usasciiFromUOffsets[] = { 0, 3, 6 }; + + static const UChar latin1FromU[] = { 0x61, 0xa0, 0x4e00, 0x31, 0xd800, 0xdfff, 0x39 }; + static const uint8_t latin1FromUBytes[] = { 0x61, 0xa0, 0x31, 0x39 }; + static const int32_t latin1FromUOffsets[] = { 0, 1, 3, 6 }; + + /* US-ASCII */ + if(!testConvertFromUnicode(usasciiFromU, sizeof(usasciiFromU)/U_SIZEOF_UCHAR, + usasciiFromUBytes, sizeof(usasciiFromUBytes), + "US-ASCII", + UCNV_FROM_U_CALLBACK_SKIP, usasciiFromUOffsets, + NULL, 0) + ) { + log_err("u->US-ASCII with skip did not match.\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* SBCS NLTC codepage 367 for US-ASCII */ + if(!testConvertFromUnicode(usasciiFromU, sizeof(usasciiFromU)/U_SIZEOF_UCHAR, + usasciiFromUBytes, sizeof(usasciiFromUBytes), + "ibm-367", + UCNV_FROM_U_CALLBACK_SKIP, usasciiFromUOffsets, + NULL, 0) + ) { + log_err("u->ibm-367 with skip did not match.\n"); + } +#endif + + /* ISO-Latin-1 */ + if(!testConvertFromUnicode(latin1FromU, sizeof(latin1FromU)/U_SIZEOF_UCHAR, + latin1FromUBytes, sizeof(latin1FromUBytes), + "LATIN_1", + UCNV_FROM_U_CALLBACK_SKIP, latin1FromUOffsets, + NULL, 0) + ) { + log_err("u->LATIN_1 with skip did not match.\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* windows-1252 */ + if(!testConvertFromUnicode(latin1FromU, sizeof(latin1FromU)/U_SIZEOF_UCHAR, + latin1FromUBytes, sizeof(latin1FromUBytes), + "windows-1252", + UCNV_FROM_U_CALLBACK_SKIP, latin1FromUOffsets, + NULL, 0) + ) { + log_err("u->windows-1252 with skip did not match.\n"); + } + } + + { + static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 }; + static const uint8_t toIBM943[]= { 0x61, 0x61 }; + static const int32_t offset[]= {0, 4}; + + /* EUC_JP*/ + static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 }; + static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x61, 0x8e, 0xe0, + }; + static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2, 6, 7, 7}; + + /*EUC_TW*/ + static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, }; + static const uint8_t to_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x61, 0xe6, 0xca, 0x8a, + }; + static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2, 6, 7, 7, 8,}; + + /*ISO-2022-JP*/ + static const UChar iso_2022_jp_inputText[]={0x0041, 0x00E9/*unassigned*/,0x0042, }; + static const uint8_t to_iso_2022_jp[]={ + 0x41, + 0x42, + + }; + static const int32_t from_iso_2022_jpOffs [] ={0,2}; + + /*ISO-2022-JP*/ + UChar const iso_2022_jp_inputText2[]={0x0041, 0x00E9/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, }; + static const uint8_t to_iso_2022_jp2[]={ + 0x41, + 0x43, + + }; + static const int32_t from_iso_2022_jpOffs2 [] ={0,2}; + + /*ISO-2022-cn*/ + static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712/*unassigned*/, 0x0042, }; + static const uint8_t to_iso_2022_cn[]={ + 0x41, 0x42 + }; + static const int32_t from_iso_2022_cnOffs [] ={ + 0, 2 + }; + + /*ISO-2022-CN*/ + static const UChar iso_2022_cn_inputText1[]={0x0041, 0x3712/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, }; + static const uint8_t to_iso_2022_cn1[]={ + 0x41, 0x43 + + }; + static const int32_t from_iso_2022_cnOffs1 [] ={ 0, 2 }; + + /*ISO-2022-kr*/ + static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042, }; + static const uint8_t to_iso_2022_kr[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0e, 0x25, 0x50, + 0x25, 0x50, + 0x0f, 0x42, + }; + static const int32_t from_iso_2022_krOffs [] ={ + -1,-1,-1,-1, + 0, + 1,1,1, + 3,3, + 4,4 + }; + + /*ISO-2022-kr*/ + static const UChar iso_2022_kr_inputText1[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0,0xd801/*illegal*/, 0x0042, }; + static const uint8_t to_iso_2022_kr1[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0e, 0x25, 0x50, + 0x25, 0x50, + + }; + static const int32_t from_iso_2022_krOffs1 [] ={ + -1,-1,-1,-1, + 0, + 1,1,1, + 3,3, + + }; + /* HZ encoding */ + static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, }; + + static const uint8_t to_hz[]={ + 0x7e, 0x7d, 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x26, 0x30, + 0x7e, 0x7d, 0x42, + + }; + static const int32_t from_hzOffs [] ={ + 0,0,0, + 1,1,1,1, + 3,3, + 4,4,4,4 + }; + + static const UChar hz_inputText1[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0,0xd801/*illegal*/, 0x0042, }; + + static const uint8_t to_hz1[]={ + 0x7e, 0x7d, 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x26, 0x30, + + + }; + static const int32_t from_hzOffs1 [] ={ + 0,0,0, + 1,1,1,1, + 3,3, + + }; + +#endif + + static const UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, }; + + static const uint8_t to_SCSU[]={ + 0x41, + 0x42 + + + }; + static const int32_t from_SCSUOffs [] ={ + 0, + 2, + + }; + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* ISCII */ + static const UChar iscii_inputText[]={ 0x0041, 0x3712/*unassigned*/, 0x0042, }; + static const uint8_t to_iscii[]={ + 0x41, + 0x42, + }; + static const int32_t from_isciiOffs [] ={ + 0,2, + + }; + /*ISCII*/ + static const UChar iscii_inputText1[]={0x0044, 0x3712/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, }; + static const uint8_t to_iscii1[]={ + 0x44, + 0x43, + + }; + static const int32_t from_isciiOffs1 [] ={0,2}; + + if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]), + toIBM943, sizeof(toIBM943), "ibm-943", + UCNV_FROM_U_CALLBACK_SKIP, offset, NULL, 0 )) + log_err("u-> ibm-943 with skip did not match.\n"); + + if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]), + to_euc_jp, sizeof(to_euc_jp), "euc-jp", + UCNV_FROM_U_CALLBACK_SKIP, fromEUC_JPOffs, NULL, 0 )) + log_err("u-> euc-jp with skip did not match.\n"); + + if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]), + to_euc_tw, sizeof(to_euc_tw), "euc-tw", + UCNV_FROM_U_CALLBACK_SKIP, from_euc_twOffs, NULL, 0 )) + log_err("u-> euc-tw with skip did not match.\n"); + + /*iso_2022_jp*/ + if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]), + to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_jpOffs, NULL, 0 )) + log_err("u-> iso-2022-jp with skip did not match.\n"); + + /* with context */ + if(!testConvertFromUnicodeWithContext(iso_2022_jp_inputText2, sizeof(iso_2022_jp_inputText2)/sizeof(iso_2022_jp_inputText2[0]), + to_iso_2022_jp2, sizeof(to_iso_2022_jp2), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_jpOffs2, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND )) + log_err("u-> iso-2022-jp with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n"); + + /*iso_2022_cn*/ + if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]), + to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_cnOffs, NULL, 0 )) + log_err("u-> iso-2022-cn with skip did not match.\n"); + /*with context*/ + if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText1, sizeof(iso_2022_cn_inputText1)/sizeof(iso_2022_cn_inputText1[0]), + to_iso_2022_cn1, sizeof(to_iso_2022_cn1), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_cnOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND )) + log_err("u-> iso-2022-cn with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n"); + + /*iso_2022_kr*/ + if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]), + to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_krOffs, NULL, 0 )) + log_err("u-> iso-2022-kr with skip did not match.\n"); + /*with context*/ + if(!testConvertFromUnicodeWithContext(iso_2022_kr_inputText1, sizeof(iso_2022_kr_inputText1)/sizeof(iso_2022_kr_inputText1[0]), + to_iso_2022_kr1, sizeof(to_iso_2022_kr1), "iso-2022-kr", + UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_krOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND )) + log_err("u-> iso-2022-kr with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n"); + + /*hz*/ + if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]), + to_hz, sizeof(to_hz), "HZ", + UCNV_FROM_U_CALLBACK_SKIP, from_hzOffs, NULL, 0 )) + log_err("u-> HZ with skip did not match.\n"); + /*with context*/ + if(!testConvertFromUnicodeWithContext(hz_inputText1, sizeof(hz_inputText1)/sizeof(hz_inputText1[0]), + to_hz1, sizeof(to_hz1), "hz", + UCNV_FROM_U_CALLBACK_SKIP, from_hzOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND )) + log_err("u-> hz with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n"); +#endif + + /*SCSU*/ + if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]), + to_SCSU, sizeof(to_SCSU), "SCSU", + UCNV_FROM_U_CALLBACK_SKIP, from_SCSUOffs, NULL, 0 )) + log_err("u-> SCSU with skip did not match.\n"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + /*ISCII*/ + if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]), + to_iscii, sizeof(to_iscii), "ISCII,version=0", + UCNV_FROM_U_CALLBACK_SKIP, from_isciiOffs, NULL, 0 )) + log_err("u-> iscii with skip did not match.\n"); + /*with context*/ + if(!testConvertFromUnicodeWithContext(iscii_inputText1, sizeof(iscii_inputText1)/sizeof(iscii_inputText1[0]), + to_iscii1, sizeof(to_iscii1), "ISCII,version=0", + UCNV_FROM_U_CALLBACK_SKIP, from_isciiOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND )) + log_err("u-> iscii with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n"); +#endif + } + + log_verbose("Testing fromUnicode for BOCU-1 with UCNV_TO_U_CALLBACK_SKIP\n"); + { + static const uint8_t sampleText[]={ /* from cintltst/bocu1tst.c/TestBOCU1 text 1 */ + 0xFB, 0xEE, 0x28, /* from source offset 0 */ + 0x24, 0x1E, 0x52, + 0xB2, + 0x20, + 0xB3, + 0xB1, + 0x0D, + 0x0A, + + 0x20, /* from 8 */ + 0x00, + 0xD0, 0x6C, + 0xB6, + 0xD8, 0xA5, + 0x20, + 0x68, + 0x59, + + 0xF9, 0x28, /* from 16 */ + 0x6D, + 0x20, + 0x73, + 0xE0, 0x2D, + 0xDE, 0x43, + 0xD0, 0x33, + 0x20, + + 0xFA, 0x83, /* from 24 */ + 0x25, 0x01, + 0xFB, 0x16, 0x87, + 0x4B, 0x16, + 0x20, + 0xE6, 0xBD, + 0xEB, 0x5B, + 0x4B, 0xCC, + + 0xF9, 0xA2, /* from 32 */ + 0xFC, 0x10, 0x3E, + 0xFE, 0x16, 0x3A, 0x8C, + 0x20, + 0xFC, 0x03, 0xAC, + + 0x01, /* from 41 */ + 0xDE, 0x83, + 0x20, + 0x09 + }; + static const UChar expected[]={ + 0xFEFF, 0x0061, 0x0062, 0x0020, /* 0 */ + 0x0063, 0x0061, 0x000D, 0x000A, + + 0x0020, 0x0000, 0x00DF, 0x00E6, /* 8 */ + 0x0930, 0x0020, 0x0918, 0x0909, + + 0x3086, 0x304D, 0x0020, 0x3053, /* 16 */ + 0x4000, 0x4E00, 0x7777, 0x0020, + + 0x9FA5, 0x4E00, 0xAC00, 0xBCDE, /* 24 */ + 0x0020, 0xD7A3, 0xDC00, 0xD800, + + 0xD800, 0xDC00, 0xD845, 0xDDDD, /* 32 */ + 0xDBBB, 0xDDEE, 0x0020, 0xDBFF, + + 0xDFFF, 0x0001, 0x0E40, 0x0020, /* 40 */ + 0x0009 + }; + static const int32_t offsets[]={ + 0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, + 16, 16, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, + 24, 24, 25, 25, 26, 26, 26, 27, 27, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 34, 34, 34, 36, 36, 36, 36, 38, 39, 39, 39, + 41, 42, 42, 43, 44 + }; + + /* BOCU-1 fromUnicode never calls callbacks, so this only tests single-byte and offsets behavior */ + if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected), + sampleText, sizeof(sampleText), + "BOCU-1", + UCNV_FROM_U_CALLBACK_SKIP, offsets, NULL, 0) + ) { + log_err("u->BOCU-1 with skip did not match.\n"); + } + } + + log_verbose("Testing fromUnicode for CESU-8 with UCNV_TO_U_CALLBACK_SKIP\n"); + { + const uint8_t sampleText[]={ + 0x61, /* 'a' */ + 0xc4, 0xb5, /* U+0135 */ + 0xed, 0x80, 0xa0, /* Hangul U+d020 */ + 0xed, 0xa0, 0x81, 0xed, 0xb0, 0x81, /* surrogate pair for U+10401 */ + 0xee, 0x80, 0x80, /* PUA U+e000 */ + 0xed, 0xb0, 0x81, /* unpaired trail surrogate U+dc01 */ + 0x62, /* 'b' */ + 0xed, 0xa0, 0x81, /* unpaired lead surrogate U+d801 */ + 0xd0, 0x80 /* U+0400 */ + }; + UChar expected[]={ + 0x0061, + 0x0135, + 0xd020, + 0xd801, 0xdc01, + 0xe000, + 0xdc01, + 0x0062, + 0xd801, + 0x0400 + }; + int32_t offsets[]={ + 0, + 1, 1, + 2, 2, 2, + 3, 3, 3, 4, 4, 4, + 5, 5, 5, + 6, 6, 6, + 7, + 8, 8, 8, + 9, 9 + }; + + /* CESU-8 fromUnicode never calls callbacks, so this only tests conversion and offsets behavior */ + + /* without offsets */ + if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected), + sampleText, sizeof(sampleText), + "CESU-8", + UCNV_FROM_U_CALLBACK_SKIP, NULL, NULL, 0) + ) { + log_err("u->CESU-8 with skip did not match.\n"); + } + + /* with offsets */ + if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected), + sampleText, sizeof(sampleText), + "CESU-8", + UCNV_FROM_U_CALLBACK_SKIP, offsets, NULL, 0) + ) { + log_err("u->CESU-8 with skip did not match.\n"); + } + } + + /*to Unicode*/ + log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_SKIP \n"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + { + + static const UChar IBM_949skiptoUnicode[]= {0x0000, 0xAC00, 0xAC01, 0xD700 }; + static const UChar IBM_943skiptoUnicode[]= { 0x6D63, 0x6D64, 0x6D66 }; + static const UChar IBM_930skiptoUnicode[]= { 0x6D63, 0x6D64, 0x6D66 }; + + static const int32_t fromIBM949Offs [] = { 0, 1, 3, 5}; + static const int32_t fromIBM943Offs [] = { 0, 2, 4}; + static const int32_t fromIBM930Offs [] = { 1, 3, 5}; + + if(!testConvertToUnicode(expskipIBM_949, sizeof(expskipIBM_949), + IBM_949skiptoUnicode, sizeof(IBM_949skiptoUnicode)/sizeof(IBM_949skiptoUnicode),"ibm-949", + UCNV_TO_U_CALLBACK_SKIP, fromIBM949Offs, NULL, 0 )) + log_err("ibm-949->u with skip did not match.\n"); + if(!testConvertToUnicode(expskipIBM_943, sizeof(expskipIBM_943), + IBM_943skiptoUnicode, sizeof(IBM_943skiptoUnicode)/sizeof(IBM_943skiptoUnicode[0]),"ibm-943", + UCNV_TO_U_CALLBACK_SKIP, fromIBM943Offs, NULL, 0 )) + log_err("ibm-943->u with skip did not match.\n"); + + + if(!testConvertToUnicode(expskipIBM_930, sizeof(expskipIBM_930), + IBM_930skiptoUnicode, sizeof(IBM_930skiptoUnicode)/sizeof(IBM_930skiptoUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SKIP, fromIBM930Offs, NULL, 0 )) + log_err("ibm-930->u with skip did not match.\n"); + + + if(!testConvertToUnicodeWithContext(expskipIBM_930, sizeof(expskipIBM_930), + IBM_930skiptoUnicode, sizeof(IBM_930skiptoUnicode)/sizeof(IBM_930skiptoUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SKIP, fromIBM930Offs, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND )) + log_err("ibm-930->u with skip did not match.\n"); + } +#endif + + { + static const uint8_t usasciiToUBytes[] = { 0x61, 0x80, 0x31 }; + static const UChar usasciiToU[] = { 0x61, 0x31 }; + static const int32_t usasciiToUOffsets[] = { 0, 2 }; + + static const uint8_t latin1ToUBytes[] = { 0x61, 0xa0, 0x31 }; + static const UChar latin1ToU[] = { 0x61, 0xa0, 0x31 }; + static const int32_t latin1ToUOffsets[] = { 0, 1, 2 }; + + /* US-ASCII */ + if(!testConvertToUnicode(usasciiToUBytes, sizeof(usasciiToUBytes), + usasciiToU, sizeof(usasciiToU)/U_SIZEOF_UCHAR, + "US-ASCII", + UCNV_TO_U_CALLBACK_SKIP, usasciiToUOffsets, + NULL, 0) + ) { + log_err("US-ASCII->u with skip did not match.\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* SBCS NLTC codepage 367 for US-ASCII */ + if(!testConvertToUnicode(usasciiToUBytes, sizeof(usasciiToUBytes), + usasciiToU, sizeof(usasciiToU)/U_SIZEOF_UCHAR, + "ibm-367", + UCNV_TO_U_CALLBACK_SKIP, usasciiToUOffsets, + NULL, 0) + ) { + log_err("ibm-367->u with skip did not match.\n"); + } +#endif + + /* ISO-Latin-1 */ + if(!testConvertToUnicode(latin1ToUBytes, sizeof(latin1ToUBytes), + latin1ToU, sizeof(latin1ToU)/U_SIZEOF_UCHAR, + "LATIN_1", + UCNV_TO_U_CALLBACK_SKIP, latin1ToUOffsets, + NULL, 0) + ) { + log_err("LATIN_1->u with skip did not match.\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* windows-1252 */ + if(!testConvertToUnicode(latin1ToUBytes, sizeof(latin1ToUBytes), + latin1ToU, sizeof(latin1ToU)/U_SIZEOF_UCHAR, + "windows-1252", + UCNV_TO_U_CALLBACK_SKIP, latin1ToUOffsets, + NULL, 0) + ) { + log_err("windows-1252->u with skip did not match.\n"); + } +#endif + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + { + static const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={ + 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44 + }; + static const UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63, 0x03b4 + }; + static const int32_t from_EBCIDIC_STATEFULOffsets []={ 1, 5}; + + + /* euc-jp*/ + static const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x8f, 0xda, 0xa1, /*unassigned*/ + 0x8e, 0xe0, + }; + static const UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec, 0x00a2}; + static const int32_t from_euc_jpOffs [] ={ 0, 1, 3, 9}; + + /*EUC_TW*/ + static const uint8_t sampleTxt_euc_tw[]={ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/ + 0xe6, 0xca, 0x8a, + }; + static const UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2, 0x8706, 0x8a, }; + static const int32_t from_euc_twOffs [] ={ 0, 1, 3, 11, 13}; + /*iso-2022-jp*/ + static const uint8_t sampleTxt_iso_2022_jp[]={ + 0x41, + 0x1b, 0x24, 0x42, 0x2A, 0x44, /*unassigned*/ + 0x1b, 0x28, 0x42, 0x42, + + }; + static const UChar iso_2022_jptoUnicode[]={ 0x41,0x42 }; + static const int32_t from_iso_2022_jpOffs [] ={ 0,9 }; + + /*iso-2022-cn*/ + static const uint8_t sampleTxt_iso_2022_cn[]={ + 0x0f, 0x41, 0x44, + 0x1B, 0x24, 0x29, 0x47, + 0x0E, 0x40, 0x6f, /*unassigned*/ + 0x0f, 0x42, + + }; + + static const UChar iso_2022_cntoUnicode[]={ 0x41, 0x44,0x42 }; + static const int32_t from_iso_2022_cnOffs [] ={ 1, 2, 11 }; + + /*iso-2022-kr*/ + static const uint8_t sampleTxt_iso_2022_kr[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0E, 0x7f, 0x1E, + 0x0e, 0x25, 0x50, + 0x0f, 0x51, + 0x42, 0x43, + + }; + static const UChar iso_2022_krtoUnicode[]={ 0x41,0x03A0,0x51, 0x42,0x43}; + static const int32_t from_iso_2022_krOffs [] ={ 4, 9, 12, 13 , 14 }; + + /*hz*/ + static const uint8_t sampleTxt_hz[]={ + 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x7f, 0x1E, /*unassigned*/ + 0x26, 0x30, + 0x7e, 0x7d, 0x42, + 0x7e, 0x7b, 0x7f, 0x1E,/*unassigned*/ + 0x7e, 0x7d, 0x42, + }; + static const UChar hztoUnicode[]={ + 0x41, + 0x03a0, + 0x03A0, + 0x42, + 0x42,}; + + static const int32_t from_hzOffs [] ={0,3,7,11,18, }; + + /*ISCII*/ + static const uint8_t sampleTxt_iscii[]={ + 0x41, + 0xa1, + 0xEB, /*unassigned*/ + 0x26, + 0x30, + 0xa2, + 0xEC, /*unassigned*/ + 0x42, + }; + static const UChar isciitoUnicode[]={ + 0x41, + 0x0901, + 0x26, + 0x30, + 0x0902, + 0x42, + }; + + static const int32_t from_isciiOffs [] ={0,1,3,4,5,7 }; + + /*LMBCS*/ + static const uint8_t sampleTxtLMBCS[]={ 0x12, 0xc9, 0x50, + 0x12, 0x92, 0xa0, /*unassigned*/ + 0x12, 0x92, 0xA1, + }; + static const UChar LMBCSToUnicode[]={ 0x4e2e, 0xe5c4}; + static const int32_t fromLMBCS[] = {0, 6}; + + if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL), + EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SKIP, from_EBCIDIC_STATEFULOffsets, NULL, 0 )) + log_err("EBCIDIC_STATEFUL->u with skip did not match.\n"); + + if(!testConvertToUnicodeWithContext(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL), + EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SKIP, from_EBCIDIC_STATEFULOffsets, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND )) + log_err("EBCIDIC_STATEFUL->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp), + euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp", + UCNV_TO_U_CALLBACK_SKIP, from_euc_jpOffs , NULL, 0)) + log_err("euc-jp->u with skip did not match.\n"); + + + + if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw), + euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw", + UCNV_TO_U_CALLBACK_SKIP, from_euc_twOffs , NULL, 0)) + log_err("euc-tw->u with skip did not match.\n"); + + + if(!testConvertToUnicode(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_jpOffs , NULL, 0)) + log_err("iso-2022-jp->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iso_2022_cn, sizeof(sampleTxt_iso_2022_cn), + iso_2022_cntoUnicode, sizeof(iso_2022_cntoUnicode)/sizeof(iso_2022_cntoUnicode[0]),"iso-2022-cn", + UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_cnOffs , NULL, 0)) + log_err("iso-2022-cn->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iso_2022_kr, sizeof(sampleTxt_iso_2022_kr), + iso_2022_krtoUnicode, sizeof(iso_2022_krtoUnicode)/sizeof(iso_2022_krtoUnicode[0]),"iso-2022-kr", + UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_krOffs , NULL, 0)) + log_err("iso-2022-kr->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_hz, sizeof(sampleTxt_hz), + hztoUnicode, sizeof(hztoUnicode)/sizeof(hztoUnicode[0]),"HZ", + UCNV_TO_U_CALLBACK_SKIP, from_hzOffs , NULL, 0)) + log_err("HZ->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iscii, sizeof(sampleTxt_iscii), + isciitoUnicode, sizeof(isciitoUnicode)/sizeof(isciitoUnicode[0]),"ISCII,version=0", + UCNV_TO_U_CALLBACK_SKIP, from_isciiOffs , NULL, 0)) + log_err("iscii->u with skip did not match.\n"); + + if(!testConvertToUnicode(sampleTxtLMBCS, sizeof(sampleTxtLMBCS), + LMBCSToUnicode, sizeof(LMBCSToUnicode)/sizeof(LMBCSToUnicode[0]),"LMBCS-1", + UCNV_TO_U_CALLBACK_SKIP, fromLMBCS , NULL, 0)) + log_err("LMBCS->u with skip did not match.\n"); + + } +#endif + + log_verbose("Testing to Unicode for UTF-8 with UCNV_TO_U_CALLBACK_SKIP \n"); + { + const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c, + 0xe0, 0x80, 0x61,}; + UChar expected1[] = { 0x0031, 0x4e8c, 0x0061}; + int32_t offsets1[] = { 0x0000, 0x0001, 0x0006}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8", + UCNV_TO_U_CALLBACK_SKIP, offsets1, NULL, 0 )) + log_err("utf8->u with skip did not match.\n");; + } + + log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SKIP \n"); + { + const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,}; + UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061,0xfffe,0xfffe}; + int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003,4,5}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU", + UCNV_TO_U_CALLBACK_SKIP, offsets1, NULL, 0 )) + log_err("scsu->u with skip did not match.\n"); + } + + log_verbose("Testing toUnicode for BOCU-1 with UCNV_TO_U_CALLBACK_SKIP\n"); + { + const uint8_t sampleText[]={ /* modified from cintltst/bocu1tst.c/TestBOCU1 text 1 */ + 0xFB, 0xEE, 0x28, /* single-code point sequence at offset 0 */ + 0x24, 0x1E, 0x52, /* 3 */ + 0xB2, /* 6 */ + 0x20, /* 7 */ + 0x40, 0x07, /* 8 - wrong trail byte */ + 0xB3, /* 10 */ + 0xB1, /* 11 */ + 0xD0, 0x20, /* 12 - wrong trail byte */ + 0x0D, /* 14 */ + 0x0A, /* 15 */ + 0x20, /* 16 */ + 0x00, /* 17 */ + 0xD0, 0x6C, /* 18 */ + 0xB6, /* 20 */ + 0xD8, 0xA5, /* 21 */ + 0x20, /* 23 */ + 0x68, /* 24 */ + 0x59, /* 25 */ + 0xF9, 0x28, /* 26 */ + 0x6D, /* 28 */ + 0x20, /* 29 */ + 0x73, /* 30 */ + 0xE0, 0x2D, /* 31 */ + 0xDE, 0x43, /* 33 */ + 0xD0, 0x33, /* 35 */ + 0x20, /* 37 */ + 0xFA, 0x83, /* 38 */ + 0x25, 0x01, /* 40 */ + 0xFB, 0x16, 0x87, /* 42 */ + 0x4B, 0x16, /* 45 */ + 0x20, /* 47 */ + 0xE6, 0xBD, /* 48 */ + 0xEB, 0x5B, /* 50 */ + 0x4B, 0xCC, /* 52 */ + 0xF9, 0xA2, /* 54 */ + 0xFC, 0x10, 0x3E, /* 56 */ + 0xFE, 0x16, 0x3A, 0x8C, /* 59 */ + 0x20, /* 63 */ + 0xFC, 0x03, 0xAC, /* 64 */ + 0xFF, /* 67 - FF just resets the state without encoding anything */ + 0x01, /* 68 */ + 0xDE, 0x83, /* 69 */ + 0x20, /* 71 */ + 0x09 /* 72 */ + }; + UChar expected[]={ + 0xFEFF, 0x0061, 0x0062, 0x0020, + 0x0063, 0x0061, 0x000D, 0x000A, + 0x0020, 0x0000, 0x00DF, 0x00E6, + 0x0930, 0x0020, 0x0918, 0x0909, + 0x3086, 0x304D, 0x0020, 0x3053, + 0x4000, 0x4E00, 0x7777, 0x0020, + 0x9FA5, 0x4E00, 0xAC00, 0xBCDE, + 0x0020, 0xD7A3, 0xDC00, 0xD800, + 0xD800, 0xDC00, 0xD845, 0xDDDD, + 0xDBBB, 0xDDEE, 0x0020, 0xDBFF, + 0xDFFF, 0x0001, 0x0E40, 0x0020, + 0x0009 + }; + int32_t offsets[]={ + 0, 3, 6, 7, /* skip 8, */ + 10, 11, /* skip 12, */ + 14, 15, 16, 17, 18, + 20, 21, 23, 24, 25, 26, 28, 29, + 30, 31, 33, 35, 37, 38, + 40, 42, 45, 47, 48, + 50, 52, 54, /* trail */ 54, 56, /* trail */ 56, 59, /* trail */ 59, + 63, 64, /* trail */ 64, /* reset only 67, */ + 68, 69, + 71, 72 + }; + + if(!testConvertToUnicode(sampleText, sizeof(sampleText), + expected, ARRAY_LENGTH(expected), "BOCU-1", + UCNV_TO_U_CALLBACK_SKIP, offsets, NULL, 0) + ) { + log_err("BOCU-1->u with skip did not match.\n"); + } + } + + log_verbose("Testing toUnicode for CESU-8 with UCNV_TO_U_CALLBACK_SKIP\n"); + { + const uint8_t sampleText[]={ + 0x61, /* 0 'a' */ + 0xc0, 0x80, /* 1 non-shortest form */ + 0xc4, 0xb5, /* 3 U+0135 */ + 0xed, 0x80, 0xa0, /* 5 Hangul U+d020 */ + 0xed, 0xa0, 0x81, 0xed, 0xb0, 0x81, /* 8 surrogate pair for U+10401 */ + 0xee, 0x80, 0x80, /* 14 PUA U+e000 */ + 0xed, 0xb0, 0x81, /* 17 unpaired trail surrogate U+dc01 */ + 0xf0, 0x90, 0x80, 0x80, /* 20 illegal 4-byte form for U+10000 */ + 0x62, /* 24 'b' */ + 0xed, 0xa0, 0x81, /* 25 unpaired lead surrogate U+d801 */ + 0xed, 0xa0, /* 28 incomplete sequence */ + 0xd0, 0x80 /* 30 U+0400 */ + }; + UChar expected[]={ + 0x0061, + /* skip */ + 0x0135, + 0xd020, + 0xd801, 0xdc01, + 0xe000, + 0xdc01, + /* skip */ + 0x0062, + 0xd801, + 0x0400 + }; + int32_t offsets[]={ + 0, + /* skip 1, */ + 3, + 5, + 8, 11, + 14, + 17, + /* skip 20, 20, */ + 24, + 25, + /* skip 28 */ + 30 + }; + + /* without offsets */ + if(!testConvertToUnicode(sampleText, sizeof(sampleText), + expected, ARRAY_LENGTH(expected), "CESU-8", + UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, 0) + ) { + log_err("CESU-8->u with skip did not match.\n"); + } + + /* with offsets */ + if(!testConvertToUnicode(sampleText, sizeof(sampleText), + expected, ARRAY_LENGTH(expected), "CESU-8", + UCNV_TO_U_CALLBACK_SKIP, offsets, NULL, 0) + ) { + log_err("CESU-8->u with skip did not match.\n"); + } + } +} + +static void TestStop(int32_t inputsize, int32_t outputsize) +{ + static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 }; + static const UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 }; + + static const uint8_t expstopIBM_949[]= { + 0x00, 0xb0, 0xa1, 0xb0, 0xa2}; + + static const uint8_t expstopIBM_943[] = { + 0x9f, 0xaf, 0x9f, 0xb1}; + + static const uint8_t expstopIBM_930[] = { + 0x0e, 0x5d, 0x5f, 0x5d, 0x63}; + + static const UChar IBM_949stoptoUnicode[]= {0x0000, 0xAC00, 0xAC01}; + static const UChar IBM_943stoptoUnicode[]= { 0x6D63, 0x6D64}; + static const UChar IBM_930stoptoUnicode[]= { 0x6D63, 0x6D64}; + + + static const int32_t toIBM949Offsstop [] = { 0, 1, 1, 2, 2}; + static const int32_t toIBM943Offsstop [] = { 0, 0, 1, 1}; + static const int32_t toIBM930Offsstop [] = { 0, 0, 0, 1, 1}; + + static const int32_t fromIBM949Offs [] = { 0, 1, 3}; + static const int32_t fromIBM943Offs [] = { 0, 2}; + static const int32_t fromIBM930Offs [] = { 1, 3}; + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + /*From Unicode*/ + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expstopIBM_949, sizeof(expstopIBM_949), "ibm-949", + UCNV_FROM_U_CALLBACK_STOP, toIBM949Offsstop, NULL, 0 )) + log_err("u-> ibm-949 with stop did not match.\n"); + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expstopIBM_943, sizeof(expstopIBM_943), "ibm-943", + UCNV_FROM_U_CALLBACK_STOP, toIBM943Offsstop , NULL, 0)) + log_err("u-> ibm-943 with stop did not match.\n"); + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expstopIBM_930, sizeof(expstopIBM_930), "ibm-930", + UCNV_FROM_U_CALLBACK_STOP, toIBM930Offsstop, NULL, 0 )) + log_err("u-> ibm-930 with stop did not match.\n"); + + log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_STOP \n"); + { + static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 }; + static const uint8_t toIBM943[]= { 0x61,}; + static const int32_t offset[]= {0,} ; + + /*EUC_JP*/ + static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 }; + static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,}; + static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2,}; + + /*EUC_TW*/ + static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, }; + static const uint8_t to_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,}; + static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2,}; + + /*ISO-2022-JP*/ + static const UChar iso_2022_jp_inputText[]={0x0041, 0x00E9, 0x0042, }; + static const uint8_t to_iso_2022_jp[]={ + 0x41, + + }; + static const int32_t from_iso_2022_jpOffs [] ={0,}; + + /*ISO-2022-cn*/ + static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712, 0x0042, }; + static const uint8_t to_iso_2022_cn[]={ + 0x41, + + }; + static const int32_t from_iso_2022_cnOffs [] ={ + 0,0, + 2,2, + }; + + /*ISO-2022-kr*/ + static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042, }; + static const uint8_t to_iso_2022_kr[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0e, 0x25, 0x50, + }; + static const int32_t from_iso_2022_krOffs [] ={ + -1,-1,-1,-1, + 0, + 1,1,1, + }; + + /* HZ encoding */ + static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, }; + + static const uint8_t to_hz[]={ + 0x7e, 0x7d, 0x41, + 0x7e, 0x7b, 0x26, 0x30, + + }; + static const int32_t from_hzOffs [] ={ + 0, 0,0, + 1,1,1,1, + }; + + /*ISCII*/ + static const UChar iscii_inputText[]={ 0x0041, 0x3712, 0x0042, }; + static const uint8_t to_iscii[]={ + 0x41, + }; + static const int32_t from_isciiOffs [] ={ + 0, + }; + + if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]), + toIBM943, sizeof(toIBM943), "ibm-943", + UCNV_FROM_U_CALLBACK_STOP, offset, NULL, 0 )) + log_err("u-> ibm-943 with stop did not match.\n"); + + if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]), + to_euc_jp, sizeof(to_euc_jp), "euc-jp", + UCNV_FROM_U_CALLBACK_STOP, fromEUC_JPOffs, NULL, 0 )) + log_err("u-> euc-jp with stop did not match.\n"); + + if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]), + to_euc_tw, sizeof(to_euc_tw), "euc-tw", + UCNV_FROM_U_CALLBACK_STOP, from_euc_twOffs, NULL, 0 )) + log_err("u-> euc-tw with stop did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]), + to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_jpOffs, NULL, 0 )) + log_err("u-> iso-2022-jp with stop did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]), + to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_jpOffs, NULL, 0 )) + log_err("u-> iso-2022-jp with stop did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]), + to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_cnOffs, NULL, 0 )) + log_err("u-> iso-2022-cn with stop did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]), + to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr", + UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_krOffs, NULL, 0 )) + log_err("u-> iso-2022-kr with stop did not match.\n"); + + if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]), + to_hz, sizeof(to_hz), "HZ", + UCNV_FROM_U_CALLBACK_STOP, from_hzOffs, NULL, 0 )) + log_err("u-> HZ with stop did not match.\n");\ + + if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]), + to_iscii, sizeof(to_iscii), "ISCII,version=0", + UCNV_FROM_U_CALLBACK_STOP, from_isciiOffs, NULL, 0 )) + log_err("u-> iscii with stop did not match.\n"); + + + } +#endif + + log_verbose("Testing fromUnicode for SCSU with UCNV_FROM_U_CALLBACK_STOP \n"); + { + static const UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, }; + + static const uint8_t to_SCSU[]={ + 0x41, + + }; + int32_t from_SCSUOffs [] ={ + 0, + + }; + if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]), + to_SCSU, sizeof(to_SCSU), "SCSU", + UCNV_FROM_U_CALLBACK_STOP, from_SCSUOffs, NULL, 0 )) + log_err("u-> SCSU with skip did not match.\n"); + + } + + /*to Unicode*/ + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertToUnicode(expstopIBM_949, sizeof(expstopIBM_949), + IBM_949stoptoUnicode, sizeof(IBM_949stoptoUnicode)/sizeof(IBM_949stoptoUnicode[0]),"ibm-949", + UCNV_TO_U_CALLBACK_STOP, fromIBM949Offs, NULL, 0 )) + log_err("ibm-949->u with stop did not match.\n"); + if(!testConvertToUnicode(expstopIBM_943, sizeof(expstopIBM_943), + IBM_943stoptoUnicode, sizeof(IBM_943stoptoUnicode)/sizeof(IBM_943stoptoUnicode[0]),"ibm-943", + UCNV_TO_U_CALLBACK_STOP, fromIBM943Offs, NULL, 0 )) + log_err("ibm-943->u with stop did not match.\n"); + if(!testConvertToUnicode(expstopIBM_930, sizeof(expstopIBM_930), + IBM_930stoptoUnicode, sizeof(IBM_930stoptoUnicode)/sizeof(IBM_930stoptoUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_STOP, fromIBM930Offs, NULL, 0 )) + log_err("ibm-930->u with stop did not match.\n"); + + log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_STOP \n"); + { + + static const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={ + 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44 + }; + static const UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63 }; + static const int32_t from_EBCIDIC_STATEFULOffsets []={ 1}; + + + /*EUC-JP*/ + static const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x8f, 0xda, 0xa1, /*unassigned*/ + 0x8e, 0xe0, + }; + static const UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec}; + static const int32_t from_euc_jpOffs [] ={ 0, 1, 3}; + + /*EUC_TW*/ + static const uint8_t sampleTxt_euc_tw[]={ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/ + 0xe6, 0xca, 0x8a, + }; + UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2}; + int32_t from_euc_twOffs [] ={ 0, 1, 3}; + + + + if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL), + EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_STOP, from_EBCIDIC_STATEFULOffsets, NULL, 0 )) + log_err("EBCIDIC_STATEFUL->u with stop did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp), + euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp", + UCNV_TO_U_CALLBACK_STOP, from_euc_jpOffs , NULL, 0)) + log_err("euc-jp->u with stop did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw), + euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw", + UCNV_TO_U_CALLBACK_STOP, from_euc_twOffs, NULL, 0 )) + log_err("euc-tw->u with stop did not match.\n"); + } +#endif + + log_verbose("Testing toUnicode for UTF-8 with UCNV_TO_U_CALLBACK_STOP \n"); + { + static const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c, + 0xe0, 0x80, 0x61,}; + static const UChar expected1[] = { 0x0031, 0x4e8c,}; + static const int32_t offsets1[] = { 0x0000, 0x0001}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8", + UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 )) + log_err("utf8->u with stop did not match.\n");; + } + log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_STOP \n"); + { + static const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,0x04}; + static const UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061}; + static const int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU", + UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 )) + log_err("scsu->u with stop did not match.\n");; + } + +} + +static void TestSub(int32_t inputsize, int32_t outputsize) +{ + static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 }; + static const UChar sampleText2[]= { 0x6D63, 0x6D64, 0x6D65, 0x6D66 }; + + static const uint8_t expsubIBM_949[] = + { 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xaf, 0xfe, 0xc8, 0xd3 }; + + static const uint8_t expsubIBM_943[] = { + 0x9f, 0xaf, 0x9f, 0xb1, 0xfc, 0xfc, 0x89, 0x59 }; + + static const uint8_t expsubIBM_930[] = { + 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfe, 0xfe, 0x46, 0x6b, 0x0f }; + + static const UChar IBM_949subtoUnicode[]= {0x0000, 0xAC00, 0xAC01, 0xfffd, 0xD700 }; + static const UChar IBM_943subtoUnicode[]= {0x6D63, 0x6D64, 0xfffd, 0x6D66 }; + static const UChar IBM_930subtoUnicode[]= {0x6D63, 0x6D64, 0xfffd, 0x6D66 }; + + static const int32_t toIBM949Offssub [] ={ 0, 1, 1, 2, 2, 3, 3, 4, 4 }; + static const int32_t toIBM943Offssub [] ={ 0, 0, 1, 1, 2, 2, 3, 3 }; + static const int32_t toIBM930Offssub [] ={ 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 }; + + static const int32_t fromIBM949Offs [] = { 0, 1, 3, 5, 7 }; + static const int32_t fromIBM943Offs [] = { 0, 2, 4, 6 }; + static const int32_t fromIBM930Offs [] = { 1, 3, 5, 7 }; + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + /*from unicode*/ + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expsubIBM_949, sizeof(expsubIBM_949), "ibm-949", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM949Offssub, NULL, 0 )) + log_err("u-> ibm-949 with subst did not match.\n"); + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expsubIBM_943, sizeof(expsubIBM_943), "ibm-943", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM943Offssub , NULL, 0)) + log_err("u-> ibm-943 with subst did not match.\n"); + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expsubIBM_930, sizeof(expsubIBM_930), "ibm-930", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM930Offssub, NULL, 0 )) + log_err("u-> ibm-930 with subst did not match.\n"); + + log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_SUBSTITUTE \n"); + { + static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 }; + static const uint8_t toIBM943[]= { 0x61, 0xfc, 0xfc, 0xfc, 0xfc, 0x61 }; + static const int32_t offset[]= {0, 1, 1, 3, 3, 4}; + + + /* EUC_JP*/ + static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 }; + static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0xf4, 0xfe, 0xf4, 0xfe, + 0x61, 0x8e, 0xe0, + }; + static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2, 3, 3, 5, 5, 6, 7, 7}; + + /*EUC_TW*/ + static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, }; + static const uint8_t to_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0xfd, 0xfe, 0xfd, 0xfe, + 0x61, 0xe6, 0xca, 0x8a, + }; + + static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2, 3, 3, 5, 5, 6, 7, 7, 8,}; + + if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]), + toIBM943, sizeof(toIBM943), "ibm-943", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset, NULL, 0 )) + log_err("u-> ibm-943 with substitute did not match.\n"); + + if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]), + to_euc_jp, sizeof(to_euc_jp), "euc-jp", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, fromEUC_JPOffs, NULL, 0 )) + log_err("u-> euc-jp with substitute did not match.\n"); + + if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]), + to_euc_tw, sizeof(to_euc_tw), "euc-tw", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_euc_twOffs, NULL, 0 )) + log_err("u-> euc-tw with substitute did not match.\n"); + } +#endif + + log_verbose("Testing fromUnicode for SCSU with UCNV_FROM_U_CALLBACK_SUBSTITUTE \n"); + { + UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, }; + + const uint8_t to_SCSU[]={ + 0x41, + 0x0e, 0xff,0xfd, + 0x42 + + + }; + int32_t from_SCSUOffs [] ={ + 0, + 1,1,1, + 2, + + }; + const uint8_t to_SCSU_1[]={ + 0x41, + + }; + int32_t from_SCSUOffs_1 [] ={ + 0, + + }; + if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]), + to_SCSU, sizeof(to_SCSU), "SCSU", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_SCSUOffs, NULL, 0 )) + log_err("u-> SCSU with substitute did not match.\n"); + + if(!testConvertFromUnicodeWithContext(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]), + to_SCSU_1, sizeof(to_SCSU_1), "SCSU", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_SCSUOffs_1, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND )) + log_err("u-> SCSU with substitute did not match.\n"); + } + + log_verbose("Testing fromUnicode for UTF-8 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n"); + { + static const UChar testinput[]={ 0x20ac, 0xd801, 0xdc01, 0xdc01, 0xd801, 0xffff, 0x0061,}; + static const uint8_t expectedUTF8[]= { 0xe2, 0x82, 0xac, + 0xf0, 0x90, 0x90, 0x81, + 0xef, 0xbf, 0xbd, 0xef, 0xbf, 0xbd, + 0xef, 0xbf, 0xbf, 0x61, + + }; + static const int32_t offsets[]={ 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 }; + if(!testConvertFromUnicode(testinput, sizeof(testinput)/sizeof(testinput[0]), + expectedUTF8, sizeof(expectedUTF8), "utf8", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0 )) { + log_err("u-> utf8 with stop did not match.\n"); + } + } + + log_verbose("Testing fromUnicode for UTF-16 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n"); + { + static const UChar in[]={ 0x0041, 0xfeff }; + + static const uint8_t out[]={ +#if U_IS_BIG_ENDIAN + 0xfe, 0xff, + 0x00, 0x41, + 0xfe, 0xff +#else + 0xff, 0xfe, + 0x41, 0x00, + 0xff, 0xfe +#endif + }; + static const int32_t offsets[]={ + -1, -1, 0, 0, 1, 1 + }; + + if(!testConvertFromUnicode(in, ARRAY_LENGTH(in), + out, sizeof(out), "UTF-16", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0) + ) { + log_err("u->UTF-16 with substitute did not match.\n"); + } + } + + log_verbose("Testing fromUnicode for UTF-32 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n"); + { + static const UChar in[]={ 0x0041, 0xfeff }; + + static const uint8_t out[]={ +#if U_IS_BIG_ENDIAN + 0x00, 0x00, 0xfe, 0xff, + 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0xfe, 0xff +#else + 0xff, 0xfe, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, + 0xff, 0xfe, 0x00, 0x00 +#endif + }; + static const int32_t offsets[]={ + -1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1 + }; + + if(!testConvertFromUnicode(in, ARRAY_LENGTH(in), + out, sizeof(out), "UTF-32", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0) + ) { + log_err("u->UTF-32 with substitute did not match.\n"); + } + } + + /*to unicode*/ + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertToUnicode(expsubIBM_949, sizeof(expsubIBM_949), + IBM_949subtoUnicode, sizeof(IBM_949subtoUnicode)/sizeof(IBM_949subtoUnicode[0]),"ibm-949", + UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM949Offs, NULL, 0 )) + log_err("ibm-949->u with substitute did not match.\n"); + if(!testConvertToUnicode(expsubIBM_943, sizeof(expsubIBM_943), + IBM_943subtoUnicode, sizeof(IBM_943subtoUnicode)/sizeof(IBM_943subtoUnicode[0]),"ibm-943", + UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offs, NULL, 0 )) + log_err("ibm-943->u with substitute did not match.\n"); + if(!testConvertToUnicode(expsubIBM_930, sizeof(expsubIBM_930), + IBM_930subtoUnicode, sizeof(IBM_930subtoUnicode)/sizeof(IBM_930subtoUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM930Offs, NULL, 0 )) + log_err("ibm-930->u with substitute did not match.\n"); + + log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); + { + + const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={ + 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44 + }; + UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63, 0xfffd, 0x03b4 + }; + int32_t from_EBCIDIC_STATEFULOffsets []={ 1, 3, 5}; + + + /* EUC_JP*/ + const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x8f, 0xda, 0xa1, /*unassigned*/ + 0x8e, 0xe0, 0x8a + }; + UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec, 0xfffd, 0x00a2, 0x008a }; + int32_t from_euc_jpOffs [] ={ 0, 1, 3, 6, 9, 11 }; + + /*EUC_TW*/ + const uint8_t sampleTxt_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/ + 0xe6, 0xca, 0x8a, + }; + UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2, 0xfffd, 0x8706, 0x8a, }; + int32_t from_euc_twOffs [] ={ 0, 1, 3, 7, 11, 13}; + + + if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL), + EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930", + UCNV_TO_U_CALLBACK_SUBSTITUTE, from_EBCIDIC_STATEFULOffsets, NULL, 0 )) + log_err("EBCIDIC_STATEFUL->u with substitute did not match.\n"); + + + if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp), + euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp", + UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_jpOffs, NULL, 0 )) + log_err("euc-jp->u with substitute did not match.\n"); + + + if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw), + euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw", + UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_twOffs, NULL, 0 )) + log_err("euc-tw->u with substitute did not match.\n"); + + + if(!testConvertToUnicodeWithContext(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp), + euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp", + UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_jpOffs, NULL, 0 ,"i", U_ILLEGAL_CHAR_FOUND)) + log_err("euc-jp->u with substitute did not match.\n"); + } +#endif + + log_verbose("Testing toUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); + { + const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c, + 0xe0, 0x80, 0x61,}; + UChar expected1[] = { 0x0031, 0x4e8c, 0xfffd, 0x0061}; + int32_t offsets1[] = { 0x0000, 0x0001, 0x0004, 0x0006}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 )) + log_err("utf8->u with substitute did not match.\n");; + } + log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); + { + const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,}; + UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061,0xfffd,0xfffd}; + int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003,4,5}; + + if(!testConvertToUnicode(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 )) + log_err("scsu->u with stop did not match.\n");; + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing ibm-930 subchar/subchar1\n"); + { + static const UChar u1[]={ 0x6d63, 0x6d64, 0x6d65, 0x6d66, 0xdf }; + static const uint8_t s1[]={ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfe, 0xfe, 0x46, 0x6b, 0x0f, 0x3f }; + static const int32_t offsets1[]={ 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4 }; + + static const UChar u2[]={ 0x6d63, 0x6d64, 0xfffd, 0x6d66, 0x1a }; + static const uint8_t s2[]={ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfc, 0xfc, 0x46, 0x6b, 0x0f, 0x57 }; + static const int32_t offsets2[]={ 1, 3, 5, 7, 10 }; + + if(!testConvertFromUnicode(u1, ARRAY_LENGTH(u1), s1, ARRAY_LENGTH(s1), "ibm-930", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0) + ) { + log_err("u->ibm-930 subchar/subchar1 did not match.\n"); + } + + if(!testConvertToUnicode(s2, ARRAY_LENGTH(s2), u2, ARRAY_LENGTH(u2), "ibm-930", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0) + ) { + log_err("ibm-930->u subchar/subchar1 did not match.\n"); + } + } + + log_verbose("Testing GB 18030 with substitute callbacks\n"); + { + static const UChar u2[]={ + 0x24, 0x7f, 0x80, 0x1f9, 0x20ac, 0x4e00, 0x9fa6, 0xffff, 0xd800, 0xdc00, 0xfffd, 0xdbff, 0xdfff }; + static const uint8_t gb2[]={ + 0x24, 0x7f, 0x81, 0x30, 0x81, 0x30, 0xa8, 0xbf, 0xa2, 0xe3, 0xd2, 0xbb, 0x82, 0x35, 0x8f, 0x33, 0x84, 0x31, 0xa4, 0x39, 0x90, 0x30, 0x81, 0x30, 0xe3, 0x32, 0x9a, 0x36, 0xe3, 0x32, 0x9a, 0x35 }; + static const int32_t offsets2[]={ + 0, 1, 2, 6, 8, 10, 12, 16, 20, 20, 24, 28, 28 }; + + if(!testConvertToUnicode(gb2, ARRAY_LENGTH(gb2), u2, ARRAY_LENGTH(u2), "gb18030", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0) + ) { + log_err("gb18030->u with substitute did not match.\n"); + } + } +#endif + + log_verbose("Testing UTF-7 toUnicode with substitute callbacks\n"); + { + static const uint8_t utf7[]={ + /* a~ a+AB~ a+AB\x0c a+AB- a+AB. a+. */ + 0x61, 0x7e, 0x61, 0x2b, 0x41, 0x42, 0x7e, 0x61, 0x2b, 0x41, 0x42, 0x0c, 0x61, 0x2b, 0x41, 0x42, 0x2d, 0x61, 0x2b, 0x41, 0x42, 0x2e, 0x61, 0x2b, 0x2e + }; + static const UChar unicode[]={ + 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd + }; + static const int32_t offsets[]={ + 0, 1, 2, 4, 7, 9, 12, 14, 17, 19, 22, 23 + }; + + if(!testConvertToUnicode(utf7, ARRAY_LENGTH(utf7), unicode, ARRAY_LENGTH(unicode), "UTF-7", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0) + ) { + log_err("UTF-7->u with substitute did not match.\n"); + } + } + + log_verbose("Testing UTF-16 toUnicode with substitute callbacks\n"); + { + static const uint8_t + in1[]={ 0xfe, 0xff, 0x4e, 0x00, 0xfe, 0xff }, + in2[]={ 0xff, 0xfe, 0x4e, 0x00, 0xfe, 0xff }, + in3[]={ 0xfe, 0xfd, 0x4e, 0x00, 0xfe, 0xff }; + + static const UChar + out1[]={ 0x4e00, 0xfeff }, + out2[]={ 0x004e, 0xfffe }, + out3[]={ 0xfefd, 0x4e00, 0xfeff }; + + static const int32_t + offsets1[]={ 2, 4 }, + offsets2[]={ 2, 4 }, + offsets3[]={ 0, 2, 4 }; + + if(!testConvertToUnicode(in1, ARRAY_LENGTH(in1), out1, ARRAY_LENGTH(out1), "UTF-16", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0) + ) { + log_err("UTF-16 (BE BOM)->u with substitute did not match.\n"); + } + + if(!testConvertToUnicode(in2, ARRAY_LENGTH(in2), out2, ARRAY_LENGTH(out2), "UTF-16", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0) + ) { + log_err("UTF-16 (LE BOM)->u with substitute did not match.\n"); + } + + if(!testConvertToUnicode(in3, ARRAY_LENGTH(in3), out3, ARRAY_LENGTH(out3), "UTF-16", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets3, NULL, 0) + ) { + log_err("UTF-16 (no BOM)->u with substitute did not match.\n"); + } + } + + log_verbose("Testing UTF-32 toUnicode with substitute callbacks\n"); + { + static const uint8_t + in1[]={ 0x00, 0x00, 0xfe, 0xff, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff }, + in2[]={ 0xff, 0xfe, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0xfe, 0xff, 0x00, 0x00 }, + in3[]={ 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x40, 0x00, 0x00, 0xdc, 0x01 }, + in4[]={ 0x00, 0x01, 0x02, 0x03, 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x4e, 0x00 }; + + static const UChar + out1[]={ UTF16_LEAD(0x100f00), UTF16_TRAIL(0x100f00), 0xfeff }, + out2[]={ UTF16_LEAD(0x0f1000), UTF16_TRAIL(0x0f1000), 0xfffe }, + out3[]={ 0xfefe, UTF16_LEAD(0x100f00), UTF16_TRAIL(0x100f00), 0xfffd, 0xfffd }, + out4[]={ UTF16_LEAD(0x10203), UTF16_TRAIL(0x10203), 0xfffd, 0x4e00 }; + + static const int32_t + offsets1[]={ 4, 4, 8 }, + offsets2[]={ 4, 4, 8 }, + offsets3[]={ 0, 4, 4, 8, 12 }, + offsets4[]={ 0, 0, 4, 8 }; + + if(!testConvertToUnicode(in1, ARRAY_LENGTH(in1), out1, ARRAY_LENGTH(out1), "UTF-32", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0) + ) { + log_err("UTF-32 (BE BOM)->u with substitute did not match.\n"); + } + + if(!testConvertToUnicode(in2, ARRAY_LENGTH(in2), out2, ARRAY_LENGTH(out2), "UTF-32", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0) + ) { + log_err("UTF-32 (LE BOM)->u with substitute did not match.\n"); + } + + if(!testConvertToUnicode(in3, ARRAY_LENGTH(in3), out3, ARRAY_LENGTH(out3), "UTF-32", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets3, NULL, 0) + ) { + log_err("UTF-32 (no BOM)->u with substitute did not match.\n"); + } + + if(!testConvertToUnicode(in4, ARRAY_LENGTH(in4), out4, ARRAY_LENGTH(out4), "UTF-32", + UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets4, NULL, 0) + ) { + log_err("UTF-32 (no BOM, with error)->u with substitute did not match.\n"); + } + } +} + +static void TestSubWithValue(int32_t inputsize, int32_t outputsize) +{ + UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 }; + UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 }; + + const uint8_t expsubwvalIBM_949[]= { + 0x00, 0xb0, 0xa1, 0xb0, 0xa2, + 0x25, 0x55, 0x45, 0x46, 0x36, 0x37, 0xc8, 0xd3 }; + + const uint8_t expsubwvalIBM_943[]= { + 0x9f, 0xaf, 0x9f, 0xb1, + 0x25, 0x55, 0x36, 0x44, 0x36, 0x35, 0x89, 0x59 }; + + const uint8_t expsubwvalIBM_930[] = { + 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x0f, 0x6c, 0xe4, 0xf6, 0xc4, 0xf6, 0xf5, 0x0e, 0x46, 0x6b, 0x0f }; + + int32_t toIBM949Offs [] ={ 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4 }; + int32_t toIBM943Offs [] = { 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3 }; + int32_t toIBM930Offs [] = { 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3 }; /* last item: 3,3,3,3 because there's SO+DBCS+SI */ + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + /*from Unicode*/ + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expsubwvalIBM_949, sizeof(expsubwvalIBM_949), "ibm-949", + UCNV_FROM_U_CALLBACK_ESCAPE, toIBM949Offs, NULL, 0 )) + log_err("u-> ibm-949 with subst with value did not match.\n"); + + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expsubwvalIBM_943, sizeof(expsubwvalIBM_943), "ibm-943", + UCNV_FROM_U_CALLBACK_ESCAPE, toIBM943Offs, NULL, 0 )) + log_err("u-> ibm-943 with sub with value did not match.\n"); + + if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expsubwvalIBM_930, sizeof(expsubwvalIBM_930), "ibm-930", + UCNV_FROM_U_CALLBACK_ESCAPE, toIBM930Offs, NULL, 0 )) + log_err("u-> ibm-930 with subst with value did not match.\n"); + + + log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_ESCAPE \n"); + { + static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 }; + static const uint8_t toIBM943[]= { 0x61, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x43, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x61 }; + static const int32_t offset[]= {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 4}; + + + /* EUC_JP*/ + static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2, }; + static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x43, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x61, 0x8e, 0xe0, + }; + static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2, + 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, + 5, 5, 5, 5, 5, 5, + 6, 7, 7, + }; + + /*EUC_TW*/ + static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, }; + static const uint8_t to_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x43, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x61, 0xe6, 0xca, 0x8a, + }; + static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, + 6, 7, 7, 8, + }; + /*ISO-2022-JP*/ + static const UChar iso_2022_jp_inputText1[]={ 0x3000, 0x00E9, 0x3001,0x00E9, 0x0042} ; + static const uint8_t to_iso_2022_jp1[]={ + 0x1b, 0x24, 0x42, 0x21, 0x21, + 0x1b, 0x28, 0x42, 0x25, 0x55, 0x30, 0x30, 0x45, 0x39, + 0x1b, 0x24, 0x42, 0x21, 0x22, + 0x1b, 0x28, 0x42, 0x25, 0x55, 0x30, 0x30, 0x45, 0x39, + 0x42, + }; + + static const int32_t from_iso_2022_jpOffs1 [] ={ + 0,0,0,0,0, + 1,1,1,1,1,1,1,1,1, + 2,2,2,2,2, + 3,3,3,3,3,3,3,3,3, + 4, + }; + /* surrogate pair*/ + static const UChar iso_2022_jp_inputText2[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042} ; + static const uint8_t to_iso_2022_jp2[]={ + 0x1b, 0x24, 0x42, 0x21, 0x21, + 0x1b, 0x28, 0x42, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x1b, 0x24, 0x42, 0x21, 0x22, + 0x1b, 0x28, 0x42, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x42, + }; + static const int32_t from_iso_2022_jpOffs2 [] ={ + 0,0,0,0,0, + 1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1, + 3,3,3,3,3, + 4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4, + 6, + }; + + /*ISO-2022-cn*/ + static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712, 0x0042, }; + static const uint8_t to_iso_2022_cn[]={ + 0x41, + 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, + 0x42, + }; + static const int32_t from_iso_2022_cnOffs [] ={ + 0, + 1,1,1,1,1,1, + 2, + }; + + static const UChar iso_2022_cn_inputText4[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042}; + + static const uint8_t to_iso_2022_cn4[]={ + 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21, + 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x0e, 0x21, 0x22, + 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x42, + }; + static const int32_t from_iso_2022_cnOffs4 [] ={ + 0,0,0,0,0,0,0, + 1,1,1,1,1,1,1, + 1,1,1,1,1,1, + 3,3,3, + 4,4,4,4,4,4,4, + 4,4,4,4,4,4, + 6 + + }; + + /*ISO-2022-kr*/ + static const UChar iso_2022_kr_inputText2[]={ 0x0041, 0x03A0,0xD84D, 0xDC56/*unassigned*/,0x03A0, 0x0042,0xD84D, 0xDC56/*unassigned*/,0x43 }; + static const uint8_t to_iso_2022_kr2[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0e, 0x25, 0x50, + 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x0e, 0x25, 0x50, + 0x0f, 0x42, + 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x43 + }; + static const int32_t from_iso_2022_krOffs2 [] ={ + -1,-1,-1,-1, + 0, + 1,1,1, + 2,2,2,2,2,2,2, + 2,2,2,2,2,2, + 4,4,4, + 5,5, + 6,6,6,6,6,6, + 6,6,6,6,6,6, + 8, + }; + + static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042,0x3712/*unassigned*/,0x43 }; + static const uint8_t to_iso_2022_kr[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0e, 0x25, 0x50, + 0x0f, 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/ + 0x0e, 0x25, 0x50, + 0x0f, 0x42, + 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/ + 0x43 + }; + + + static const int32_t from_iso_2022_krOffs [] ={ + -1,-1,-1,-1, + 0, + 1,1,1, + 2,2,2,2,2,2,2, + 3,3,3, + 4,4, + 5,5,5,5,5,5, + 6, + }; + /* HZ encoding */ + static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, }; + + static const uint8_t to_hz[]={ + 0x7e, 0x7d, 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x7e, 0x7d, 0x25, 0x55, 0x30, 0x36, 0x36, 0x32, /*unassigned*/ + 0x7e, 0x7b, 0x26, 0x30, + 0x7e, 0x7d, 0x42, + + }; + static const int32_t from_hzOffs [] ={ + 0,0,0, + 1,1,1,1, + 2,2,2,2,2,2,2,2, + 3,3,3,3, + 4,4,4 + }; + + static const UChar hz_inputText2[]={ 0x0041, 0x03A0,0xD84D, 0xDC56/*unassigned*/,0x03A0, 0x0042,0xD84D, 0xDC56/*unassigned*/,0x43 }; + static const uint8_t to_hz2[]={ + 0x7e, 0x7d, 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x7e, 0x7d, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x7e, 0x7b, 0x26, 0x30, + 0x7e, 0x7d, 0x42, + 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, + 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x43 + }; + static const int32_t from_hzOffs2 [] ={ + 0,0,0, + 1,1,1,1, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2, + 4,4,4,4, + 5,5,5, + 6,6,6,6,6,6, + 6,6,6,6,6,6, + 8, + }; + + /*ISCII*/ + static const UChar iscii_inputText[]={ 0x0041, 0x0901,0x3712/*unassigned*/,0x0902, 0x0042,0x3712/*unassigned*/,0x43 }; + static const uint8_t to_iscii[]={ + 0x41, + 0xef, 0x42, 0xa1, + 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/ + 0xa2, + 0x42, + 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/ + 0x43 + }; + + + static const int32_t from_isciiOffs [] ={ + 0, + 1,1,1, + 2,2,2,2,2,2, + 3, + 4, + 5,5,5,5,5,5, + 6, + }; + + if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]), + toIBM943, sizeof(toIBM943), "ibm-943", + UCNV_FROM_U_CALLBACK_ESCAPE, offset, NULL, 0 )) + log_err("u-> ibm-943 with subst with value did not match.\n"); + + if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]), + to_euc_jp, sizeof(to_euc_jp), "euc-jp", + UCNV_FROM_U_CALLBACK_ESCAPE, fromEUC_JPOffs, NULL, 0 )) + log_err("u-> euc-jp with subst with value did not match.\n"); + + if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]), + to_euc_tw, sizeof(to_euc_tw), "euc-tw", + UCNV_FROM_U_CALLBACK_ESCAPE, from_euc_twOffs, NULL, 0 )) + log_err("u-> euc-tw with subst with value did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_jp_inputText1, sizeof(iso_2022_jp_inputText1)/sizeof(iso_2022_jp_inputText1[0]), + to_iso_2022_jp1, sizeof(to_iso_2022_jp1), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs1, NULL, 0 )) + log_err("u-> iso_2022_jp with subst with value did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_jp_inputText1, sizeof(iso_2022_jp_inputText1)/sizeof(iso_2022_jp_inputText1[0]), + to_iso_2022_jp1, sizeof(to_iso_2022_jp1), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs1, NULL, 0 )) + log_err("u-> iso_2022_jp with subst with value did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_jp_inputText2, sizeof(iso_2022_jp_inputText2)/sizeof(iso_2022_jp_inputText2[0]), + to_iso_2022_jp2, sizeof(to_iso_2022_jp2), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs2, NULL, 0 )) + log_err("u-> iso_2022_jp with subst with value did not match.\n"); + /*ESCAPE OPTIONS*/ + { + /* surrogate pair*/ + static const UChar iso_2022_jp_inputText3[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0901c } ; + static const uint8_t to_iso_2022_jp3_v2[]={ + 0x1b, 0x24, 0x42, 0x21, 0x21, + 0x1b, 0x28, 0x42, 0x26, 0x23, 0x31, 0x34, 0x34, 0x34, 0x37, 0x30, 0x3b, + + 0x1b, 0x24, 0x42, 0x21, 0x22, + 0x1b, 0x28, 0x42, 0x26, 0x23, 0x31, 0x34, 0x34, 0x34, 0x37, 0x30, 0x3b, + + 0x42, + 0x26, 0x23, 0x33, 0x36, 0x38, 0x39, 0x32, 0x3b, + }; + + static const int32_t from_iso_2022_jpOffs3_v2 [] ={ + 0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1, + + 3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4, + + 6, + 7,7,7,7,7,7,7,7,7 + }; + + if(!testConvertFromUnicodeWithContext(iso_2022_jp_inputText3, sizeof(iso_2022_jp_inputText3)/sizeof(iso_2022_jp_inputText3[0]), + to_iso_2022_jp3_v2, sizeof(to_iso_2022_jp3_v2), "iso-2022-jp", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs3_v2, NULL, 0,UCNV_ESCAPE_XML_DEC,U_ZERO_ERROR )) + log_err("u-> iso-2022-jp with sub & UCNV_ESCAPE_XML_DEC did not match.\n"); + } + { + static const UChar iso_2022_cn_inputText5[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902}; + static const uint8_t to_iso_2022_cn5_v2[]={ + 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21, + 0x0f, 0x5c, 0x75, 0x44, 0x38, 0x34, 0x44, + 0x5c, 0x75, 0x44, 0x43, 0x35, 0x36, + 0x0e, 0x21, 0x22, + 0x0f, 0x5c, 0x75, 0x44, 0x38, 0x34, 0x44, + 0x5c, 0x75, 0x44, 0x43, 0x35, 0x36, + 0x42, + 0x5c, 0x75, 0x30, 0x39, 0x30, 0x32, + }; + static const int32_t from_iso_2022_cnOffs5_v2 [] ={ + 0,0,0,0,0,0,0, + 1,1,1,1,1,1,1, + 1,1,1,1,1,1, + 3,3,3, + 4,4,4,4,4,4,4, + 4,4,4,4,4,4, + 6, + 7,7,7,7,7,7 + }; + if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText5, sizeof(iso_2022_cn_inputText5)/sizeof(iso_2022_cn_inputText5[0]), + to_iso_2022_cn5_v2, sizeof(to_iso_2022_cn5_v2), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs5_v2, NULL, 0,UCNV_ESCAPE_JAVA,U_ZERO_ERROR )) + log_err("u-> iso-2022-cn with sub & UCNV_ESCAPE_JAVA did not match.\n"); + + } + { + static const UChar iso_2022_cn_inputText6[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902}; + static const uint8_t to_iso_2022_cn6_v2[]={ + 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21, + 0x0f, 0x7b, 0x55, 0x2b, 0x32, 0x33, 0x34, 0x35, 0x36, 0x7d, + 0x0e, 0x21, 0x22, + 0x0f, 0x7b, 0x55, 0x2b, 0x32, 0x33, 0x34, 0x35, 0x36, 0x7d, + 0x42, + 0x7b, 0x55, 0x2b, 0x30, 0x39, 0x30, 0x32, 0x7d + }; + static const int32_t from_iso_2022_cnOffs6_v2 [] ={ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 6, + 7, 7, 7, 7, 7, 7, 7, 7, + }; + if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText6, sizeof(iso_2022_cn_inputText6)/sizeof(iso_2022_cn_inputText6[0]), + to_iso_2022_cn6_v2, sizeof(to_iso_2022_cn6_v2), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs6_v2, NULL, 0,UCNV_ESCAPE_UNICODE,U_ZERO_ERROR )) + log_err("u-> iso-2022-cn with sub & UCNV_ESCAPE_UNICODE did not match.\n"); + + } + { + static const UChar iso_2022_cn_inputText7[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902}; + static const uint8_t to_iso_2022_cn7_v2[]={ + 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21, + 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x0e, 0x21, 0x22, + 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, 0x25, 0x55, 0x44, 0x43, 0x35, 0x36, + 0x42, 0x25, 0x55, 0x30, 0x39, 0x30, 0x32, + }; + static const int32_t from_iso_2022_cnOffs7_v2 [] ={ + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 6, + 7, 7, 7, 7, 7, 7, + }; + if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText7, sizeof(iso_2022_cn_inputText7)/sizeof(iso_2022_cn_inputText7[0]), + to_iso_2022_cn7_v2, sizeof(to_iso_2022_cn7_v2), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs7_v2, NULL, 0,"K" ,U_ZERO_ERROR )) + log_err("u-> iso-2022-cn with sub & K did not match.\n"); + + } + { + static const uint8_t to_iso_2022_cn4_v3[]={ + 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21, + 0x0f, 0x5c, 0x55, 0x30, 0x30, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x0e, 0x21, 0x22, + 0x0f, 0x5c, 0x55, 0x30, 0x30, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x42 + }; + + + static const int32_t from_iso_2022_cnOffs4_v3 [] ={ + 0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1, + + 3,3,3, + 4,4,4,4,4,4,4,4,4,4,4, + + 6 + + }; + if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText4, sizeof(iso_2022_cn_inputText4)/sizeof(iso_2022_cn_inputText4[0]), + to_iso_2022_cn4_v3, sizeof(to_iso_2022_cn4_v3), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs4_v3, NULL, 0,UCNV_ESCAPE_C,U_ZERO_ERROR )) + { + log_err("u-> iso-2022-cn with skip & UCNV_ESCAPE_C did not match.\n"); + } + } + if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]), + to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs, NULL, 0 )) + log_err("u-> iso_2022_cn with subst with value did not match.\n"); + + if(!testConvertFromUnicode(iso_2022_cn_inputText4, sizeof(iso_2022_cn_inputText4)/sizeof(iso_2022_cn_inputText4[0]), + to_iso_2022_cn4, sizeof(to_iso_2022_cn4), "iso-2022-cn", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs4, NULL, 0 )) + log_err("u-> iso_2022_cn with subst with value did not match.\n"); + if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]), + to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_krOffs, NULL, 0 )) + log_err("u-> iso_2022_kr with subst with value did not match.\n"); + if(!testConvertFromUnicode(iso_2022_kr_inputText2, sizeof(iso_2022_kr_inputText2)/sizeof(iso_2022_kr_inputText2[0]), + to_iso_2022_kr2, sizeof(to_iso_2022_kr2), "iso-2022-kr", + UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_krOffs2, NULL, 0 )) + log_err("u-> iso_2022_kr2 with subst with value did not match.\n"); + if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]), + to_hz, sizeof(to_hz), "HZ", + UCNV_FROM_U_CALLBACK_ESCAPE, from_hzOffs, NULL, 0 )) + log_err("u-> hz with subst with value did not match.\n"); + if(!testConvertFromUnicode(hz_inputText2, sizeof(hz_inputText2)/sizeof(hz_inputText2[0]), + to_hz2, sizeof(to_hz2), "HZ", + UCNV_FROM_U_CALLBACK_ESCAPE, from_hzOffs2, NULL, 0 )) + log_err("u-> hz with subst with value did not match.\n"); + + if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]), + to_iscii, sizeof(to_iscii), "ISCII,version=0", + UCNV_FROM_U_CALLBACK_ESCAPE, from_isciiOffs, NULL, 0 )) + log_err("u-> iscii with subst with value did not match.\n"); + } +#endif + + log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_ESCAPE \n"); + /*to Unicode*/ + { +#if !UCONFIG_NO_LEGACY_CONVERSION + static const uint8_t sampleTxtToU[]= { 0x00, 0x9f, 0xaf, + 0x81, 0xad, /*unassigned*/ + 0x89, 0xd3 }; + static const UChar IBM_943toUnicode[] = { 0x0000, 0x6D63, + 0x25, 0x58, 0x38, 0x31, 0x25, 0x58, 0x41, 0x44, + 0x7B87}; + static const int32_t fromIBM943Offs [] = { 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 5}; + + /* EUC_JP*/ + static const uint8_t sampleTxt_EUC_JP[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae, + 0x8f, 0xda, 0xa1, /*unassigned*/ + 0x8e, 0xe0, + }; + static const UChar EUC_JPtoUnicode[]={ 0x0061, 0x4edd, 0x5bec, + 0x25, 0x58, 0x38, 0x46, 0x25, 0x58, 0x44, 0x41, 0x25, 0x58, 0x41, 0x31, + 0x00a2 }; + static const int32_t fromEUC_JPOffs [] ={ 0, 1, 3, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 9, + }; + + /*EUC_TW*/ + static const uint8_t sampleTxt_euc_tw[]={ + 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5, + 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/ + 0xe6, 0xca, 0x8a, + }; + static const UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2, + 0x25, 0x58, 0x38, 0x45, 0x25, 0x58, 0x41, 0x41, 0x25, 0x58, 0x42, 0x42, 0x25, 0x58, 0x43, 0x43, + 0x8706, 0x8a, }; + static const int32_t from_euc_twOffs [] ={ 0, 1, 3, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 11, 13}; + + /*iso-2022-jp*/ + static const uint8_t sampleTxt_iso_2022_jp[]={ + 0x1b, 0x28, 0x42, 0x41, + 0x1b, 0x24, 0x42, 0x2A, 0x44, /*unassigned*/ + 0x1b, 0x28, 0x42, 0x42, + + }; + static const UChar iso_2022_jptoUnicode[]={ 0x41,0x25,0x58,0x32,0x41,0x25,0x58,0x34,0x34, 0x42 }; + static const int32_t from_iso_2022_jpOffs [] ={ 3, 7, 7, 7, 7, 7, 7, 7, 7, 12 }; + + /*iso-2022-cn*/ + static const uint8_t sampleTxt_iso_2022_cn[]={ + 0x0f, 0x41, 0x44, + 0x1B, 0x24, 0x29, 0x47, + 0x0E, 0x40, 0x6c, /*unassigned*/ + 0x0f, 0x42, + + }; + static const UChar iso_2022_cntoUnicode[]={ 0x41, 0x44,0x25,0x58,0x34,0x30,0x25,0x58,0x36,0x43,0x42 }; + static const int32_t from_iso_2022_cnOffs [] ={ 1, 2, 8, 8, 8, 8, 8, 8, 8, 8, 11 }; + + /*iso-2022-kr*/ + static const uint8_t sampleTxt_iso_2022_kr[]={ + 0x1b, 0x24, 0x29, 0x43, + 0x41, + 0x0E, 0x7f, 0x1E, + 0x0e, 0x25, 0x50, + 0x0f, 0x51, + 0x42, 0x43, + + }; + static const UChar iso_2022_krtoUnicode[]={ 0x41,0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45,0x03A0,0x51, 0x42,0x43}; + static const int32_t from_iso_2022_krOffs [] ={ 4, 6, 6, 6, 6, 6, 6, 6, 6, 9, 12, 13 , 14 }; + + /*hz*/ + static const uint8_t sampleTxt_hz[]={ + 0x41, + 0x7e, 0x7b, 0x26, 0x30, + 0x7f, 0x1E, /*unassigned*/ + 0x26, 0x30, + 0x7e, 0x7d, 0x42, + 0x7e, 0x7b, 0x7f, 0x1E,/*unassigned*/ + 0x7e, 0x7d, 0x42, + }; + static const UChar hztoUnicode[]={ + 0x41, + 0x03a0, + 0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45, + 0x03A0, + 0x42, + 0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45, + 0x42,}; + + static const int32_t from_hzOffs [] ={0,3,5,5,5,5,5,5,5,5,7,11,14,14,14,14,14,14,14,14,18, }; + + + /*iscii*/ + static const uint8_t sampleTxt_iscii[]={ + 0x41, + 0x30, + 0xEB, /*unassigned*/ + 0xa3, + 0x42, + 0xEC, /*unassigned*/ + 0x42, + }; + static const UChar isciitoUnicode[]={ + 0x41, + 0x30, + 0x25, 0x58, 0x45, 0x42, + 0x0903, + 0x42, + 0x25, 0x58, 0x45, 0x43, + 0x42,}; + + static const int32_t from_isciiOffs [] ={0,1,2,2,2,2,3,4,5,5,5,5,6 }; +#endif + + /*UTF8*/ + static const uint8_t sampleTxtUTF8[]={ + 0x20, 0x64, 0x50, + 0xC2, 0x7E, /* truncated char */ + 0x20, + 0xE0, 0xB5, 0x7E, /* truncated char */ + 0x40, + }; + static const UChar UTF8ToUnicode[]={ + 0x0020, 0x0064, 0x0050, + 0x0025, 0x0058, 0x0043, 0x0032, 0x007E, /* \xC2~ */ + 0x0020, + 0x0025, 0x0058, 0x0045, 0x0030, 0x0025, 0x0058, 0x0042, 0x0035, 0x007E, + 0x0040 + }; + static const int32_t fromUTF8[] = { + 0, 1, 2, + 3, 3, 3, 3, 4, + 5, + 6, 6, 6, 6, 6, 6, 6, 6, 8, + 9 + }; + static const UChar UTF8ToUnicodeXML_DEC[]={ + 0x0020, 0x0064, 0x0050, + 0x0026, 0x0023, 0x0031, 0x0039, 0x0034, 0x003B, 0x007E, /* Â~ */ + 0x0020, + 0x0026, 0x0023, 0x0032, 0x0032, 0x0034, 0x003B, 0x0026, 0x0023, 0x0031, 0x0038, 0x0031, 0x003B, 0x007E, + 0x0040 + }; + static const int32_t fromUTF8XML_DEC[] = { + 0, 1, 2, + 3, 3, 3, 3, 3, 3, 4, + 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, + 9 + }; + + +#if !UCONFIG_NO_LEGACY_CONVERSION + if(!testConvertToUnicode(sampleTxtToU, sizeof(sampleTxtToU), + IBM_943toUnicode, sizeof(IBM_943toUnicode)/sizeof(IBM_943toUnicode[0]),"ibm-943", + UCNV_TO_U_CALLBACK_ESCAPE, fromIBM943Offs, NULL, 0 )) + log_err("ibm-943->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_EUC_JP, sizeof(sampleTxt_EUC_JP), + EUC_JPtoUnicode, sizeof(EUC_JPtoUnicode)/sizeof(EUC_JPtoUnicode[0]),"euc-jp", + UCNV_TO_U_CALLBACK_ESCAPE, fromEUC_JPOffs, NULL, 0)) + log_err("euc-jp->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw), + euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw", + UCNV_TO_U_CALLBACK_ESCAPE, from_euc_twOffs, NULL, 0)) + log_err("euc-tw->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs, NULL, 0)) + log_err("iso-2022-jp->u with substitute with value did not match.\n"); + + if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs, NULL, 0,"K",U_ZERO_ERROR)) + log_err("iso-2022-jp->u with substitute with value did not match.\n"); + + {/* test UCNV_TO_U_CALLBACK_ESCAPE with options */ + { + static const UChar iso_2022_jptoUnicodeDec[]={ + 0x0041, + 0x0026, 0x0023, 0x0034, 0x0032, 0x003b, + 0x0026, 0x0023, 0x0036, 0x0038, 0x003b, + 0x0042 }; + static const int32_t from_iso_2022_jpOffsDec [] ={ 3,7,7,7,7,7,7,7,7,7,7,12, }; + if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicodeDec, sizeof(iso_2022_jptoUnicodeDec)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsDec, NULL, 0,UCNV_ESCAPE_XML_DEC,U_ZERO_ERROR )) + log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_XML_DEC did not match.\n"); + } + { + static const UChar iso_2022_jptoUnicodeHex[]={ + 0x0041, + 0x0026, 0x0023, 0x0078, 0x0032, 0x0041, 0x003b, + 0x0026, 0x0023, 0x0078, 0x0034, 0x0034, 0x003b, + 0x0042 }; + static const int32_t from_iso_2022_jpOffsHex [] ={ 3,7,7,7,7,7,7,7,7,7,7,7,7,12 }; + if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicodeHex, sizeof(iso_2022_jptoUnicodeHex)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsHex, NULL, 0,UCNV_ESCAPE_XML_HEX,U_ZERO_ERROR )) + log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_XML_HEX did not match.\n"); + } + { + static const UChar iso_2022_jptoUnicodeC[]={ + 0x0041, + 0x005C, 0x0078, 0x0032, 0x0041, + 0x005C, 0x0078, 0x0034, 0x0034, + 0x0042 }; + int32_t from_iso_2022_jpOffsC [] ={ 3,7,7,7,7,7,7,7,7,12 }; + if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp), + iso_2022_jptoUnicodeC, sizeof(iso_2022_jptoUnicodeC)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsC, NULL, 0,UCNV_ESCAPE_C,U_ZERO_ERROR )) + log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_C did not match.\n"); + } + } + if(!testConvertToUnicode(sampleTxt_iso_2022_cn, sizeof(sampleTxt_iso_2022_cn), + iso_2022_cntoUnicode, sizeof(iso_2022_cntoUnicode)/sizeof(iso_2022_cntoUnicode[0]),"iso-2022-cn", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs, NULL, 0)) + log_err("iso-2022-cn->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iso_2022_kr, sizeof(sampleTxt_iso_2022_kr), + iso_2022_krtoUnicode, sizeof(iso_2022_krtoUnicode)/sizeof(iso_2022_krtoUnicode[0]),"iso-2022-kr", + UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_krOffs, NULL, 0)) + log_err("iso-2022-kr->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_hz, sizeof(sampleTxt_hz), + hztoUnicode, sizeof(hztoUnicode)/sizeof(hztoUnicode[0]),"HZ", + UCNV_TO_U_CALLBACK_ESCAPE, from_hzOffs, NULL, 0)) + log_err("hz->u with substitute with value did not match.\n"); + + if(!testConvertToUnicode(sampleTxt_iscii, sizeof(sampleTxt_iscii), + isciitoUnicode, sizeof(isciitoUnicode)/sizeof(isciitoUnicode[0]),"ISCII,version=0", + UCNV_TO_U_CALLBACK_ESCAPE, from_isciiOffs, NULL, 0)) + log_err("ISCII ->u with substitute with value did not match.\n"); +#endif + + if(!testConvertToUnicode(sampleTxtUTF8, sizeof(sampleTxtUTF8), + UTF8ToUnicode, sizeof(UTF8ToUnicode)/sizeof(UTF8ToUnicode[0]),"UTF-8", + UCNV_TO_U_CALLBACK_ESCAPE, fromUTF8, NULL, 0)) + log_err("UTF8->u with UCNV_TO_U_CALLBACK_ESCAPE with value did not match.\n"); + if(!testConvertToUnicodeWithContext(sampleTxtUTF8, sizeof(sampleTxtUTF8), + UTF8ToUnicodeXML_DEC, sizeof(UTF8ToUnicodeXML_DEC)/sizeof(UTF8ToUnicodeXML_DEC[0]),"UTF-8", + UCNV_TO_U_CALLBACK_ESCAPE, fromUTF8XML_DEC, NULL, 0, UCNV_ESCAPE_XML_DEC, U_ZERO_ERROR)) + log_err("UTF8->u with UCNV_TO_U_CALLBACK_ESCAPE with value did not match.\n"); + } +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestLegalAndOthers(int32_t inputsize, int32_t outputsize) +{ + static const UChar legalText[] = { 0x0000, 0xAC00, 0xAC01, 0xD700 }; + static const uint8_t templegal949[] ={ 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xc8, 0xd3 }; + static const int32_t to949legal[] = {0, 1, 1, 2, 2, 3, 3}; + + + static const uint8_t text943[] = { + 0x82, 0xa9, 0x82, 0x20, /*0xc8,*/ 0x61, 0x8a, 0xbf, 0x8e, 0x9a }; + static const UChar toUnicode943sub[] = { 0x304b, 0xfffd, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57}; + static const UChar toUnicode943skip[]= { 0x304b, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57}; + static const UChar toUnicode943stop[]= { 0x304b}; + + static const int32_t fromIBM943Offssub[] = {0, 2, 4, 5, 7}; + static const int32_t fromIBM943Offsskip[] = { 0, 4, 5, 7}; + static const int32_t fromIBM943Offsstop[] = { 0}; + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + /*checking with a legal value*/ + if(!testConvertFromUnicode(legalText, sizeof(legalText)/sizeof(legalText[0]), + templegal949, sizeof(templegal949), "ibm-949", + UCNV_FROM_U_CALLBACK_SKIP, to949legal, NULL, 0 )) + log_err("u-> ibm-949 with skip did not match.\n"); + + /*checking illegal value for ibm-943 with substitute*/ + if(!testConvertToUnicode(text943, sizeof(text943), + toUnicode943sub, sizeof(toUnicode943sub)/sizeof(toUnicode943sub[0]),"ibm-943", + UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offssub, NULL, 0 )) + log_err("ibm-943->u with subst did not match.\n"); + /*checking illegal value for ibm-943 with skip */ + if(!testConvertToUnicode(text943, sizeof(text943), + toUnicode943skip, sizeof(toUnicode943skip)/sizeof(toUnicode943skip[0]),"ibm-943", + UCNV_TO_U_CALLBACK_SKIP, fromIBM943Offsskip, NULL, 0 )) + log_err("ibm-943->u with skip did not match.\n"); + + /*checking illegal value for ibm-943 with stop */ + if(!testConvertToUnicode(text943, sizeof(text943), + toUnicode943stop, sizeof(toUnicode943stop)/sizeof(toUnicode943stop[0]),"ibm-943", + UCNV_TO_U_CALLBACK_STOP, fromIBM943Offsstop, NULL, 0 )) + log_err("ibm-943->u with stop did not match.\n"); + +} + +static void TestSingleByte(int32_t inputsize, int32_t outputsize) +{ + static const uint8_t sampleText[] = { + 0x82, 0xa9, 0x61, 0x62, 0x63 , 0x82, + 0xff, /*0x82, 0xa9,*/ 0x32, 0x33}; + static const UChar toUnicode943sub[] = {0x304b, 0x0061, 0x0062, 0x0063, 0xfffd,/*0x304b,*/ 0x0032, 0x0033}; + static const int32_t fromIBM943Offssub[] = {0, 2, 3, 4, 5, 7, 8}; + /*checking illegal value for ibm-943 with substitute*/ + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + if(!testConvertToUnicode(sampleText, sizeof(sampleText), + toUnicode943sub, sizeof(toUnicode943sub)/sizeof(toUnicode943sub[0]),"ibm-943", + UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offssub, NULL, 0 )) + log_err("ibm-943->u with subst did not match.\n"); +} + +static void TestEBCDIC_STATEFUL_Sub(int32_t inputsize, int32_t outputsize) +{ + /*EBCDIC_STATEFUL*/ + static const UChar ebcdic_inputTest[] = { 0x0061, 0x6d64, 0x0061, 0x00A2, 0x6d65, 0x0061 }; + static const uint8_t toIBM930[]= { 0x62, 0x0e, 0x5d, 0x63, 0x0f, 0x62, 0xb1, 0x0e, 0xfe, 0xfe, 0x0f, 0x62 }; + static const int32_t offset_930[]= { 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5 }; +/* s SO doubl SI sng s SO fe fe SI s */ + + /*EBCDIC_STATEFUL with subChar=3f*/ + static const uint8_t toIBM930_subvaried[]= { 0x62, 0x0e, 0x5d, 0x63, 0x0f, 0x62, 0xb1, 0x3f, 0x62 }; + static const int32_t offset_930_subvaried[]= { 0, 1, 1, 1, 2, 2, 3, 4, 5 }; + static const char mySubChar[]={ 0x3f}; + + gInBufferSize = inputsize; + gOutBufferSize = outputsize; + + if(!testConvertFromUnicode(ebcdic_inputTest, sizeof(ebcdic_inputTest)/sizeof(ebcdic_inputTest[0]), + toIBM930, sizeof(toIBM930), "ibm-930", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset_930, NULL, 0 )) + log_err("u-> ibm-930(EBCDIC_STATEFUL) with subst did not match.\n"); + + if(!testConvertFromUnicode(ebcdic_inputTest, sizeof(ebcdic_inputTest)/sizeof(ebcdic_inputTest[0]), + toIBM930_subvaried, sizeof(toIBM930_subvaried), "ibm-930", + UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset_930_subvaried, mySubChar, 1 )) + log_err("u-> ibm-930(EBCDIC_STATEFUL) with subst(setSubChar=0x3f) did not match.\n"); +} +#endif + +UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets, + const char *mySubChar, int8_t len) +{ + + + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + char junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const UChar *src; + char *end; + char *targ; + int32_t *offs; + int i; + int32_t realBufferSize; + char *realBufferEnd; + const UChar *realSourceEnd; + const UChar *sourceLimit; + UBool checkOffsets = TRUE; + UBool doFlush; + char junk[9999]; + char offset_str[9999]; + char *p; + UConverterFromUCallback oldAction = NULL; + const void* oldContext = NULL; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = (char)0xF0; + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = 0xFF; + setNuConvTestName(codepage, "FROM"); + + log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize, + gOutBufferSize); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; + } + + log_verbose("Converter opened..\n"); + + /*----setting the callback routine----*/ + ucnv_setFromUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) + { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*------------------------*/ + /*setting the subChar*/ + if(mySubChar != NULL){ + ucnv_setSubstChars(conv, mySubChar, len, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + } + /*------------*/ + + src = source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = source + sourceLen; + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min(targ + gOutBufferSize, realBufferEnd); + sourceLimit = nct_min(src + gInBufferSize, realSourceEnd); + + doFlush = (UBool)(sourceLimit == realSourceEnd); + + if(targ == realBufferEnd) + { + log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName); + return FALSE; + } + log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE"); + + + status = U_ZERO_ERROR; + + ucnv_fromUnicode (conv, + (char **)&targ, + (const char *)end, + &src, + sourceLimit, + checkOffsets ? offs : NULL, + doFlush, /* flush if we're at the end of the input data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (sourceLimit < realSourceEnd)) ); + + + if(status==U_INVALID_CHAR_FOUND || status == U_ILLEGAL_CHAR_FOUND){ + UChar errChars[50]; /* should be sufficient */ + int8_t errLen = 50; + UErrorCode err = U_ZERO_ERROR; + const UChar* limit= NULL; + const UChar* start= NULL; + ucnv_getInvalidUChars(conv,errChars, &errLen, &err); + if(U_FAILURE(err)){ + log_err("ucnv_getInvalidUChars failed with error : %s\n",u_errorName(err)); + } + /* src points to limit of invalid chars */ + limit = src; + /* length of in invalid chars should be equal to returned length*/ + start = src - errLen; + if(u_strncmp(errChars,start,errLen)!=0){ + log_err("ucnv_getInvalidUChars did not return the correct invalid chars for encoding %s \n", ucnv_getName(conv,&err)); + } + } + /* allow failure codes for the stop callback */ + if(U_FAILURE(status) && + (callback != UCNV_FROM_U_CALLBACK_STOP || (status != U_INVALID_CHAR_FOUND && status != U_ILLEGAL_CHAR_FOUND))) + { + log_err("Problem in fromUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-junkout); + if(VERBOSITY) + { + + junk[0] = 0; + offset_str[0] = 0; + for(p = junkout;p<targ;p++) + { + sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printSeq(expect, expectLen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + + if(expectLen != targ-junkout) + { + log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout)); + printSeqErr(expect, expectLen); + return FALSE; + } + + if (checkOffsets && (expectOffsets != 0) ) + { + log_verbose("comparing %d offsets..\n", targ-junkout); + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){ + log_err("did not get the expected offsets while %s \n", gNuConvTestName); + log_err("Got Output : "); + printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout)); + log_err("Got Offsets: "); + for(p=junkout;p<targ;p++) + log_err("%d,", junokout[p-junkout]); + log_err("\n"); + log_err("Expected Offsets: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + log_err("\n"); + return FALSE; + } + } + + if(!memcmp(junkout, expect, expectLen)) + { + log_verbose("String matches! %s\n", gNuConvTestName); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_err("source: "); + printUSeqErr(source, sourceLen); + log_err("Got: "); + printSeqErr((const uint8_t *)junkout, expectLen); + log_err("Expected: "); + printSeqErr(expect, expectLen); + return FALSE; + } +} + +UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, + const char *mySubChar, int8_t len) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + UChar junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const char *src; + const char *realSourceEnd; + const char *srcLimit; + UChar *targ; + UChar *end; + int32_t *offs; + int i; + UBool checkOffsets = TRUE; + char junk[9999]; + char offset_str[9999]; + UChar *p; + UConverterToUCallback oldAction = NULL; + const void* oldContext = NULL; + + int32_t realBufferSize; + UChar *realBufferEnd; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = 0xFFFE; + + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = -1; + + setNuConvTestName(codepage, "TO"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",gNuConvTestName); + return TRUE; + } + + log_verbose("Converter opened..\n"); + + src = (const char *)source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = src + sourcelen; + /*----setting the callback routine----*/ + ucnv_setToUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) + { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*-------------------------------------*/ + /*setting the subChar*/ + if(mySubChar != NULL){ + ucnv_setSubstChars(conv, mySubChar, len, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + } + /*------------*/ + + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min( targ + gOutBufferSize, realBufferEnd); + srcLimit = nct_min(realSourceEnd, src + gInBufferSize); + + if(targ == realBufferEnd) + { + log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName); + return FALSE; + } + log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end); + + + + status = U_ZERO_ERROR; + + ucnv_toUnicode (conv, + &targ, + end, + (const char **)&src, + (const char *)srcLimit, + checkOffsets ? offs : NULL, + (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of the source data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */ + + if(status==U_INVALID_CHAR_FOUND || status == U_ILLEGAL_CHAR_FOUND){ + char errChars[50]; /* should be sufficient */ + int8_t errLen = 50; + UErrorCode err = U_ZERO_ERROR; + const char* limit= NULL; + const char* start= NULL; + ucnv_getInvalidChars(conv,errChars, &errLen, &err); + if(U_FAILURE(err)){ + log_err("ucnv_getInvalidChars failed with error : %s\n",u_errorName(err)); + } + /* src points to limit of invalid chars */ + limit = src; + /* length of in invalid chars should be equal to returned length*/ + start = src - errLen; + if(uprv_strncmp(errChars,start,errLen)!=0){ + log_err("ucnv_getInvalidChars did not return the correct invalid chars for encoding %s \n", ucnv_getName(conv,&err)); + } + } + /* allow failure codes for the stop callback */ + if(U_FAILURE(status) && + (callback != UCNV_TO_U_CALLBACK_STOP || (status != U_INVALID_CHAR_FOUND && status != U_ILLEGAL_CHAR_FOUND && status != U_TRUNCATED_CHAR_FOUND))) + { + log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :", + sourcelen, targ-junkout); + if(VERBOSITY) + { + + junk[0] = 0; + offset_str[0] = 0; + + for(p = junkout;p<targ;p++) + { + sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printUSeq(expect, expectlen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2); + + if (checkOffsets && (expectOffsets != 0)) + { + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))) + { + log_err("did not get the expected offsets while %s \n", gNuConvTestName); + log_err("Got offsets: "); + for(p=junkout;p<targ;p++) + log_err(" %2d,", junokout[p-junkout]); + log_err("\n"); + log_err("Expected offsets: "); + for(i=0; i<(targ-junkout); i++) + log_err(" %2d,", expectOffsets[i]); + log_err("\n"); + log_err("Got output: "); + for(i=0; i<(targ-junkout); i++) + log_err("0x%04x,", junkout[i]); + log_err("\n"); + log_err("From source: "); + for(i=0; i<(src-(const char *)source); i++) + log_err(" 0x%02x,", (unsigned char)source[i]); + log_err("\n"); + } + } + + if(!memcmp(junkout, expect, expectlen*2)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + log_err("Got: "); + printUSeqErr(junkout, expectlen); + log_err("Expected: "); + printUSeqErr(expect, expectlen); + log_err("\n"); + return FALSE; + } +} + +UBool testConvertFromUnicodeWithContext(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets, + const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError) +{ + + + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + char junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const UChar *src; + char *end; + char *targ; + int32_t *offs; + int i; + int32_t realBufferSize; + char *realBufferEnd; + const UChar *realSourceEnd; + const UChar *sourceLimit; + UBool checkOffsets = TRUE; + UBool doFlush; + char junk[9999]; + char offset_str[9999]; + char *p; + UConverterFromUCallback oldAction = NULL; + const void* oldContext = NULL; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = (char)0xF0; + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = 0xFF; + setNuConvTestName(codepage, "FROM"); + + log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize, + gOutBufferSize); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; /* Because the err has already been logged. */ + } + + log_verbose("Converter opened..\n"); + + /*----setting the callback routine----*/ + ucnv_setFromUCallBack (conv, callback, context, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) + { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*------------------------*/ + /*setting the subChar*/ + if(mySubChar != NULL){ + ucnv_setSubstChars(conv, mySubChar, len, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting substitution chars! %s\n", myErrorName(status)); + } + } + /*------------*/ + + src = source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = source + sourceLen; + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min(targ + gOutBufferSize, realBufferEnd); + sourceLimit = nct_min(src + gInBufferSize, realSourceEnd); + + doFlush = (UBool)(sourceLimit == realSourceEnd); + + if(targ == realBufferEnd) + { + log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName); + return FALSE; + } + log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE"); + + + status = U_ZERO_ERROR; + + ucnv_fromUnicode (conv, + (char **)&targ, + (const char *)end, + &src, + sourceLimit, + checkOffsets ? offs : NULL, + doFlush, /* flush if we're at the end of the input data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (sourceLimit < realSourceEnd)) ); + + /* allow failure codes for the stop callback */ + if(U_FAILURE(status) && status != expectedError) + { + log_err("Problem in fromUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-junkout); + if(VERBOSITY) + { + + junk[0] = 0; + offset_str[0] = 0; + for(p = junkout;p<targ;p++) + { + sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printSeq(expect, expectLen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + + if(expectLen != targ-junkout) + { + log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout)); + printSeqErr(expect, expectLen); + return FALSE; + } + + if (checkOffsets && (expectOffsets != 0) ) + { + log_verbose("comparing %d offsets..\n", targ-junkout); + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){ + log_err("did not get the expected offsets while %s \n", gNuConvTestName); + log_err("Got Output : "); + printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout)); + log_err("Got Offsets: "); + for(p=junkout;p<targ;p++) + log_err("%d,", junokout[p-junkout]); + log_err("\n"); + log_err("Expected Offsets: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + log_err("\n"); + return FALSE; + } + } + + if(!memcmp(junkout, expect, expectLen)) + { + log_verbose("String matches! %s\n", gNuConvTestName); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_err("source: "); + printUSeqErr(source, sourceLen); + log_err("Got: "); + printSeqErr((const uint8_t *)junkout, expectLen); + log_err("Expected: "); + printSeqErr(expect, expectLen); + return FALSE; + } +} +UBool testConvertToUnicodeWithContext( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, + const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + UChar junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const char *src; + const char *realSourceEnd; + const char *srcLimit; + UChar *targ; + UChar *end; + int32_t *offs; + int i; + UBool checkOffsets = TRUE; + char junk[9999]; + char offset_str[9999]; + UChar *p; + UConverterToUCallback oldAction = NULL; + const void* oldContext = NULL; + + int32_t realBufferSize; + UChar *realBufferEnd; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = 0xFFFE; + + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = -1; + + setNuConvTestName(codepage, "TO"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",gNuConvTestName); + return TRUE; + } + + log_verbose("Converter opened..\n"); + + src = (const char *)source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = src + sourcelen; + /*----setting the callback routine----*/ + ucnv_setToUCallBack (conv, callback, context, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) + { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*-------------------------------------*/ + /*setting the subChar*/ + if(mySubChar != NULL){ + ucnv_setSubstChars(conv, mySubChar, len, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + } + /*------------*/ + + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min( targ + gOutBufferSize, realBufferEnd); + srcLimit = nct_min(realSourceEnd, src + gInBufferSize); + + if(targ == realBufferEnd) + { + log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName); + return FALSE; + } + log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end); + + + + status = U_ZERO_ERROR; + + ucnv_toUnicode (conv, + &targ, + end, + (const char **)&src, + (const char *)srcLimit, + checkOffsets ? offs : NULL, + (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of the source data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */ + + /* allow failure codes for the stop callback */ + if(U_FAILURE(status) && status!=expectedError) + { + log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :", + sourcelen, targ-junkout); + if(VERBOSITY) + { + + junk[0] = 0; + offset_str[0] = 0; + + for(p = junkout;p<targ;p++) + { + sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printUSeq(expect, expectlen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2); + + if (checkOffsets && (expectOffsets != 0)) + { + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))) + { + log_err("did not get the expected offsets while %s \n", gNuConvTestName); + log_err("Got offsets: "); + for(p=junkout;p<targ;p++) + log_err(" %2d,", junokout[p-junkout]); + log_err("\n"); + log_err("Expected offsets: "); + for(i=0; i<(targ-junkout); i++) + log_err(" %2d,", expectOffsets[i]); + log_err("\n"); + log_err("Got output: "); + for(i=0; i<(targ-junkout); i++) + log_err("0x%04x,", junkout[i]); + log_err("\n"); + log_err("From source: "); + for(i=0; i<(src-(const char *)source); i++) + log_err(" 0x%02x,", (unsigned char)source[i]); + log_err("\n"); + } + } + + if(!memcmp(junkout, expect, expectlen*2)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + log_err("Got: "); + printUSeqErr(junkout, expectlen); + log_err("Expected: "); + printUSeqErr(expect, expectlen); + log_err("\n"); + return FALSE; + } +} + +static void TestCallBackFailure(void) { + UErrorCode status = U_USELESS_COLLATOR_ERROR; + ucnv_cbFromUWriteBytes(NULL, NULL, -1, -1, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Error: ucnv_cbFromUWriteBytes did not react correctly to a bad UErrorCode\n"); + } + ucnv_cbFromUWriteUChars(NULL, NULL, NULL, -1, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Error: ucnv_cbFromUWriteUChars did not react correctly to a bad UErrorCode\n"); + } + ucnv_cbFromUWriteSub(NULL, -1, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Error: ucnv_cbFromUWriteSub did not react correctly to a bad UErrorCode\n"); + } + ucnv_cbToUWriteUChars(NULL, NULL, -1, -1, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Error: ucnv_cbToUWriteUChars did not react correctly to a bad UErrorCode\n"); + } +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h new file mode 100644 index 00000000000..ebce4ae8d2b --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h @@ -0,0 +1,69 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File NCCBTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda creation +********************************************************************************* +*/ +#ifndef _NCCBTST +#define _NCCBTST +/* C API TEST FOR CALL BACK ROUTINES OF CODESET CONVERSION COMPONENT */ +#include "cintltst.h" +#include "unicode/utypes.h" + + +static void TestSkipCallBack(void); +static void TestStopCallBack(void); +static void TestSubCallBack(void); +static void TestSubWithValueCallBack(void); +static void TestLegalAndOtherCallBack(void); +static void TestSingleByteCallBack(void); + + +static void TestSkip(int32_t inputsize, int32_t outputsize); + +static void TestStop(int32_t inputsize, int32_t outputsize); + +static void TestSub(int32_t inputsize, int32_t outputsize); + +static void TestSubWithValue(int32_t inputsize, int32_t outputsize); + +static void TestLegalAndOthers(int32_t inputsize, int32_t outputsize); +static void TestSingleByte(int32_t inputsize, int32_t outputsize); +static void TestEBCDIC_STATEFUL_Sub(int32_t inputsize, int32_t outputsize); + +/* Following will return FALSE *only* on a mismach. They will return TRUE on any other error OR success, because + * the error would have been emitted to log_err separately. */ + +UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback, const int32_t *expectOffsets, + const char *mySubChar, int8_t len); + + +UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, + const char *mySubChar, int8_t len); + +UBool testConvertFromUnicodeWithContext(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets, + const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError); + +UBool testConvertToUnicodeWithContext( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, + const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError); + +static void printSeq(const uint8_t* a, int len); +static void printUSeq(const UChar* a, int len); +static void printSeqErr(const uint8_t* a, int len); +static void printUSeqErr(const UChar* a, int len); +static void setNuConvTestName(const char *codepage, const char *direction); + + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c new file mode 100644 index 00000000000..2158bfd41c3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c @@ -0,0 +1,755 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ***************************************************************************/ +/***************************************************************************** +* +* File NCNVCBTS +* +* Modification History: +* Name Date Description +* Madhu Katragadda 06/23/2000 Tests for Conveter FallBack API and Functionality +****************************************************************************** +*/ +#include <stdio.h> +#include "unicode/uloc.h" +#include "unicode/ucnv.h" +#include "unicode/ucnv_err.h" +#include "cintltst.h" +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "ncnvfbts.h" +#include "cmemory.h" +#include "cstring.h" + +#if !UCONFIG_NO_LEGACY_CONVERSION +#define NEW_MAX_BUFFER 999 + + +#define nct_min(x,y) ((x<y) ? x : y) + +static int32_t gInBufferSize = 0; +static int32_t gOutBufferSize = 0; +static char gNuConvTestName[1024]; + +static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err) +{ + if(cnv && cnv[0] == '@') { + return ucnv_openPackage("testdata", cnv+1, err); + } else { + return ucnv_open(cnv, err); + } +} + + +static void printSeq(const unsigned char* a, int len) +{ + int i=0; + log_verbose("{"); + while (i<len) + log_verbose("0x%02x ", a[i++]); + log_verbose("}\n"); +} + +static void printUSeq(const UChar* a, int len) +{ + int i=0; + log_verbose("{U+"); + while (i<len) + log_verbose("0x%04x ", a[i++]); + log_verbose("}\n"); +} + +static void printSeqErr(const unsigned char* a, int len) +{ + int i=0; + fprintf(stderr, "{"); + while (i<len) + fprintf(stderr, "0x%02x ", a[i++]); + fprintf(stderr, "}\n"); +} + +static void printUSeqErr(const UChar* a, int len) +{ + int i=0; + fprintf(stderr, "{U+"); + while (i<len) + fprintf(stderr, "0x%04x ", a[i++]); + fprintf(stderr,"}\n"); +} + +static void TestConverterFallBack(void) +{ + TestConvertFallBackWithBufferSizes(10,10); + TestConvertFallBackWithBufferSizes(2,3); + TestConvertFallBackWithBufferSizes(3,2); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,1); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,2); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,3); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,4); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,5); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,6); + TestConvertFallBackWithBufferSizes(1,NEW_MAX_BUFFER); + TestConvertFallBackWithBufferSizes(2,NEW_MAX_BUFFER); + TestConvertFallBackWithBufferSizes(3,NEW_MAX_BUFFER); + TestConvertFallBackWithBufferSizes(4,NEW_MAX_BUFFER); + TestConvertFallBackWithBufferSizes(5,NEW_MAX_BUFFER); + TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,NEW_MAX_BUFFER); + +} + + +void addTestConverterFallBack(TestNode** root); + +void addTestConverterFallBack(TestNode** root) +{ + addTest(root, &TestConverterFallBack, "tsconv/ncnvfbts/TestConverterFallBack"); + +} + + +/* Note that this test already makes use of statics, so it's not really + multithread safe. + This convenience function lets us make the error messages actually useful. +*/ + +static void setNuConvTestName(const char *codepage, const char *direction) +{ + sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]", + codepage, + direction, + (int)gInBufferSize, + (int)gOutBufferSize); +} + + +static UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UBool fallback, const int32_t *expectOffsets) +{ + + + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + char junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const UChar *src; + char *end; + char *targ; + int32_t *offs; + int i; + int32_t realBufferSize; + char *realBufferEnd; + const UChar *realSourceEnd; + const UChar *sourceLimit; + UBool checkOffsets = TRUE; + UBool doFlush; + UBool action=FALSE; + char *p; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = (char)0xF0; + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = 0xFF; + setNuConvTestName(codepage, "FROM"); + + log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize, + gOutBufferSize); + + conv = my_ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; + } + + log_verbose("Converter opened..\n"); + /*----setting the callback routine----*/ + ucnv_setFallback (conv, fallback); + action = ucnv_usesFallback(conv); + if(action != fallback){ + log_err("FAIL: Error is setting fallback. Errocode=%s\n", myErrorName(status)); + } + /*------------------------*/ + src = source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = source + sourceLen; + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min(targ + gOutBufferSize, realBufferEnd); + sourceLimit = nct_min(src + gInBufferSize, realSourceEnd); + + doFlush = (UBool)(sourceLimit == realSourceEnd); + + if(targ == realBufferEnd) + { + log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName); + return FALSE; + } + log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE"); + + + status = U_ZERO_ERROR; + + ucnv_fromUnicode (conv, + (char **)&targ, + (const char *)end, + &src, + sourceLimit, + checkOffsets ? offs : NULL, + doFlush, /* flush if we're at the end of the input data */ + &status); + + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (sourceLimit < realSourceEnd) ); + + if(U_FAILURE(status)) + { + log_err("Problem doing toUnicode, errcode %d %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-junkout); + if(VERBOSITY) + { + char junk[9999]; + char offset_str[9999]; + + junk[0] = 0; + offset_str[0] = 0; + for(p = junkout;p<targ;p++) + { + sprintf(junk + uprv_strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printSeq((const unsigned char*)expect, expectLen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + + if(expectLen != targ-junkout) + { + log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + printSeqErr((const unsigned char*)expect, expectLen); + return FALSE; + } + + if (checkOffsets && (expectOffsets != 0) ) + { + log_verbose("\ncomparing %d offsets..\n", targ-junkout); + if(uprv_memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){ + log_err("\ndid not get the expected offsets while %s \n", gNuConvTestName); + log_err("Got : "); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + for(p=junkout;p<targ;p++) + log_err("%d, ", junokout[p-junkout]); + log_err("\nExpected: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + } + } + + log_verbose("\n\ncomparing..\n"); + if(!memcmp(junkout, expect, expectLen)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + printSeqErr((const unsigned char*)junkout, expectLen); + printSeqErr((const unsigned char*)expect, expectLen); + return FALSE; + } +} + +static UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UBool fallback, const int32_t *expectOffsets) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + UChar junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const char *src; + const char *realSourceEnd; + const char *srcLimit; + UChar *targ; + UChar *end; + int32_t *offs; + int i; + UBool checkOffsets = TRUE; + char junk[9999]; + char offset_str[9999]; + UChar *p; + UBool action; + + int32_t realBufferSize; + UChar *realBufferEnd; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = 0xFFFE; + + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = -1; + + setNuConvTestName(codepage, "TO"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = my_ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",gNuConvTestName); + return TRUE; /* because it has been logged */ + } + + log_verbose("Converter opened..\n"); + + src = (const char *)source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = src + sourcelen; + /*----setting the fallback routine----*/ + ucnv_setFallback (conv, fallback); + action = ucnv_usesFallback(conv); + if(action != fallback){ + log_err("FAIL: Error is setting fallback. Errocode=%s\n", myErrorName(status)); + } + /*-------------------------------------*/ + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min( targ + gOutBufferSize, realBufferEnd); + srcLimit = nct_min(realSourceEnd, src + gInBufferSize); + + if(targ == realBufferEnd) + { + log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName); + return FALSE; + } + log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end); + + + + status = U_ZERO_ERROR; + + ucnv_toUnicode (conv, + &targ, + end, + (const char **)&src, + (const char *)srcLimit, + checkOffsets ? offs : NULL, + (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of hte source data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (srcLimit < realSourceEnd) ); /* while we just need another buffer */ + + + if(U_FAILURE(status)) + { + log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :", + sourcelen, targ-junkout); + if(VERBOSITY) + { + + junk[0] = 0; + offset_str[0] = 0; + + for(p = junkout;p<targ;p++) + { + sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p); + sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]); + } + + log_verbose(junk); + printUSeq(expect, expectlen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2); + + if (checkOffsets && (expectOffsets != 0)) + { + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))) + { + log_err("\n\ndid not get the expected offsets while %s \n", gNuConvTestName); + log_err("\nGot : "); + for(p=junkout;p<targ;p++) + log_err("%d, ", junokout[p-junkout]); + log_err("\nExpected: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + log_err(""); + for(i=0; i<(targ-junkout); i++) + log_err("0x%04X,", junkout[i]); + log_err(""); + for(i=0; i<(src-(const char *)source); i++) + log_err("0x%04X,", (unsigned char)source[i]); + } + } + + if(!memcmp(junkout, expect, expectlen*2)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + printUSeqErr(junkout, expectlen); + printf("\n"); + printUSeqErr(expect, expectlen); + return FALSE; + } +} + + + +static void TestConvertFallBackWithBufferSizes(int32_t outsize, int32_t insize ) +{ + + static const UChar SBCSText[] = + { 0x0021, 0xFF01, 0x0022, 0xFF02, 0x0023, 0xFF03, 0x003A, 0xFF1A, 0x003B, 0xFF1B, 0x003C, 0xFF1C }; + /* 21, ?, 22, ?, 23, ?, 3a, ?, 3b, ?, 3c, ? SBCS*/ + static const uint8_t expectedNative[] = + { 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c}; + static const UChar retrievedSBCSText[]= + { 0x0021, 0x0021, 0x0022, 0x0022, 0x0023, 0x0023, 0x003A, 0x003A, 0x003B, 0x003B, 0x003C, 0x003C }; + static const int32_t toNativeOffs [] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}; + static const int32_t fromNativeoffs [] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + + + /* 1363 isn't DBCS, but it has the DBCS section */ + static const UChar DBCSText[] = + { 0x00a1, 0x00ad, 0x2010, 0x00b7, 0x30fb}; + static const uint8_t expectedIBM1363_DBCS[] = + { 0xa2, 0xae, 0xa1 ,0xa9, 0xa1, 0xa9,0xa1 ,0xa4, 0xa1, 0xa4}; + static const UChar retrievedDBCSText[]= + { 0x00a1, 0x2010, 0x2010, 0x30fb, 0x30fb }; + static const int32_t toIBM1363Offs_DBCS[] = + { 0x00, 0x00, 0x01,0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04}; + static const int32_t fromIBM1363offs_DBCS[] = + { 0, 2, 4, 6, 8}; + + + static const UChar MBCSText[] = + { 0x0001, 0x263a, 0x2013, 0x2014, 0x263b, 0x0002}; + static const uint8_t expectedIBM950[] = + { 0x01, 0x01, 0xa1, 0x56, 0xa1, 0x56, 0x02, 0x02}; + static const UChar retrievedMBCSText[]= + { 0x0001, 0x0001, 0x2014, 0x2014, 0x0002, 0x0002}; + static const int32_t toIBM950Offs [] = + { 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05}; + static const int32_t fromIBM950offs [] = + { 0, 1, 2, 4, 6, 7}; + + static const UChar MBCSText1363[] = + { 0x0005, + 0xffe8, + 0x0007, + 0x2022, + 0x005c, + 0x00b7, + 0x3016, + 0x30fb, + 0x9a36}; + static const uint8_t expectedIBM1363[] = + { 0x05, + 0x05, + 0x07, + 0x07, + 0x7f, + 0xa1, 0xa4, + 0xa1, 0xe0, + 0xa1, 0xa4, + 0xf5, 0xe2}; + static const UChar retrievedMBCSText1363[]= + { 0x0005, 0x0005, 0x0007, 0x0007, 0x001a, 0x30fb, 0x25a1, 0x30fb, 0x9a36}; + static const int32_t toIBM1363Offs [] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08}; + static const int32_t fromIBM1363offs [] = + { 0, 1, 2, 3, 4, 5, 7, 9, 11}; + + + + static const char* nativeCodePage[]={ + /*NLCS Mapping*/ + "ibm-437", + "ibm-850", + "ibm-878", + "ibm-923", + "ibm-1051", + "ibm-1089", + "ibm-1250", + "ibm-1251", + "ibm-1253", + "ibm-1254", + "ibm-1255", + "ibm-1256", + "ibm-1257", + "ibm-1258", + "ibm-1276" + }; + + int32_t i=0; + gInBufferSize = insize; + gOutBufferSize = outsize; + + for(i=0; i<sizeof(nativeCodePage)/sizeof(nativeCodePage[0]); i++){ + log_verbose("Testing %s\n", nativeCodePage[i]); + if(!testConvertFromUnicode(SBCSText, sizeof(SBCSText)/sizeof(SBCSText[0]), + expectedNative, sizeof(expectedNative), nativeCodePage[i], TRUE, toNativeOffs )) + log_err("u-> %s(SBCS) with FallBack did not match.\n", nativeCodePage[i]); + + if(!testConvertToUnicode(expectedNative, sizeof(expectedNative), + retrievedSBCSText, sizeof(retrievedSBCSText)/sizeof(retrievedSBCSText[0]), nativeCodePage[i], TRUE, fromNativeoffs )) + log_err("%s->u(SBCS) with Fallback did not match.\n", nativeCodePage[i]); + } + + /*DBCS*/ + if(!testConvertFromUnicode(DBCSText, sizeof(DBCSText)/sizeof(DBCSText[0]), + expectedIBM1363_DBCS, sizeof(expectedIBM1363_DBCS), "ibm-1363", TRUE, toIBM1363Offs_DBCS )) + log_err("u-> ibm-1363(DBCS portion) with FallBack did not match.\n"); + + if(!testConvertToUnicode(expectedIBM1363_DBCS, sizeof(expectedIBM1363_DBCS), + retrievedDBCSText, sizeof(retrievedDBCSText)/sizeof(retrievedDBCSText[0]),"ibm-1363", TRUE, fromIBM1363offs_DBCS )) + log_err("ibm-1363->u(DBCS portion) with Fallback did not match.\n"); + + + /*MBCS*/ + if(!testConvertFromUnicode(MBCSText, sizeof(MBCSText)/sizeof(MBCSText[0]), + expectedIBM950, sizeof(expectedIBM950), "ibm-950", TRUE, toIBM950Offs )) + log_err("u-> ibm-950(MBCS) with FallBack did not match.\n"); + + if(!testConvertToUnicode(expectedIBM950, sizeof(expectedIBM950), + retrievedMBCSText, sizeof(retrievedMBCSText)/sizeof(retrievedMBCSText[0]),"ibm-950", TRUE, fromIBM950offs )) + log_err("ibm-950->u(MBCS) with Fallback did not match.\n"); + + /*commented untill data table is available*/ + log_verbose("toUnicode fallback with fallback data for MBCS\n"); + { + const uint8_t IBM950input[] = { + 0xf4, 0x87, 0xa4, 0x4a, 0xf4, 0x88, 0xa4, 0x4b, + 0xf9, 0x92, 0xdc, 0xb0, }; + UChar expectedUnicodeText[]= { 0x5165, 0x5165, 0x516b, 0x516b, 0x9ef9, 0x9ef9}; + int32_t fromIBM950inputOffs [] = { 0, 2, 4, 6, 8, 10}; + /* for testing reverse fallback behavior */ + UChar expectedFallbackFalse[]= { 0x5165, 0x5165, 0x516b, 0x516b, 0x9ef9, 0x9ef9}; + + if(!testConvertToUnicode(IBM950input, sizeof(IBM950input), + expectedUnicodeText, sizeof(expectedUnicodeText)/sizeof(expectedUnicodeText[0]),"ibm-950", TRUE, fromIBM950inputOffs )) + log_err("ibm-950->u(MBCS) with Fallback did not match.\n"); + if(!testConvertToUnicode(IBM950input, sizeof(IBM950input), + expectedFallbackFalse, sizeof(expectedFallbackFalse)/sizeof(expectedFallbackFalse[0]),"ibm-950", FALSE, fromIBM950inputOffs )) + log_err("ibm-950->u(MBCS) with Fallback did not match.\n"); + + } + log_verbose("toUnicode fallback with fallback data for euc-tw\n"); + { + const uint8_t euc_tw_input[] = { + 0xA7, 0xCC, 0x8E, 0xA2, 0xA1, 0xAB, + 0xA8, 0xC7, 0xC8, 0xDE, + 0xA8, 0xCD, 0x8E, 0xA2, 0xA2, 0xEA,}; + UChar expectedUnicodeText[]= { 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278}; + int32_t from_euc_tw_offs [] = { 0, 2, 6, 8, 10, 12}; + /* for testing reverse fallback behavior */ + UChar expectedFallbackFalse[]= { 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278}; + + if(!testConvertToUnicode(euc_tw_input, sizeof(euc_tw_input), + expectedUnicodeText, sizeof(expectedUnicodeText)/sizeof(expectedUnicodeText[0]),"euc-tw", TRUE, from_euc_tw_offs )) + log_err("from euc-tw->u with Fallback did not match.\n"); + + if(!testConvertToUnicode(euc_tw_input, sizeof(euc_tw_input), + expectedFallbackFalse, sizeof(expectedFallbackFalse)/sizeof(expectedFallbackFalse[0]),"euc-tw", FALSE, from_euc_tw_offs )) + log_err("from euc-tw->u with Fallback false did not match.\n"); + + + } + log_verbose("fromUnicode to euc-tw with fallback data euc-tw\n"); + { + UChar inputText[]= { 0x0001, 0x008e, 0x203e, 0x2223, 0xff5c, 0x5296, + 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278, 0xEDEC}; + const uint8_t expected_euc_tw[] = { + 0x01, 0x1a, 0xa2, 0xa3, + 0xa2, 0xde, 0xa2, 0xde, + 0x8e, 0xa2, 0xe5, 0xb9, + 0x8e, 0xa2, 0xa1, 0xab, 0x8e, 0xa2, 0xa1, 0xab, + 0xc8, 0xde, 0xc8, 0xde, + 0x8e, 0xa2, 0xa2, 0xea, 0x8e, 0xa2, 0xa2, 0xea, + 0x8e, 0xac, 0xc6, 0xf7}; + int32_t to_euc_tw_offs [] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, + 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12}; + + if(!testConvertFromUnicode(inputText, sizeof(inputText)/sizeof(inputText[0]), + expected_euc_tw, sizeof(expected_euc_tw), "euc-tw", TRUE, to_euc_tw_offs )) + log_err("u-> euc-tw with FallBack did not match.\n"); + + } + + /*MBCS 1363*/ + if(!testConvertFromUnicode(MBCSText1363, sizeof(MBCSText1363)/sizeof(MBCSText1363[0]), + expectedIBM1363, sizeof(expectedIBM1363), "ibm-1363", TRUE, toIBM1363Offs )) + log_err("u-> ibm-1363(MBCS) with FallBack did not match.\n"); + + if(!testConvertToUnicode(expectedIBM1363, sizeof(expectedIBM1363), + retrievedMBCSText1363, sizeof(retrievedMBCSText1363)/sizeof(retrievedMBCSText1363[0]),"ibm-1363", TRUE, fromIBM1363offs )) + log_err("ibm-1363->u(MBCS) with Fallback did not match.\n"); + + + /*some more test to increase the code coverage in MBCS. Create an test converter from test1.ucm + which is test file for MBCS conversion with single-byte codepage data.*/ + { + + /* MBCS with single byte codepage data test1.ucm*/ + const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, 0x0003}; + const uint8_t expectedtest1[] = { 0x00, 0x05, 0xff, 0x07, 0x08, 0xff,}; + int32_t totest1Offs[] = { 0, 1, 2, 3, 5, 7}; + + const uint8_t test1input[] = { 0x00, 0x05, 0x06, 0x07, 0x08, 0x09}; + const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xfffd, 0xfffd, 0xfffe}; + int32_t fromtest1Offs[] = { 0, 1, 2, 3, 3, 4,5}; + + /*from Unicode*/ + if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest1, sizeof(expectedtest1), "@test1", TRUE, totest1Offs )) + log_err("u-> test1(MBCS conversion with single-byte) did not match.\n"); + + /*to Unicode*/ + if(!testConvertToUnicode(test1input, sizeof(test1input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test1", TRUE, fromtest1Offs )) + log_err("test1(MBCS conversion with single-byte) -> u did not match.\n"); + + } + + /*some more test to increase the code coverage in MBCS. Create an test converter from test3.ucm + which is test file for MBCS conversion with three-byte codepage data.*/ + { + + /* MBCS with three byte codepage data test3.ucm*/ + const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, 0x000b, 0xd84d, 0xdc56, 0x000e, 0x0003, }; + const uint8_t expectedtest3[] = { 0x00, 0x05, 0xff, 0x07, 0xff, 0x01, 0x02, 0x0b, 0x01, 0x02, 0x0a, 0xff, 0xff,}; + int32_t totest3Offs[] = { 0, 1, 2, 3, 5, 7, 7, 7, 8, 8, 8, 10, 11}; + + const uint8_t test3input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a, + 0x01, 0x02, 0x0e, 0x01, 0x02, 0x0d, 0x03, 0x01, 0x02, 0x0f,}; + const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, + 0x000e, 0xd891, 0xdd67, 0xfffd, 0xfffd }; + int32_t fromtest3Offs[] = { 0, 1, 2, 3, 6, 6, 7, 7, 10, 13, 13, 16, 17}; + + /*from Unicode*/ + if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest3, sizeof(expectedtest3), "@test3", TRUE, totest3Offs )) + log_err("u-> test3(MBCS conversion with three-byte) did not match.\n"); + + /*to Unicode*/ + if(!testConvertToUnicode(test3input, sizeof(test3input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test3", TRUE, fromtest3Offs )) + log_err("test3(MBCS conversion with three-byte) -> u did not match.\n"); + + } + + /*some more test to increase the code coverage in MBCS. Create an test converter from test4.ucm + which is test file for MBCS conversion with four-byte codepage data.*/ + { + + /* MBCS with three byte codepage data test4.ucm*/ + const UChar unicodeInput[] = + { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, + 0xd84d, 0xdc56, 0x000e, 0xd891, 0xdd67, 0x000f}; + const uint8_t expectedtest4[] = + { 0x00, 0x05, 0xff, 0x01, 0x02, 0x03, 0x0b, 0x07, 0xff, + 0x01, 0x02, 0x03, 0x0a, 0xff, 0xff, 0xff}; + int32_t totest4Offs[] = + { 0, 1, 2, 3, 3, 3, 3, 4, 6, 8, 8, 8, 8, 10, 11, 13}; + + const uint8_t test4input[] = + { 0x00, 0x05, 0x06, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x0a, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x02, 0x03, 0x0d, 0x03, 0x01, 0x02, 0x03, 0x0c,}; + const UChar expectedUnicode[] = + { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, + 0xd84d, 0xdc56, 0x000e, 0xd891, 0xdd67, 0x1a, 0xfffd}; + int32_t fromtest4Offs[] = + { 0, 1, 2, 3, 7, 7, 8, 8, 9, 9, 13, 17, 17, 21, 22,}; + + /*from Unicode*/ + if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest4, sizeof(expectedtest4), "@test4", TRUE, totest4Offs )) + log_err("u-> test4(MBCS conversion with four-byte) did not match.\n"); + + /*to Unicode*/ + if(!testConvertToUnicode(test4input, sizeof(test4input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test4", TRUE, fromtest4Offs )) + log_err("test4(MBCS conversion with four-byte) -> u did not match.\n"); + + } + /* Test for jitterbug 509 EBCDIC_STATEFUL Converters*/ + { + const UChar unicodeInput[] = {0x00AF, 0x2013, 0x2223, 0x004C, 0x5F5D, 0xFF5E }; + const uint8_t expectedtest1[] = {0x0E,0x42,0xA1, 0x44,0x4A, 0x42,0x4F, 0x0F,0xD3, 0x0E,0x65,0x60, 0x43,0xA1,0x0f }; + int32_t totest1Offs[] = {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5 }; + const uint8_t test1input[] = {0x0E,0x42,0xA1, 0x44,0x4A, 0x42,0x4F, 0x0F,0xD3, 0x0E,0x65,0x60, 0x43,0xA1 }; + const UChar expectedUnicode[] = {0x203e, 0x2014, 0xff5c, 0x004c, 0x5f5e, 0x223c }; + int32_t fromtest1Offs[] = {1, 3, 5, 8, 10, 12 }; + /*from Unicode*/ + if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest1, sizeof(expectedtest1), "ibm-1371", TRUE, totest1Offs )) + log_err("u-> ibm-1371(MBCS conversion with single-byte) did not match.,\n"); + /*to Unicode*/ + if(!testConvertToUnicode(test1input, sizeof(test1input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "ibm-1371", TRUE, fromtest1Offs )) + log_err("ibm-1371(MBCS conversion with single-byte) -> u did not match.,\n"); + } + +} +#else +void addTestConverterFallBack(TestNode** root) +{ + /* test nothing... */ + +} +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h new file mode 100644 index 00000000000..a47e141ccfc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h @@ -0,0 +1,36 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File NCCBTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda creation +********************************************************************************* +*/ +#ifndef _NCNVFBTS +#define _NCNVFBTS +/* C API TEST FOR FALL BACK ROUTINES OF CODESET CONVERSION COMPONENT */ +#include "cintltst.h" +#include "unicode/utypes.h" + +static void TestConverterFallBack(void); +static void TestConvertFallBackWithBufferSizes(int32_t outsize, int32_t insize ); +static UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UBool fallback, const int32_t *expectOffsets); +static UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UBool fallback, const int32_t *expectOffsets); + + +static void printSeq(const unsigned char* a, int len); +static void printUSeq(const UChar* a, int len); +static void printSeqErr(const unsigned char* a, int len); +static void printUSeqErr(const UChar* a, int len); +static void setNuConvTestName(const char *codepage, const char *direction); + + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c new file mode 100644 index 00000000000..2f56c15f88d --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c @@ -0,0 +1,2055 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/***************************************************************************** +* +* File CCONVTST.C +* +* Modification History: +* Name Description +* Madhu Katragadda 7/7/2000 Converter Tests for extended code coverage +****************************************************************************** +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "unicode/uloc.h" +#include "unicode/ucnv.h" +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/uset.h" +#include "cintltst.h" + +#define MAX_LENGTH 999 + +#define UNICODE_LIMIT 0x10FFFF +#define SURROGATE_HIGH_START 0xD800 +#define SURROGATE_LOW_END 0xDFFF + +static int32_t gInBufferSize = 0; +static int32_t gOutBufferSize = 0; +static char gNuConvTestName[1024]; + +#define nct_min(x,y) ((x<y) ? x : y) +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void printSeq(const unsigned char* a, int len); +static void printSeqErr(const unsigned char* a, int len); +static void printUSeq(const UChar* a, int len); +static void printUSeqErr(const UChar* a, int len); +static UBool convertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus); +static UBool convertToU( const uint8_t *source, int sourceLen, const UChar *expect, int expectLen, + const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus); + +static UBool testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback, const int32_t *expectOffsets, UBool testReset); +static UBool testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, UBool testReset); + +static void setNuConvTestName(const char *codepage, const char *direction) +{ + sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]", + codepage, + direction, + (int)gInBufferSize, + (int)gOutBufferSize); +} + + +static void TestSurrogateBehaviour(void); +static void TestErrorBehaviour(void); + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestToUnicodeErrorBehaviour(void); +static void TestGetNextErrorBehaviour(void); +#endif + +static void TestRegressionUTF8(void); +static void TestRegressionUTF32(void); +static void TestAvailableConverters(void); +static void TestFlushInternalBuffer(void); /*for improved code coverage in ucnv_cnv.c*/ +static void TestResetBehaviour(void); +static void TestTruncated(void); +static void TestUnicodeSet(void); + +static void TestWithBufferSize(int32_t osize, int32_t isize); + + +static void printSeq(const unsigned char* a, int len) +{ + int i=0; + log_verbose("\n{"); + while (i<len) + log_verbose("0x%02X ", a[i++]); + log_verbose("}\n"); +} + +static void printUSeq(const UChar* a, int len) +{ + int i=0; + log_verbose("\n{"); + while (i<len) + log_verbose("%0x04X ", a[i++]); + log_verbose("}\n"); +} + +static void printSeqErr(const unsigned char* a, int len) +{ + int i=0; + fprintf(stderr, "\n{"); + while (i<len) fprintf(stderr, "0x%02X ", a[i++]); + fprintf(stderr, "}\n"); +} + +static void printUSeqErr(const UChar* a, int len) +{ + int i=0; + fprintf(stderr, "\n{"); + while (i<len) + fprintf(stderr, "0x%04X ", a[i++]); + fprintf(stderr,"}\n"); +} + +void addExtraTests(TestNode** root); + +void addExtraTests(TestNode** root) +{ + addTest(root, &TestSurrogateBehaviour, "tsconv/ncnvtst/TestSurrogateBehaviour"); + addTest(root, &TestErrorBehaviour, "tsconv/ncnvtst/TestErrorBehaviour"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestToUnicodeErrorBehaviour, "tsconv/ncnvtst/ToUnicodeErrorBehaviour"); + addTest(root, &TestGetNextErrorBehaviour, "tsconv/ncnvtst/TestGetNextErrorBehaviour"); +#endif + + addTest(root, &TestAvailableConverters, "tsconv/ncnvtst/TestAvailableConverters"); + addTest(root, &TestFlushInternalBuffer, "tsconv/ncnvtst/TestFlushInternalBuffer"); + addTest(root, &TestResetBehaviour, "tsconv/ncnvtst/TestResetBehaviour"); + addTest(root, &TestRegressionUTF8, "tsconv/ncnvtst/TestRegressionUTF8"); + addTest(root, &TestRegressionUTF32, "tsconv/ncnvtst/TestRegressionUTF32"); + addTest(root, &TestTruncated, "tsconv/ncnvtst/TestTruncated"); + addTest(root, &TestUnicodeSet, "tsconv/ncnvtst/TestUnicodeSet"); +} + +/*test surrogate behaviour*/ +static void TestSurrogateBehaviour(){ + log_verbose("Testing for SBCS and LATIN_1\n"); + { + UChar sampleText[] = {0x0031, 0xd801, 0xdc01, 0x0032}; + const uint8_t expected[] = {0x31, 0x1a, 0x32}; + +#if !UCONFIG_NO_LEGACY_CONVERSION + /*SBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-920", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-920 [UCNV_SBCS] not match.\n"); +#endif + + /*LATIN_1*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "LATIN_1", 0, TRUE, U_ZERO_ERROR )) + log_err("u-> LATIN_1 not match.\n"); + + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing for DBCS and MBCS\n"); + { + UChar sampleText[] = {0x00a1, 0xd801, 0xdc01, 0x00a4}; + const uint8_t expected[] = {0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4}; + int32_t offsets[] = {0x00, 0x00, 0x01, 0x01, 0x03, 0x03 }; + + /*DBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", offsets , TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n"); + /*MBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", offsets, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n"); + } + + log_verbose("Testing for ISO-2022-jp\n"); + { + UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + const uint8_t expected[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42, + 0x31,0x1A, 0x32}; + + + int32_t offsets[] = {0,0,0,0,0,1,1,2,2,2,2,3,5 }; + + /*iso-2022-jp*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-jp", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-jp", offsets , TRUE, U_ZERO_ERROR)) + log_err("u-> not match.\n"); + } + + log_verbose("Testing for ISO-2022-cn\n"); + { + static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = { + 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B, + 0x36, 0x21, + 0x0F, 0x31, + 0x1A, + 0x32 + }; + + + + static const int32_t offsets[] = { + 0, 0, 0, 0, 0, 0, 0, + 1, 1, + 2, 2, + 3, + 5, }; + + /*iso-2022-CN*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-cn", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-cn", offsets , TRUE, U_ZERO_ERROR)) + log_err("u-> not match.\n"); + } + + log_verbose("Testing for ISO-2022-kr\n"); + { + static const UChar sampleText[] = { 0x4e00,0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = {0x1B, 0x24, 0x29, 0x43, + 0x0E, 0x6C, 0x69, + 0x0f, 0x1A, + 0x0e, 0x6F, 0x4B, + 0x0F, 0x31, + 0x1A, + 0x32 }; + + static const int32_t offsets[] = {-1, -1, -1, -1, + 0, 0, 0, + 1, 1, + 3, 3, 3, + 4, 4, + 5, + 7, + }; + + /*iso-2022-kr*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-kr", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-kr", offsets , TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n"); + } + + log_verbose("Testing for HZ\n"); + { + static const UChar sampleText[] = { 0x4e00, 0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = {0x7E, 0x7B, 0x52, 0x3B, + 0x7E, 0x7D, 0x1A, + 0x7E, 0x7B, 0x36, 0x21, + 0x7E, 0x7D, 0x31, + 0x1A, + 0x32 }; + + + static const int32_t offsets[] = {0,0,0,0, + 1,1,1, + 3,3,3,3, + 4,4,4, + 5, + 7,}; + + /*hz*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "HZ", 0 , TRUE, U_ZERO_ERROR)) + log_err("u-> HZ not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "HZ", offsets , TRUE, U_ZERO_ERROR)) + log_err("u-> HZ not match.\n"); + } +#endif + + /*UTF-8*/ + log_verbose("Testing for UTF8\n"); + { + static const UChar sampleText[] = { 0x4e00, 0x0701, 0x0031, 0xbfc1, 0xd801, 0xdc01, 0x0032}; + static const int32_t offsets[]={0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x06 }; + static const uint8_t expected[] = {0xe4, 0xb8, 0x80, 0xdc, 0x81, 0x31, + 0xeb, 0xbf, 0x81, 0xF0, 0x90, 0x90, 0x81, 0x32}; + + + static const int32_t fromOffsets[] = { 0x0000, 0x0003, 0x0005, 0x0006, 0x0009, 0x0009, 0x000D }; + /*UTF-8*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", offsets, TRUE, U_ZERO_ERROR )) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", 0, TRUE, U_ZERO_ERROR )) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", offsets, FALSE, U_ZERO_ERROR )) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", 0, FALSE, U_ZERO_ERROR )) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + + if(!convertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", 0, TRUE, U_ZERO_ERROR )) + log_err("UTF8 -> u did not match.\n"); + if(!convertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", 0, FALSE, U_ZERO_ERROR )) + log_err("UTF8 -> u did not match.\n"); + if(!convertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", fromOffsets, TRUE, U_ZERO_ERROR )) + log_err("UTF8 ->u did not match.\n"); + if(!convertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", fromOffsets, FALSE, U_ZERO_ERROR )) + log_err("UTF8 -> u did not match.\n"); + + } +} + +/*test various error behaviours*/ +static void TestErrorBehaviour(){ + log_verbose("Testing for SBCS and LATIN_1\n"); + { + static const UChar sampleText[] = { 0x0031, 0xd801}; + static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032}; + static const uint8_t expected0[] = { 0x31}; + static const uint8_t expected[] = { 0x31, 0x1a}; + static const uint8_t expected2[] = { 0x31, 0x1a, 0x32}; + +#if !UCONFIG_NO_LEGACY_CONVERSION + /*SBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-920", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-920 [UCNV_SBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected0, sizeof(expected0), "ibm-920", 0, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-920 [UCNV_SBCS] \n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-920", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-920 [UCNV_SBCS] did not match\n"); +#endif + + /*LATIN_1*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "LATIN_1", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> LATIN_1 is supposed to fail\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected0, sizeof(expected0), "LATIN_1", 0, FALSE, U_ZERO_ERROR)) + log_err("u-> LATIN_1 is supposed to fail\n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "LATIN_1", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> LATIN_1 did not match\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing for DBCS and MBCS\n"); + { + static const UChar sampleText[] = { 0x00a1, 0xd801}; + static const uint8_t expected[] = { 0xa2, 0xae}; + static const int32_t offsets[] = { 0x00, 0x00}; + static const uint8_t expectedSUB[] = { 0xa2, 0xae, 0xa1, 0xe0}; + static const int32_t offsetsSUB[] = { 0x00, 0x00, 0x01, 0x01}; + + static const UChar sampleText2[] = { 0x00a1, 0xd801, 0x00a4}; + static const uint8_t expected2[] = { 0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4}; + static const int32_t offsets2[] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02}; + + static const UChar sampleText3MBCS[] = { 0x0001, 0x00a4, 0xdc01}; + static const uint8_t expected3MBCS[] = { 0x01, 0xa2, 0xb4, 0xa1, 0xe0}; + static const int32_t offsets3MBCS[] = { 0x00, 0x01, 0x01, 0x02, 0x02}; + + static const UChar sampleText4MBCS[] = { 0x0061, 0xFFE4, 0xdc01}; + static const uint8_t expected4MBCS[] = { 0x61, 0x8f, 0xa2, 0xc3, 0xf4, 0xfe}; + static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01, 0x01, 0x02, 0x02 }; + + /*DBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "ibm-1363", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", 0, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n"); + + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "ibm-1363", offsetsSUB, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", offsets, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n"); + + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-1363", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] did not match \n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-1363", offsets2, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] did not match \n"); + + /*MBCS*/ + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "ibm-1363", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", 0, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-1363", 0, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-1363", 0, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "ibm-1363", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n"); + + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "ibm-1363", offsets3MBCS, TRUE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "ibm-1363", offsets3MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "euc-jp", offsets4MBCS, TRUE, U_ZERO_ERROR)) + log_err("u-> euc-jp [UCNV_MBCS] \n"); + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "euc-jp", offsets4MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> euc-jp [UCNV_MBCS] \n"); + } + + /*iso-2022-jp*/ + log_verbose("Testing for iso-2022-jp\n"); + { + static const UChar sampleText[] = { 0x0031, 0xd801}; + static const uint8_t expected[] = { 0x31}; + static const uint8_t expectedSUB[] = { 0x31, 0x1a}; + static const int32_t offsets[] = { 0x00, 1}; + + static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032}; + static const uint8_t expected2[] = { 0x31,0x1A,0x32}; + static const int32_t offsets2[] = { 0x00,0x01,0x02}; + + static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01}; + static const uint8_t expected4MBCS[] = { 0x61, 0x1b, 0x24, 0x42, 0x30, 0x6c,0x1b,0x28,0x42,0x1a}; + static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01 ,0x01, 0x01, 0x01,0x02,0x02,0x02,0x02 }; + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "iso-2022-jp", offsets, TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-jp [UCNV_MBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-jp", offsets, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-jp", offsets2, TRUE, U_ZERO_ERROR)) + log_err("u->iso-2022-jp[UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-jp", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-jp [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-jp", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-jp [UCNV_DBCS] did not match\n"); + + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "iso-2022-jp", offsets4MBCS, TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-jp [UCNV_MBCS] \n"); + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "iso-2022-jp", offsets4MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-jp [UCNV_MBCS] \n"); + } + + /*iso-2022-cn*/ + log_verbose("Testing for iso-2022-cn\n"); + { + static const UChar sampleText[] = { 0x0031, 0xd801}; + static const uint8_t expected[] = { 0x31}; + static const uint8_t expectedSUB[] = { 0x31, 0x1A}; + static const int32_t offsets[] = { 0x00, 1}; + + static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032}; + static const uint8_t expected2[] = { 0x31, 0x1A,0x32}; + static const int32_t offsets2[] = { 0x00, 0x01,0x02}; + + static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01}; + static const uint8_t expected3MBCS[] = {0x51, 0x50, 0x1A}; + static const int32_t offsets3MBCS[] = { 0x00, 0x01, 0x02 }; + + static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01}; + static const uint8_t expected4MBCS[] = { 0x61, 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x52, 0x3b, 0x0f, 0x1a }; + static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01 ,0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02 }; + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "iso-2022-cn", offsets, TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn [UCNV_MBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-cn", offsets, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-cn", offsets2, TRUE, U_ZERO_ERROR)) + log_err("u->iso-2022-cn[UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-cn", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-cn", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn [UCNV_DBCS] did not match\n"); + + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "iso-2022-cn", offsets3MBCS, TRUE, U_ZERO_ERROR)) + log_err("u->iso-2022-cn [UCNV_MBCS] \n"); + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "iso-2022-cn", offsets3MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn[UCNV_MBCS] \n"); + + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "iso-2022-cn", offsets4MBCS, TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn [UCNV_MBCS] \n"); + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "iso-2022-cn", offsets4MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-cn [UCNV_MBCS] \n"); + } + + /*iso-2022-kr*/ + log_verbose("Testing for iso-2022-kr\n"); + { + static const UChar sampleText[] = { 0x0031, 0xd801}; + static const uint8_t expected[] = { 0x1b, 0x24, 0x29, 0x43, 0x31}; + static const uint8_t expectedSUB[] = { 0x1b, 0x24, 0x29, 0x43, 0x31, 0x1A}; + static const int32_t offsets[] = { -1, -1, -1, -1, 0x00, 1}; + + static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032}; + static const uint8_t expected2[] = { 0x1b, 0x24, 0x29, 0x43, 0x31, 0x1A, 0x32}; + static const int32_t offsets2[] = { -1, -1, -1, -1, 0x00, 0x01, 0x02}; + + static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01}; + static const uint8_t expected3MBCS[] = { 0x1b, 0x24, 0x29, 0x43, 0x51, 0x50, 0x1A }; + static const int32_t offsets3MBCS[] = { -1, -1, -1, -1, 0x00, 0x01, 0x02, 0x02 }; + + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "iso-2022-kr", offsets, TRUE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr [UCNV_MBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-kr", offsets, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-kr", offsets2, TRUE, U_ZERO_ERROR)) + log_err("u->iso-2022-kr[UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-kr", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "iso-2022-kr", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr [UCNV_DBCS] did not match\n"); + + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "iso-2022-kr", offsets3MBCS, TRUE, U_ZERO_ERROR)) + log_err("u->iso-2022-kr [UCNV_MBCS] \n"); + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "iso-2022-kr", offsets3MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> iso-2022-kr[UCNV_MBCS] \n"); + } + + /*HZ*/ + log_verbose("Testing for HZ\n"); + { + static const UChar sampleText[] = { 0x0031, 0xd801}; + static const uint8_t expected[] = { 0x7e, 0x7d, 0x31}; + static const uint8_t expectedSUB[] = { 0x7e, 0x7d, 0x31, 0x1A}; + static const int32_t offsets[] = { 0x00, 0x00, 0x00, 1}; + + static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032}; + static const uint8_t expected2[] = { 0x7e, 0x7d, 0x31, 0x1A, 0x32 }; + static const int32_t offsets2[] = { 0x00, 0x00, 0x00, 0x01, 0x02 }; + + static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01}; + static const uint8_t expected3MBCS[] = { 0x7e, 0x7d, 0x51, 0x50, 0x1A }; + static const int32_t offsets3MBCS[] = { 0x00, 0x00, 0x00, 0x01, 0x02}; + + static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01}; + static const uint8_t expected4MBCS[] = { 0x7e, 0x7d, 0x61, 0x7e, 0x7b, 0x52, 0x3b, 0x7e, 0x7d, 0x1a }; + static const int32_t offsets4MBCS[] = { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01 ,0x01, 0x02, 0x02, 0x02 }; + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedSUB, sizeof(expectedSUB), "HZ", offsets, TRUE, U_ZERO_ERROR)) + log_err("u-> HZ [UCNV_MBCS] \n"); + if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "HZ", offsets, FALSE, U_ZERO_ERROR)) + log_err("u-> ibm-1363 [UCNV_MBCS] \n"); + + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "HZ", offsets2, TRUE, U_ZERO_ERROR)) + log_err("u->HZ[UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "HZ", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> HZ [UCNV_DBCS] did not match\n"); + if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]), + expected2, sizeof(expected2), "HZ", offsets2, FALSE, U_ZERO_ERROR)) + log_err("u-> HZ [UCNV_DBCS] did not match\n"); + + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "HZ", offsets3MBCS, TRUE, U_ZERO_ERROR)) + log_err("u->HZ [UCNV_MBCS] \n"); + if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]), + expected3MBCS, sizeof(expected3MBCS), "HZ", offsets3MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> HZ[UCNV_MBCS] \n"); + + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "HZ", offsets4MBCS, TRUE, U_ZERO_ERROR)) + log_err("u-> HZ [UCNV_MBCS] \n"); + if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]), + expected4MBCS, sizeof(expected4MBCS), "HZ", offsets4MBCS, FALSE, U_ZERO_ERROR)) + log_err("u-> HZ [UCNV_MBCS] \n"); + } +#endif +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +/*test different convertToUnicode error behaviours*/ +static void TestToUnicodeErrorBehaviour() +{ + log_verbose("Testing error conditions for DBCS\n"); + { + uint8_t sampleText[] = { 0xa2, 0xae, 0x03, 0x04}; + const UChar expected[] = { 0x00a1 }; + + if(!convertToU(sampleText, sizeof(sampleText), + expected, sizeof(expected)/sizeof(expected[0]), "ibm-1363", 0, TRUE, U_ZERO_ERROR )) + log_err("DBCS (ibm-1363)->Unicode did not match.\n"); + if(!convertToU(sampleText, sizeof(sampleText), + expected, sizeof(expected)/sizeof(expected[0]), "ibm-1363", 0, FALSE, U_ZERO_ERROR )) + log_err("DBCS (ibm-1363)->Unicode with flush = false did not match.\n"); + } + log_verbose("Testing error conditions for SBCS\n"); + { + uint8_t sampleText[] = { 0xa2, 0xFF}; + const UChar expected[] = { 0x00c2 }; + + /* uint8_t sampleText2[] = { 0xa2, 0x70 }; + const UChar expected2[] = { 0x0073 };*/ + + if(!convertToU(sampleText, sizeof(sampleText), + expected, sizeof(expected)/sizeof(expected[0]), "ibm-1051", 0, TRUE, U_ZERO_ERROR )) + log_err("SBCS (ibm-1051)->Unicode did not match.\n"); + if(!convertToU(sampleText, sizeof(sampleText), + expected, sizeof(expected)/sizeof(expected[0]), "ibm-1051", 0, FALSE, U_ZERO_ERROR )) + log_err("SBCS (ibm-1051)->Unicode with flush = false did not match.\n"); + + } +} + +static void TestGetNextErrorBehaviour(){ + /*Test for unassigned character*/ +#define INPUT_SIZE 1 + static const char input1[INPUT_SIZE]={ 0x70 }; + const char* source=(const char*)input1; + UErrorCode err=U_ZERO_ERROR; + UChar32 c=0; + UConverter *cnv=ucnv_open("ibm-424", &err); + if(U_FAILURE(err)) { + log_data_err("Unable to open a SBCS(ibm-424) converter: %s\n", u_errorName(err)); + return; + } + c=ucnv_getNextUChar(cnv, &source, source + INPUT_SIZE, &err); + if(err != U_INVALID_CHAR_FOUND && c!=0xfffd){ + log_err("FAIL in TestGetNextErrorBehaviour(unassigned): Expected: U_INVALID_CHAR_ERROR or 0xfffd ----Got:%s and 0x%lx\n", myErrorName(err), c); + } + ucnv_close(cnv); +} +#endif + +#define MAX_UTF16_LEN 2 +#define MAX_UTF8_LEN 4 + +/*Regression test for utf8 converter*/ +static void TestRegressionUTF8(){ + UChar32 currCh = 0; + int32_t offset8; + int32_t offset16; + UChar *standardForm = (UChar*)malloc(MAX_LENGTH*sizeof(UChar)); + uint8_t *utf8 = (uint8_t*)malloc(MAX_LENGTH); + + while (currCh <= UNICODE_LIMIT) { + offset16 = 0; + offset8 = 0; + while(currCh <= UNICODE_LIMIT + && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN) + && offset8 < (MAX_LENGTH - MAX_UTF8_LEN)) + { + if (currCh == SURROGATE_HIGH_START) { + currCh = SURROGATE_LOW_END + 1; /* Skip surrogate range */ + } + UTF16_APPEND_CHAR_SAFE(standardForm, offset16, MAX_LENGTH, currCh); + UTF8_APPEND_CHAR_SAFE(utf8, offset8, MAX_LENGTH, currCh); + currCh++; + } + if(!convertFromU(standardForm, offset16, + utf8, offset8, "UTF8", 0, TRUE, U_ZERO_ERROR )) { + log_err("Unicode->UTF8 did not match.\n"); + } + if(!convertToU(utf8, offset8, + standardForm, offset16, "UTF8", 0, TRUE, U_ZERO_ERROR )) { + log_err("UTF8->Unicode did not match.\n"); + } + } + + free(standardForm); + free(utf8); + + { + static const char src8[] = { (char)0xCC, (char)0x81, (char)0xCC, (char)0x80 }; + static const UChar expected[] = { 0x0301, 0x0300 }; + UConverter *conv8; + UErrorCode err = U_ZERO_ERROR; + UChar pivotBuffer[100]; + const UChar* const pivEnd = pivotBuffer + 100; + const char* srcBeg; + const char* srcEnd; + UChar* pivBeg; + + conv8 = ucnv_open("UTF-8", &err); + + srcBeg = src8; + pivBeg = pivotBuffer; + srcEnd = src8 + 3; + ucnv_toUnicode(conv8, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on first call.\n"); + } + + srcEnd = src8 + 4; + ucnv_toUnicode(conv8, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on second call.\n"); + } + + if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) { + log_err("Did not get expected results for UTF-8.\n"); + } + ucnv_close(conv8); + } +} + +#define MAX_UTF32_LEN 1 + +static void TestRegressionUTF32(){ + UChar32 currCh = 0; + int32_t offset32; + int32_t offset16; + UChar *standardForm = (UChar*)malloc(MAX_LENGTH*sizeof(UChar)); + UChar32 *utf32 = (UChar32*)malloc(MAX_LENGTH*sizeof(UChar32)); + + while (currCh <= UNICODE_LIMIT) { + offset16 = 0; + offset32 = 0; + while(currCh <= UNICODE_LIMIT + && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN) + && offset32 < (MAX_LENGTH/sizeof(UChar32) - MAX_UTF32_LEN)) + { + if (currCh == SURROGATE_HIGH_START) { + currCh = SURROGATE_LOW_END + 1; /* Skip surrogate range */ + } + UTF16_APPEND_CHAR_SAFE(standardForm, offset16, MAX_LENGTH, currCh); + UTF32_APPEND_CHAR_SAFE(utf32, offset32, MAX_LENGTH, currCh); + currCh++; + } + if(!convertFromU(standardForm, offset16, + (const uint8_t *)utf32, offset32*sizeof(UChar32), "UTF32_PlatformEndian", 0, TRUE, U_ZERO_ERROR )) { + log_err("Unicode->UTF32 did not match.\n"); + } + if(!convertToU((const uint8_t *)utf32, offset32*sizeof(UChar32), + standardForm, offset16, "UTF32_PlatformEndian", 0, TRUE, U_ZERO_ERROR )) { + log_err("UTF32->Unicode did not match.\n"); + } + } + free(standardForm); + free(utf32); + + { + /* Check for lone surrogate error handling. */ + static const UChar sampleBadStartSurrogate[] = { 0x0031, 0xD800, 0x0032 }; + static const UChar sampleBadEndSurrogate[] = { 0x0031, 0xDC00, 0x0032 }; + static const uint8_t expectedUTF32BE[] = { + 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0xff, 0xfd, + 0x00, 0x00, 0x00, 0x32 + }; + static const uint8_t expectedUTF32LE[] = { + 0x31, 0x00, 0x00, 0x00, + 0xfd, 0xff, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00 + }; + static const int32_t offsetsUTF32[] = { + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02 + }; + + if(!convertFromU(sampleBadStartSurrogate, sizeof(sampleBadStartSurrogate)/sizeof(sampleBadStartSurrogate[0]), + expectedUTF32BE, sizeof(expectedUTF32BE), "UTF-32BE", offsetsUTF32, TRUE, U_ZERO_ERROR)) + log_err("u->UTF-32BE\n"); + if(!convertFromU(sampleBadEndSurrogate, sizeof(sampleBadEndSurrogate)/sizeof(sampleBadEndSurrogate[0]), + expectedUTF32BE, sizeof(expectedUTF32BE), "UTF-32BE", offsetsUTF32, TRUE, U_ZERO_ERROR)) + log_err("u->UTF-32BE\n"); + + if(!convertFromU(sampleBadStartSurrogate, sizeof(sampleBadStartSurrogate)/sizeof(sampleBadStartSurrogate[0]), + expectedUTF32LE, sizeof(expectedUTF32LE), "UTF-32LE", offsetsUTF32, TRUE, U_ZERO_ERROR)) + log_err("u->UTF-32LE\n"); + if(!convertFromU(sampleBadEndSurrogate, sizeof(sampleBadEndSurrogate)/sizeof(sampleBadEndSurrogate[0]), + expectedUTF32LE, sizeof(expectedUTF32LE), "UTF-32LE", offsetsUTF32, TRUE, U_ZERO_ERROR)) + log_err("u->UTF-32LE\n"); + } + + { + static const char srcBE[] = { 0, 0, 0, 0x31, 0, 0, 0, 0x30 }; + static const UChar expected[] = { 0x0031, 0x0030 }; + UConverter *convBE; + UErrorCode err = U_ZERO_ERROR; + UChar pivotBuffer[100]; + const UChar* const pivEnd = pivotBuffer + 100; + const char* srcBeg; + const char* srcEnd; + UChar* pivBeg; + + convBE = ucnv_open("UTF-32BE", &err); + + srcBeg = srcBE; + pivBeg = pivotBuffer; + srcEnd = srcBE + 5; + ucnv_toUnicode(convBE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on first call.\n"); + } + + srcEnd = srcBE + 8; + ucnv_toUnicode(convBE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on second call.\n"); + } + + if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) { + log_err("Did not get expected results for UTF-32BE.\n"); + } + ucnv_close(convBE); + } + { + static const char srcLE[] = { 0x31, 0, 0, 0, 0x30, 0, 0, 0 }; + static const UChar expected[] = { 0x0031, 0x0030 }; + UConverter *convLE; + UErrorCode err = U_ZERO_ERROR; + UChar pivotBuffer[100]; + const UChar* const pivEnd = pivotBuffer + 100; + const char* srcBeg; + const char* srcEnd; + UChar* pivBeg; + + convLE = ucnv_open("UTF-32LE", &err); + + srcBeg = srcLE; + pivBeg = pivotBuffer; + srcEnd = srcLE + 5; + ucnv_toUnicode(convLE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on first call.\n"); + } + + srcEnd = srcLE + 8; + ucnv_toUnicode(convLE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err); + if (srcBeg != srcEnd) { + log_err("Did not consume whole buffer on second call.\n"); + } + + if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) { + log_err("Did not get expected results for UTF-32LE.\n"); + } + ucnv_close(convLE); + } +} + +/*Walk through the available converters*/ +static void TestAvailableConverters(){ + UErrorCode status=U_ZERO_ERROR; + UConverter *conv=NULL; + int32_t i=0; + for(i=0; i < ucnv_countAvailable(); i++){ + status=U_ZERO_ERROR; + conv=ucnv_open(ucnv_getAvailableName(i), &status); + if(U_FAILURE(status)){ + log_err("ERROR: converter creation failed. Failure in alias table or the data table for \n converter=%s. Error=%s\n", + ucnv_getAvailableName(i), myErrorName(status)); + continue; + } + ucnv_close(conv); + } + +} + +static void TestFlushInternalBuffer(){ + TestWithBufferSize(MAX_LENGTH, 1); + TestWithBufferSize(1, 1); + TestWithBufferSize(1, MAX_LENGTH); + TestWithBufferSize(MAX_LENGTH, MAX_LENGTH); +} + +static void TestWithBufferSize(int32_t insize, int32_t outsize){ + + gInBufferSize =insize; + gOutBufferSize = outsize; + + log_verbose("Testing fromUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); + { + UChar sampleText[] = + { 0x0031, 0x0032, 0x0033, 0x0000, 0x4e00, 0x4e8c, 0x4e09, 0x002E }; + const uint8_t expectedUTF8[] = + { 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E }; + int32_t toUTF8Offs[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07}; + /* int32_t fmUTF8Offs[] = + { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, 0x000d };*/ + + /*UTF-8*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF8, sizeof(expectedUTF8), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE, toUTF8Offs ,FALSE)) + log_err("u-> UTF8 did not match.\n"); + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_ESCAPE \n"); + { + UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 }; + const uint8_t toIBM943[]= { 0x61, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x43, 0x30, 0x31, + 0x25, 0x55, 0x44, 0x38, 0x30, 0x31, + 0x61 }; + int32_t offset[]= {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 4}; + + if(!testConvertFromU(inputTest, sizeof(inputTest)/sizeof(inputTest[0]), + toIBM943, sizeof(toIBM943), "ibm-943", + (UConverterFromUCallback)UCNV_FROM_U_CALLBACK_ESCAPE, offset,FALSE)) + log_err("u-> ibm-943 with subst with value did not match.\n"); + } +#endif + + log_verbose("Testing fromUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n"); + { + const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c, + 0xe0, 0x80, 0x61}; + UChar expected1[] = { 0x0031, 0x4e8c, 0xfffd, 0x0061}; + int32_t offsets1[] = { 0x0000, 0x0001, 0x0004, 0x0006}; + + if(!testConvertToU(sampleText1, sizeof(sampleText1), + expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8", UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1,FALSE)) + log_err("utf8->u with substitute did not match.\n");; + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_ESCAPE \n"); + /*to Unicode*/ + { + const uint8_t sampleTxtToU[]= { 0x00, 0x9f, 0xaf, + 0x81, 0xad, /*unassigned*/ + 0x89, 0xd3 }; + UChar IBM_943toUnicode[] = { 0x0000, 0x6D63, + 0x25, 0x58, 0x38, 0x31, 0x25, 0x58, 0x41, 0x44, + 0x7B87}; + int32_t fromIBM943Offs [] = { 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 5}; + + if(!testConvertToU(sampleTxtToU, sizeof(sampleTxtToU), + IBM_943toUnicode, sizeof(IBM_943toUnicode)/sizeof(IBM_943toUnicode[0]),"ibm-943", + (UConverterToUCallback)UCNV_TO_U_CALLBACK_ESCAPE, fromIBM943Offs,FALSE)) + log_err("ibm-943->u with substitute with value did not match.\n"); + + } +#endif +} + +static UBool convertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus) +{ + + int32_t i=0; + char *p=0; + const UChar *src; + char buffer[MAX_LENGTH]; + int32_t offsetBuffer[MAX_LENGTH]; + int32_t *offs=0; + char *targ; + char *targetLimit; + UChar *sourceLimit=0; + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; + } + log_verbose("Converter %s opened..\n", ucnv_getName(conv, &status)); + + for(i=0; i<MAX_LENGTH; i++){ + buffer[i]=(char)0xF0; + offsetBuffer[i]=0xFF; + } + + src=source; + sourceLimit=(UChar*)src+(sourceLen); + targ=buffer; + targetLimit=targ+MAX_LENGTH; + offs=offsetBuffer; + ucnv_fromUnicode (conv, + (char **)&targ, + (const char *)targetLimit, + &src, + sourceLimit, + expectOffsets ? offs : NULL, + doFlush, + &status); + ucnv_close(conv); + if(status != expectedStatus){ + log_err("ucnv_fromUnicode() failed for codepage=%s. Error =%s Expected=%s\n", codepage, myErrorName(status), myErrorName(expectedStatus)); + return FALSE; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-buffer); + + if(expectLen != targ-buffer) + { + log_err("Expected %d chars out, got %d FROM Unicode to %s\n", expectLen, targ-buffer, codepage); + log_verbose("Expected %d chars out, got %d FROM Unicode to %s\n", expectLen, targ-buffer, codepage); + printSeqErr((const unsigned char *)buffer, (int32_t)(targ-buffer)); + printSeqErr((const unsigned char*)expect, expectLen); + return FALSE; + } + + if(memcmp(buffer, expect, expectLen)){ + log_err("String does not match. FROM Unicode to codePage%s\n", codepage); + log_info("\nGot:"); + printSeqErr((const unsigned char *)buffer, expectLen); + log_info("\nExpected:"); + printSeqErr((const unsigned char *)expect, expectLen); + return FALSE; + } + else { + log_verbose("Matches!\n"); + } + + if (expectOffsets != 0){ + log_verbose("comparing %d offsets..\n", targ-buffer); + if(memcmp(offsetBuffer,expectOffsets,(targ-buffer) * sizeof(int32_t) )){ + log_err("did not get the expected offsets. for FROM Unicode to %s\n", codepage); + log_info("\nGot : "); + printSeqErr((const unsigned char*)buffer, (int32_t)(targ-buffer)); + for(p=buffer;p<targ;p++) + log_info("%d, ", offsetBuffer[p-buffer]); + log_info("\nExpected: "); + for(i=0; i< (targ-buffer); i++) + log_info("%d,", expectOffsets[i]); + } + } + + return TRUE; +} + + +static UBool convertToU( const uint8_t *source, int sourceLen, const UChar *expect, int expectLen, + const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + int32_t i=0; + UChar *p=0; + const char* src; + UChar buffer[MAX_LENGTH]; + int32_t offsetBuffer[MAX_LENGTH]; + int32_t *offs=0; + UChar *targ; + UChar *targetLimit; + uint8_t *sourceLimit=0; + + + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; + } + log_verbose("Converter %s opened..\n", ucnv_getName(conv, &status)); + + + + for(i=0; i<MAX_LENGTH; i++){ + buffer[i]=0xFFFE; + offsetBuffer[i]=-1; + } + + src=(const char *)source; + sourceLimit=(uint8_t*)(src+(sourceLen)); + targ=buffer; + targetLimit=targ+MAX_LENGTH; + offs=offsetBuffer; + + + + ucnv_toUnicode (conv, + &targ, + targetLimit, + (const char **)&src, + (const char *)sourceLimit, + expectOffsets ? offs : NULL, + doFlush, + &status); + + ucnv_close(conv); + if(status != expectedStatus){ + log_err("ucnv_fromUnicode() failed for codepage=%s. Error =%s Expected=%s\n", codepage, myErrorName(status), myErrorName(expectedStatus)); + return FALSE; + } + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-buffer); + + + + + log_verbose("comparing %d uchars (%d bytes)..\n",expectLen,expectLen*2); + + if (expectOffsets != 0) { + if(memcmp(offsetBuffer, expectOffsets, (targ-buffer) * sizeof(int32_t))){ + + log_err("did not get the expected offsets from %s To UNICODE\n", codepage); + log_info("\nGot : "); + for(p=buffer;p<targ;p++) + log_info("%d, ", offsetBuffer[p-buffer]); + log_info("\nExpected: "); + for(i=0; i<(targ-buffer); i++) + log_info("%d, ", expectOffsets[i]); + log_info("\nGot result:"); + for(i=0; i<(targ-buffer); i++) + log_info("0x%04X,", buffer[i]); + log_info("\nFrom Input:"); + for(i=0; i<(src-(const char *)source); i++) + log_info("0x%02X,", (unsigned char)source[i]); + log_info("\n"); + } + } + if(memcmp(buffer, expect, expectLen*2)){ + log_err("String does not match. from codePage %s TO Unicode\n", codepage); + log_info("\nGot:"); + printUSeqErr(buffer, expectLen); + log_info("\nExpected:"); + printUSeqErr(expect, expectLen); + return FALSE; + } + else { + log_verbose("Matches!\n"); + } + + return TRUE; +} + + +static UBool testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets, UBool testReset) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + char junkout[MAX_LENGTH]; /* FIX */ + int32_t junokout[MAX_LENGTH]; /* FIX */ + char *p; + const UChar *src; + char *end; + char *targ; + int32_t *offs; + int i; + int32_t realBufferSize; + char *realBufferEnd; + const UChar *realSourceEnd; + const UChar *sourceLimit; + UBool checkOffsets = TRUE; + UBool doFlush; + + UConverterFromUCallback oldAction = NULL; + const void* oldContext = NULL; + + for(i=0;i<MAX_LENGTH;i++) + junkout[i] = (char)0xF0; + for(i=0;i<MAX_LENGTH;i++) + junokout[i] = 0xFF; + + setNuConvTestName(codepage, "FROM"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TRUE; + } + + log_verbose("Converter opened..\n"); + /*----setting the callback routine----*/ + ucnv_setFromUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*------------------------*/ + + src = source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = source + sourceLen; + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != MAX_LENGTH ) + checkOffsets = FALSE; + + do + { + end = nct_min(targ + gOutBufferSize, realBufferEnd); + sourceLimit = nct_min(src + gInBufferSize, realSourceEnd); + + doFlush = (UBool)(sourceLimit == realSourceEnd); + + if(targ == realBufferEnd) + { + log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName); + return FALSE; + } + log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE"); + + + status = U_ZERO_ERROR; + if(gInBufferSize ==999 && gOutBufferSize==999) + doFlush = FALSE; + ucnv_fromUnicode (conv, + (char **)&targ, + (const char *)end, + &src, + sourceLimit, + offs, + doFlush, /* flush if we're at the end of the input data */ + &status); + if(testReset) + ucnv_resetToUnicode(conv); + if(gInBufferSize ==999 && gOutBufferSize==999) + ucnv_resetToUnicode(conv); + + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && sourceLimit < realSourceEnd) ); + + if(U_FAILURE(status)) { + log_err("Problem doing fromUnicode to %s, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-junkout); + if(VERBOSITY) + { + char junk[999]; + char offset_str[999]; + char *ptr; + + junk[0] = 0; + offset_str[0] = 0; + for(ptr = junkout;ptr<targ;ptr++) + { + sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*ptr); + sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[ptr-junkout]); + } + + log_verbose(junk); + printSeq((const unsigned char *)expect, expectLen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + + if(expectLen != targ-junkout) + { + log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_info("\nGot:"); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + log_info("\nExpected:"); + printSeqErr((const unsigned char*)expect, expectLen); + return FALSE; + } + + if (checkOffsets && (expectOffsets != 0) ) + { + log_verbose("comparing %d offsets..\n", targ-junkout); + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){ + log_err("did not get the expected offsets. %s", gNuConvTestName); + log_err("Got : "); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + for(p=junkout;p<targ;p++) + log_err("%d, ", junokout[p-junkout]); + log_err("\nExpected: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + } + } + + log_verbose("comparing..\n"); + if(!memcmp(junkout, expect, expectLen)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + printUSeqErr(source, sourceLen); + log_info("\nGot:"); + printSeqErr((const unsigned char *)junkout, expectLen); + log_info("\nExpected:"); + printSeqErr((const unsigned char *)expect, expectLen); + + return FALSE; + } +} + +static UBool testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, UBool testReset) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + UChar junkout[MAX_LENGTH]; /* FIX */ + int32_t junokout[MAX_LENGTH]; /* FIX */ + const char *src; + const char *realSourceEnd; + const char *srcLimit; + UChar *p; + UChar *targ; + UChar *end; + int32_t *offs; + int i; + UBool checkOffsets = TRUE; + int32_t realBufferSize; + UChar *realBufferEnd; + UBool doFlush; + + UConverterToUCallback oldAction = NULL; + const void* oldContext = NULL; + + + for(i=0;i<MAX_LENGTH;i++) + junkout[i] = 0xFFFE; + + for(i=0;i<MAX_LENGTH;i++) + junokout[i] = -1; + + setNuConvTestName(codepage, "TO"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = ucnv_open(codepage, &status); + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",gNuConvTestName); + return TRUE; + } + + log_verbose("Converter opened..\n"); + /*----setting the callback routine----*/ + ucnv_setToUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status); + if (U_FAILURE(status)) { + log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status)); + } + /*-------------------------------------*/ + + src = (const char *)source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = src + sourcelen; + + if ( gOutBufferSize != realBufferSize ) + checkOffsets = FALSE; + + if( gInBufferSize != MAX_LENGTH ) + checkOffsets = FALSE; + + do + { + end = nct_min( targ + gOutBufferSize, realBufferEnd); + srcLimit = nct_min(realSourceEnd, src + gInBufferSize); + + if(targ == realBufferEnd) + { + log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName); + return FALSE; + } + log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end); + + /* oldTarg = targ; */ + + status = U_ZERO_ERROR; + doFlush=(UBool)((gInBufferSize ==999 && gOutBufferSize==999)?(srcLimit == realSourceEnd) : FALSE); + + ucnv_toUnicode (conv, + &targ, + end, + (const char **)&src, + (const char *)srcLimit, + offs, + doFlush, /* flush if we're at the end of hte source data */ + &status); + if(testReset) + ucnv_resetFromUnicode(conv); + if(gInBufferSize ==999 && gOutBufferSize==999) + ucnv_resetToUnicode(conv); + /* offs += (targ-oldTarg); */ + + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */ + + if(U_FAILURE(status)) + { + log_err("Problem doing %s toUnicode, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName); + return FALSE; + } + + log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :", + sourcelen, targ-junkout); + if(VERBOSITY) + { + char junk[999]; + char offset_str[999]; + + UChar *ptr; + + junk[0] = 0; + offset_str[0] = 0; + + for(ptr = junkout;ptr<targ;ptr++) + { + sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*ptr); + sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[ptr-junkout]); + } + + log_verbose(junk); + + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2); + + if (checkOffsets && (expectOffsets != 0)) + { + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))){ + + log_err("did not get the expected offsets. %s",gNuConvTestName); + for(p=junkout;p<targ;p++) + log_err("%d, ", junokout[p-junkout]); + log_err("\nExpected: "); + for(i=0; i<(targ-junkout); i++) + log_err("%d,", expectOffsets[i]); + log_err(""); + for(i=0; i<(targ-junkout); i++) + log_err("%X,", junkout[i]); + log_err(""); + for(i=0; i<(src-(const char *)source); i++) + log_err("%X,", (unsigned char)source[i]); + } + } + + if(!memcmp(junkout, expect, expectlen*2)) + { + log_verbose("Matches!\n"); + return TRUE; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + log_info("\nGot:"); + printUSeq(junkout, expectlen); + log_info("\nExpected:"); + printUSeq(expect, expectlen); + return FALSE; + } +} + + +static void TestResetBehaviour(void){ +#if !UCONFIG_NO_LEGACY_CONVERSION + log_verbose("Testing Reset for DBCS and MBCS\n"); + { + static const UChar sampleText[] = {0x00a1, 0xd801, 0xdc01, 0x00a4}; + static const uint8_t expected[] = {0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4}; + static const int32_t offsets[] = {0x00, 0x00, 0x01, 0x01, 0x03, 0x03 }; + + + static const UChar sampleText1[] = {0x00a1, 0x00a4, 0x00a7, 0x00a8}; + static const uint8_t expected1[] = {0xa2, 0xae,0xA2,0xB4,0xA1,0xD7,0xA1,0xA7}; + static const int32_t offsets1[] = { 0,2,4,6}; + + /*DBCS*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n"); + + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "ibm-1363",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("ibm-1363 -> did not match.\n"); + /*MBCS*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n"); + + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "ibm-1363",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("ibm-1363 -> did not match.\n"); + + } + + log_verbose("Testing Reset for ISO-2022-jp\n"); + { + static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42, + 0x31,0x1A, 0x32}; + + + static const int32_t offsets[] = {0,0,0,0,0,1,1,2,2,2,2,3,5 }; + + + static const UChar sampleText1[] = {0x4e00, 0x04e01, 0x0031,0x001A, 0x0032}; + static const uint8_t expected1[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42, + 0x31,0x1A, 0x32}; + static const int32_t offsets1[] = { 3,5,10,11,12}; + + /*iso-2022-jp*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-jp", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("u-> not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-jp", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> not match.\n"); + + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-jp",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("iso-2022-jp -> did not match.\n"); + + } + + log_verbose("Testing Reset for ISO-2022-cn\n"); + { + static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = { + 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B, + 0x36, 0x21, + 0x0f, 0x31, + 0x1A, + 0x32 + }; + + + static const int32_t offsets[] = { + 0, 0, 0, 0, 0, 0, 0, + 1, 1, + 2, 2, + 3, + 5, }; + + UChar sampleText1[] = {0x4e00, 0x04e01, 0x0031,0x001A, 0x0032}; + static const uint8_t expected1[] = { + 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B, + 0x36, 0x21, + 0x1B, 0x24, 0x29, 0x47, 0x24, 0x22, + 0x0f, 0x1A, + 0x32 + }; + static const int32_t offsets1[] = { 5,7,13,16,17}; + + /*iso-2022-CN*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-cn", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("u-> not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-cn", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> not match.\n"); + + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-cn",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("iso-2022-cn -> did not match.\n"); + } + + log_verbose("Testing Reset for ISO-2022-kr\n"); + { + UChar sampleText[] = { 0x4e00,0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = {0x1B, 0x24, 0x29, 0x43, + 0x0E, 0x6C, 0x69, + 0x0f, 0x1A, + 0x0e, 0x6F, 0x4B, + 0x0F, 0x31, + 0x1A, + 0x32 }; + + static const int32_t offsets[] = {-1, -1, -1, -1, + 0, 0, 0, + 1, 1, + 3, 3, 3, + 4, 4, + 5, + 7, + }; + static const UChar sampleText1[] = { 0x4e00,0x0041, 0x04e01, 0x0031, 0x0042, 0x0032}; + + static const uint8_t expected1[] = {0x1B, 0x24, 0x29, 0x43, + 0x0E, 0x6C, 0x69, + 0x0f, 0x41, + 0x0e, 0x6F, 0x4B, + 0x0F, 0x31, + 0x42, + 0x32 }; + + static const int32_t offsets1[] = { + 5, 8, 10, + 13, 14, 15 + + }; + /*iso-2022-kr*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-kr", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "iso-2022-kr", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n"); + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-kr",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("iso-2022-kr -> did not match.\n"); + } + + log_verbose("Testing Reset for HZ\n"); + { + static const UChar sampleText[] = { 0x4e00, 0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032}; + + static const uint8_t expected[] = {0x7E, 0x7B, 0x52, 0x3B, + 0x7E, 0x7D, 0x1A, + 0x7E, 0x7B, 0x36, 0x21, + 0x7E, 0x7D, 0x31, + 0x1A, + 0x32 }; + + + static const int32_t offsets[] = {0,0,0,0, + 1,1,1, + 3,3,3,3, + 4,4,4, + 5, + 7,}; + static const UChar sampleText1[] = { 0x4e00, 0x0035, 0x04e01, 0x0031, 0x0041, 0x0032}; + + static const uint8_t expected1[] = {0x7E, 0x7B, 0x52, 0x3B, + 0x7E, 0x7D, 0x35, + 0x7E, 0x7B, 0x36, 0x21, + 0x7E, 0x7D, 0x31, + 0x41, + 0x32 }; + + + static const int32_t offsets1[] = {2,6,9,13,14,15 + }; + + /*hz*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "HZ", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE)) + log_err("u-> not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "HZ", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> not match.\n"); + if(!testConvertToU(expected1, sizeof(expected1), + sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "hz",UCNV_TO_U_CALLBACK_SUBSTITUTE , + offsets1, TRUE)) + log_err("hz -> did not match.\n"); + } +#endif + + /*UTF-8*/ + log_verbose("Testing for UTF8\n"); + { + static const UChar sampleText[] = { 0x4e00, 0x0701, 0x0031, 0xbfc1, 0xd801, 0xdc01, 0x0032}; + int32_t offsets[]={0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x06 }; + static const uint8_t expected[] = {0xe4, 0xb8, 0x80, 0xdc, 0x81, 0x31, + 0xeb, 0xbf, 0x81, 0xF0, 0x90, 0x90, 0x81, 0x32}; + + + static const int32_t fromOffsets[] = { 0x0000, 0x0003, 0x0005, 0x0006, 0x0009, 0x0009, 0x000D }; + /*UTF-8*/ + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE)) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE)) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE)) + log_err("u-> UTF8 with offsets and flush true did not match.\n"); + if(!testConvertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8",UCNV_TO_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("UTF8 -> did not match.\n"); + if(!testConvertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", UCNV_TO_U_CALLBACK_SUBSTITUTE , NULL, TRUE)) + log_err("UTF8 -> did not match.\n"); + if(!testConvertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8",UCNV_TO_U_CALLBACK_SUBSTITUTE , fromOffsets, TRUE)) + log_err("UTF8 -> did not match.\n"); + if(!testConvertToU(expected, sizeof(expected), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", UCNV_TO_U_CALLBACK_SUBSTITUTE , fromOffsets, TRUE)) + log_err("UTF8 -> did not match.\n"); + + } + +} + +/* Test that U_TRUNCATED_CHAR_FOUND is set. */ +static void +doTestTruncated(const char *cnvName, const uint8_t *bytes, int32_t length) { + UConverter *cnv; + + UChar buffer[2]; + UChar *target, *targetLimit; + const char *source, *sourceLimit; + + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + cnv=ucnv_open(cnvName, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("error TestTruncated: unable to open \"%s\" - %s\n", cnvName, u_errorName(errorCode)); + return; + } + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("error TestTruncated: unable to set the stop callback on \"%s\" - %s\n", + cnvName, u_errorName(errorCode)); + ucnv_close(cnv); + return; + } + + source=(const char *)bytes; + sourceLimit=source+length; + target=buffer; + targetLimit=buffer+LENGTHOF(buffer); + + /* 1. input bytes with flush=FALSE, then input nothing with flush=TRUE */ + ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, FALSE, &errorCode); + if(U_FAILURE(errorCode) || source!=sourceLimit || target!=buffer) { + log_err("error TestTruncated(%s, 1a): input bytes[%d], flush=FALSE: %s, input left %d, output %d\n", + cnvName, length, u_errorName(errorCode), (int)(sourceLimit-source), (int)(target-buffer)); + } + + errorCode=U_ZERO_ERROR; + source=sourceLimit; + target=buffer; + ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &errorCode); + if(errorCode!=U_TRUNCATED_CHAR_FOUND || target!=buffer) { + log_err("error TestTruncated(%s, 1b): no input (previously %d), flush=TRUE: %s (should be U_TRUNCATED_CHAR_FOUND), output %d\n", + cnvName, (int)length, u_errorName(errorCode), (int)(target-buffer)); + } + + /* 2. input bytes with flush=TRUE */ + ucnv_resetToUnicode(cnv); + + errorCode=U_ZERO_ERROR; + source=(const char *)bytes; + target=buffer; + ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &errorCode); + if(errorCode!=U_TRUNCATED_CHAR_FOUND || source!=sourceLimit || target!=buffer) { + log_err("error TestTruncated(%s, 2): input bytes[%d], flush=TRUE: %s (should be U_TRUNCATED_CHAR_FOUND), input left %d, output %d\n", + cnvName, length, u_errorName(errorCode), (int)(sourceLimit-source), (int)(target-buffer)); + } + + + ucnv_close(cnv); +} + +static void +TestTruncated() { + static const struct { + const char *cnvName; + uint8_t bytes[8]; /* partial input bytes resulting in no output */ + int32_t length; + } testCases[]={ + { "IMAP-mailbox-name", { 0x26 }, 1 }, /* & */ + { "IMAP-mailbox-name", { 0x26, 0x42 }, 2 }, /* &B */ + { "IMAP-mailbox-name", { 0x26, 0x42, 0x42 }, 3 }, /* &BB */ + { "IMAP-mailbox-name", { 0x26, 0x41, 0x41 }, 3 }, /* &AA */ + + { "UTF-7", { 0x2b, 0x42 }, 2 }, /* +B */ + { "UTF-8", { 0xd1 }, 1 }, + + { "UTF-16BE", { 0x4e }, 1 }, + { "UTF-16LE", { 0x4e }, 1 }, + { "UTF-16", { 0x4e }, 1 }, + { "UTF-16", { 0xff }, 1 }, + { "UTF-16", { 0xfe, 0xff, 0x4e }, 3 }, + + { "UTF-32BE", { 0, 0, 0x4e }, 3 }, + { "UTF-32LE", { 0x4e }, 1 }, + { "UTF-32", { 0, 0, 0x4e }, 3 }, + { "UTF-32", { 0xff }, 1 }, + { "UTF-32", { 0, 0, 0xfe, 0xff, 0 }, 5 }, + { "SCSU", { 0x0e, 0x4e }, 2 }, /* SQU 0x4e */ + +#if !UCONFIG_NO_LEGACY_CONVERSION + { "BOCU-1", { 0xd5 }, 1 }, + + { "Shift-JIS", { 0xe0 }, 1 }, + + { "ibm-939", { 0x0e, 0x41 }, 2 } /* SO 0x41 */ +#else + { "BOCU-1", { 0xd5 }, 1 ,} +#endif + }; + int32_t i; + + for(i=0; i<LENGTHOF(testCases); ++i) { + doTestTruncated(testCases[i].cnvName, testCases[i].bytes, testCases[i].length); + } +} + +typedef struct NameRange { + const char *name; + UChar32 start, end, start2, end2, notStart, notEnd; +} NameRange; + +static void +TestUnicodeSet() { + UErrorCode errorCode; + UConverter *cnv; + USet *set; + const char *name; + int32_t i, count; + + static const char *const completeSetNames[]={ + "UTF-7", + "UTF-8", + "UTF-16", + "UTF-16BE", + "UTF-16LE", + "UTF-32", + "UTF-32BE", + "UTF-32LE", + "SCSU", + "BOCU-1", + "CESU-8", +#if !UCONFIG_NO_LEGACY_CONVERSION + "gb18030", +#endif + "IMAP-mailbox-name" + }; + + static const char *const lmbcsNames[]={ +#if !UCONFIG_NO_LEGACY_CONVERSION + "LMBCS-1", + "LMBCS-2", + "LMBCS-3", + "LMBCS-4", + "LMBCS-5", + "LMBCS-6", + "LMBCS-8", + "LMBCS-11", + "LMBCS-16", + "LMBCS-17", + "LMBCS-18", + "LMBCS-19" +#endif + }; + + static const NameRange nameRanges[]={ + { "US-ASCII", 0, 0x7f, -1, -1, 0x80, 0x10ffff }, +#if !UCONFIG_NO_LEGACY_CONVERSION + { "ibm-367", 0, 0x7f, -1, -1, 0x80, 0x10ffff }, +#endif + { "ISO-8859-1", 0, 0x7f, -1, -1, 0x100, 0x10ffff }, +#if !UCONFIG_NO_LEGACY_CONVERSION + { "UTF-8", 0, 0xd7ff, 0xe000, 0x10ffff, 0xd800, 0xdfff }, + { "windows-1251", 0, 0x7f, 0x410, 0x44f, 0x3000, 0xd7ff }, + { "HZ", 0x410, 0x44f, 0x4e00, 0x4eff, 0xac00, 0xd7ff }, + { "shift-jis", 0x3041, 0x3093, 0x30a1, 0x30f3, 0x900, 0x1cff } +#else + { "UTF-8", 0, 0xd7ff, 0xe000, 0x10ffff, 0xd800, 0xdfff } +#endif + }; + + /* open an empty set */ + set=uset_open(1, 0); + + count=ucnv_countAvailable(); + for(i=0; i<count; ++i) { + errorCode=U_ZERO_ERROR; + name=ucnv_getAvailableName(i); + cnv=ucnv_open(name, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: unable to open converter %s - %s\n", + name, u_errorName(errorCode)); + continue; + } + + uset_clear(set); + ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n", + name, u_errorName(errorCode)); + } else if(uset_size(set)==0) { + log_err("error: ucnv_getUnicodeSet(%s) returns an empty set\n", name); + } + + ucnv_close(cnv); + } + + /* test converters that are known to convert all of Unicode (except maybe for surrogates) */ + for(i=0; i<LENGTHOF(completeSetNames); ++i) { + errorCode=U_ZERO_ERROR; + name=completeSetNames[i]; + cnv=ucnv_open(name, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: unable to open converter %s - %s\n", + name, u_errorName(errorCode)); + continue; + } + + uset_clear(set); + ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n", + name, u_errorName(errorCode)); + } else if(!uset_containsRange(set, 0, 0xd7ff) || !uset_containsRange(set, 0xe000, 0x10ffff)) { + log_err("error: ucnv_getUnicodeSet(%s) does not return an all-Unicode set\n", name); + } + + ucnv_close(cnv); + } + + /* test LMBCS variants which convert all of Unicode except for U+F6xx */ + for(i=0; i<LENGTHOF(lmbcsNames); ++i) { + errorCode=U_ZERO_ERROR; + name=lmbcsNames[i]; + cnv=ucnv_open(name, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: unable to open converter %s - %s\n", + name, u_errorName(errorCode)); + continue; + } + + uset_clear(set); + ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n", + name, u_errorName(errorCode)); + } else if(!uset_containsRange(set, 0, 0xf5ff) || !uset_containsRange(set, 0xf700, 0x10ffff)) { + log_err("error: ucnv_getUnicodeSet(%s) does not return an all-Unicode set (minus U+F6xx)\n", name); + } + + ucnv_close(cnv); + } + + /* test specific sets */ + for(i=0; i<LENGTHOF(nameRanges); ++i) { + errorCode=U_ZERO_ERROR; + name=nameRanges[i].name; + cnv=ucnv_open(name, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("error: unable to open converter %s - %s\n", + name, u_errorName(errorCode)); + continue; + } + + uset_clear(set); + ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n", + name, u_errorName(errorCode)); + } else if( + !uset_containsRange(set, nameRanges[i].start, nameRanges[i].end) || + (nameRanges[i].start2>=0 && !uset_containsRange(set, nameRanges[i].start2, nameRanges[i].end2)) + ) { + log_err("error: ucnv_getUnicodeSet(%s) does not contain the expected ranges\n", name); + } else if(nameRanges[i].notStart>=0) { + /* simulate containsAny() with the C API */ + uset_complement(set); + if(!uset_containsRange(set, nameRanges[i].notStart, nameRanges[i].notEnd)) { + log_err("error: ucnv_getUnicodeSet(%s) contains part of the unexpected range\n", name); + } + } + + ucnv_close(cnv); + } + + errorCode = U_ZERO_ERROR; + ucnv_getUnicodeSet(NULL, set, UCNV_ROUNDTRIP_SET, &errorCode); + if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("error: ucnv_getUnicodeSet(NULL) returned wrong status code %s\n", u_errorName(errorCode)); + } + errorCode = U_PARSE_ERROR; + /* Make sure that it does nothing if an error is passed in. Difficult to proper test for. */ + ucnv_getUnicodeSet(NULL, NULL, UCNV_ROUNDTRIP_SET, &errorCode); + if (errorCode != U_PARSE_ERROR) { + log_err("error: ucnv_getUnicodeSet(NULL) returned wrong status code %s\n", u_errorName(errorCode)); + } + + uset_close(set); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c new file mode 100644 index 00000000000..61b11214beb --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c @@ -0,0 +1,310 @@ +/* + ******************************************************************************* + * + * Copyright (C) 2003-2007, International Business Machines + * Corporation and others. All Rights Reserved. + * + ******************************************************************************* + * file name: nfsprep.c + * encoding: US-ASCII + * tab size: 8 (not used) + * indentation:4 + * + * created on: 2003jul11 + * created by: Ram Viswanadha + */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_IDNA + +#include "nfsprep.h" +#include "ustr_imp.h" +#include "cintltst.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) +#define NFS4_MAX_BUFFER_SIZE 1000 +#define PREFIX_SUFFIX_SEPARATOR 0x0040 /* '@' */ + + +const char* NFS4DataFileNames[5] ={ + "nfscss", + "nfscsi", + "nfscis", + "nfsmxp", + "nfsmxs" +}; + + +int32_t +nfs4_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + NFS4ProfileState state, + UParseError* parseError, + UErrorCode* status){ + + UChar b1Stack[NFS4_MAX_BUFFER_SIZE], + b2Stack[NFS4_MAX_BUFFER_SIZE]; + char b3Stack[NFS4_MAX_BUFFER_SIZE]; + + /* initialize pointers to stack buffers */ + UChar *b1 = b1Stack, *b2 = b2Stack; + char *b3=b3Stack; + int32_t b1Len=0, b2Len=0, b3Len=0, + b1Capacity = NFS4_MAX_BUFFER_SIZE, + b2Capacity = NFS4_MAX_BUFFER_SIZE, + b3Capacity = NFS4_MAX_BUFFER_SIZE, + reqLength=0; + + UStringPrepProfile* profile = NULL; + /* get the test data path */ + const char *testdatapath = NULL; + + if(status==NULL || U_FAILURE(*status)){ + return 0; + } + if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + testdatapath = loadTestData(status); + + /* convert the string from UTF-8 to UTF-16 */ + u_strFromUTF8(b1,b1Capacity,&b1Len,src,srcLength,status); + if(*status == U_BUFFER_OVERFLOW_ERROR){ + + /* reset the status */ + *status = U_ZERO_ERROR; + + b1 = (UChar*) malloc(b1Len * U_SIZEOF_UCHAR); + if(b1==NULL){ + *status = U_MEMORY_ALLOCATION_ERROR; + goto CLEANUP; + } + + b1Capacity = b1Len; + u_strFromUTF8(b1, b1Capacity, &b1Len, src, srcLength, status); + } + + /* open the profile */ + profile = usprep_open(testdatapath, NFS4DataFileNames[state], status); + /* prepare the string */ + b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Capacity, USPREP_DEFAULT, parseError, status); + if(*status == U_BUFFER_OVERFLOW_ERROR){ + *status = U_ZERO_ERROR; + b2 = (UChar*) malloc(b2Len * U_SIZEOF_UCHAR); + if(b2== NULL){ + *status = U_MEMORY_ALLOCATION_ERROR; + goto CLEANUP; + } + b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Len, USPREP_DEFAULT, parseError, status); + } + + /* convert the string back to UTF-8 */ + u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status); + if(*status == U_BUFFER_OVERFLOW_ERROR){ + *status = U_ZERO_ERROR; + b3 = (char*) malloc(b3Len); + if(b3== NULL){ + *status = U_MEMORY_ALLOCATION_ERROR; + goto CLEANUP; + } + b3Capacity = b3Len; + u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status); + } + + reqLength = b3Len; + if(dest!=NULL && reqLength <= destCapacity){ + memmove(dest, b3, reqLength); + } + +CLEANUP: + if(b1!=b1Stack){ + free(b1); + } + if(b2!=b2Stack){ + free(b2); + } + if(b3!=b3Stack){ + free(b3); + } + + return u_terminateChars(dest, destCapacity, reqLength, status); +} + +/* sorted array for binary search*/ +static const char* special_prefixes[]={ + "\x0041\x004e\x004f\x004e\x0059\x004d\x004f\x0055\x0053", + "\x0041\x0055\x0054\x0048\x0045\x004e\x0054\x0049\x0043\x0041\x0054\x0045\x0044", + "\x0042\x0041\x0054\x0043\x0048", + "\x0044\x0049\x0041\x004c\x0055\x0050", + "\x0045\x0056\x0045\x0052\x0059\x004f\x004e\x0045", + "\x0047\x0052\x004f\x0055\x0050", + "\x0049\x004e\x0054\x0045\x0052\x0041\x0043\x0054\x0049\x0056\x0045", + "\x004e\x0045\x0054\x0057\x004f\x0052\x004b", + "\x004f\x0057\x004e\x0045\x0052", +}; + + +/* binary search the sorted array */ +static int +findStringIndex(const char* const *sortedArr, int32_t sortedArrLen, const char* target, int32_t targetLen){ + + int left, middle, right,rc; + + left =0; + right= sortedArrLen-1; + + while(left <= right){ + middle = (left+right)/2; + rc=strncmp(sortedArr[middle],target, targetLen); + + if(rc<0){ + left = middle+1; + }else if(rc >0){ + right = middle -1; + }else{ + return middle; + } + } + return -1; +} + +static void +getPrefixSuffix(const char *src, int32_t srcLength, + const char **prefix, int32_t *prefixLen, + const char **suffix, int32_t *suffixLen, + UErrorCode *status){ + + int32_t i=0; + *prefix = src; + while(i<srcLength){ + if(src[i] == PREFIX_SUFFIX_SEPARATOR){ + if((i+1) == srcLength){ + /* we reached the end of the string */ + *suffix = NULL; + i++; + break; + } + i++;/* the prefix contains the separator */ + *suffix = src + i; + break; + } + i++; + } + *prefixLen = i; + *suffixLen = srcLength - i; + /* special prefixes must not be followed by suffixes! */ + if((findStringIndex(special_prefixes,LENGTHOF(special_prefixes), *prefix, *prefixLen-1) != -1) && (*suffix != NULL)){ + *status = U_PARSE_ERROR; + return; + } + +} + +int32_t +nfs4_mixed_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UParseError* parseError, + UErrorCode* status){ + + const char *prefix = NULL, *suffix = NULL; + int32_t prefixLen=0, suffixLen=0; + char pStack[NFS4_MAX_BUFFER_SIZE], + sStack[NFS4_MAX_BUFFER_SIZE]; + char *p=pStack, *s=sStack; + int32_t pLen=0, sLen=0, reqLen=0, + pCapacity = NFS4_MAX_BUFFER_SIZE, + sCapacity = NFS4_MAX_BUFFER_SIZE; + + + if(status==NULL || U_FAILURE(*status)){ + return 0; + } + if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + if(srcLength == -1){ + srcLength = (int32_t)strlen(src); + } + getPrefixSuffix(src, srcLength, &prefix, &prefixLen, &suffix, &suffixLen, status); + + /* prepare the prefix */ + pLen = nfs4_prepare(prefix, prefixLen, p, pCapacity, NFS4_MIXED_PREP_PREFIX, parseError, status); + if(*status == U_BUFFER_OVERFLOW_ERROR){ + *status = U_ZERO_ERROR; + p = (char*) malloc(pLen); + if(p == NULL){ + *status = U_MEMORY_ALLOCATION_ERROR; + goto CLEANUP; + } + pLen = nfs4_prepare(prefix, prefixLen, p, pLen, NFS4_MIXED_PREP_PREFIX, parseError, status); + } + + /* prepare the suffix */ + if(suffix != NULL){ + sLen = nfs4_prepare(suffix, suffixLen, s, sCapacity, NFS4_MIXED_PREP_SUFFIX, parseError, status); + if(*status == U_BUFFER_OVERFLOW_ERROR){ + *status = U_ZERO_ERROR; + s = (char*) malloc(pLen); + if(s == NULL){ + *status = U_MEMORY_ALLOCATION_ERROR; + goto CLEANUP; + } + sLen = nfs4_prepare(suffix, suffixLen, s, sLen, NFS4_MIXED_PREP_SUFFIX, parseError, status); + } + } + reqLen = pLen+sLen+1 /* for the delimiter */; + if(dest != NULL && reqLen <= destCapacity){ + memmove(dest, p, pLen); + /* add the suffix */ + if(suffix!=NULL){ + dest[pLen++] = PREFIX_SUFFIX_SEPARATOR; + memmove(dest+pLen, s, sLen); + } + } + +CLEANUP: + if(p != pStack){ + free(p); + } + if(s != sStack){ + free(s); + } + + return u_terminateChars(dest, destCapacity, reqLen, status); +} + +int32_t +nfs4_cis_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UParseError* parseError, + UErrorCode* status){ + return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CIS_PREP, parseError, status); +} + + +int32_t +nfs4_cs_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UBool isCaseSensitive, + UParseError* parseError, + UErrorCode* status){ + if(isCaseSensitive){ + return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CS, parseError, status); + }else{ + return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CI, parseError, status); + } +} + +#endif +/* + * Hey, Emacs, please set the following: + * + * Local Variables: + * indent-tabs-mode: nil + * End: + * + */ + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h new file mode 100644 index 00000000000..fe3e63d5429 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h @@ -0,0 +1,113 @@ +/* + ******************************************************************************* + * + * Copyright (C) 2003, International Business Machines + * Corporation and others. All Rights Reserved. + * + ******************************************************************************* + * file name: nfsprep.h + * encoding: US-ASCII + * tab size: 8 (not used) + * indentation:4 + * + * created on: 2003jul11 + * created by: Ram Viswanadha + */ +#ifndef _NFSPREP_H +#define _NFSPREP_H + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_IDNA + +#include "unicode/ustring.h" +#include "unicode/usprep.h" +#include <stdlib.h> +#include <string.h> + + +/* this enum must be kept in syn with NFS4DataFileNames array in nfsprep.c */ +enum NFS4ProfileState{ + NFS4_CS_PREP_CS, + NFS4_CS_PREP_CI, + NFS4_CIS_PREP, + NFS4_MIXED_PREP_PREFIX, + NFS4_MIXED_PREP_SUFFIX +}; + +typedef enum NFS4ProfileState NFS4ProfileState; + +/** + * Prepares the source UTF-8 string for use in file names and + * returns UTF-8 string on output. + * @param src + * @param srcLen + * @param dest + * @param destCapacity + * @param state + * @param parseError + * @param status + */ +int32_t +nfs4_prepare(const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + NFS4ProfileState state, + UParseError* parseError, + UErrorCode* status); + +/** + * @param dest + * @param destCapacity + * @param src + * @param srcLen + * @param state + * @param parseError + * @param status + */ +int32_t +nfs4_mixed_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UParseError* parseError, + UErrorCode* status); + +/** + * @param dest + * @param destCapacity + * @param src + * @param srcLen + * @param state + * @param parseError + * @param status + */ +int32_t +nfs4_cis_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UParseError* parseError, + UErrorCode* status); + +/** + * @param dest + * @param destCapacity + * @param src + * @param srcLen + * @param state + * @param parseError + * @param status + */ +int32_t +nfs4_cs_prepare( const char* src, int32_t srcLength, + char* dest, int32_t destCapacity, + UBool isCaseSensitive, + UParseError* parseError, + UErrorCode* status); +#endif + +#endif +/* + * Hey, Emacs, please set the following: + * + * Local Variables: + * indent-tabs-mode: nil + * End: + * + */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c new file mode 100644 index 00000000000..bdd84eb0023 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c @@ -0,0 +1,5369 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************* +* +* File CCONVTST.C +* +* Modification History: +* Name Description +* Steven R. Loomis 7/8/1999 Adding input buffer test +******************************************************************************** +*/ +#include <stdio.h> +#include "cstring.h" +#include "unicode/uloc.h" +#include "unicode/ucnv.h" +#include "unicode/ucnv_err.h" +#include "cintltst.h" +#include "unicode/utypes.h" +#include "unicode/ustring.h" +#include "unicode/ucol.h" +#include "cmemory.h" + +static void TestNextUChar(UConverter* cnv, const char* source, const char* limit, const int32_t results[], const char* message); +static void TestNextUCharError(UConverter* cnv, const char* source, const char* limit, UErrorCode expected, const char* message); +#if !UCONFIG_NO_COLLATION +static void TestJitterbug981(void); +#endif +static void TestJitterbug1293(void); +static void TestNewConvertWithBufferSizes(int32_t osize, int32_t isize) ; +static void TestConverterTypesAndStarters(void); +static void TestAmbiguous(void); +static void TestSignatureDetection(void); +static void TestUTF7(void); +static void TestIMAP(void); +static void TestUTF8(void); +static void TestCESU8(void); +static void TestUTF16(void); +static void TestUTF16BE(void); +static void TestUTF16LE(void); +static void TestUTF32(void); +static void TestUTF32BE(void); +static void TestUTF32LE(void); +static void TestLATIN1(void); + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestSBCS(void); +static void TestDBCS(void); +static void TestMBCS(void); + +#ifdef U_ENABLE_GENERIC_ISO_2022 +static void TestISO_2022(void); +#endif + +static void TestISO_2022_JP(void); +static void TestISO_2022_JP_1(void); +static void TestISO_2022_JP_2(void); +static void TestISO_2022_KR(void); +static void TestISO_2022_KR_1(void); +static void TestISO_2022_CN(void); +static void TestISO_2022_CN_EXT(void); +static void TestJIS(void); +static void TestHZ(void); +#endif + +static void TestSCSU(void); + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestEBCDIC_STATEFUL(void); +static void TestGB18030(void); +static void TestLMBCS(void); +static void TestJitterbug255(void); +static void TestEBCDICUS4XML(void); +static void TestJitterbug915(void); +static void TestISCII(void); + +static void TestCoverageMBCS(void); +static void TestJitterbug2346(void); +static void TestJitterbug2411(void); +static void TestJB5275(void); +static void TestJB5275_1(void); +#endif + +static void TestRoundTrippingAllUTF(void); +static void TestConv(const uint16_t in[], + int len, + const char* conv, + const char* lang, + char byteArr[], + int byteArrLen); +void addTestNewConvert(TestNode** root); + +/* open a converter, using test data if it begins with '@' */ +static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err); + + +#define NEW_MAX_BUFFER 999 + +static int32_t gInBufferSize = NEW_MAX_BUFFER; +static int32_t gOutBufferSize = NEW_MAX_BUFFER; +static char gNuConvTestName[1024]; + +#define nct_min(x,y) ((x<y) ? x : y) + +static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err) +{ + if(cnv && cnv[0] == '@') { + return ucnv_openPackage(loadTestData(err), cnv+1, err); + } else { + return ucnv_open(cnv, err); + } +} + +static void printSeq(const unsigned char* a, int len) +{ + int i=0; + log_verbose("{"); + while (i<len) + log_verbose("0x%02x ", a[i++]); + log_verbose("}\n"); +} + +static void printUSeq(const UChar* a, int len) +{ + int i=0; + log_verbose("{U+"); + while (i<len) log_verbose("0x%04x ", a[i++]); + log_verbose("}\n"); +} + +static void printSeqErr(const unsigned char* a, int len) +{ + int i=0; + fprintf(stderr, "{"); + while (i<len) + fprintf(stderr, "0x%02x ", a[i++]); + fprintf(stderr, "}\n"); +} + +static void printUSeqErr(const UChar* a, int len) +{ + int i=0; + fprintf(stderr, "{U+"); + while (i<len) + fprintf(stderr, "0x%04x ", a[i++]); + fprintf(stderr,"}\n"); +} + +static void +TestNextUChar(UConverter* cnv, const char* source, const char* limit, const int32_t results[], const char* message) +{ + const char* s0; + const char* s=(char*)source; + const int32_t *r=results; + UErrorCode errorCode=U_ZERO_ERROR; + UChar32 c; + + while(s<limit) { + s0=s; + c=ucnv_getNextUChar(cnv, &s, limit, &errorCode); + if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) { + break; /* no more significant input */ + } else if(U_FAILURE(errorCode)) { + log_err("%s ucnv_getNextUChar() failed: %s\n", message, u_errorName(errorCode)); + break; + } else if( + /* test the expected number of input bytes only if >=0 */ + (*r>=0 && (int32_t)(s-s0)!=*r) || + c!=*(r+1) + ) { + log_err("%s ucnv_getNextUChar() result %lx from %d bytes, should have been %lx from %d bytes.\n", + message, c, (s-s0), *(r+1), *r); + break; + } + r+=2; + } +} + +static void +TestNextUCharError(UConverter* cnv, const char* source, const char* limit, UErrorCode expected, const char* message) +{ + const char* s=(char*)source; + UErrorCode errorCode=U_ZERO_ERROR; + uint32_t c; + c=ucnv_getNextUChar(cnv, &s, limit, &errorCode); + if(errorCode != expected){ + log_err("FAIL: Expected:%s when %s-----Got:%s\n", myErrorName(expected), message, myErrorName(errorCode)); + } + if(c != 0xFFFD && c != 0xffff){ + log_err("FAIL: Expected return value of 0xfffd or 0xffff when %s-----Got 0x%lx\n", message, c); + } + +} + +static void TestInBufSizes(void) +{ + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,1); +#if 1 + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,2); + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,3); + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,4); + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,5); + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,6); + TestNewConvertWithBufferSizes(1,1); + TestNewConvertWithBufferSizes(2,3); + TestNewConvertWithBufferSizes(3,2); +#endif +} + +static void TestOutBufSizes(void) +{ +#if 1 + TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,NEW_MAX_BUFFER); + TestNewConvertWithBufferSizes(1,NEW_MAX_BUFFER); + TestNewConvertWithBufferSizes(2,NEW_MAX_BUFFER); + TestNewConvertWithBufferSizes(3,NEW_MAX_BUFFER); + TestNewConvertWithBufferSizes(4,NEW_MAX_BUFFER); + TestNewConvertWithBufferSizes(5,NEW_MAX_BUFFER); + +#endif +} + + +void addTestNewConvert(TestNode** root) +{ + addTest(root, &TestInBufSizes, "tsconv/nucnvtst/TestInBufSizes"); + addTest(root, &TestOutBufSizes, "tsconv/nucnvtst/TestOutBufSizes"); + addTest(root, &TestConverterTypesAndStarters, "tsconv/nucnvtst/TestConverterTypesAndStarters"); + addTest(root, &TestAmbiguous, "tsconv/nucnvtst/TestAmbiguous"); + addTest(root, &TestSignatureDetection, "tsconv/nucnvtst/TestSignatureDetection"); + addTest(root, &TestUTF7, "tsconv/nucnvtst/TestUTF7"); + addTest(root, &TestIMAP, "tsconv/nucnvtst/TestIMAP"); + addTest(root, &TestUTF8, "tsconv/nucnvtst/TestUTF8"); + + /* test ucnv_getNextUChar() for charsets that encode single surrogates with complete byte sequences */ + addTest(root, &TestCESU8, "tsconv/nucnvtst/TestCESU8"); + addTest(root, &TestUTF16, "tsconv/nucnvtst/TestUTF16"); + addTest(root, &TestUTF16BE, "tsconv/nucnvtst/TestUTF16BE"); + addTest(root, &TestUTF16LE, "tsconv/nucnvtst/TestUTF16LE"); + addTest(root, &TestUTF32, "tsconv/nucnvtst/TestUTF32"); + addTest(root, &TestUTF32BE, "tsconv/nucnvtst/TestUTF32BE"); + addTest(root, &TestUTF32LE, "tsconv/nucnvtst/TestUTF32LE"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestLMBCS, "tsconv/nucnvtst/TestLMBCS"); +#endif + + addTest(root, &TestLATIN1, "tsconv/nucnvtst/TestLATIN1"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestSBCS, "tsconv/nucnvtst/TestSBCS"); + addTest(root, &TestDBCS, "tsconv/nucnvtst/TestDBCS"); + addTest(root, &TestMBCS, "tsconv/nucnvtst/TestMBCS"); + +#ifdef U_ENABLE_GENERIC_ISO_2022 + addTest(root, &TestISO_2022, "tsconv/nucnvtst/TestISO_2022"); +#endif + + addTest(root, &TestISO_2022_JP, "tsconv/nucnvtst/TestISO_2022_JP"); + addTest(root, &TestJIS, "tsconv/nucnvtst/TestJIS"); + addTest(root, &TestISO_2022_JP_1, "tsconv/nucnvtst/TestISO_2022_JP_1"); + addTest(root, &TestISO_2022_JP_2, "tsconv/nucnvtst/TestISO_2022_JP_2"); + addTest(root, &TestISO_2022_KR, "tsconv/nucnvtst/TestISO_2022_KR"); + addTest(root, &TestISO_2022_KR_1, "tsconv/nucnvtst/TestISO_2022_KR_1"); + addTest(root, &TestISO_2022_CN, "tsconv/nucnvtst/TestISO_2022_CN"); + addTest(root, &TestISO_2022_CN_EXT, "tsconv/nucnvtst/TestISO_2022_CN_EXT"); + addTest(root, &TestJitterbug915, "tsconv/nucnvtst/TestJitterbug915"); + addTest(root, &TestHZ, "tsconv/nucnvtst/TestHZ"); +#endif + + addTest(root, &TestSCSU, "tsconv/nucnvtst/TestSCSU"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestEBCDIC_STATEFUL, "tsconv/nucnvtst/TestEBCDIC_STATEFUL"); + addTest(root, &TestGB18030, "tsconv/nucnvtst/TestGB18030"); + addTest(root, &TestJitterbug255, "tsconv/nucnvtst/TestJitterbug255"); + addTest(root, &TestEBCDICUS4XML, "tsconv/nucnvtst/TestEBCDICUS4XML"); + addTest(root, &TestISCII, "tsconv/nucnvtst/TestISCII"); + addTest(root, &TestJB5275, "tsconv/nucnvtst/TestJB5275"); + addTest(root, &TestJB5275_1, "tsconv/nucnvtst/TestJB5275_1"); +#if !UCONFIG_NO_COLLATION + addTest(root, &TestJitterbug981, "tsconv/nucnvtst/TestJitterbug981"); +#endif + + addTest(root, &TestJitterbug1293, "tsconv/nucnvtst/TestJitterbug1293"); +#endif + + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestCoverageMBCS, "tsconv/nucnvtst/TestCoverageMBCS"); +#endif + + addTest(root, &TestRoundTrippingAllUTF, "tsconv/nucnvtst/TestRoundTrippingAllUTF"); + +#if !UCONFIG_NO_LEGACY_CONVERSION + addTest(root, &TestJitterbug2346, "tsconv/nucnvtst/TestJitterbug2346"); + addTest(root, &TestJitterbug2411, "tsconv/nucnvtst/TestJitterbug2411"); +#endif + +} + + +/* Note that this test already makes use of statics, so it's not really + multithread safe. + This convenience function lets us make the error messages actually useful. +*/ + +static void setNuConvTestName(const char *codepage, const char *direction) +{ + sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]", + codepage, + direction, + (int)gInBufferSize, + (int)gOutBufferSize); +} + +typedef enum +{ + TC_OK = 0, /* test was OK */ + TC_MISMATCH = 1, /* Match failed - err was printed */ + TC_FAIL = 2 /* Test failed, don't print an err because it was already printed. */ +} ETestConvertResult; + +/* Note: This function uses global variables and it will not do offset +checking without gOutBufferSize and gInBufferSize set to NEW_MAX_BUFFER */ +static ETestConvertResult testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen, + const char *codepage, const int32_t *expectOffsets , UBool useFallback) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + char junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + char *p; + const UChar *src; + char *end; + char *targ; + int32_t *offs; + int i; + int32_t realBufferSize; + char *realBufferEnd; + const UChar *realSourceEnd; + const UChar *sourceLimit; + UBool checkOffsets = TRUE; + UBool doFlush; + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = (char)0xF0; + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = 0xFF; + + setNuConvTestName(codepage, "FROM"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = my_ucnv_open(codepage, &status); + + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",codepage); + return TC_FAIL; + } + if(useFallback){ + ucnv_setFallback(conv,useFallback); + } + + log_verbose("Converter opened..\n"); + + src = source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = source + sourceLen; + + if ( gOutBufferSize != realBufferSize || gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min(targ + gOutBufferSize, realBufferEnd); + sourceLimit = nct_min(src + gInBufferSize, realSourceEnd); + + doFlush = (UBool)(sourceLimit == realSourceEnd); + + if(targ == realBufferEnd) { + log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName); + return TC_FAIL; + } + log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE"); + + + status = U_ZERO_ERROR; + + ucnv_fromUnicode (conv, + &targ, + end, + &src, + sourceLimit, + checkOffsets ? offs : NULL, + doFlush, /* flush if we're at the end of the input data */ + &status); + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && sourceLimit < realSourceEnd) ); + + if(U_FAILURE(status)) { + log_err("Problem doing fromUnicode to %s, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName); + return TC_FAIL; + } + + log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :", + sourceLen, targ-junkout); + + if(VERBOSITY) + { + char junk[9999]; + char offset_str[9999]; + char *ptr; + + junk[0] = 0; + offset_str[0] = 0; + for(ptr = junkout;ptr<targ;ptr++) { + sprintf(junk + strlen(junk), "0x%02x, ", (int)(0xFF & *ptr)); + sprintf(offset_str + strlen(offset_str), "0x%02x, ", (int)(0xFF & junokout[ptr-junkout])); + } + + log_verbose(junk); + printSeq((const uint8_t *)expect, expectLen); + if ( checkOffsets ) { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + if(expectLen != targ-junkout) { + log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName); + printf("\nGot:"); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + printf("\nExpected:"); + printSeqErr((const unsigned char*)expect, expectLen); + return TC_MISMATCH; + } + + if (checkOffsets && (expectOffsets != 0) ) { + log_verbose("comparing %d offsets..\n", targ-junkout); + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){ + log_err("did not get the expected offsets. %s\n", gNuConvTestName); + printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout)); + log_err("\n"); + log_err("Got : "); + for(p=junkout;p<targ;p++) { + log_err("%d,", junokout[p-junkout]); + } + log_err("\n"); + log_err("Expected: "); + for(i=0; i<(targ-junkout); i++) { + log_err("%d,", expectOffsets[i]); + } + log_err("\n"); + } + } + + log_verbose("comparing..\n"); + if(!memcmp(junkout, expect, expectLen)) { + log_verbose("Matches!\n"); + return TC_OK; + } else { + log_err("String does not match u->%s\n", gNuConvTestName); + printUSeqErr(source, sourceLen); + printf("\nGot:"); + printSeqErr((const unsigned char *)junkout, expectLen); + printf("\nExpected:"); + printSeqErr((const unsigned char *)expect, expectLen); + + return TC_MISMATCH; + } +} + +/* Note: This function uses global variables and it will not do offset +checking without gOutBufferSize and gInBufferSize set to NEW_MAX_BUFFER */ +static ETestConvertResult testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen, + const char *codepage, const int32_t *expectOffsets, UBool useFallback) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *conv = 0; + UChar junkout[NEW_MAX_BUFFER]; /* FIX */ + int32_t junokout[NEW_MAX_BUFFER]; /* FIX */ + const char *src; + const char *realSourceEnd; + const char *srcLimit; + UChar *p; + UChar *targ; + UChar *end; + int32_t *offs; + int i; + UBool checkOffsets = TRUE; + + int32_t realBufferSize; + UChar *realBufferEnd; + + + for(i=0;i<NEW_MAX_BUFFER;i++) + junkout[i] = 0xFFFE; + + for(i=0;i<NEW_MAX_BUFFER;i++) + junokout[i] = -1; + + setNuConvTestName(codepage, "TO"); + + log_verbose("\n========= %s\n", gNuConvTestName); + + conv = my_ucnv_open(codepage, &status); + + if(U_FAILURE(status)) + { + log_data_err("Couldn't open converter %s\n",gNuConvTestName); + return TC_FAIL; + } + if(useFallback){ + ucnv_setFallback(conv,useFallback); + } + log_verbose("Converter opened..\n"); + + src = (const char *)source; + targ = junkout; + offs = junokout; + + realBufferSize = (sizeof(junkout)/sizeof(junkout[0])); + realBufferEnd = junkout + realBufferSize; + realSourceEnd = src + sourcelen; + + if ( gOutBufferSize != realBufferSize || gInBufferSize != NEW_MAX_BUFFER ) + checkOffsets = FALSE; + + do + { + end = nct_min( targ + gOutBufferSize, realBufferEnd); + srcLimit = nct_min(realSourceEnd, src + gInBufferSize); + + if(targ == realBufferEnd) + { + log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjet=%08lx %s",targ,gNuConvTestName); + return TC_FAIL; + } + log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end); + + /* oldTarg = targ; */ + + status = U_ZERO_ERROR; + + ucnv_toUnicode (conv, + &targ, + end, + &src, + srcLimit, + checkOffsets ? offs : NULL, + (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of hte source data */ + &status); + + /* offs += (targ-oldTarg); */ + + } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */ + + if(U_FAILURE(status)) + { + log_err("Problem doing %s toUnicode, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName); + return TC_FAIL; + } + + log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :", + sourcelen, targ-junkout); + if(VERBOSITY) + { + char junk[9999]; + char offset_str[9999]; + UChar *ptr; + + junk[0] = 0; + offset_str[0] = 0; + + for(ptr = junkout;ptr<targ;ptr++) + { + sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*ptr); + sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[ptr-junkout]); + } + + log_verbose(junk); + printUSeq(expect, expectlen); + if ( checkOffsets ) + { + log_verbose("\nOffsets:"); + log_verbose(offset_str); + } + log_verbose("\n"); + } + ucnv_close(conv); + + log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2); + + if (checkOffsets && (expectOffsets != 0)) + { + if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))){ + log_err("did not get the expected offsets. %s\n",gNuConvTestName); + log_err("Got: "); + for(p=junkout;p<targ;p++) { + log_err("%d,", junokout[p-junkout]); + } + log_err("\n"); + log_err("Expected: "); + for(i=0; i<(targ-junkout); i++) { + log_err("%d,", expectOffsets[i]); + } + log_err("\n"); + log_err("output: "); + for(i=0; i<(targ-junkout); i++) { + log_err("%X,", junkout[i]); + } + log_err("\n"); + log_err("input: "); + for(i=0; i<(src-(const char *)source); i++) { + log_err("%X,", (unsigned char)source[i]); + } + log_err("\n"); + } + } + + if(!memcmp(junkout, expect, expectlen*2)) + { + log_verbose("Matches!\n"); + return TC_OK; + } + else + { + log_err("String does not match. %s\n", gNuConvTestName); + log_verbose("String does not match. %s\n", gNuConvTestName); + printf("\nGot:"); + printUSeqErr(junkout, expectlen); + printf("\nExpected:"); + printUSeqErr(expect, expectlen); + return TC_MISMATCH; + } +} + + +static void TestNewConvertWithBufferSizes(int32_t outsize, int32_t insize ) +{ +/** test chars #1 */ + /* 1 2 3 1Han 2Han 3Han . */ + static const UChar sampleText[] = + { 0x0031, 0x0032, 0x0033, 0x0000, 0x4e00, 0x4e8c, 0x4e09, 0x002E }; + + + static const uint8_t expectedUTF8[] = + { 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E }; + static const int32_t toUTF8Offs[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07}; + static const int32_t fmUTF8Offs[] = + { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, 0x000d }; + +#ifdef U_ENABLE_GENERIC_ISO_2022 + /* Same as UTF8, but with ^[%B preceeding */ + static const const uint8_t expectedISO2022[] = + { 0x1b, 0x25, 0x42, 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E }; + static const int32_t toISO2022Offs[] = + { -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07 }; /* right? */ + static const int32_t fmISO2022Offs[] = + { 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x000a, 0x000d, 0x0010 }; /* is this right? */ +#endif + + /* 1 2 3 0, <SO> h1 h2 h3 <SI> . EBCDIC_STATEFUL */ + static const uint8_t expectedIBM930[] = + { 0xF1, 0xF2, 0xF3, 0x00, 0x0E, 0x45, 0x41, 0x45, 0x42, 0x45, 0x43, 0x0F, 0x4B }; + static const int32_t toIBM930Offs[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, }; + static const int32_t fmIBM930Offs[] = + { 0x0000, 0x0001, 0x0002, 0x0003, 0x0005, 0x0007, 0x0009, 0x000c}; + + /* 1 2 3 0 h1 h2 h3 . MBCS*/ + static const uint8_t expectedIBM943[] = + { 0x31, 0x32, 0x33, 0x00, 0x88, 0xea, 0x93, 0xf1, 0x8e, 0x4f, 0x2e }; + static const int32_t toIBM943Offs [] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07 }; + static const int32_t fmIBM943Offs[] = + { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0006, 0x0008, 0x000a}; + + /* 1 2 3 0 h1 h2 h3 . DBCS*/ + static const uint8_t expectedIBM9027[] = + { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x4c, 0x41, 0x4c, 0x48, 0x4c, 0x55, 0xfe, 0xfe}; + static const int32_t toIBM9027Offs [] = + { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07}; + + /* 1 2 3 0 <?> <?> <?> . SBCS*/ + static const uint8_t expectedIBM920[] = + { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2e }; + static const int32_t toIBM920Offs [] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + + /* 1 2 3 0 <?> <?> <?> . SBCS*/ + static const uint8_t expectedISO88593[] = + { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2E }; + static const int32_t toISO88593Offs[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + + /* 1 2 3 0 <?> <?> <?> . <?> LATIN_1*/ + static const uint8_t expectedLATIN1[] = + { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2E }; + static const int32_t toLATIN1Offs[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + + + /* etc */ + static const uint8_t expectedUTF16BE[] = + { 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x4e, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x00, 0x2e }; + static const int32_t toUTF16BEOffs[]= + { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07}; + static const int32_t fmUTF16BEOffs[] = + { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e }; + + static const uint8_t expectedUTF16LE[] = + { 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x4e, 0x2e, 0x00 }; + static const int32_t toUTF16LEOffs[]= + { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07}; + static const int32_t fmUTF16LEOffs[] = + { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e }; + + static const uint8_t expectedUTF32BE[] = + { 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x33, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x4e, 0x8c, + 0x00, 0x00, 0x4e, 0x09, + 0x00, 0x00, 0x00, 0x2e }; + static const int32_t toUTF32BEOffs[]= + { 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08 }; + static const int32_t fmUTF32BEOffs[] = + { 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c }; + + static const uint8_t expectedUTF32LE[] = + { 0x31, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4e, 0x00, 0x00, + 0x8c, 0x4e, 0x00, 0x00, + 0x09, 0x4e, 0x00, 0x00, + 0x2e, 0x00, 0x00, 0x00 }; + static const int32_t toUTF32LEOffs[]= + { 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08 }; + static const int32_t fmUTF32LEOffs[] = + { 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c }; + + + + +/** Test chars #2 **/ + + /* Sahha [health], slashed h's */ + static const UChar malteseUChars[] = { 0x0053, 0x0061, 0x0127, 0x0127, 0x0061 }; + static const uint8_t expectedMaltese913[] = { 0x53, 0x61, 0xB1, 0xB1, 0x61 }; + + /* LMBCS */ + static const UChar LMBCSUChars[] = { 0x0027, 0x010A, 0x0000, 0x0127, 0x2666, 0x0220 }; + static const uint8_t expectedLMBCS[] = { 0x27, 0x06, 0x04, 0x00, 0x01, 0x73, 0x01, 0x04, 0x14, 0x02, 0x20 }; + static const int32_t toLMBCSOffs[] = { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x04 , 0x05, 0x05, 0x05 }; + static const int32_t fmLMBCSOffs[] = { 0x0000, 0x0001, 0x0003, 0x0004, 0x0006, 0x0008}; + /*********************************** START OF CODE finally *************/ + + gInBufferSize = insize; + gOutBufferSize = outsize; + + log_verbose("\n\n\nTesting conversions with InputBufferSize = %d, OutputBufferSize = %d\n", gInBufferSize, gOutBufferSize); + + + /*UTF-8*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF8, sizeof(expectedUTF8), "UTF8", toUTF8Offs,FALSE ); + + log_verbose("Test surrogate behaviour for UTF8\n"); + { + static const UChar testinput[]={ 0x20ac, 0xd801, 0xdc01, 0xdc01 }; + static const uint8_t expectedUTF8test2[]= { 0xe2, 0x82, 0xac, + 0xf0, 0x90, 0x90, 0x81, + 0xef, 0xbf, 0xbd + }; + static const int32_t offsets[]={ 0, 0, 0, 1, 1, 1, 1, 3, 3, 3 }; + testConvertFromU(testinput, sizeof(testinput)/sizeof(testinput[0]), + expectedUTF8test2, sizeof(expectedUTF8test2), "UTF8", offsets,FALSE ); + + + } + +#if !UCONFIG_NO_LEGACY_CONVERSION && defined(U_ENABLE_GENERIC_ISO_2022) + /*ISO-2022*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedISO2022, sizeof(expectedISO2022), "ISO_2022", toISO2022Offs,FALSE ); +#endif + + /*UTF16 LE*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF16LE, sizeof(expectedUTF16LE), "utf-16le", toUTF16LEOffs,FALSE ); + /*UTF16 BE*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF16BE, sizeof(expectedUTF16BE), "utf-16be", toUTF16BEOffs,FALSE ); + /*UTF32 LE*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF32LE, sizeof(expectedUTF32LE), "utf-32le", toUTF32LEOffs,FALSE ); + /*UTF32 BE*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedUTF32BE, sizeof(expectedUTF32BE), "utf-32be", toUTF32BEOffs,FALSE ); + + /*LATIN_1*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedLATIN1, sizeof(expectedLATIN1), "LATIN_1", toLATIN1Offs,FALSE ); + +#if !UCONFIG_NO_LEGACY_CONVERSION + /*EBCDIC_STATEFUL*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedIBM930, sizeof(expectedIBM930), "ibm-930", toIBM930Offs,FALSE ); + + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedISO88593, sizeof(expectedISO88593), "iso-8859-3", toISO88593Offs,FALSE ); + + /*MBCS*/ + + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedIBM943, sizeof(expectedIBM943), "ibm-943", toIBM943Offs,FALSE ); + /*DBCS*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedIBM9027, sizeof(expectedIBM9027), "@ibm9027", toIBM9027Offs,FALSE ); + /*SBCS*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedIBM920, sizeof(expectedIBM920), "ibm-920", toIBM920Offs,FALSE ); + /*SBCS*/ + testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]), + expectedISO88593, sizeof(expectedISO88593), "iso-8859-3", toISO88593Offs,FALSE ); +#endif + + +/****/ + + /*UTF-8*/ + testConvertToU(expectedUTF8, sizeof(expectedUTF8), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf8", fmUTF8Offs,FALSE); +#if !UCONFIG_NO_LEGACY_CONVERSION && defined(U_ENABLE_GENERIC_ISO_2022) + /*ISO-2022*/ + testConvertToU(expectedISO2022, sizeof(expectedISO2022), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ISO_2022", fmISO2022Offs,FALSE); +#endif + + /*UTF16 LE*/ + testConvertToU(expectedUTF16LE, sizeof(expectedUTF16LE), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16le", fmUTF16LEOffs,FALSE); + /*UTF16 BE*/ + testConvertToU(expectedUTF16BE, sizeof(expectedUTF16BE), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16be", fmUTF16BEOffs,FALSE); + /*UTF32 LE*/ + testConvertToU(expectedUTF32LE, sizeof(expectedUTF32LE), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-32le", fmUTF32LEOffs,FALSE); + /*UTF32 BE*/ + testConvertToU(expectedUTF32BE, sizeof(expectedUTF32BE), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-32be", fmUTF32BEOffs,FALSE); + +#if !UCONFIG_NO_LEGACY_CONVERSION + /*EBCDIC_STATEFUL*/ + testConvertToU(expectedIBM930, sizeof(expectedIBM930), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ibm-930", fmIBM930Offs,FALSE); + /*MBCS*/ + testConvertToU(expectedIBM943, sizeof(expectedIBM943), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ibm-943", fmIBM943Offs,FALSE); +#endif + + /* Try it again to make sure it still works */ + testConvertToU(expectedUTF16LE, sizeof(expectedUTF16LE), + sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16le", fmUTF16LEOffs,FALSE); + +#if !UCONFIG_NO_LEGACY_CONVERSION + testConvertToU(expectedMaltese913, sizeof(expectedMaltese913), + malteseUChars, sizeof(malteseUChars)/sizeof(malteseUChars[0]), "latin3", NULL,FALSE); + + testConvertFromU(malteseUChars, sizeof(malteseUChars)/sizeof(malteseUChars[0]), + expectedMaltese913, sizeof(expectedMaltese913), "iso-8859-3", NULL,FALSE ); + + /*LMBCS*/ + testConvertFromU(LMBCSUChars, sizeof(LMBCSUChars)/sizeof(LMBCSUChars[0]), + expectedLMBCS, sizeof(expectedLMBCS), "LMBCS-1", toLMBCSOffs,FALSE ); + testConvertToU(expectedLMBCS, sizeof(expectedLMBCS), + LMBCSUChars, sizeof(LMBCSUChars)/sizeof(LMBCSUChars[0]), "LMBCS-1", fmLMBCSOffs,FALSE); +#endif + + /* UTF-7 examples are mostly from http://www.imc.org/rfc2152 */ + { + /* encode directly set D and set O */ + static const uint8_t utf7[] = { + /* + Hi Mom -+Jjo--! + A+ImIDkQ. + +- + +ZeVnLIqe + */ + 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x2b, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x21, + 0x41, 0x2b, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2e, + 0x2b, 0x2d, + 0x2b, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65 + }; + static const UChar unicode[] = { + /* + Hi Mom -<WHITE SMILING FACE>-! + A<NOT IDENTICAL TO><ALPHA>. + + + [Japanese word "nihongo"] + */ + 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x263a, 0x2d, 0x21, + 0x41, 0x2262, 0x0391, 0x2e, + 0x2b, + 0x65e5, 0x672c, 0x8a9e + }; + static const int32_t toUnicodeOffsets[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 14, + 15, 17, 19, 23, + 24, + 27, 29, 32 + }; + static const int32_t fromUnicodeOffsets[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10, + 11, 12, 12, 12, 13, 13, 13, 13, 14, + 15, 15, + 16, 16, 16, 17, 17, 17, 18, 18, 18 + }; + + /* same but escaping set O (the exclamation mark) */ + static const uint8_t utf7Restricted[] = { + /* + Hi Mom -+Jjo--+ACE- + A+ImIDkQ. + +- + +ZeVnLIqe + */ + 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x2b, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x2b, 0x41, 0x43, 0x45, 0x2d, + 0x41, 0x2b, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2e, + 0x2b, 0x2d, + 0x2b, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65 + }; + static const int32_t toUnicodeOffsetsR[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 15, + 19, 21, 23, 27, + 28, + 31, 33, 36 + }; + static const int32_t fromUnicodeOffsetsR[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10, + 11, 12, 12, 12, 13, 13, 13, 13, 14, + 15, 15, + 16, 16, 16, 17, 17, 17, 18, 18, 18 + }; + + testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, utf7, sizeof(utf7), "UTF-7", fromUnicodeOffsets,FALSE); + + testConvertToU(utf7, sizeof(utf7), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "UTF-7", toUnicodeOffsets,FALSE); + + testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, utf7Restricted, sizeof(utf7Restricted), "UTF-7,version=1", fromUnicodeOffsetsR,FALSE); + + testConvertToU(utf7Restricted, sizeof(utf7Restricted), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "UTF-7,version=1", toUnicodeOffsetsR,FALSE); + } + + /* + * IMAP-mailbox-name examples are mostly from http://www.imc.org/rfc2152, + * modified according to RFC 2060, + * and supplemented with the one example in RFC 2060 itself. + */ + { + static const uint8_t imap[] = { + /* Hi Mom -&Jjo--! + A&ImIDkQ-. + &- + &ZeVnLIqe- + \ + ~peter + /mail + /&ZeVnLIqe- + /&U,BTFw- + */ + 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x26, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x21, + 0x41, 0x26, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2d, 0x2e, + 0x26, 0x2d, + 0x26, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65, 0x2d, + 0x5c, + 0x7e, 0x70, 0x65, 0x74, 0x65, 0x72, + 0x2f, 0x6d, 0x61, 0x69, 0x6c, + 0x2f, 0x26, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65, 0x2d, + 0x2f, 0x26, 0x55, 0x2c, 0x42, 0x54, 0x46, 0x77, 0x2d + }; + static const UChar unicode[] = { + /* Hi Mom -<WHITE SMILING FACE>-! + A<NOT IDENTICAL TO><ALPHA>. + & + [Japanese word "nihongo"] + \ + ~peter + /mail + /<65e5, 672c, 8a9e> + /<53f0, 5317> + */ + 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x263a, 0x2d, 0x21, + 0x41, 0x2262, 0x0391, 0x2e, + 0x26, + 0x65e5, 0x672c, 0x8a9e, + 0x5c, + 0x7e, 0x70, 0x65, 0x74, 0x65, 0x72, + 0x2f, 0x6d, 0x61, 0x69, 0x6c, + 0x2f, 0x65e5, 0x672c, 0x8a9e, + 0x2f, 0x53f0, 0x5317 + }; + static const int32_t toUnicodeOffsets[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 14, + 15, 17, 19, 24, + 25, + 28, 30, 33, + 37, + 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, + 49, 51, 53, 56, + 60, 62, 64 + }; + static const int32_t fromUnicodeOffsets[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10, + 11, 12, 12, 12, 13, 13, 13, 13, 13, 14, + 15, 15, + 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, + 19, + 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, + 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34, + 35, 36, 36, 36, 37, 37, 37, 37, 37 + }; + + testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, imap, sizeof(imap), "IMAP-mailbox-name", fromUnicodeOffsets,FALSE); + + testConvertToU(imap, sizeof(imap), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "IMAP-mailbox-name", toUnicodeOffsets,FALSE); + } + + /* Test UTF-8 bad data handling*/ + { + static const uint8_t utf8[]={ + 0x61, + 0xf7, 0xbf, 0xbf, 0xbf, /* > 10FFFF */ + 0x00, + 0x62, + 0xfb, 0xbf, 0xbf, 0xbf, 0xbf, /* > 10FFFF */ + 0xfb, 0xbf, 0xbf, 0xbf, 0xbf, /* > 10FFFF */ + 0xf4, 0x8f, 0xbf, 0xbf, /* 10FFFF */ + 0xdf, 0xbf, /* 7ff */ + 0xbf, /* truncated tail */ + 0xf4, 0x90, 0x80, 0x80, /* 11FFFF */ + 0x02 + }; + + static const uint16_t utf8Expected[]={ + 0x0061, + 0xfffd, + 0x0000, + 0x0062, + 0xfffd, + 0xfffd, + 0xdbff, 0xdfff, + 0x07ff, + 0xfffd, + 0xfffd, + 0x0002 + }; + + static const int32_t utf8Offsets[]={ + 0, 1, 5, 6, 7, 12, 17, 17, 21, 23, 24, 28 + }; + testConvertToU(utf8, sizeof(utf8), + utf8Expected, sizeof(utf8Expected)/sizeof(utf8Expected[0]), "utf-8", utf8Offsets ,FALSE); + + } + + /* Test UTF-32BE bad data handling*/ + { + static const uint8_t utf32[]={ + 0x00, 0x00, 0x00, 0x61, + 0x00, 0x11, 0x00, 0x00, /* 0x110000 out of range */ + 0x00, 0x10, 0xff, 0xff, /* 0x10FFFF in range */ + 0x00, 0x00, 0x00, 0x62, + 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */ + 0x7f, 0xff, 0xff, 0xff, /* 0x7fffffff out of range */ + 0x00, 0x00, 0x01, 0x62, + 0x00, 0x00, 0x02, 0x62 + }; + static const uint16_t utf32Expected[]={ + 0x0061, + 0xfffd, /* 0x110000 out of range */ + 0xDBFF, /* 0x10FFFF in range */ + 0xDFFF, + 0x0062, + 0xfffd, /* 0xffffffff out of range */ + 0xfffd, /* 0x7fffffff out of range */ + 0x0162, + 0x0262 + }; + static const int32_t utf32Offsets[]={ + 0, 4, 8, 8, 12, 16, 20, 24, 28 + }; + static const uint8_t utf32ExpectedBack[]={ + 0x00, 0x00, 0x00, 0x61, + 0x00, 0x00, 0xff, 0xfd, /* 0x110000 out of range */ + 0x00, 0x10, 0xff, 0xff, /* 0x10FFFF in range */ + 0x00, 0x00, 0x00, 0x62, + 0x00, 0x00, 0xff, 0xfd, /* 0xffffffff out of range */ + 0x00, 0x00, 0xff, 0xfd, /* 0x7fffffff out of range */ + 0x00, 0x00, 0x01, 0x62, + 0x00, 0x00, 0x02, 0x62 + }; + static const int32_t utf32OffsetsBack[]={ + 0,0,0,0, + 1,1,1,1, + 2,2,2,2, + 4,4,4,4, + 5,5,5,5, + 6,6,6,6, + 7,7,7,7, + 8,8,8,8 + }; + + testConvertToU(utf32, sizeof(utf32), + utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), "utf-32be", utf32Offsets ,FALSE); + testConvertFromU(utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), + utf32ExpectedBack, sizeof(utf32ExpectedBack), "utf-32be", utf32OffsetsBack, FALSE); + } + + /* Test UTF-32LE bad data handling*/ + { + static const uint8_t utf32[]={ + 0x61, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x00, /* 0x110000 out of range */ + 0xff, 0xff, 0x10, 0x00, /* 0x10FFFF in range */ + 0x62, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */ + 0xff, 0xff, 0xff, 0x7f, /* 0x7fffffff out of range */ + 0x62, 0x01, 0x00, 0x00, + 0x62, 0x02, 0x00, 0x00, + }; + + static const uint16_t utf32Expected[]={ + 0x0061, + 0xfffd, /* 0x110000 out of range */ + 0xDBFF, /* 0x10FFFF in range */ + 0xDFFF, + 0x0062, + 0xfffd, /* 0xffffffff out of range */ + 0xfffd, /* 0x7fffffff out of range */ + 0x0162, + 0x0262 + }; + static const int32_t utf32Offsets[]={ + 0, 4, 8, 8, 12, 16, 20, 24, 28 + }; + static const uint8_t utf32ExpectedBack[]={ + 0x61, 0x00, 0x00, 0x00, + 0xfd, 0xff, 0x00, 0x00, /* 0x110000 out of range */ + 0xff, 0xff, 0x10, 0x00, /* 0x10FFFF in range */ + 0x62, 0x00, 0x00, 0x00, + 0xfd, 0xff, 0x00, 0x00, /* 0xffffffff out of range */ + 0xfd, 0xff, 0x00, 0x00, /* 0x7fffffff out of range */ + 0x62, 0x01, 0x00, 0x00, + 0x62, 0x02, 0x00, 0x00 + }; + static const int32_t utf32OffsetsBack[]={ + 0,0,0,0, + 1,1,1,1, + 2,2,2,2, + 4,4,4,4, + 5,5,5,5, + 6,6,6,6, + 7,7,7,7, + 8,8,8,8 + }; + testConvertToU(utf32, sizeof(utf32), + utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), "utf-32le", utf32Offsets,FALSE ); + testConvertFromU(utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), + utf32ExpectedBack, sizeof(utf32ExpectedBack), "utf-32le", utf32OffsetsBack, FALSE); + } +} + +static void TestCoverageMBCS(){ +#if 0 + UErrorCode status = U_ZERO_ERROR; + const char *directory = loadTestData(&status); + char* tdpath = NULL; + char* saveDirectory = (char*)malloc(sizeof(char) *(strlen(u_getDataDirectory())+1)); + int len = strlen(directory); + char* index=NULL; + + tdpath = (char*) malloc(sizeof(char) * (len * 2)); + uprv_strcpy(saveDirectory,u_getDataDirectory()); + log_verbose("Retrieved data directory %s \n",saveDirectory); + uprv_strcpy(tdpath,directory); + index=strrchr(tdpath,(char)U_FILE_SEP_CHAR); + + if((unsigned int)(index-tdpath) != (strlen(tdpath)-1)){ + *(index+1)=0; + } + u_setDataDirectory(tdpath); + log_verbose("ICU data directory is set to: %s \n" ,tdpath); +#endif + + /*some more test to increase the code coverage in MBCS. Create an test converter from test1.ucm + which is test file for MBCS conversion with single-byte codepage data.*/ + { + + /* MBCS with single byte codepage data test1.ucm*/ + const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0x0003}; + const uint8_t expectedtest1[] = { 0x00, 0x05, 0xff, 0x07, 0xff,}; + int32_t totest1Offs[] = { 0, 1, 2, 3, 5, }; + + /*from Unicode*/ + testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest1, sizeof(expectedtest1), "@test1", totest1Offs,FALSE ); + } + + /*some more test to increase the code coverage in MBCS. Create an test converter from test3.ucm + which is test file for MBCS conversion with three-byte codepage data.*/ + { + + /* MBCS with three byte codepage data test3.ucm*/ + const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0x000e}; + const uint8_t expectedtest3[] = { 0x00, 0x05, 0xff, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a, 0xff,}; + int32_t totest3Offs[] = { 0, 1, 2, 3, 3, 3, 4, 6, 6, 6, 8}; + + const uint8_t test3input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a, 0x01, 0x02, 0x0c,}; + const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; + int32_t fromtest3Offs[] = { 0, 1, 2, 3, 6, 6, 7, 7, 10 }; + + /*from Unicode*/ + testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest3, sizeof(expectedtest3), "@test3", totest3Offs,FALSE ); + + /*to Unicode*/ + testConvertToU(test3input, sizeof(test3input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test3", fromtest3Offs ,FALSE); + + } + + /*some more test to increase the code coverage in MBCS. Create an test converter from test4.ucm + which is test file for MBCS conversion with four-byte codepage data.*/ + { + + /* MBCS with three byte codepage data test4.ucm*/ + static const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0x000e}; + static const uint8_t expectedtest4[] = { 0x00, 0x05, 0xff, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x01, 0x02, 0x03, 0x0a, 0xff,}; + static const int32_t totest4Offs[] = { 0, 1, 2, 3, 3, 3, 3, 4, 6, 6, 6, 6, 8,}; + + static const uint8_t test4input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x02, 0x03, 0x0c,}; + static const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; + static const int32_t fromtest4Offs[] = { 0, 1, 2, 3, 7, 7, 8, 8, 12,}; + + /*from Unicode*/ + testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]), + expectedtest4, sizeof(expectedtest4), "@test4", totest4Offs,FALSE ); + + /*to Unicode*/ + testConvertToU(test4input, sizeof(test4input), + expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test4", fromtest4Offs,FALSE ); + + } +#if 0 + free(tdpath); + /* restore the original data directory */ + log_verbose("Setting the data directory to %s \n", saveDirectory); + u_setDataDirectory(saveDirectory); + free(saveDirectory); +#endif + +} + +static void TestConverterType(const char *convName, UConverterType convType) { + UConverter* myConverter; + UErrorCode err = U_ZERO_ERROR; + + myConverter = my_ucnv_open(convName, &err); + + if (U_FAILURE(err)) { + log_data_err("Failed to create an %s converter\n", convName); + return; + } + else + { + if (ucnv_getType(myConverter)!=convType) { + log_err("ucnv_getType Failed for %s. Got enum value 0x%X\n", + convName, convType); + } + else { + log_verbose("ucnv_getType %s ok\n", convName); + } + } + ucnv_close(myConverter); +} + +static void TestConverterTypesAndStarters() +{ +#if !UCONFIG_NO_LEGACY_CONVERSION + UConverter* myConverter; + UErrorCode err = U_ZERO_ERROR; + UBool mystarters[256]; + +/* const UBool expectedKSCstarters[256] = { + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};*/ + + + log_verbose("Testing KSC, ibm-930, ibm-878 for starters and their conversion types."); + + myConverter = ucnv_open("ksc", &err); + if (U_FAILURE(err)) { + log_data_err("Failed to create an ibm-ksc converter\n"); + return; + } + else + { + if (ucnv_getType(myConverter)!=UCNV_MBCS) + log_err("ucnv_getType Failed for ibm-949\n"); + else + log_verbose("ucnv_getType ibm-949 ok\n"); + + if(myConverter!=NULL) + ucnv_getStarters(myConverter, mystarters, &err); + + /*if (memcmp(expectedKSCstarters, mystarters, sizeof(expectedKSCstarters))) + log_err("Failed ucnv_getStarters for ksc\n"); + else + log_verbose("ucnv_getStarters ok\n");*/ + + } + ucnv_close(myConverter); + + TestConverterType("ibm-930", UCNV_EBCDIC_STATEFUL); + TestConverterType("ibm-878", UCNV_SBCS); +#endif + + TestConverterType("iso-8859-1", UCNV_LATIN_1); + + TestConverterType("ibm-1208", UCNV_UTF8); + + TestConverterType("utf-8", UCNV_UTF8); + TestConverterType("UTF-16BE", UCNV_UTF16_BigEndian); + TestConverterType("UTF-16LE", UCNV_UTF16_LittleEndian); + TestConverterType("UTF-32BE", UCNV_UTF32_BigEndian); + TestConverterType("UTF-32LE", UCNV_UTF32_LittleEndian); + +#if !UCONFIG_NO_LEGACY_CONVERSION + +#if defined(U_ENABLE_GENERIC_ISO_2022) + TestConverterType("iso-2022", UCNV_ISO_2022); +#endif + + TestConverterType("hz", UCNV_HZ); +#endif + + TestConverterType("scsu", UCNV_SCSU); + +#if !UCONFIG_NO_LEGACY_CONVERSION + TestConverterType("x-iscii-de", UCNV_ISCII); +#endif + + TestConverterType("ascii", UCNV_US_ASCII); + TestConverterType("utf-7", UCNV_UTF7); + TestConverterType("IMAP-mailbox-name", UCNV_IMAP_MAILBOX); + TestConverterType("bocu-1", UCNV_BOCU1); +} + +static void +TestAmbiguousConverter(UConverter *cnv) { + static const char inBytes[3]={ 0x61, 0x5B, 0x5c }; + UChar outUnicode[20]={ 0, 0, 0, 0 }; + + const char *s; + UChar *u; + UErrorCode errorCode; + UBool isAmbiguous; + + /* try to convert an 'a', a square bracket and a US-ASCII backslash */ + errorCode=U_ZERO_ERROR; + s=inBytes; + u=outUnicode; + ucnv_toUnicode(cnv, &u, u+20, &s, s+3, NULL, TRUE, &errorCode); + if(U_FAILURE(errorCode)) { + /* we do not care about general failures in this test; the input may just not be mappable */ + return; + } + + if(outUnicode[0]!=0x61 || outUnicode[1]!=0x5B || outUnicode[2]==0xfffd) { + /* not a close ASCII-family encoding, or 0x5c is unassigned/illegal: this test is not applicable */ + /* There are some encodings that are partially ASCII based, + like the ISO-7 and GSM series of codepages, which we ignore. */ + return; + } + + isAmbiguous=ucnv_isAmbiguous(cnv); + + /* check that outUnicode[1]!=0x5c is exactly the same as ucnv_isAmbiguous() */ + if((outUnicode[2]!=0x5c)!=isAmbiguous) { + log_err("error: converter \"%s\" needs a backslash fix: %d but ucnv_isAmbiguous()==%d\n", + ucnv_getName(cnv, &errorCode), outUnicode[2]!=0x5c, isAmbiguous); + return; + } + + if(outUnicode[2]!=0x5c) { + /* needs fixup, fix it */ + ucnv_fixFileSeparator(cnv, outUnicode, (int32_t)(u-outUnicode)); + if(outUnicode[2]!=0x5c) { + /* the fix failed */ + log_err("error: ucnv_fixFileSeparator(%s) failed\n", ucnv_getName(cnv, &errorCode)); + return; + } + } +} + +static void TestAmbiguous() +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *ascii_cnv = 0, *sjis_cnv = 0, *cnv; + static const char target[] = { + /* "\\usr\\local\\share\\data\\icutest.txt" */ + 0x5c, 0x75, 0x73, 0x72, + 0x5c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5c, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x5c, 0x64, 0x61, 0x74, 0x61, + 0x5c, 0x69, 0x63, 0x75, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74, + 0 + }; + UChar asciiResult[200], sjisResult[200]; + int32_t asciiLength = 0, sjisLength = 0, i; + const char *name; + + /* enumerate all converters */ + status=U_ZERO_ERROR; + for(i=0; (name=ucnv_getAvailableName(i))!=NULL; ++i) { + cnv=ucnv_open(name, &status); + if(U_SUCCESS(status)) { + TestAmbiguousConverter(cnv); + ucnv_close(cnv); + } else { + log_err("error: unable to open available converter \"%s\"\n", name); + status=U_ZERO_ERROR; + } + } + +#if !UCONFIG_NO_LEGACY_CONVERSION + sjis_cnv = ucnv_open("ibm-943", &status); + if (U_FAILURE(status)) + { + log_data_err("Failed to create a SJIS converter\n"); + return; + } + ascii_cnv = ucnv_open("LATIN-1", &status); + if (U_FAILURE(status)) + { + log_data_err("Failed to create a LATIN-1 converter\n"); + ucnv_close(sjis_cnv); + return; + } + /* convert target from SJIS to Unicode */ + sjisLength = ucnv_toUChars(sjis_cnv, sjisResult, sizeof(sjisResult)/U_SIZEOF_UCHAR, target, (int32_t)strlen(target), &status); + if (U_FAILURE(status)) + { + log_err("Failed to convert the SJIS string.\n"); + ucnv_close(sjis_cnv); + ucnv_close(ascii_cnv); + return; + } + /* convert target from Latin-1 to Unicode */ + asciiLength = ucnv_toUChars(ascii_cnv, asciiResult, sizeof(asciiResult)/U_SIZEOF_UCHAR, target, (int32_t)strlen(target), &status); + if (U_FAILURE(status)) + { + log_err("Failed to convert the Latin-1 string.\n"); + ucnv_close(sjis_cnv); + ucnv_close(ascii_cnv); + return; + } + if (!ucnv_isAmbiguous(sjis_cnv)) + { + log_err("SJIS converter should contain ambiguous character mappings.\n"); + ucnv_close(sjis_cnv); + ucnv_close(ascii_cnv); + return; + } + if (u_strcmp(sjisResult, asciiResult) == 0) + { + log_err("File separators for SJIS don't need to be fixed.\n"); + } + ucnv_fixFileSeparator(sjis_cnv, sjisResult, sjisLength); + if (u_strcmp(sjisResult, asciiResult) != 0) + { + log_err("Fixing file separator for SJIS failed.\n"); + } + ucnv_close(sjis_cnv); + ucnv_close(ascii_cnv); +#endif +} + +static void +TestSignatureDetection(){ + /* with null terminated strings */ + { + static const char* data[] = { + "\xFE\xFF\x00\x00", /* UTF-16BE */ + "\xFF\xFE\x00\x00", /* UTF-16LE */ + "\xEF\xBB\xBF\x00", /* UTF-8 */ + "\x0E\xFE\xFF\x00", /* SCSU */ + + "\xFE\xFF", /* UTF-16BE */ + "\xFF\xFE", /* UTF-16LE */ + "\xEF\xBB\xBF", /* UTF-8 */ + "\x0E\xFE\xFF", /* SCSU */ + + "\xFE\xFF\x41\x42", /* UTF-16BE */ + "\xFF\xFE\x41\x41", /* UTF-16LE */ + "\xEF\xBB\xBF\x41", /* UTF-8 */ + "\x0E\xFE\xFF\x41", /* SCSU */ + + "\x2B\x2F\x76\x38\x2D", /* UTF-7 */ + "\x2B\x2F\x76\x38\x41", /* UTF-7 */ + "\x2B\x2F\x76\x39\x41", /* UTF-7 */ + "\x2B\x2F\x76\x2B\x41", /* UTF-7 */ + "\x2B\x2F\x76\x2F\x41", /* UTF-7 */ + + "\xDD\x73\x66\x73" /* UTF-EBCDIC */ + }; + static const char* expected[] = { + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + + "UTF-7", + "UTF-7", + "UTF-7", + "UTF-7", + "UTF-7", + "UTF-EBCDIC" + }; + static const int32_t expectedLength[] ={ + 2, + 2, + 3, + 3, + + 2, + 2, + 3, + 3, + + 2, + 2, + 3, + 3, + + 5, + 4, + 4, + 4, + 4, + 4 + }; + int i=0; + UErrorCode err; + int32_t signatureLength = -1; + const char* source = NULL; + const char* enc = NULL; + for( ; i<sizeof(data)/sizeof(char*); i++){ + err = U_ZERO_ERROR; + source = data[i]; + enc = ucnv_detectUnicodeSignature(source, -1 , &signatureLength, &err); + if(U_FAILURE(err)){ + log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i. Error: %s\n", source,i,u_errorName(err)); + continue; + } + if(enc == NULL || strcmp(enc,expected[i]) !=0){ + log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i. Expected: %s. Got: %s\n",source,i,expected[i],enc); + continue; + } + if(signatureLength != expectedLength[i]){ + log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i.Expected Length: %i. Got length: %i\n",source,i,signatureLength,expectedLength[i]); + } + } + } + { + static const char* data[] = { + "\xFE\xFF\x00", /* UTF-16BE */ + "\xFF\xFE\x00", /* UTF-16LE */ + "\xEF\xBB\xBF\x00", /* UTF-8 */ + "\x0E\xFE\xFF\x00", /* SCSU */ + "\x00\x00\xFE\xFF", /* UTF-32BE */ + "\xFF\xFE\x00\x00", /* UTF-32LE */ + "\xFE\xFF", /* UTF-16BE */ + "\xFF\xFE", /* UTF-16LE */ + "\xEF\xBB\xBF", /* UTF-8 */ + "\x0E\xFE\xFF", /* SCSU */ + "\x00\x00\xFE\xFF", /* UTF-32BE */ + "\xFF\xFE\x00\x00", /* UTF-32LE */ + "\xFE\xFF\x41\x42", /* UTF-16BE */ + "\xFF\xFE\x41\x41", /* UTF-16LE */ + "\xEF\xBB\xBF\x41", /* UTF-8 */ + "\x0E\xFE\xFF\x41", /* SCSU */ + "\x00\x00\xFE\xFF\x41", /* UTF-32BE */ + "\xFF\xFE\x00\x00\x42", /* UTF-32LE */ + "\xFB\xEE\x28", /* BOCU-1 */ + "\xFF\x41\x42" /* NULL */ + }; + static const int len[] = { + 3, + 3, + 4, + 4, + 4, + 4, + 2, + 2, + 3, + 3, + 4, + 4, + 4, + 4, + 4, + 4, + 5, + 5, + 3, + 3 + }; + + static const char* expected[] = { + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + "UTF-32BE", + "UTF-32LE", + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + "UTF-32BE", + "UTF-32LE", + "UTF-16BE", + "UTF-16LE", + "UTF-8", + "SCSU", + "UTF-32BE", + "UTF-32LE", + "BOCU-1", + NULL + }; + static const int32_t expectedLength[] ={ + 2, + 2, + 3, + 3, + 4, + 4, + 2, + 2, + 3, + 3, + 4, + 4, + 2, + 2, + 3, + 3, + 4, + 4, + 3, + 0 + }; + int i=0; + UErrorCode err; + int32_t signatureLength = -1; + int32_t sourceLength=-1; + const char* source = NULL; + const char* enc = NULL; + for( ; i<sizeof(data)/sizeof(char*); i++){ + err = U_ZERO_ERROR; + source = data[i]; + sourceLength = len[i]; + enc = ucnv_detectUnicodeSignature(source, sourceLength , &signatureLength, &err); + if(U_FAILURE(err)){ + log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i. Error: %s\n", source,i,u_errorName(err)); + continue; + } + if(enc == NULL || strcmp(enc,expected[i]) !=0){ + if(expected[i] !=NULL){ + log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i. Expected: %s. Got: %s\n",source,i,expected[i],enc); + continue; + } + } + if(signatureLength != expectedLength[i]){ + log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i.Expected Length: %i. Got length: %i\n",source,i,signatureLength,expectedLength[i]); + } + } + } +} + +void +static TestUTF7() { + /* test input */ + static const uint8_t in[]={ + /* H - +Jjo- - ! +- +2AHcAQ */ + 0x48, + 0x2d, + 0x2b, 0x4a, 0x6a, 0x6f, + 0x2d, 0x2d, + 0x21, + 0x2b, 0x2d, + 0x2b, 0x32, 0x41, 0x48, 0x63, 0x41, 0x51 + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x48, + 1, 0x2d, + 4, 0x263a, /* <WHITE SMILING FACE> */ + 2, 0x2d, + 1, 0x21, + 2, 0x2b, + 7, 0x10401 + }; + + const char *cnvName; + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-7", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-7 converter: %s\n", u_errorName(errorCode)); /* sholdn't be a data err */ + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-7"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + cnvName = ucnv_getName(cnv, &errorCode); + if (U_FAILURE(errorCode) || uprv_strcmp(cnvName, "UTF-7") != 0) { + log_err("UTF-7 converter is called %s: %s\n", cnvName, u_errorName(errorCode)); + } + ucnv_close(cnv); +} + +void +static TestIMAP() { + /* test input */ + static const uint8_t in[]={ + /* H - &Jjo- - ! &- &2AHcAQ- \ */ + 0x48, + 0x2d, + 0x26, 0x4a, 0x6a, 0x6f, + 0x2d, 0x2d, + 0x21, + 0x26, 0x2d, + 0x26, 0x32, 0x41, 0x48, 0x63, 0x41, 0x51, 0x2d + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x48, + 1, 0x2d, + 4, 0x263a, /* <WHITE SMILING FACE> */ + 2, 0x2d, + 1, 0x21, + 2, 0x26, + 7, 0x10401 + }; + + const char *cnvName; + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("IMAP-mailbox-name", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a IMAP-mailbox-name converter: %s\n", u_errorName(errorCode)); /* sholdn't be a data err */ + return; + } + TestNextUChar(cnv, source, limit, results, "IMAP-mailbox-name"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + cnvName = ucnv_getName(cnv, &errorCode); + if (U_FAILURE(errorCode) || uprv_strcmp(cnvName, "IMAP-mailbox-name") != 0) { + log_err("IMAP-mailbox-name converter is called %s: %s\n", cnvName, u_errorName(errorCode)); + } + ucnv_close(cnv); +} + +void +static TestUTF8() { + /* test input */ + static const uint8_t in[]={ + 0x61, + 0xc2, 0x80, + 0xe0, 0xa0, 0x80, + 0xf0, 0x90, 0x80, 0x80, + 0xf4, 0x84, 0x8c, 0xa1, + 0xf0, 0x90, 0x90, 0x81 + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x61, + 2, 0x80, + 3, 0x800, + 4, 0x10000, + 4, 0x104321, + 4, 0x10401 + }; + + /* error test input */ + static const uint8_t in2[]={ + 0x61, + 0xc0, 0x80, /* illegal non-shortest form */ + 0xe0, 0x80, 0x80, /* illegal non-shortest form */ + 0xf0, 0x80, 0x80, 0x80, /* illegal non-shortest form */ + 0xc0, 0xc0, /* illegal trail byte */ + 0xf4, 0x90, 0x80, 0x80, /* 0x110000 out of range */ + 0xf8, 0x80, 0x80, 0x80, 0x80, /* too long */ + 0xfe, /* illegal byte altogether */ + 0x62 + }; + + /* expected error test results */ + static const int32_t results2[]={ + /* number of bytes read, code point */ + 1, 0x61, + 22, 0x62 + }; + + UConverterToUCallback cb; + const void *p; + + const char *source=(const char *)in,*limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-8", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-8 converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-8"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + /* test error behavior with a skip callback */ + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode); + source=(const char *)in2; + limit=(const char *)(in2+sizeof(in2)); + TestNextUChar(cnv, source, limit, results2, "UTF-8"); + + ucnv_close(cnv); +} + +void +static TestCESU8() { + /* test input */ + static const uint8_t in[]={ + 0x61, + 0xc2, 0x80, + 0xe0, 0xa0, 0x80, + 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, + 0xed, 0xb0, 0x81, 0xed, 0xa0, 0x82, + 0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf, + 0xef, 0xbf, 0xbc + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x61, + 2, 0x80, + 3, 0x800, + 6, 0x10000, + 3, 0xdc01, + -1,0xd802, /* may read 3 or 6 bytes */ + -1,0x10ffff,/* may read 0 or 3 bytes */ + 3, 0xfffc + }; + + /* error test input */ + static const uint8_t in2[]={ + 0x61, + 0xc0, 0x80, /* illegal non-shortest form */ + 0xe0, 0x80, 0x80, /* illegal non-shortest form */ + 0xf0, 0x80, 0x80, 0x80, /* illegal non-shortest form */ + 0xc0, 0xc0, /* illegal trail byte */ + 0xf0, 0x90, 0x80, 0x80, /* illegal 4-byte supplementary code point */ + 0xf4, 0x84, 0x8c, 0xa1, /* illegal 4-byte supplementary code point */ + 0xf0, 0x90, 0x90, 0x81, /* illegal 4-byte supplementary code point */ + 0xf4, 0x90, 0x80, 0x80, /* 0x110000 out of range */ + 0xf8, 0x80, 0x80, 0x80, 0x80, /* too long */ + 0xfe, /* illegal byte altogether */ + 0x62 + }; + + /* expected error test results */ + static const int32_t results2[]={ + /* number of bytes read, code point */ + 1, 0x61, + 34, 0x62 + }; + + UConverterToUCallback cb; + const void *p; + + const char *source=(const char *)in,*limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("CESU-8", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a CESU-8 converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "CESU-8"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + /* test error behavior with a skip callback */ + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode); + source=(const char *)in2; + limit=(const char *)(in2+sizeof(in2)); + TestNextUChar(cnv, source, limit, results2, "CESU-8"); + + ucnv_close(cnv); +} + +void +static TestUTF16() { + /* test input */ + static const uint8_t in1[]={ + 0xfe, 0xff, 0x4e, 0x00, 0xfe, 0xff + }; + static const uint8_t in2[]={ + 0xff, 0xfe, 0x4e, 0x00, 0xfe, 0xff + }; + static const uint8_t in3[]={ + 0xfe, 0xfe, 0x4e, 0x00, 0xfe, 0xff, 0xd8, 0x40, 0xdc, 0x01 + }; + + /* expected test results */ + static const int32_t results1[]={ + /* number of bytes read, code point */ + 4, 0x4e00, + 2, 0xfeff + }; + static const int32_t results2[]={ + /* number of bytes read, code point */ + 4, 0x004e, + 2, 0xfffe + }; + static const int32_t results3[]={ + /* number of bytes read, code point */ + 2, 0xfefe, + 2, 0x4e00, + 2, 0xfeff, + 4, 0x20001 + }; + + const char *source, *limit; + + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-16", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-16 converter: %s\n", u_errorName(errorCode)); + return; + } + + source=(const char *)in1, limit=(const char *)in1+sizeof(in1); + TestNextUChar(cnv, source, limit, results1, "UTF-16"); + + source=(const char *)in2, limit=(const char *)in2+sizeof(in2); + ucnv_resetToUnicode(cnv); + TestNextUChar(cnv, source, limit, results2, "UTF-16"); + + source=(const char *)in3, limit=(const char *)in3+sizeof(in3); + ucnv_resetToUnicode(cnv); + TestNextUChar(cnv, source, limit, results3, "UTF-16"); + + /* Test the condition when source >= sourceLimit */ + ucnv_resetToUnicode(cnv); + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + ucnv_close(cnv); +} + +void +static TestUTF16BE() { + /* test input */ + static const uint8_t in[]={ + 0x00, 0x61, + 0x00, 0xc0, + 0x00, 0x31, + 0x00, 0xf4, + 0xce, 0xfe, + 0xd8, 0x01, 0xdc, 0x01 + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 2, 0x61, + 2, 0xc0, + 2, 0x31, + 2, 0xf4, + 2, 0xcefe, + 4, 0x10401 + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("utf-16be", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF16-BE converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-16BE"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for the condition where there is an invalid character*/ + { + static const uint8_t source2[]={0x61}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an invalid character"); + } +#if 0 + /* + * Test disabled because currently the UTF-16BE/LE converters are supposed + * to not set errors for unpaired surrogates. + * This may change with + * Jitterbug 1838 - forbid converting surrogate code points in UTF-16/32 + */ + + /*Test for the condition where there is a surrogate pair*/ + { + const uint8_t source2[]={0xd8, 0x01}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an truncated surrogate character"); + } +#endif + ucnv_close(cnv); +} + +static void +TestUTF16LE() { + /* test input */ + static const uint8_t in[]={ + 0x61, 0x00, + 0x31, 0x00, + 0x4e, 0x2e, + 0x4e, 0x00, + 0x01, 0xd8, 0x01, 0xdc + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 2, 0x61, + 2, 0x31, + 2, 0x2e4e, + 2, 0x4e, + 4, 0x10401 + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("utf-16le", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF16-LE converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-16LE"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for the condition where there is an invalid character*/ + { + static const uint8_t source2[]={0x61}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an invalid character"); + } +#if 0 + /* + * Test disabled because currently the UTF-16BE/LE converters are supposed + * to not set errors for unpaired surrogates. + * This may change with + * Jitterbug 1838 - forbid converting surrogate code points in UTF-16/32 + */ + + /*Test for the condition where there is a surrogate character*/ + { + static const uint8_t source2[]={0x01, 0xd8}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an truncated surrogate character"); + } +#endif + + ucnv_close(cnv); +} + +void +static TestUTF32() { + /* test input */ + static const uint8_t in1[]={ + 0x00, 0x00, 0xfe, 0xff, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff + }; + static const uint8_t in2[]={ + 0xff, 0xfe, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0xfe, 0xff, 0x00, 0x00 + }; + static const uint8_t in3[]={ + 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x40, 0x00, 0x00, 0xdc, 0x01 + }; + + /* expected test results */ + static const int32_t results1[]={ + /* number of bytes read, code point */ + 8, 0x100f00, + 4, 0xfeff + }; + static const int32_t results2[]={ + /* number of bytes read, code point */ + 8, 0x0f1000, + 4, 0xfffe + }; + static const int32_t results3[]={ + /* number of bytes read, code point */ + 4, 0xfefe, + 4, 0x100f00, + 4, 0xfffd, /* unmatched surrogate */ + 4, 0xfffd /* unmatched surrogate */ + }; + + const char *source, *limit; + + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-32", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-32 converter: %s\n", u_errorName(errorCode)); + return; + } + + source=(const char *)in1, limit=(const char *)in1+sizeof(in1); + TestNextUChar(cnv, source, limit, results1, "UTF-32"); + + source=(const char *)in2, limit=(const char *)in2+sizeof(in2); + ucnv_resetToUnicode(cnv); + TestNextUChar(cnv, source, limit, results2, "UTF-32"); + + source=(const char *)in3, limit=(const char *)in3+sizeof(in3); + ucnv_resetToUnicode(cnv); + TestNextUChar(cnv, source, limit, results3, "UTF-32"); + + /* Test the condition when source >= sourceLimit */ + ucnv_resetToUnicode(cnv); + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + ucnv_close(cnv); +} + +static void +TestUTF32BE() { + /* test input */ + static const uint8_t in[]={ + 0x00, 0x00, 0x00, 0x61, + 0x00, 0x00, 0x30, 0x61, + 0x00, 0x00, 0xdc, 0x00, + 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x00, 0xdf, 0xff, + 0x00, 0x00, 0xff, 0xfe, + 0x00, 0x10, 0xab, 0xcd, + 0x00, 0x10, 0xff, 0xff + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 4, 0x61, + 4, 0x3061, + 4, 0xfffd, + 4, 0xfffd, + 4, 0xfffd, + 4, 0xfffe, + 4, 0x10abcd, + 4, 0x10ffff + }; + + /* error test input */ + static const uint8_t in2[]={ + 0x00, 0x00, 0x00, 0x61, + 0x00, 0x11, 0x00, 0x00, /* 0x110000 out of range */ + 0x00, 0x00, 0x00, 0x62, + 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */ + 0x7f, 0xff, 0xff, 0xff, /* 0x7fffffff out of range */ + 0x00, 0x00, 0x01, 0x62, + 0x00, 0x00, 0x02, 0x62 + }; + + /* expected error test results */ + static const int32_t results2[]={ + /* number of bytes read, code point */ + 4, 0x61, + 8, 0x62, + 12, 0x162, + 4, 0x262 + }; + + UConverterToUCallback cb; + const void *p; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-32BE", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-32BE converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-32BE"); + + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + /* test error behavior with a skip callback */ + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode); + source=(const char *)in2; + limit=(const char *)(in2+sizeof(in2)); + TestNextUChar(cnv, source, limit, results2, "UTF-32BE"); + + ucnv_close(cnv); +} + +static void +TestUTF32LE() { + /* test input */ + static const uint8_t in[]={ + 0x61, 0x00, 0x00, 0x00, + 0x61, 0x30, 0x00, 0x00, + 0x00, 0xdc, 0x00, 0x00, + 0x00, 0xd8, 0x00, 0x00, + 0xff, 0xdf, 0x00, 0x00, + 0xfe, 0xff, 0x00, 0x00, + 0xcd, 0xab, 0x10, 0x00, + 0xff, 0xff, 0x10, 0x00 + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 4, 0x61, + 4, 0x3061, + 4, 0xfffd, + 4, 0xfffd, + 4, 0xfffd, + 4, 0xfffe, + 4, 0x10abcd, + 4, 0x10ffff + }; + + /* error test input */ + static const uint8_t in2[]={ + 0x61, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x00, /* 0x110000 out of range */ + 0x62, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */ + 0xff, 0xff, 0xff, 0x7f, /* 0x7fffffff out of range */ + 0x62, 0x01, 0x00, 0x00, + 0x62, 0x02, 0x00, 0x00, + }; + + /* expected error test results */ + static const int32_t results2[]={ + /* number of bytes read, code point */ + 4, 0x61, + 8, 0x62, + 12, 0x162, + 4, 0x262, + }; + + UConverterToUCallback cb; + const void *p; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("UTF-32LE", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a UTF-32LE converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "UTF-32LE"); + + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + + /* test error behavior with a skip callback */ + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode); + source=(const char *)in2; + limit=(const char *)(in2+sizeof(in2)); + TestNextUChar(cnv, source, limit, results2, "UTF-32LE"); + + ucnv_close(cnv); +} + +static void +TestLATIN1() { + /* test input */ + static const uint8_t in[]={ + 0x61, + 0x31, + 0x32, + 0xc0, + 0xf0, + 0xf4, + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x61, + 1, 0x31, + 1, 0x32, + 1, 0xc0, + 1, 0xf0, + 1, 0xf4, + }; + static const uint16_t in1[] = { + 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, + 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f, + 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c, + 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d, + 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e, + 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e, + 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d, + 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa, + 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08, + 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d, + 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06, + 0xcb, 0x82 + }; + static const uint8_t out1[] = { + 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, + 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f, + 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c, + 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d, + 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e, + 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e, + 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d, + 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa, + 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08, + 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d, + 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06, + 0xcb, 0x82 + }; + static const uint16_t in2[]={ + 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23, + 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A, + 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F, + 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21, + 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E, + 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x0F, 0x2F, 0x2A, 0x70, + 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A, + 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F, + 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47, + 0x1B, 0x4F, 0x22, 0x48, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, + 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, + 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21, + 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B, + 0x4F, 0x22, 0x6C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50, + 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F, + 0x22, 0x5C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C, + 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F, + 0x23, 0x71, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, + 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B, + 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B, + 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23, + 0x6F, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, + 0x37, 0x20, 0x2A, 0x2F, + }; + static const unsigned char out2[]={ + 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23, + 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A, + 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F, + 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21, + 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E, + 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x0F, 0x2F, 0x2A, 0x70, + 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A, + 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F, + 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47, + 0x1B, 0x4F, 0x22, 0x48, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, + 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, + 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21, + 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B, + 0x4F, 0x22, 0x6C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50, + 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F, + 0x22, 0x5C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C, + 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F, + 0x23, 0x71, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, + 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B, + 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B, + 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23, + 0x6F, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, + 0x37, 0x20, 0x2A, 0x2F, + }; + const char *source=(const char *)in; + const char *limit=(const char *)in+sizeof(in); + + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("LATIN_1", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a LATIN_1 converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "LATIN_1"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + TestConv((uint16_t*)in1,sizeof(in1)/2,"LATIN_1","LATIN-1",(char*)out1,sizeof(out1)); + TestConv((uint16_t*)in2,sizeof(in2)/2,"ASCII","ASCII",(char*)out2,sizeof(out2)); + + ucnv_close(cnv); +} + +static void +TestSBCS() { + /* test input */ + static const uint8_t in[]={ 0x61, 0xc0, 0x80, 0xe0, 0xf0, 0xf4}; + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x61, + 1, 0xbf, + 1, 0xc4, + 1, 0x2021, + 1, 0xf8ff, + 1, 0x00d9 + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("x-mac-turkish", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a SBCS(x-mac-turkish) converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "SBCS(x-mac-turkish)"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for Illegal character */ /* + { + static const uint8_t input1[]={ 0xA1 }; + const char* illegalsource=(const char*)input1; + TestNextUCharError(cnv, illegalsource, illegalsource+sizeof(illegalsource), U_INVALID_CHAR_FOUND, "source has a illegal characte"); + } + */ + ucnv_close(cnv); +} + +static void +TestDBCS() { + /* test input */ + static const uint8_t in[]={ + 0x44, 0x6a, + 0xc4, 0x9c, + 0x7a, 0x74, + 0x46, 0xab, + 0x42, 0x5b, + + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 2, 0x00a7, + 2, 0xe1d2, + 2, 0x6962, + 2, 0xf842, + 2, 0xffe5, + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + + UConverter *cnv=my_ucnv_open("@ibm9027", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a DBCS(@ibm9027) converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "DBCS(@ibm9027)"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for the condition where there is an invalid character*/ + { + static const uint8_t source2[]={0x1a, 0x1b}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character"); + } + /*Test for the condition where we have a truncated char*/ + { + static const uint8_t source1[]={0xc4}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated"); + } + ucnv_close(cnv); +} + +static void +TestMBCS() { + /* test input */ + static const uint8_t in[]={ + 0x01, + 0xa6, 0xa3, + 0x00, + 0xa6, 0xa1, + 0x08, + 0xc2, 0x76, + 0xc2, 0x78, + + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x0001, + 2, 0x250c, + 1, 0x0000, + 2, 0x2500, + 1, 0x0008, + 2, 0xd60c, + 2, 0xd60e, + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + + UConverter *cnv=ucnv_open("ibm-1363", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a MBCS(ibm-1363) converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "MBCS(ibm-1363)"); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for the condition where there is an invalid character*/ + { + static const uint8_t source2[]={0xa1, 0x01}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character"); + } + /*Test for the condition where we have a truncated char*/ + { + static const uint8_t source1[]={0xc4}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated"); + } + ucnv_close(cnv); + +} + +#ifdef U_ENABLE_GENERIC_ISO_2022 + +static void +TestISO_2022() { + /* test input */ + static const uint8_t in[]={ + 0x1b, 0x25, 0x42, + 0x31, + 0x32, + 0x61, + 0xc2, 0x80, + 0xe0, 0xa0, 0x80, + 0xf0, 0x90, 0x80, 0x80 + }; + + + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 4, 0x0031, /* 4 bytes including the escape sequence */ + 1, 0x0032, + 1, 0x61, + 2, 0x80, + 3, 0x800, + 4, 0x10000 + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + + cnv=ucnv_open("ISO_2022", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "ISO_2022"); + + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source-1, U_ILLEGAL_ARGUMENT_ERROR, "sourceLimit < source"); + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + /*Test for the condition where we have a truncated char*/ + { + static const uint8_t source1[]={0xc4}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated"); + } + /*Test for the condition where there is an invalid character*/ + { + static const uint8_t source2[]={0xa1, 0x01}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_CHAR_FOUND, "an invalid character"); + } + ucnv_close(cnv); +} + +#endif + +static void +TestSmallTargetBuffer(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){ + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + int len=0; + int i=2; + UErrorCode errorCode=U_ZERO_ERROR; + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 10); + ucnv_reset(cnv); + for(;--i>0; ){ + uSource = (UChar*) source; + uSourceLimit=(const UChar*)sourceLimit; + cTarget = cBuf; + uTarget = uBuf; + cSource = cBuf; + cTargetLimit = cBuf; + uTargetLimit = uBuf; + + do{ + + cTargetLimit = cTargetLimit+ i; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,FALSE, &errorCode); + if(errorCode==U_BUFFER_OVERFLOW_ERROR){ + errorCode=U_ZERO_ERROR; + continue; + } + + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + + }while (uSource<uSourceLimit); + + cSourceLimit =cTarget; + do{ + uTargetLimit=uTargetLimit+i; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,FALSE,&errorCode); + if(errorCode==U_BUFFER_OVERFLOW_ERROR){ + errorCode=U_ZERO_ERROR; + continue; + } + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + }while(cSource<cSourceLimit); + + uSource = source; + test =uBuf; + for(len=0;len<(int)(source - sourceLimit);len++){ + if(uBuf[len]!=uSource[len]){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",uSource[len],(int)uBuf[len]) ; + } + } + } + free(uBuf); + free(cBuf); +} +/* Test for Jitterbug 778 */ +static void TestToAndFromUChars(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){ + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + int numCharsInTarget=0; + UErrorCode errorCode=U_ZERO_ERROR; + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = source; + uSourceLimit=sourceLimit; + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_reset(cnv); + numCharsInTarget=ucnv_fromUChars(cnv, cTarget, (int32_t)(cTargetLimit-cTarget), uSource, (int32_t)(uSourceLimit-uSource), &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + test =uBuf; + ucnv_toUChars(cnv,uTarget,(int32_t)(uTargetLimit-uTarget),cSource,numCharsInTarget,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUChars conversion failed, reason %s\n", u_errorName(errorCode)); + return; + } + uSource = source; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + free(uBuf); + free(cBuf); +} + +static void TestSmallSourceBuffer(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){ + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + int len=0; + int i=2; + const UChar *temp = sourceLimit; + UErrorCode errorCode=U_ZERO_ERROR; + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 10); + + ucnv_reset(cnv); + for(;--i>0;){ + uSource = (UChar*) source; + cTarget = cBuf; + uTarget = uBuf; + cSource = cBuf; + cTargetLimit = cBuf; + uTargetLimit = uBuf+uBufSize*5; + cTargetLimit = cTargetLimit+uBufSize*10; + uSourceLimit=uSource; + do{ + + if (uSourceLimit < sourceLimit) { + uSourceLimit = uSourceLimit+1; + } + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,FALSE, &errorCode); + if(errorCode==U_BUFFER_OVERFLOW_ERROR){ + errorCode=U_ZERO_ERROR; + continue; + } + + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + + }while (uSource<temp); + + cSourceLimit =cBuf; + do{ + if (cSourceLimit < cBuf + (cTarget - cBuf)) { + cSourceLimit = cSourceLimit+1; + } + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,FALSE,&errorCode); + if(errorCode==U_BUFFER_OVERFLOW_ERROR){ + errorCode=U_ZERO_ERROR; + continue; + } + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + }while(cSource<cTarget); + + uSource = source; + test =uBuf; + for(;len<(int)(source - sourceLimit);len++){ + if(uBuf[len]!=uSource[len]){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",uSource[len],(int)uBuf[len]) ; + } + } + } + free(uBuf); + free(cBuf); +} +static void +TestGetNextUChar2022(UConverter* cnv, const char* source, const char* limit, + const uint16_t results[], const char* message){ + const char* s0; + const char* s=(char*)source; + const uint16_t *r=results; + UErrorCode errorCode=U_ZERO_ERROR; + uint32_t c,exC; + ucnv_reset(cnv); + while(s<limit) { + s0=s; + c=ucnv_getNextUChar(cnv, &s, limit, &errorCode); + if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) { + break; /* no more significant input */ + } else if(U_FAILURE(errorCode)) { + log_err("%s ucnv_getNextUChar() failed: %s\n", message, u_errorName(errorCode)); + break; + } else { + if(UTF_IS_FIRST_SURROGATE(*r)){ + int i =0, len = 2; + UTF_NEXT_CHAR_SAFE(r, i, len, exC, FALSE); + r++; + }else{ + exC = *r; + } + if(c!=(uint32_t)(exC)) + log_err("%s ucnv_getNextUChar() Expected: \\u%04X Got: \\u%04X \n",message,(uint32_t) (*r),c); + } + r++; + } +} + +static int TestJitterbug930(const char* enc){ + UErrorCode err = U_ZERO_ERROR; + UConverter*converter; + char out[80]; + char*target = out; + UChar in[4]; + const UChar*source = in; + int32_t off[80]; + int32_t* offsets = off; + int numOffWritten=0; + UBool flush = 0; + converter = my_ucnv_open(enc, &err); + + in[0] = 0x41; /* 0x4E00;*/ + in[1] = 0x4E01; + in[2] = 0x4E02; + in[3] = 0x4E03; + + memset(off, '*', sizeof(off)); + + ucnv_fromUnicode (converter, + &target, + target+2, + &source, + source+3, + offsets, + flush, + &err); + + /* writes three bytes into the output buffer: 41 1B 24 + * but offsets contains 0 1 1 + */ + while(*offsets< off[10]){ + numOffWritten++; + offsets++; + } + log_verbose("Testing Jitterbug 930 for encoding %s",enc); + if(numOffWritten!= (int)(target-out)){ + log_err("Jitterbug 930 test for enc: %s failed. Expected: %i Got: %i",enc, (int)(target-out),numOffWritten); + } + + err = U_ZERO_ERROR; + + memset(off,'*' , sizeof(off)); + + flush = 1; + offsets=off; + ucnv_fromUnicode (converter, + &target, + target+4, + &source, + source, + offsets, + flush, + &err); + numOffWritten=0; + while(*offsets< off[10]){ + numOffWritten++; + if(*offsets!= -1){ + log_err("Jitterbug 930 test for enc: %s failed. Expected: %i Got: %i",enc,-1,*offsets) ; + } + offsets++; + } + + /* writes 42 43 7A into output buffer, + * offsets contains -1 -1 -1 + */ + ucnv_close(converter); + return 0; +} + +static void +TestHZ() { + /* test input */ + static const uint16_t in[]={ + 0x3000, 0x3001, 0x3002, 0x00B7, 0x02C9, 0x02C7, 0x00A8, 0x3003, 0x3005, 0x2014, + 0xFF5E, 0x2016, 0x2026, 0x007E, 0x997C, 0x70B3, 0x75C5, 0x5E76, 0x73BB, 0x83E0, + 0x64AD, 0x62E8, 0x94B5, 0x000A, 0x6CE2, 0x535A, 0x52C3, 0x640F, 0x94C2, 0x7B94, + 0x4F2F, 0x5E1B, 0x8236, 0x000A, 0x8116, 0x818A, 0x6E24, 0x6CCA, 0x9A73, 0x6355, + 0x535C, 0x54FA, 0x8865, 0x000A, 0x57E0, 0x4E0D, 0x5E03, 0x6B65, 0x7C3F, 0x90E8, + 0x6016, 0x248F, 0x2490, 0x000A, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, + 0x2497, 0x2498, 0x2499, 0x000A, 0x249A, 0x249B, 0x2474, 0x2475, 0x2476, 0x2477, + 0x2478, 0x2479, 0x247A, 0x000A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, 0x2480, + 0x2481, 0x2482, 0x2483, 0x000A, 0x0041, 0x0043, 0x0044, 0x0045, 0x0046, 0x007E, + 0x0048, 0x0049, 0x004A, 0x000A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, + 0x0051, 0x0052, 0x0053, 0x000A, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, + 0x005A, 0x005B, 0x005C, 0x000A + }; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("HZ", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open HZ converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + TestGetNextUChar2022(cnv, cBuf, cTarget, in, "HZ encoding"); + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestJitterbug930("csISO2022JP"); + ucnv_close(cnv); + free(offsets); + free(uBuf); + free(cBuf); +} + +static void +TestISCII(){ + /* test input */ + static const uint16_t in[]={ + /* test full range of Devanagari */ + 0x0901,0x0902,0x0903,0x0905,0x0906,0x0907,0x0908,0x0909,0x090A, + 0x090B,0x090E,0x090F,0x0910,0x090D,0x0912,0x0913,0x0914,0x0911, + 0x0915,0x0916,0x0917,0x0918,0x0919,0x091A,0x091B,0x091C,0x091D, + 0x091E,0x091F,0x0920,0x0921,0x0922,0x0923,0x0924,0x0925,0x0926, + 0x0927,0x0928,0x0929,0x092A,0x092B,0x092C,0x092D,0x092E,0x092F, + 0x095F,0x0930,0x0931,0x0932,0x0933,0x0934,0x0935,0x0936,0x0937, + 0x0938,0x0939,0x200D,0x093E,0x093F,0x0940,0x0941,0x0942,0x0943, + 0x0946,0x0947,0x0948,0x0945,0x094A,0x094B,0x094C,0x0949,0x094D, + 0x093d,0x0966,0x0967,0x0968,0x0969,0x096A,0x096B,0x096C, + 0x096D,0x096E,0x096F, + /* test Soft halant*/ + 0x0915,0x094d, 0x200D, + /* test explicit halant */ + 0x0915,0x094d, 0x200c, + /* test double danda */ + 0x965, + /* test ASCII */ + 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23, + 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A, + /* tests from Lotus */ + 0x0061,0x0915,0x000D,0x000A,0x0996,0x0043, + 0x0930,0x094D,0x200D, + 0x0901,0x000D,0x000A,0x0905,0x0985,0x0043, + 0x0915,0x0921,0x002B,0x095F, + /* tamil range */ + 0x0B86, 0xB87, 0xB88, + /* telugu range */ + 0x0C05, 0x0C02, 0x0C03,0x0c31, + /* kannada range */ + 0x0C85, 0xC82, 0x0C83, + /* test Abbr sign and Anudatta */ + 0x0970, 0x952, + /* 0x0958, + 0x0959, + 0x095A, + 0x095B, + 0x095C, + 0x095D, + 0x095E, + 0x095F,*/ + 0x0960 /* Vocallic RRI 0xAB, 0xE9*/, + 0x0944 /* Vowel Sign Vocallic RRI 0xDF, 0xE9 */, + 0x090C , + 0x0962, + 0x0961 /* Vocallic LL 0xa6, 0xE9 */, + 0x0963 /* Vowel Sign Vocallic LL 0xdb, 0xE9, */, + 0x0950 /* OM Symbol 0xa1, 0xE9,*/, + 0x093D /* Avagraha 0xEA, 0xE9*/, + 0x0958, + 0x0959, + 0x095A, + 0x095B, + 0x095C, + 0x095D, + 0x095E, + 0x0020, 0x094D, 0x0930, 0x0000, 0x00A0 + }; + static const unsigned char byteArr[]={ + + 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9, + 0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2, + 0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb, + 0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4, + 0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd, + 0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, + 0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, + 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8, + 0xea,0xe9,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa, + /* test soft halant */ + 0xb3, 0xE8, 0xE9, + /* test explicit halant */ + 0xb3, 0xE8, 0xE8, + /* test double danda */ + 0xea, 0xea, + /* test ASCII */ + 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23, + 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A, + /* test ATR code */ + + /* tests from Lotus */ + 0x61,0xEF,0x42,0xEF,0x30,0xB3,0x0D,0x0A,0xEF,0x43,0xB4,0x43, + 0xEF,0x42,0xCF,0xE8,0xD9, + 0xEF,0x42,0xA1,0x0D,0x0A,0xEF,0x42,0xA4,0xEF,0x43,0xA4,0x43, + 0xEF,0x42,0xB3,0xBF,0x2B,0xEF,0x42,0xCE, + /* tamil range */ + 0xEF, 0x44, 0xa5, 0xa6, 0xa7, + /* telugu range */ + 0xEF, 0x45,0xa4, 0xa2, 0xa3,0xd0, + /* kannada range */ + 0xEF, 0x48,0xa4, 0xa2, 0xa3, + /* anudatta and abbreviation sign */ + 0xEF, 0x42, 0xF0, 0xBF, 0xF0, 0xB8, + + + 0xAA, 0xE9,/* RI + NUKTA 0x0960*/ + + 0xDF, 0xE9,/* Vowel sign RI + NUKTA 0x0944*/ + + 0xa6, 0xE9,/* Vowel I + NUKTA 0x090C*/ + + 0xdb, 0xE9,/* Vowel sign I + Nukta 0x0962*/ + + 0xa7, 0xE9,/* Vowel II + NUKTA 0x0961*/ + + 0xdc, 0xE9,/* Vowel sign II + Nukta 0x0963*/ + + 0xa1, 0xE9,/* chandrabindu + Nukta 0x0950*/ + + 0xEA, 0xE9, /* Danda + Nukta 0x093D*/ + + 0xB3, 0xE9, /* Ka + NUKTA */ + + 0xB4, 0xE9, /* Kha + NUKTA */ + + 0xB5, 0xE9, /* Ga + NUKTA */ + + 0xBA, 0xE9, + + 0xBF, 0xE9, + + 0xC0, 0xE9, + + 0xC9, 0xE9, + /* INV halant RA */ + 0xD9, 0xE8, 0xCF, + 0x00, 0x00A0, + /* just consume unhandled codepoints */ + 0xEF, 0x30, + + }; + testConvertToU(byteArr,(sizeof(byteArr)),in,(sizeof(in)/U_SIZEOF_UCHAR),"x-iscii-de",NULL,TRUE); + TestConv(in,(sizeof(in)/2),"ISCII,version=0","hindi", (char *)byteArr,sizeof(byteArr)); + +} + +static void +TestISO_2022_JP() { + /* test input */ + static const uint16_t in[]={ + 0x0041,/*0x00E9,*/0x3000, 0x3001, 0x3002, 0x0020, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, 0x005C, 0x000D, 0x000A, + 0x301C, 0x2016, 0x2026, 0x2025, 0x2018, 0x2019, 0x201C, 0x000D, 0x000A, + 0x201D, 0x3014, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + }; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ISO_2022_JP_1", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open an ISO_2022_JP_1 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-JP encoding"); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestJitterbug930("csISO2022JP"); + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void TestConv(const uint16_t in[],int len, const char* conv, const char* lang, char byteArr[],int byteArrLen){ + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120*10; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) ); + int32_t* myOff= offsets; + cnv=my_ucnv_open(conv, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a %s converter: %s\n", conv, u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)); + cBuf =(char*)malloc(uBufSize * sizeof(char)); + uSource = (const UChar*)in; + uSourceLimit=uSource+len; + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + /*log_verbose("length of compressed string for language %s using %s:%i \n",conv,lang,(cTarget-cBuf));*/ + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed, reason: %s\n", u_errorName(errorCode)); + return; + } + + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("for codepage %s : Expected : \\u%04X \t Got: \\u%04X\n",conv,*uSource,(int)*test) ; + } + uSource++; + test++; + } + TestSmallTargetBuffer(in,(const UChar*)&in[len],cnv); + TestSmallSourceBuffer(in,(const UChar*)&in[len],cnv); + TestGetNextUChar2022(cnv, cBuf, cTarget, in, conv); + if(byteArr && byteArrLen!=0){ + TestGetNextUChar2022(cnv, byteArr, (byteArr+byteArrLen), in, lang); + TestToAndFromUChars(in,(const UChar*)&in[len],cnv); + { + cSource = byteArr; + cSourceLimit = cSource+byteArrLen; + test=uBuf; + myOff = offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + } + } + + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} +static UChar U_CALLCONV +_charAt(int32_t offset, void *context) { + return ((char*)context)[offset]; +} + +static int32_t +unescape(UChar* dst, int32_t dstLen,const char* src,int32_t srcLen,UErrorCode *status){ + int32_t srcIndex=0; + int32_t dstIndex=0; + if(U_FAILURE(*status)){ + return 0; + } + if((dst==NULL && dstLen>0) || (src==NULL ) || dstLen < -1 || srcLen <-1 ){ + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + if(srcLen==-1){ + srcLen = (int32_t)uprv_strlen(src); + } + + for (; srcIndex<srcLen; ) { + UChar32 c = src[srcIndex++]; + if (c == 0x005C /*'\\'*/) { + c = u_unescapeAt(_charAt,&srcIndex,srcLen,(void*)src); /* advances i*/ + if (c == (UChar32)0xFFFFFFFF) { + *status=U_INVALID_CHAR_FOUND; /* return empty string */ + break; /* invalid escape sequence */ + } + } + if(dstIndex < dstLen){ + if(c>0xFFFF){ + dst[dstIndex++] = UTF16_LEAD(c); + if(dstIndex<dstLen){ + dst[dstIndex]=UTF16_TRAIL(c); + }else{ + *status=U_BUFFER_OVERFLOW_ERROR; + } + }else{ + dst[dstIndex]=(UChar)c; + } + + }else{ + *status = U_BUFFER_OVERFLOW_ERROR; + } + dstIndex++; /* for preflighting */ + } + return dstIndex; +} + +static void +TestFullRoundtrip(const char* cp){ + UChar usource[10] ={0}; + UChar nsrc[10] = {0}; + uint32_t i=1; + int len=0, ulen; + nsrc[0]=0x0061; + /* Test codepoint 0 */ + TestConv(usource,1,cp,"",NULL,0); + TestConv(usource,2,cp,"",NULL,0); + nsrc[2]=0x5555; + TestConv(nsrc,3,cp,"",NULL,0); + + for(;i<=0x10FFFF;i++){ + if(i==0xD800){ + i=0xDFFF; + continue; + } + if(i<=0xFFFF){ + usource[0] =(UChar) i; + len=1; + }else{ + usource[0]=UTF16_LEAD(i); + usource[1]=UTF16_TRAIL(i); + len=2; + } + ulen=len; + if(i==0x80) { + usource[2]=0; + } + /* Test only single code points */ + TestConv(usource,ulen,cp,"",NULL,0); + /* Test codepoint repeated twice */ + usource[ulen]=usource[0]; + usource[ulen+1]=usource[1]; + ulen+=len; + TestConv(usource,ulen,cp,"",NULL,0); + /* Test codepoint repeated 3 times */ + usource[ulen]=usource[0]; + usource[ulen+1]=usource[1]; + ulen+=len; + TestConv(usource,ulen,cp,"",NULL,0); + /* Test codepoint in between 2 codepoints */ + nsrc[1]=usource[0]; + nsrc[2]=usource[1]; + nsrc[len+1]=0x5555; + TestConv(nsrc,len+2,cp,"",NULL,0); + uprv_memset(usource,0,sizeof(UChar)*10); + } +} + +static void +TestRoundTrippingAllUTF(void){ + if(!QUICK){ + log_verbose("Running exhaustive round trip test for BOCU-1\n"); + TestFullRoundtrip("BOCU-1"); + log_verbose("Running exhaustive round trip test for SCSU\n"); + TestFullRoundtrip("SCSU"); + log_verbose("Running exhaustive round trip test for UTF-8\n"); + TestFullRoundtrip("UTF-8"); + log_verbose("Running exhaustive round trip test for CESU-8\n"); + TestFullRoundtrip("CESU-8"); + log_verbose("Running exhaustive round trip test for UTF-16BE\n"); + TestFullRoundtrip("UTF-16BE"); + log_verbose("Running exhaustive round trip test for UTF-16LE\n"); + TestFullRoundtrip("UTF-16LE"); + log_verbose("Running exhaustive round trip test for UTF-16\n"); + TestFullRoundtrip("UTF-16"); + log_verbose("Running exhaustive round trip test for UTF-32BE\n"); + TestFullRoundtrip("UTF-32BE"); + log_verbose("Running exhaustive round trip test for UTF-32LE\n"); + TestFullRoundtrip("UTF-32LE"); + log_verbose("Running exhaustive round trip test for UTF-32\n"); + TestFullRoundtrip("UTF-32"); + log_verbose("Running exhaustive round trip test for UTF-7\n"); + TestFullRoundtrip("UTF-7"); + log_verbose("Running exhaustive round trip test for UTF-7\n"); + TestFullRoundtrip("UTF-7,version=1"); + log_verbose("Running exhaustive round trip test for IMAP-mailbox-name\n"); + TestFullRoundtrip("IMAP-mailbox-name"); + log_verbose("Running exhaustive round trip test for GB18030\n"); + TestFullRoundtrip("GB18030"); + } +} + +static void +TestSCSU() { + + static const uint16_t germanUTF16[]={ + 0x00d6, 0x006c, 0x0020, 0x0066, 0x006c, 0x0069, 0x0065, 0x00df, 0x0074 + }; + + static const uint8_t germanSCSU[]={ + 0xd6, 0x6c, 0x20, 0x66, 0x6c, 0x69, 0x65, 0xdf, 0x74 + }; + + static const uint16_t russianUTF16[]={ + 0x041c, 0x043e, 0x0441, 0x043a, 0x0432, 0x0430 + }; + + static const uint8_t russianSCSU[]={ + 0x12, 0x9c, 0xbe, 0xc1, 0xba, 0xb2, 0xb0 + }; + + static const uint16_t japaneseUTF16[]={ + 0x3000, 0x266a, 0x30ea, 0x30f3, 0x30b4, 0x53ef, 0x611b, + 0x3044, 0x3084, 0x53ef, 0x611b, 0x3044, 0x3084, 0x30ea, 0x30f3, + 0x30b4, 0x3002, 0x534a, 0x4e16, 0x7d00, 0x3082, 0x524d, 0x306b, + 0x6d41, 0x884c, 0x3057, 0x305f, 0x300c, 0x30ea, 0x30f3, 0x30b4, + 0x306e, 0x6b4c, 0x300d, 0x304c, 0x3074, 0x3063, 0x305f, 0x308a, + 0x3059, 0x308b, 0x304b, 0x3082, 0x3057, 0x308c, 0x306a, 0x3044, + 0x3002, 0x7c73, 0x30a2, 0x30c3, 0x30d7, 0x30eb, 0x30b3, 0x30f3, + 0x30d4, 0x30e5, 0x30fc, 0x30bf, 0x793e, 0x306e, 0x30d1, 0x30bd, + 0x30b3, 0x30f3, 0x300c, 0x30de, 0x30c3, 0x30af, 0xff08, 0x30de, + 0x30c3, 0x30ad, 0x30f3, 0x30c8, 0x30c3, 0x30b7, 0x30e5, 0xff09, + 0x300d, 0x3092, 0x3001, 0x3053, 0x3088, 0x306a, 0x304f, 0x611b, + 0x3059, 0x308b, 0x4eba, 0x305f, 0x3061, 0x306e, 0x3053, 0x3068, + 0x3060, 0x3002, 0x300c, 0x30a2, 0x30c3, 0x30d7, 0x30eb, 0x4fe1, + 0x8005, 0x300d, 0x306a, 0x3093, 0x3066, 0x8a00, 0x3044, 0x65b9, + 0x307e, 0x3067, 0x3042, 0x308b, 0x3002 + }; + + /* SCSUEncoder produces a slightly longer result (179B vs. 178B) because of one different choice: + it uses an SQn once where a longer look-ahead could have shown that SCn is more efficient */ + static const uint8_t japaneseSCSU[]={ + 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, + 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f, + 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c, + 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d, + 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e, + 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e, + 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d, + 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa, + 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08, + 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d, + 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06, + 0xcb, 0x82 + }; + + static const uint16_t allFeaturesUTF16[]={ + 0x0041, 0x00df, 0x0401, 0x015f, 0x00df, 0x01df, 0xf000, 0xdbff, + 0xdfff, 0x000d, 0x000a, 0x0041, 0x00df, 0x0401, 0x015f, 0x00df, + 0x01df, 0xf000, 0xdbff, 0xdfff + }; + + /* see comment at japaneseSCSU: the same kind of different choice yields a slightly shorter + * result here (34B vs. 35B) + */ + static const uint8_t allFeaturesSCSU[]={ + 0x41, 0xdf, 0x12, 0x81, 0x03, 0x5f, 0x10, 0xdf, 0x1b, 0x03, + 0xdf, 0x1c, 0x88, 0x80, 0x0b, 0xbf, 0xff, 0xff, 0x0d, 0x0a, + 0x41, 0x10, 0xdf, 0x12, 0x81, 0x03, 0x5f, 0x10, 0xdf, 0x13, + 0xdf, 0x14, 0x80, 0x15, 0xff + }; + static const uint16_t monkeyIn[]={ + 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A, + 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A, + 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A, + 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A, + 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A, + 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A, + 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A, + 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A, + 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A, + 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A, + 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A, + 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A, + 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A, + 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A, + /* test non-BMP code points */ + 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F, + 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8, + 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF, + 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6, + 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB, + 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0, + 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8, + 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF, + 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4, + 0xD869, 0xDED5, 0xD800, 0xDC00, 0xD800, 0xDC00, 0xD800, 0xDC00, 0xDBFF, 0xDFFF, + 0xDBFF, 0xDFFF, 0xDBFF, 0xDFFF, + + + 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A, + 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A, + 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A, + 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A, + }; + static const char *fTestCases [] = { + "\\ud800\\udc00", /* smallest surrogate*/ + "\\ud8ff\\udcff", + "\\udBff\\udFff", /* largest surrogate pair*/ + "\\ud834\\udc00", + "\\U0010FFFF", + "Hello \\u9292 \\u9192 World!", + "Hell\\u0429o \\u9292 \\u9192 W\\u00e4rld!", + "Hell\\u0429o \\u9292 \\u9292W\\u00e4rld!", + + "\\u0648\\u06c8", /* catch missing reset*/ + "\\u0648\\u06c8", + + "\\u4444\\uE001", /* lowest quotable*/ + "\\u4444\\uf2FF", /* highest quotable*/ + "\\u4444\\uf188\\u4444", + "\\u4444\\uf188\\uf288", + "\\u4444\\uf188abc\\u0429\\uf288", + "\\u9292\\u2222", + "Hell\\u0429\\u04230o \\u9292 \\u9292W\\u00e4\\u0192rld!", + "Hell\\u0429o \\u9292 \\u9292W\\u00e4rld!", + "Hello World!123456", + "Hello W\\u0081\\u011f\\u0082!", /* Latin 1 run*/ + + "abc\\u0301\\u0302", /* uses SQn for u301 u302*/ + "abc\\u4411d", /* uses SQU*/ + "abc\\u4411\\u4412d",/* uses SCU*/ + "abc\\u0401\\u0402\\u047f\\u00a5\\u0405", /* uses SQn for ua5*/ + "\\u9191\\u9191\\u3041\\u9191\\u3041\\u3041\\u3000", /* SJIS like data*/ + "\\u9292\\u2222", + "\\u9191\\u9191\\u3041\\u9191\\u3041\\u3041\\u3000", + "\\u9999\\u3051\\u300c\\u9999\\u9999\\u3060\\u9999\\u3065\\u3065\\u3065\\u300c", + "\\u3000\\u266a\\u30ea\\u30f3\\u30b4\\u53ef\\u611b\\u3044\\u3084\\u53ef\\u611b\\u3044\\u3084\\u30ea\\u30f3\\u30b4\\u3002", + + "", /* empty input*/ + "\\u0000", /* smallest BMP character*/ + "\\uFFFF", /* largest BMP character*/ + + /* regression tests*/ + "\\u6441\\ub413\\ua733\\uf8fe\\ueedb\\u587f\\u195f\\u4899\\uf23d\\u49fd\\u0aac\\u5792\\ufc22\\ufc3c\\ufc46\\u00aa", + "\\u00df\\u01df\\uf000\\udbff\\udfff\\u000d\n\\u0041\\u00df\\u0401\\u015f\\u00df\\u01df\\uf000\\udbff\\udfff", + "\\u30f9\\u8321\\u05e5\\u181c\\ud72b\\u2019\\u99c9\\u2f2f\\uc10c\\u82e1\\u2c4d\\u1ebc\\u6013\\u66dc\\ubbde\\u94a5\\u4726\\u74af\\u3083\\u55b9\\u000c", + "\\u0041\\u00df\\u0401\\u015f", + "\\u9066\\u2123abc", + "\\ud266\\u43d7\\u\\ue386\\uc9c0\\u4a6b\\u9222\\u901f\\u7410\\ua63f\\u539b\\u9596\\u482e\\u9d47\\ucfe4\\u7b71\\uc280\\uf26a\\u982f\\u862a\\u4edd\\uf513\\ufda6\\u869d\\u2ee0\\ua216\\u3ff6\\u3c70\\u89c0\\u9576\\ud5ec\\ubfda\\u6cca\\u5bb3\\ubcea\\u554c\\u914e\\ufa4a\\uede3\\u2990\\ud2f5\\u2729\\u5141\\u0f26\\uccd8\\u5413\\ud196\\ubbe2\\u51b9\\u9b48\\u0dc8\\u2195\\u21a2\\u21e9\\u00e4\\u9d92\\u0bc0\\u06c5", + "\\uf95b\\u2458\\u2468\\u0e20\\uf51b\\ue36e\\ubfc1\\u0080\\u02dd\\uf1b5\\u0cf3\\u6059\\u7489", + }; + int i=0; + for(;i<sizeof(fTestCases)/sizeof(*fTestCases);i++){ + const char* cSrc = fTestCases[i]; + UErrorCode status = U_ZERO_ERROR; + int32_t cSrcLen,srcLen; + UChar* src; + /* UConverter* cnv = ucnv_open("SCSU",&status); */ + cSrcLen = srcLen = (int32_t)uprv_strlen(fTestCases[i]); + src = (UChar*) malloc((sizeof(UChar) * srcLen) + sizeof(UChar)); + srcLen=unescape(src,srcLen,cSrc,cSrcLen,&status); + log_verbose("Testing roundtrip for src: %s at index :%d\n",cSrc,i); + TestConv(src,srcLen,"SCSU","Coverage",NULL,0); + free(src); + } + TestConv(allFeaturesUTF16,(sizeof(allFeaturesUTF16)/2),"SCSU","all features", (char *)allFeaturesSCSU,sizeof(allFeaturesSCSU)); + TestConv(allFeaturesUTF16,(sizeof(allFeaturesUTF16)/2),"SCSU","all features",(char *)allFeaturesSCSU,sizeof(allFeaturesSCSU)); + TestConv(japaneseUTF16,(sizeof(japaneseUTF16)/2),"SCSU","japaneese",(char *)japaneseSCSU,sizeof(japaneseSCSU)); + TestConv(japaneseUTF16,(sizeof(japaneseUTF16)/2),"SCSU,locale=ja","japaneese",(char *)japaneseSCSU,sizeof(japaneseSCSU)); + TestConv(germanUTF16,(sizeof(germanUTF16)/2),"SCSU","german",(char *)germanSCSU,sizeof(germanSCSU)); + TestConv(russianUTF16,(sizeof(russianUTF16)/2), "SCSU","russian",(char *)russianSCSU,sizeof(russianSCSU)); + TestConv(monkeyIn,(sizeof(monkeyIn)/2),"SCSU","monkey",NULL,0); +} + +#if !UCONFIG_NO_LEGACY_CONVERSION +static void TestJitterbug2346(){ + char source[] = { 0x1b,0x24,0x42,0x3d,0x45,0x1b,0x28,0x4a,0x0d,0x0a, + 0x1b,0x24,0x42,0x3d,0x45,0x1b,0x28,0x4a,0x0d,0x0a}; + uint16_t expected[] = {0x91CD,0x000D,0x000A,0x91CD,0x000D,0x000A}; + + UChar uTarget[500]={'\0'}; + UChar* utarget=uTarget; + UChar* utargetLimit=uTarget+sizeof(uTarget)/2; + + char cTarget[500]={'\0'}; + char* ctarget=cTarget; + char* ctargetLimit=cTarget+sizeof(cTarget); + const char* csource=source; + UChar* temp = expected; + UErrorCode err=U_ZERO_ERROR; + + UConverter* conv =ucnv_open("ISO_2022_JP",&err); + if(U_FAILURE(err)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err)); + return; + } + ucnv_toUnicode(conv,&utarget,utargetLimit,&csource,csource+sizeof(source),NULL,TRUE,&err); + if(U_FAILURE(err)) { + log_err("ISO_2022_JP to Unicode conversion failed: %s\n", u_errorName(err)); + return; + } + utargetLimit=utarget; + utarget = uTarget; + while(utarget<utargetLimit){ + if(*temp!=*utarget){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*utarget,(int)*temp) ; + } + utarget++; + temp++; + } + ucnv_fromUnicode(conv,&ctarget,ctargetLimit,(const UChar**)&utarget,utargetLimit,NULL,TRUE,&err); + if(U_FAILURE(err)) { + log_err("ISO_2022_JP from Unicode conversion failed: %s\n", u_errorName(err)); + return; + } + ctargetLimit=ctarget; + ctarget =cTarget; + ucnv_close(conv); + + +} + +static void +TestISO_2022_JP_1() { + /* test input */ + static const uint16_t in[]={ + 0x3000, 0x3001, 0x3002, 0x0020, 0xFF0E, 0x30FB, 0xFF1A, 0xFF1B, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, 0x005C, 0x000D, 0x000A, + 0x301C, 0x2016, 0x2026, 0x2025, 0x2018, 0x2019, 0x201C, 0x000D, 0x000A, + 0x201D, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x4F94, 0x4F97, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x4F78, 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84, 0x000D, 0x000A, + 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92, 0x4F93, 0x000D, 0x000A, + 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x000D, 0x000A + }; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + + cnv=ucnv_open("ISO_2022_JP_1", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + /*ucnv_close(cnv); + cnv=ucnv_open("ISO_2022,locale=jp,version=1", &errorCode);*/ + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x0e,0x24,0x053}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-JP-1]"); + } + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + ucnv_close(cnv); + free(uBuf); + free(cBuf); +} + +static void +TestISO_2022_JP_2() { + /* test input */ + static const uint16_t in[]={ + 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A, + 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A, + 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A, + 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A, + 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A, + 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A, + 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A, + 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A, + 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A, + 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A, + 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, + 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, + 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A, + 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A, + 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A, + 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A + }; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ISO_2022_JP_2", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + uSource++; + test++; + } + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x0e,0x24,0x053}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-JP-2]"); + } + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void +TestISO_2022_KR() { + /* test input */ + static const uint16_t in[]={ + 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F66,0x9F67,0x9F6A,0x000A,0x000D + ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC02,0xAC04 + ,0xAC07,0xAC08,0xAC09,0x0025,0x0026,0x0027,0x000A,0x000D,0x0028,0x0029 + ,0x002A,0x002B,0x002C,0x002D,0x002E,0x53C3,0x53C8,0x53C9,0x53CA,0x53CB + ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53DF,0x53E1,0x53E2 + ,0x53E3,0x53E4,0x000A,0x000D}; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ISO_2022,locale=kr", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,*test) ; + } + uSource++; + test++; + } + TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-KR encoding"); + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestJitterbug930("csISO2022KR"); + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x1b,0x24,0x053}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_ESCAPE_SEQUENCE, "an invalid character [ISO-2022-KR]"); + } + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void +TestISO_2022_KR_1() { + /* test input */ + static const uint16_t in[]={ + 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F67,0x9F6A,0x000A,0x000D + ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC04 + ,0xAC07,0xAC08,0xAC09,0x0025,0x0026,0x0027,0x000A,0x000D,0x0028,0x0029 + ,0x002A,0x002B,0x002C,0x002D,0x002E,0x53C3,0x53C8,0x53C9,0x53CA,0x53CB + ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53E1,0x53E2 + ,0x53E3,0x53E4,0x000A,0x000D}; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 120; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ibm-25546", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 5); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,*test) ; + } + uSource++; + test++; + } + ucnv_reset(cnv); + TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-KR encoding"); + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + ucnv_reset(cnv); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x1b,0x24,0x053}; + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_ESCAPE_SEQUENCE, "an invalid character [ISO-2022-KR]"); + } + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void TestJitterbug2411(){ + static const char* source = "\x1b\x24\x29\x43\x6b\x6b\x6e\x6e\x6a\x68\x70\x6f\x69\x75\x79\x71\x77\x65\x68\x67\x0A" + "\x1b\x24\x29\x43\x6a\x61\x73\x64\x66\x6a\x61\x73\x64\x66\x68\x6f\x69\x75\x79\x1b\x24\x29\x43"; + UConverter* kr=NULL, *kr1=NULL; + UErrorCode errorCode = U_ZERO_ERROR; + UChar tgt[100]={'\0'}; + UChar* target = tgt; + UChar* targetLimit = target+100; + kr=ucnv_open("iso-2022-kr", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022-kr converter: %s\n", u_errorName(errorCode)); + return; + } + ucnv_toUnicode(kr,&target,targetLimit,&source,source+uprv_strlen(source),NULL,TRUE,&errorCode); + if(U_FAILURE(errorCode)) { + log_err("iso-2022-kr cannot handle multiple escape sequences : %s\n", u_errorName(errorCode)); + return; + } + kr1 = ucnv_open("ibm-25546", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022-kr_1 converter: %s\n", u_errorName(errorCode)); + return; + } + target = tgt; + targetLimit = target+100; + ucnv_toUnicode(kr,&target,targetLimit,&source,source+uprv_strlen(source),NULL,TRUE,&errorCode); + + if(U_FAILURE(errorCode)) { + log_err("iso-2022-kr_1 cannot handle multiple escape sequences : %s\n", u_errorName(errorCode)); + return; + } + + ucnv_close(kr); + ucnv_close(kr1); + +} + +static void +TestJIS(){ + /* From Unicode moved to testdata/conversion.txt */ + /*To Unicode*/ + { + static const uint8_t sampleTextJIS[] = { + 0x1b,0x28,0x48,0x41,0x42, /*jis-Roman*/ + 0x1b,0x28,0x49,0x41,0x42, /*Katakana Set*/ + 0x1b,0x26,0x40,0x1b,0x24,0x42,0x21,0x21 /*recognize and ignore <esc>&@*/ + }; + static const uint16_t expectedISO2022JIS[] = { + 0x0041, 0x0042, + 0xFF81, 0xFF82, + 0x3000 + }; + static const int32_t toISO2022JISOffs[]={ + 3,4, + 8,9, + 16 + }; + + static const uint8_t sampleTextJIS7[] = { + 0x1b,0x28,0x48,0x41,0x42, /*JIS7-Roman*/ + 0x1b,0x28,0x49,0x41,0x42, /*Katakana Set*/ + 0x1b,0x24,0x42,0x21,0x21, + 0x0e,0x41,0x42,0x0f, /*Test Katakana set with SI and SO */ + 0x21,0x22, + 0x1b,0x26,0x40,0x1b,0x24,0x42,0x21,0x21 /*recognize and ignore <esc>&@*/ + }; + static const uint16_t expectedISO2022JIS7[] = { + 0x0041, 0x0042, + 0xFF81, 0xFF82, + 0x3000, + 0xFF81, 0xFF82, + 0x3001, + 0x3000 + }; + static const int32_t toISO2022JIS7Offs[]={ + 3,4, + 8,9, + 13,16, + 17, + 19,27 + }; + static const uint8_t sampleTextJIS8[] = { + 0x1b,0x28,0x48,0x41,0x42, /*JIS8-Roman*/ + 0xa1,0xc8,0xd9,/*Katakana Set*/ + 0x1b,0x28,0x42, + 0x41,0x42, + 0xb1,0xc3, /*Katakana Set*/ + 0x1b,0x24,0x42,0x21,0x21 + }; + static const uint16_t expectedISO2022JIS8[] = { + 0x0041, 0x0042, + 0xff61, 0xff88, 0xff99, + 0x0041, 0x0042, + 0xff71, 0xff83, + 0x3000 + }; + static const int32_t toISO2022JIS8Offs[]={ + 3, 4, 5, 6, + 7, 11, 12, 13, + 14, 18, + }; + + testConvertToU(sampleTextJIS,sizeof(sampleTextJIS),expectedISO2022JIS, + sizeof(expectedISO2022JIS)/sizeof(expectedISO2022JIS[0]),"JIS", toISO2022JISOffs,TRUE); + testConvertToU(sampleTextJIS7,sizeof(sampleTextJIS7),expectedISO2022JIS7, + sizeof(expectedISO2022JIS7)/sizeof(expectedISO2022JIS7[0]),"JIS7", toISO2022JIS7Offs,TRUE); + testConvertToU(sampleTextJIS8,sizeof(sampleTextJIS8),expectedISO2022JIS8, + sizeof(expectedISO2022JIS8)/sizeof(expectedISO2022JIS8[0]),"JIS8", toISO2022JIS8Offs,TRUE); + } + +} + +static void TestJitterbug915(){ +/* tests for roundtripping of the below sequence +\x1b$)G\x0E#!#"###$#%#&#'#(#)#*#+ / *plane 1 * / +\x1b$*H\x1bN"!\x1bN""\x1bN"#\x1bN"$\x1bN"% / *plane 2 * / +\x1b$+I\x1bO"D\x1bO"E\x1bO"F\x1bO"G\x1bO"H / *plane 3 * / +\x1b$+J\x1bO!D\x1bO!E\x1bO"j\x1bO"k\x1bO"l / *plane 4 * / +\x1b$+K\x1bO!t\x1bO"P\x1bO"Q\x1bO#7\x1bO"\ / *plane 5 * / +\x1b$+L\x1bO!#\x1bO",\x1bO#N\x1bO!n\x1bO#q / *plane 6 * / +\x1b$+M\x1bO"q\x1bO!N\x1bO!j\x1bO#:\x1bO#o / *plane 7 * / +*/ + static const char cSource[]={ + 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23, + 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A, + 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F, + 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21, + 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E, + 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x2F, 0x2A, 0x70, + 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A, + 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F, + 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47, + 0x1B, 0x4F, 0x22, 0x48, 0x2F, 0x2A, 0x70, 0x6C, 0x61, + 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, + 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21, + 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B, + 0x4F, 0x22, 0x6C, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50, + 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F, + 0x22, 0x5C, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, + 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, + 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C, + 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F, + 0x23, 0x71, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, + 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B, + 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B, + 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23, + 0x6F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, + 0x37, 0x20, 0x2A, 0x2F + }; + UChar uTarget[500]={'\0'}; + UChar* utarget=uTarget; + UChar* utargetLimit=uTarget+sizeof(uTarget)/2; + + char cTarget[500]={'\0'}; + char* ctarget=cTarget; + char* ctargetLimit=cTarget+sizeof(cTarget); + const char* csource=cSource; + const char* tempSrc = cSource; + UErrorCode err=U_ZERO_ERROR; + + UConverter* conv =ucnv_open("ISO_2022_CN_EXT",&err); + if(U_FAILURE(err)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err)); + return; + } + ucnv_toUnicode(conv,&utarget,utargetLimit,&csource,csource+sizeof(cSource),NULL,TRUE,&err); + if(U_FAILURE(err)) { + log_err("iso-2022-CN to Unicode conversion failed: %s\n", u_errorName(err)); + return; + } + utargetLimit=utarget; + utarget = uTarget; + ucnv_fromUnicode(conv,&ctarget,ctargetLimit,(const UChar**)&utarget,utargetLimit,NULL,TRUE,&err); + if(U_FAILURE(err)) { + log_err("iso-2022-CN from Unicode conversion failed: %s\n", u_errorName(err)); + return; + } + ctargetLimit=ctarget; + ctarget =cTarget; + while(ctarget<ctargetLimit){ + if(*ctarget != *tempSrc){ + log_err("j915[%d] Expected : \\x%02X \t Got: \\x%02X\n", (int)(ctarget-cTarget), *ctarget,(int)*tempSrc) ; + } + ++ctarget; + ++tempSrc; + } + + ucnv_close(conv); +} + +static void +TestISO_2022_CN_EXT() { + /* test input */ + static const uint16_t in[]={ + /* test Non-BMP code points */ + 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F, + 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8, + 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF, + 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6, + 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB, + 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0, + 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8, + 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF, + 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4, + 0xD869, 0xDED5, + + 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A, + 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A, + 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A, + 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A, + 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0x6332, 0x63B0, 0x643F, 0x000D, 0x000A, + 0x64D8, 0x8004, 0x6BEA, 0x6BF3, 0x6BFD, 0x6BF5, 0x6BF9, 0x6C05, 0x000D, 0x000A, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x000D, 0x000A, + 0x6C07, 0x6C06, 0x6C0D, 0x6C15, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9CE2, 0x977C, 0x9785, 0x9791, 0x9792, 0x9794, 0x97AF, 0x97AB, 0x000D, 0x000A, + 0x97A3, 0x97B2, 0x97B4, 0x9AB1, 0x9AB0, 0x9AB7, 0x9E58, 0x9AB6, 0x000D, 0x000A, + 0x9ABA, 0x9ABC, 0x9AC1, 0x9AC0, 0x9AC5, 0x9AC2, 0x9ACB, 0x9ACC, 0x000D, 0x000A, + 0x9AD1, 0x9B45, 0x9B43, 0x9B47, 0x9B49, 0x9B48, 0x9B4D, 0x9B51, 0x000D, 0x000A, + 0x98E8, 0x990D, 0x992E, 0x9955, 0x9954, 0x9ADF, 0x3443, 0x3444, 0x000D, 0x000A, + 0x3445, 0x3449, 0x344A, 0x344B, 0x60F2, 0x60F3, 0x60F4, 0x60F5, 0x000D, 0x000A, + 0x60F6, 0x60F7, 0x60F8, 0x60F9, 0x60FA, 0x60FB, 0x60FC, 0x60FD, 0x000D, 0x000A, + 0x60FE, 0x60FF, 0x6100, 0x6101, 0x6102, 0x0041, 0x0042, 0x0043, 0x000D, 0x000A, + 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x000D, 0x000A, + + 0x33E7, 0x33E8, 0x33E9, 0x33EA, 0x000D, 0x000A + + }; + + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 180; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ISO_2022,locale=cn,version=1", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 10); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + else{ + log_verbose(" Got: \\u%04X\n",(int)*test) ; + } + uSource++; + test++; + } + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x0e,0x24,0x053}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-CN-EXT]"); + } + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void +TestISO_2022_CN() { + /* test input */ + static const uint16_t in[]={ + /* jitterbug 951 */ + 0xFF2D, 0xFF49, 0xFF58, 0xFF45, 0xFF44, 0x0020, 0xFF43, 0xFF48, 0xFF41, 0xFF52, + 0x0020, 0xFF06, 0x0020, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, + 0xFF18, 0xFF19, 0xFF10, 0x0020, 0xFF4E, 0xFF55, 0xFF4D, 0xFF42, 0xFF45, 0xFF52, + 0x0020, 0xFF54, 0xFF45, 0xFF53, 0xFF54, 0x0020, 0xFF4C, 0xFF49, 0xFF4E, 0xFF45, + 0x0020, 0x0045, 0x004e, 0x0044, + /**/ + 0x4E00, 0x4E00, 0x4E01, 0x4E03, 0x60F6, 0x60F7, 0x60F8, 0x60FB, 0x000D, 0x000A, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x60FB, 0x60FC, 0x000D, 0x000A, + 0x4E07, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x0042, 0x0043, 0x000D, 0x000A, + 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A, + 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A, + 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0x6332, 0x63B0, 0x643F, 0x000D, 0x000A, + 0x64D8, 0x8004, 0x6BEA, 0x6BF3, 0x6BFD, 0x6BF5, 0x6BF9, 0x6C05, 0x000D, 0x000A, + 0x6C07, 0x6C06, 0x6C0D, 0x6C15, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A, + 0x9CE2, 0x977C, 0x9785, 0x9791, 0x9792, 0x9794, 0x97AF, 0x97AB, 0x000D, 0x000A, + 0x97A3, 0x97B2, 0x97B4, 0x9AB1, 0x9AB0, 0x9AB7, 0x9E58, 0x9AB6, 0x000D, 0x000A, + 0x9ABA, 0x9ABC, 0x9AC1, 0x9AC0, 0x9AC5, 0x9AC2, 0x9ACB, 0x9ACC, 0x000D, 0x000A, + 0x9AD1, 0x9B45, 0x9B43, 0x9B47, 0x9B49, 0x9B48, 0x9B4D, 0x9B51, 0x000D, 0x000A, + 0x98E8, 0x990D, 0x992E, 0x9955, 0x9954, 0x9ADF, 0x60FE, 0x60FF, 0x000D, 0x000A, + 0x60F2, 0x60F3, 0x60F4, 0x60F5, 0x000D, 0x000A, 0x60F9, 0x60FA, 0x000D, 0x000A, + 0x6100, 0x6101, 0x0041, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x000D, 0x000A, + 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, + 0x2487, 0x2460, 0x2461, 0xFF20, 0xFF21, 0xFF22, 0x0049, 0x004A, 0x000D, 0x000A, + + }; + const UChar* uSource; + const UChar* uSourceLimit; + const char* cSource; + const char* cSourceLimit; + UChar *uTargetLimit =NULL; + UChar *uTarget; + char *cTarget; + const char *cTargetLimit; + char *cBuf; + UChar *uBuf,*test; + int32_t uBufSize = 180; + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv; + int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5); + int32_t* myOff= offsets; + cnv=ucnv_open("ISO_2022,locale=cn,version=0", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode)); + return; + } + + uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5); + cBuf =(char*)malloc(uBufSize * sizeof(char) * 10); + uSource = (const UChar*)in; + uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0])); + cTarget = cBuf; + cTargetLimit = cBuf +uBufSize*5; + uTarget = uBuf; + uTargetLimit = uBuf+ uBufSize*5; + ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + cSource = cBuf; + cSourceLimit =cTarget; + test =uBuf; + myOff=offsets; + ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode); + if(U_FAILURE(errorCode)){ + log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode)); + return; + } + uSource = (const UChar*)in; + while(uSource<uSourceLimit){ + if(*test!=*uSource){ + log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ; + } + else{ + log_verbose(" Got: \\u%04X\n",(int)*test) ; + } + uSource++; + test++; + } + TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-CN encoding"); + TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv); + TestJitterbug930("csISO2022CN"); + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x0e,0x24,0x053}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-CN]"); + } + + ucnv_close(cnv); + free(uBuf); + free(cBuf); + free(offsets); +} + +static void +TestEBCDIC_STATEFUL() { + /* test input */ + static const uint8_t in[]={ + 0x61, + 0x1a, + 0x0f, 0x4b, + 0x42, + 0x40, + 0x36, + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x002f, + 1, 0x0092, + 2, 0x002e, + 1, 0xff62, + 1, 0x0020, + 1, 0x0096, + + }; + static const uint8_t in2[]={ + 0x0f, + 0xa1, + 0x01 + }; + + /* expected test results */ + static const int32_t results2[]={ + /* number of bytes read, code point */ + 2, 0x203E, + 1, 0x0001, + }; + + const char *source=(const char *)in, *limit=(const char *)in+sizeof(in); + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("ibm-930", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a EBCDIC_STATEFUL(ibm-930) converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, source, limit, results, "EBCDIC_STATEFUL(ibm-930)"); + ucnv_reset(cnv); + /* Test the condition when source >= sourceLimit */ + TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source"); + ucnv_reset(cnv); + /*Test for the condition where source > sourcelimit after consuming the shift chracter */ + { + static const uint8_t source1[]={0x0f}; + TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_INDEX_OUTOFBOUNDS_ERROR, "a character is truncated"); + } + /*Test for the condition where there is an invalid character*/ + ucnv_reset(cnv); + { + static const uint8_t source2[]={0x0e, 0x7F, 0xFF}; + TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [EBCDIC STATEFUL]"); + } + ucnv_reset(cnv); + source=(const char*)in2; + limit=(const char*)in2+sizeof(in2); + TestNextUChar(cnv,source,limit,results2,"EBCDIC_STATEFUL(ibm-930),seq#2"); + ucnv_close(cnv); + +} + +static void +TestGB18030() { + /* test input */ + static const uint8_t in[]={ + 0x24, + 0x7f, + 0x81, 0x30, 0x81, 0x30, + 0xa8, 0xbf, + 0xa2, 0xe3, + 0xd2, 0xbb, + 0x82, 0x35, 0x8f, 0x33, + 0x84, 0x31, 0xa4, 0x39, + 0x90, 0x30, 0x81, 0x30, + 0xe3, 0x32, 0x9a, 0x35 +#if 0 + /* + * Feature removed markus 2000-oct-26 + * Only some codepages must match surrogate pairs into supplementary code points - + * see javadoc for ucnv_getNextUChar() and implementation notes in ucnvmbcs.c . + * GB 18030 provides direct encodings for supplementary code points, therefore + * it must not combine two single-encoded surrogates into one code point. + */ + 0x83, 0x36, 0xc8, 0x30, 0x83, 0x37, 0xb0, 0x34 /* separately encoded surrogates */ +#endif + }; + + /* expected test results */ + static const int32_t results[]={ + /* number of bytes read, code point */ + 1, 0x24, + 1, 0x7f, + 4, 0x80, + 2, 0x1f9, + 2, 0x20ac, + 2, 0x4e00, + 4, 0x9fa6, + 4, 0xffff, + 4, 0x10000, + 4, 0x10ffff +#if 0 + /* Feature removed. See comment above. */ + 8, 0x10000 +#endif + }; + +/* const char *source=(const char *)in,*limit=(const char *)in+sizeof(in); */ + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv=ucnv_open("gb18030", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a gb18030 converter: %s\n", u_errorName(errorCode)); + return; + } + TestNextUChar(cnv, (const char *)in, (const char *)in+sizeof(in), results, "gb18030"); + ucnv_close(cnv); +} + +static void +TestLMBCS() { + /* LMBCS-1 string */ + static const uint8_t pszLMBCS[]={ + 0x61, + 0x01, 0x29, + 0x81, + 0xA0, + 0x0F, 0x27, + 0x0F, 0x91, + 0x14, 0x0a, 0x74, + 0x14, 0xF6, 0x02, + 0x14, 0xd8, 0x4d, 0x14, 0xdc, 0x56, /* UTF-16 surrogate pair */ + 0x10, 0x88, 0xA0, + }; + + /* Unicode UChar32 equivalents */ + static const UChar32 pszUnicode32[]={ + /* code point */ + 0x00000061, + 0x00002013, + 0x000000FC, + 0x000000E1, + 0x00000007, + 0x00000091, + 0x00000a74, + 0x00000200, + 0x00023456, /* code point for surrogate pair */ + 0x00005516 + }; + +/* Unicode UChar equivalents */ + static const UChar pszUnicode[]={ + /* code point */ + 0x0061, + 0x2013, + 0x00FC, + 0x00E1, + 0x0007, + 0x0091, + 0x0a74, + 0x0200, + 0xD84D, /* low surrogate */ + 0xDC56, /* high surrogate */ + 0x5516 + }; + +/* expected test results */ + static const int offsets32[]={ + /* number of bytes read, code point */ + 0, + 1, + 3, + 4, + 5, + 7, + 9, + 12, + 15, + 21, + 24 + }; + +/* expected test results */ + static const int offsets[]={ + /* number of bytes read, code point */ + 0, + 1, + 3, + 4, + 5, + 7, + 9, + 12, + 15, + 18, + 21, + 24 + }; + + + UConverter *cnv; + +#define NAME_LMBCS_1 "LMBCS-1" +#define NAME_LMBCS_2 "LMBCS-2" + + + /* Some basic open/close/property tests on some LMBCS converters */ + { + + char expected_subchars[] = {0x3F}; /* ANSI Question Mark */ + char new_subchars [] = {0x7F}; /* subst char used by SmartSuite..*/ + char get_subchars [1]; + const char * get_name; + UConverter *cnv1; + UConverter *cnv2; + + int8_t len = sizeof(get_subchars); + + UErrorCode errorCode=U_ZERO_ERROR; + + /* Open */ + cnv1=ucnv_open(NAME_LMBCS_1, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode)); + return; + } + cnv2=ucnv_open(NAME_LMBCS_2, &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a LMBCS-2 converter: %s\n", u_errorName(errorCode)); + return; + } + + /* Name */ + get_name = ucnv_getName (cnv1, &errorCode); + if (strcmp(NAME_LMBCS_1,get_name)){ + log_err("Unexpected converter name: %s\n", get_name); + } + get_name = ucnv_getName (cnv2, &errorCode); + if (strcmp(NAME_LMBCS_2,get_name)){ + log_err("Unexpected converter name: %s\n", get_name); + } + + /* substitution chars */ + ucnv_getSubstChars (cnv1, get_subchars, &len, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Failure on get subst chars: %s\n", u_errorName(errorCode)); + } + if (len!=1){ + log_err("Unexpected length of sub chars\n"); + } + if (get_subchars[0] != expected_subchars[0]){ + log_err("Unexpected value of sub chars\n"); + } + ucnv_setSubstChars (cnv2,new_subchars, len, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Failure on set subst chars: %s\n", u_errorName(errorCode)); + } + ucnv_getSubstChars (cnv2, get_subchars, &len, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Failure on get subst chars: %s\n", u_errorName(errorCode)); + } + if (len!=1){ + log_err("Unexpected length of sub chars\n"); + } + if (get_subchars[0] != new_subchars[0]){ + log_err("Unexpected value of sub chars\n"); + } + ucnv_close(cnv1); + ucnv_close(cnv2); + + } + + /* LMBCS to Unicode - offsets */ + { + UErrorCode errorCode=U_ZERO_ERROR; + + const char * pSource = (const char *)pszLMBCS; + const char * sourceLimit = (const char *)pszLMBCS + sizeof(pszLMBCS); + + UChar Out [sizeof(pszUnicode) + 1]; + UChar * pOut = Out; + UChar * OutLimit = Out + sizeof(pszUnicode)/sizeof(UChar); + + int32_t off [sizeof(offsets)]; + + /* last 'offset' in expected results is just the final size. + (Makes other tests easier). Compensate here: */ + + off[(sizeof(offsets)/sizeof(offsets[0]))-1] = sizeof(pszLMBCS); + + + + cnv=ucnv_open("lmbcs", &errorCode); /* use generic name for LMBCS-1 */ + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a LMBCS converter: %s\n", u_errorName(errorCode)); + return; + } + + + + ucnv_toUnicode (cnv, + &pOut, + OutLimit, + &pSource, + sourceLimit, + off, + TRUE, + &errorCode); + + + if (memcmp(off,offsets,sizeof(offsets))) + { + log_err("LMBCS->Uni: Calculated offsets do not match expected results\n"); + } + if (memcmp(Out,pszUnicode,sizeof(pszUnicode))) + { + log_err("LMBCS->Uni: Calculated codepoints do not match expected results\n"); + } + ucnv_close(cnv); + } + { + /* LMBCS to Unicode - getNextUChar */ + const char * sourceStart; + const char *source=(const char *)pszLMBCS; + const char *limit=(const char *)pszLMBCS+sizeof(pszLMBCS); + const UChar32 *results= pszUnicode32; + const int *off = offsets32; + + UErrorCode errorCode=U_ZERO_ERROR; + UChar32 uniChar; + + cnv=ucnv_open("LMBCS-1", &errorCode); + if(U_FAILURE(errorCode)) { + log_data_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode)); + return; + } + else + { + + while(source<limit) { + sourceStart=source; + uniChar=ucnv_getNextUChar(cnv, &source, source + (off[1] - off[0]), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("LMBCS-1 ucnv_getNextUChar() failed: %s\n", u_errorName(errorCode)); + break; + } else if(source-sourceStart != off[1] - off[0] || uniChar != *results) { + log_err("LMBCS-1 ucnv_getNextUChar() result %lx from %d bytes, should have been %lx from %d bytes.\n", + uniChar, (source-sourceStart), *results, *off); + break; + } + results++; + off++; + } + } + ucnv_close(cnv); + } + { /* test locale & optimization group operations: Unicode to LMBCS */ + + UErrorCode errorCode=U_ZERO_ERROR; + UConverter *cnv16he = ucnv_open("LMBCS-16,locale=he", &errorCode); + UConverter *cnv16jp = ucnv_open("LMBCS-16,locale=ja_JP", &errorCode); + UConverter *cnv01us = ucnv_open("LMBCS-1,locale=us_EN", &errorCode); + UChar uniString [] = {0x0192}; /* Latin Small letter f with hook */ + const UChar * pUniOut = uniString; + UChar * pUniIn = uniString; + uint8_t lmbcsString [4]; + const char * pLMBCSOut = (const char *)lmbcsString; + char * pLMBCSIn = (char *)lmbcsString; + + /* 0192 (hook) converts to both group 3 & group 1. input locale should differentiate */ + ucnv_fromUnicode (cnv16he, + &pLMBCSIn, (pLMBCSIn + sizeof(lmbcsString)/sizeof(lmbcsString[0])), + &pUniOut, pUniOut + sizeof(uniString)/sizeof(uniString[0]), + NULL, 1, &errorCode); + + if (lmbcsString[0] != 0x3 || lmbcsString[1] != 0x83) + { + log_err("LMBCS-16,locale=he gives unexpected translation\n"); + } + + pLMBCSIn= (char *)lmbcsString; + pUniOut = uniString; + ucnv_fromUnicode (cnv01us, + &pLMBCSIn, (const char *)(lmbcsString + sizeof(lmbcsString)/sizeof(lmbcsString[0])), + &pUniOut, pUniOut + sizeof(uniString)/sizeof(uniString[0]), + NULL, 1, &errorCode); + + if (lmbcsString[0] != 0x9F) + { + log_err("LMBCS-1,locale=US gives unexpected translation\n"); + } + + /* single byte char from mbcs char set */ + lmbcsString[0] = 0xAE; /* 1/2 width katakana letter small Yo */ + pLMBCSOut = (const char *)lmbcsString; + pUniIn = uniString; + ucnv_toUnicode (cnv16jp, + &pUniIn, pUniIn + 1, + &pLMBCSOut, (pLMBCSOut + 1), + NULL, 1, &errorCode); + if (U_FAILURE(errorCode) || pLMBCSOut != (const char *)lmbcsString+1 || pUniIn != uniString+1 || uniString[0] != 0xFF6E) + { + log_err("Unexpected results from LMBCS-16 single byte char\n"); + } + /* convert to group 1: should be 3 bytes */ + pLMBCSIn = (char *)lmbcsString; + pUniOut = uniString; + ucnv_fromUnicode (cnv01us, + &pLMBCSIn, (const char *)(pLMBCSIn + 3), + &pUniOut, pUniOut + 1, + NULL, 1, &errorCode); + if (U_FAILURE(errorCode) || pLMBCSIn != (const char *)lmbcsString+3 || pUniOut != uniString+1 + || lmbcsString[0] != 0x10 || lmbcsString[1] != 0x10 || lmbcsString[2] != 0xAE) + { + log_err("Unexpected results to LMBCS-1 single byte mbcs char\n"); + } + pLMBCSOut = (const char *)lmbcsString; + pUniIn = uniString; + ucnv_toUnicode (cnv01us, + &pUniIn, pUniIn + 1, + &pLMBCSOut, (const char *)(pLMBCSOut + 3), + NULL, 1, &errorCode); + if (U_FAILURE(errorCode) || pLMBCSOut != (const char *)lmbcsString+3 || pUniIn != uniString+1 || uniString[0] != 0xFF6E) + { + log_err("Unexpected results from LMBCS-1 single byte mbcs char\n"); + } + pLMBCSIn = (char *)lmbcsString; + pUniOut = uniString; + ucnv_fromUnicode (cnv16jp, + &pLMBCSIn, (const char *)(pLMBCSIn + 1), + &pUniOut, pUniOut + 1, + NULL, 1, &errorCode); + if (U_FAILURE(errorCode) || pLMBCSIn != (const char *)lmbcsString+1 || pUniOut != uniString+1 || lmbcsString[0] != 0xAE) + { + log_err("Unexpected results to LMBCS-16 single byte mbcs char\n"); + } + ucnv_close(cnv16he); + ucnv_close(cnv16jp); + ucnv_close(cnv01us); + } + { + /* Small source buffer testing, LMBCS -> Unicode */ + + UErrorCode errorCode=U_ZERO_ERROR; + + const char * pSource = (const char *)pszLMBCS; + const char * sourceLimit = (const char *)pszLMBCS + sizeof(pszLMBCS); + int codepointCount = 0; + + UChar Out [sizeof(pszUnicode) + 1]; + UChar * pOut = Out; + UChar * OutLimit = Out + sizeof(pszUnicode)/sizeof(UChar); + + + cnv = ucnv_open(NAME_LMBCS_1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode)); + return; + } + + + while ((pSource < sourceLimit) && U_SUCCESS (errorCode)) + { + ucnv_toUnicode (cnv, + &pOut, + OutLimit, + &pSource, + (pSource+1), /* claim that this is a 1- byte buffer */ + NULL, + FALSE, /* FALSE means there might be more chars in the next buffer */ + &errorCode); + + if (U_SUCCESS (errorCode)) + { + if ((pSource - (const char *)pszLMBCS) == offsets [codepointCount+1]) + { + /* we are on to the next code point: check value */ + + if (Out[0] != pszUnicode[codepointCount]){ + log_err("LMBCS->Uni result %lx should have been %lx \n", + Out[0], pszUnicode[codepointCount]); + } + + pOut = Out; /* reset for accumulating next code point */ + codepointCount++; + } + } + else + { + log_err("Unexpected Error on toUnicode: %s\n", u_errorName(errorCode)); + } + } + { + /* limits & surrogate error testing */ + char LIn [sizeof(pszLMBCS)]; + const char * pLIn = LIn; + + char LOut [sizeof(pszLMBCS)]; + char * pLOut = LOut; + + UChar UOut [sizeof(pszUnicode)]; + UChar * pUOut = UOut; + + UChar UIn [sizeof(pszUnicode)]; + const UChar * pUIn = UIn; + + int32_t off [sizeof(offsets)]; + UChar32 uniChar; + + errorCode=U_ZERO_ERROR; + + /* negative source request should always return U_ILLEGAL_ARGUMENT_ERROR */ + ucnv_fromUnicode(cnv, &pLOut,pLOut+1,&pUIn,pUIn-1,off,FALSE, &errorCode); + if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("Unexpected Error on negative source request to ucnv_fromUnicode: %s\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + ucnv_toUnicode(cnv, &pUOut,pUOut+1,(const char **)&pLIn,(const char *)(pLIn-1),off,FALSE, &errorCode); + if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("Unexpected Error on negative source request to ucnv_toUnicode: %s\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + + uniChar = ucnv_getNextUChar(cnv, (const char **)&pLIn, (const char *)(pLIn-1), &errorCode); + if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("Unexpected Error on negative source request to ucnv_getNextUChar: %s\n", u_errorName(errorCode)); + } + errorCode=U_ZERO_ERROR; + + /* 0 byte source request - no error, no pointer movement */ + ucnv_toUnicode(cnv, &pUOut,pUOut+1,(const char **)&pLIn,(const char *)pLIn,off,FALSE, &errorCode); + ucnv_fromUnicode(cnv, &pLOut,pLOut+1,&pUIn,pUIn,off,FALSE, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("0 byte source request: unexpected error: %s\n", u_errorName(errorCode)); + } + if ((pUOut != UOut) || (pUIn != UIn) || (pLOut != LOut) || (pLIn != LIn)) + { + log_err("Unexpected pointer move in 0 byte source request \n"); + } + /*0 byte source request - GetNextUChar : error & value == fffe or ffff */ + uniChar = ucnv_getNextUChar(cnv, (const char **)&pLIn, (const char *)pLIn, &errorCode); + if (errorCode != U_INDEX_OUTOFBOUNDS_ERROR) + { + log_err("Unexpected Error on 0-byte source request to ucnv_getnextUChar: %s\n", u_errorName(errorCode)); + } + if (((uint32_t)uniChar - 0xfffe) > 1) /* not 0xfffe<=uniChar<=0xffff */ + { + log_err("Unexpected value on 0-byte source request to ucnv_getnextUChar \n"); + } + errorCode = U_ZERO_ERROR; + + /* running out of target room : U_BUFFER_OVERFLOW_ERROR */ + + pUIn = pszUnicode; + ucnv_fromUnicode(cnv, &pLOut,pLOut+offsets[4],&pUIn,pUIn+sizeof(pszUnicode)/sizeof(UChar),off,FALSE, &errorCode); + if (errorCode != U_BUFFER_OVERFLOW_ERROR || pLOut != LOut + offsets[4] || pUIn != pszUnicode+4 ) + { + log_err("Unexpected results on out of target room to ucnv_fromUnicode\n"); + } + + errorCode = U_ZERO_ERROR; + + pLIn = (const char *)pszLMBCS; + ucnv_toUnicode(cnv, &pUOut,pUOut+4,&pLIn,(pLIn+sizeof(pszLMBCS)),off,FALSE, &errorCode); + if (errorCode != U_BUFFER_OVERFLOW_ERROR || pUOut != UOut + 4 || pLIn != (const char *)pszLMBCS+offsets[4]) + { + log_err("Unexpected results on out of target room to ucnv_toUnicode\n"); + } + + /* unpaired or chopped LMBCS surrogates */ + + /* OK high surrogate, Low surrogate is chopped */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + LIn [3] = (char)0x14; + LIn [4] = (char)0xDC; + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode); + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode); + if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 5) + { + log_err("Unexpected results on chopped low surrogate\n"); + } + + /* chopped at surrogate boundary */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+3),off,TRUE, &errorCode); + if (UOut[0] != 0xD801 || U_FAILURE(errorCode) || pUOut != UOut + 1 || pLIn != LIn + 3) + { + log_err("Unexpected results on chopped at surrogate boundary \n"); + } + + /* unpaired surrogate plus valid Unichar */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + LIn [3] = (char)0x14; + LIn [4] = (char)0xC9; + LIn [5] = (char)0xD0; + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+6),off,TRUE, &errorCode); + if (UOut[0] != 0xD801 || UOut[1] != 0xC9D0 || U_FAILURE(errorCode) || pUOut != UOut + 2 || pLIn != LIn + 6) + { + log_err("Unexpected results after unpaired surrogate plus valid Unichar \n"); + } + + /* unpaired surrogate plus chopped Unichar */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + LIn [3] = (char)0x14; + LIn [4] = (char)0xC9; + + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode); + if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 5) + { + log_err("Unexpected results after unpaired surrogate plus chopped Unichar \n"); + } + + /* unpaired surrogate plus valid non-Unichar */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + LIn [3] = (char)0x0F; + LIn [4] = (char)0x3B; + + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode); + if (UOut[0] != 0xD801 || UOut[1] != 0x1B || U_FAILURE(errorCode) || pUOut != UOut + 2 || pLIn != LIn + 5) + { + log_err("Unexpected results after unpaired surrogate plus valid non-Unichar\n"); + } + + /* unpaired surrogate plus chopped non-Unichar */ + LIn [0] = (char)0x14; + LIn [1] = (char)0xD8; + LIn [2] = (char)0x01; + LIn [3] = (char)0x0F; + + pLIn = LIn; + errorCode = U_ZERO_ERROR; + pUOut = UOut; + + ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+4),off,TRUE, &errorCode); + + if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 4) + { + log_err("Unexpected results after unpaired surrogate plus chopped non-Unichar\n"); + } + } + } + ucnv_close(cnv); /* final cleanup */ +} + + +static void TestJitterbug255() +{ + static const uint8_t testBytes[] = { 0x95, 0xcf, 0x8a, 0xb7, 0x0d, 0x0a, 0x00 }; + const char *testBuffer = (const char *)testBytes; + const char *testEnd = (const char *)testBytes + sizeof(testBytes); + UErrorCode status = U_ZERO_ERROR; + UChar32 result; + UConverter *cnv = 0; + + cnv = ucnv_open("shift-jis", &status); + if (U_FAILURE(status) || cnv == 0) { + log_data_err("Failed to open the converter for SJIS.\n"); + return; + } + while (testBuffer != testEnd) + { + result = ucnv_getNextUChar (cnv, &testBuffer, testEnd , &status); + if (U_FAILURE(status)) + { + log_err("Failed to convert the next UChar for SJIS.\n"); + break; + } + } + ucnv_close(cnv); +} + +static void TestEBCDICUS4XML() +{ + UChar unicodes_x[] = {0x0000, 0x0000, 0x0000, 0x0000}; + static const UChar toUnicodeMaps_x[] = {0x000A, 0x000A, 0x000D, 0x0000}; + static const char fromUnicodeMaps_x[] = {0x25, 0x25, 0x0D, 0x00}; + static const char newLines_x[] = {0x25, 0x15, 0x0D, 0x00}; + char target_x[] = {0x00, 0x00, 0x00, 0x00}; + UChar *unicodes = unicodes_x; + const UChar *toUnicodeMaps = toUnicodeMaps_x; + char *target = target_x; + const char* fromUnicodeMaps = fromUnicodeMaps_x, *newLines = newLines_x; + UErrorCode status = U_ZERO_ERROR; + UConverter *cnv = 0; + + cnv = ucnv_open("ebcdic-xml-us", &status); + if (U_FAILURE(status) || cnv == 0) { + log_data_err("Failed to open the converter for EBCDIC-XML-US.\n"); + return; + } + ucnv_toUnicode(cnv, &unicodes, unicodes+3, (const char**)&newLines, newLines+3, NULL, TRUE, &status); + if (U_FAILURE(status) || memcmp(unicodes_x, toUnicodeMaps, sizeof(UChar)*3) != 0) { + log_err("To Unicode conversion failed in EBCDICUS4XML test. %s\n", + u_errorName(status)); + printUSeqErr(unicodes_x, 3); + printUSeqErr(toUnicodeMaps, 3); + } + status = U_ZERO_ERROR; + ucnv_fromUnicode(cnv, &target, target+3, (const UChar**)&toUnicodeMaps, toUnicodeMaps+3, NULL, TRUE, &status); + if (U_FAILURE(status) || memcmp(target_x, fromUnicodeMaps, sizeof(char)*3) != 0) { + log_err("From Unicode conversion failed in EBCDICUS4XML test. %s\n", + u_errorName(status)); + printSeqErr((const unsigned char*)target_x, 3); + printSeqErr((const unsigned char*)fromUnicodeMaps, 3); + } + ucnv_close(cnv); +} +#endif /* #if !UCONFIG_NO_LEGACY_COLLATION */ + +#if !UCONFIG_NO_COLLATION + +static void TestJitterbug981(){ + const UChar* rules; + int32_t rules_length, target_cap, bytes_needed, buff_size; + UErrorCode status = U_ZERO_ERROR; + UConverter *utf8cnv; + UCollator* myCollator; + char *buff; + int numNeeded=0; + utf8cnv = ucnv_open ("utf8", &status); + if(U_FAILURE(status)){ + log_err("Could not open UTF-8 converter. Error: %s", u_errorName(status)); + return; + } + myCollator = ucol_open("zh", &status); + if(U_FAILURE(status)){ + log_err("Could not open collator for zh locale. Error: %s", u_errorName(status)); + return; + } + + rules = ucol_getRules(myCollator, &rules_length); + buff_size = rules_length * ucnv_getMaxCharSize(utf8cnv); + buff = malloc(buff_size); + + target_cap = 0; + do { + ucnv_reset(utf8cnv); + status = U_ZERO_ERROR; + if(target_cap >= buff_size) { + log_err("wanted %d bytes, only %d available\n", target_cap, buff_size); + break; + } + bytes_needed = ucnv_fromUChars(utf8cnv, buff, target_cap, + rules, rules_length, &status); + target_cap = (bytes_needed > target_cap) ? bytes_needed : target_cap +1; + if(numNeeded!=0 && numNeeded!= bytes_needed){ + log_err("ucnv_fromUChars returns different values for required capacity in pre-flight and conversion modes"); + break; + } + numNeeded = bytes_needed; + } while (status == U_BUFFER_OVERFLOW_ERROR); + ucol_close(myCollator); + ucnv_close(utf8cnv); + free(buff); +} + +#endif + +static void TestJitterbug1293(){ + static const UChar src[] = {0x30DE, 0x30A4, 0x5E83, 0x544A, 0x30BF, 0x30A4, 0x30D7,0x000}; + char target[256]; + UErrorCode status = U_ZERO_ERROR; + UConverter* conv=NULL; + int32_t target_cap, bytes_needed, numNeeded = 0; + conv = ucnv_open("shift-jis",&status); + if(U_FAILURE(status)){ + log_data_err("Could not open Shift-Jis converter. Error: %s", u_errorName(status)); + return; + } + + do{ + target_cap =0; + bytes_needed = ucnv_fromUChars(conv,target,256,src,u_strlen(src),&status); + target_cap = (bytes_needed > target_cap) ? bytes_needed : target_cap +1; + if(numNeeded!=0 && numNeeded!= bytes_needed){ + log_err("ucnv_fromUChars returns different values for required capacity in pre-flight and conversion modes"); + } + numNeeded = bytes_needed; + } while (status == U_BUFFER_OVERFLOW_ERROR); + if(U_FAILURE(status)){ + log_err("An error occured in ucnv_fromUChars. Error: %s", u_errorName(status)); + return; + } + ucnv_close(conv); +} +static void TestJB5275_1(){ + + static const char* data = "\x3B\xB3\x0A" /* Easy characters */ + "\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Gurmukhi test */ + /* Switch script: */ + "\xEF\x43\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Bengali test */ + "\x3B\xB3\x0A" /* Easy characters - new line, so should default!*/ + "\xEF\x40\x3B\xB3\x0A"; + static const UChar expected[] ={ + 0x003b, 0x0a15, 0x000a, /* Easy characters */ + 0x0a22, 0x0a3c, 0x0a5c, 0x0a4d, 0x0a39, 0x000a, /* Gurmukhi test */ + 0x09dd, 0x09dc, 0x09cd, 0x09b9, 0x000a, /* Switch script: to Bengali*/ + 0x003b, 0x0a15, 0x000a, /* Easy characters - new line, so should default!*/ + 0x003b, 0x0a15, 0x000a /* Back to Gurmukhi*/ + }; + + UErrorCode status = U_ZERO_ERROR; + UConverter* conv = ucnv_open("iscii-gur", &status); + UChar dest[100] = {'\0'}; + UChar* target = dest; + UChar* targetLimit = dest+100; + const char* source = data; + const char* sourceLimit = data+strlen(data); + const UChar* exp = expected; + log_verbose("Testing switching back to default script when new line is encountered.\n"); + ucnv_toUnicode(conv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &status); + if(U_FAILURE(status)){ + log_err("conversion failed: %s \n", u_errorName(status)); + } + targetLimit = target; + target = dest; + printUSeq(target, targetLimit-target); + while(target<targetLimit){ + if(*exp!=*target){ + log_err("did not get the expected output. \\u%04X != \\u%04X (got)\n", *exp, *target); + } + target++; + exp++; + } + ucnv_close(conv); +} + +static void TestJB5275(){ + static const char* data = + /* "\xEF\x42\xEF\x41\xA4\xD5\xE5\xB3\xEA\x0A" unsupported sequence \xEF\x41 */ + /* "\xEF\x42\xEF\x41\xD4\xDA\xB3\xE8\xEA\x0A" unsupported sequence \xEF\x41 */ + /* "\xEF\x44\xEF\x41\xC8\xE1\x8B\xDB\xB3\xE8 \xB3\xE4\xC1\xE8\x0A" unsupported sequence \xEF\x41 */ + "\xEF\x4B\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Gurmukhi test */ + "\xEF\x4A\xC0\xD4\xBF\xD4\xE8\xD8\x0A" /* Gujarati test */ + "\xEF\x48\x38\xB3\x0A" /* Kannada test */ + "\xEF\x49\x39\xB3\x0A" /* Malayalam test */ + "\xEF\x4A\x3A\xB3\x0A" /* Gujarati test */ + "\xEF\x4B\x3B\xB3\x0A" /* Punjabi test */ + /* "\xEF\x4C\x3C\xB3\x0A" unsupported sequence \xEF\x41 */; + static const UChar expected[] ={ + 0x0A22, 0x0A3C, 0x0A5C, 0x0A4D, 0x0A39, 0x000A, /* Gurmukhi test */ + 0x0AA2, 0x0AB5, 0x0AA1, 0x0AB5, 0x0ACD, 0x0AB9, 0x000A, /* Gujarati test */ + 0x0038, 0x0C95, 0x000A, /* Kannada test */ + 0x0039, 0x0D15, 0x000A, /* Malayalam test */ + 0x003A, 0x0A95, 0x000A, /* Gujarati test */ + 0x003B, 0x0A15, 0x000A, /* Punjabi test */ + }; + + UErrorCode status = U_ZERO_ERROR; + UConverter* conv = ucnv_open("iscii", &status); + UChar dest[100] = {'\0'}; + UChar* target = dest; + UChar* targetLimit = dest+100; + const char* source = data; + const char* sourceLimit = data+strlen(data); + const UChar* exp = expected; + ucnv_toUnicode(conv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &status); + if(U_FAILURE(status)){ + log_err("conversion failed: %s \n", u_errorName(status)); + } + targetLimit = target; + target = dest; + + printUSeq(target, targetLimit-target); + + while(target<targetLimit){ + if(*exp!=*target){ + log_err("did not get the expected output. \\u%04X != \\u%04X (got)\n", *exp, *target); + } + target++; + exp++; + } + ucnv_close(conv); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h new file mode 100644 index 00000000000..e70bc08163f --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h @@ -0,0 +1,23 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1997-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File NUCNVTST.H +* +* Modification History: +* Name Description +* Madhu Katragadda creation +********************************************************************************* +*/ +#ifndef _NUCNVTST +#define _NUCNVTST +/* C API TEST FOR CODESET CONVERSION COMPONENT */ +#include "cintltst.h" +#include "unicode/utypes.h" + +static void TestInBufSizes(void); + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c new file mode 100644 index 00000000000..e6cff642b23 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c @@ -0,0 +1,371 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1998-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File putiltst.c (Tests the API in putil) +* +* Modification History: +* +* Date Name Description +* 07/12/2000 Madhu Creation +******************************************************************************* +*/ + +#include "unicode/utypes.h" +#include "cintltst.h" +#include "cmemory.h" +#include "unicode/putil.h" +#include "unicode/ustring.h" +#include "cstring.h" +#include "putilimp.h" + +static UBool compareWithNAN(double x, double y); +static void doAssert(double expect, double got, const char *message); + +static void TestPUtilAPI(void){ + + double n1=0.0, y1=0.0, expn1, expy1; + double value1 = 0.021; + UVersionInfo versionArray = {0x01, 0x00, 0x02, 0x02}; + char versionString[17]; /* xxx.xxx.xxx.xxx\0 */ + char *str=0; + UBool isTrue=FALSE; + + log_verbose("Testing the API uprv_modf()\n"); + y1 = uprv_modf(value1, &n1); + expn1=0; + expy1=0.021; + if(y1 != expy1 || n1 != expn1){ + log_err("Error in uprv_modf. Expected IntegralValue=%f, Got=%f, \n Expected FractionalValue=%f, Got=%f\n", + expn1, n1, expy1, y1); + } + if(VERBOSITY){ + log_verbose("[float] x = %f n = %f y = %f\n", value1, n1, y1); + } + log_verbose("Testing the API uprv_fmod()\n"); + expn1=uprv_fmod(30.50, 15.00); + doAssert(expn1, 0.5, "uprv_fmod(30.50, 15.00) failed."); + + log_verbose("Testing the API uprv_ceil()\n"); + expn1=uprv_ceil(value1); + doAssert(expn1, 1, "uprv_ceil(0.021) failed."); + + log_verbose("Testing the API uprv_floor()\n"); + expn1=uprv_floor(value1); + doAssert(expn1, 0, "uprv_floor(0.021) failed."); + + log_verbose("Testing the API uprv_fabs()\n"); + expn1=uprv_fabs((2.02-1.345)); + doAssert(expn1, 0.675, "uprv_fabs(2.02-1.345) failed."); + + log_verbose("Testing the API uprv_fmax()\n"); + doAssert(uprv_fmax(2.4, 1.2), 2.4, "uprv_fmax(2.4, 1.2) failed."); + + log_verbose("Testing the API uprv_fmax() with x value= NaN\n"); + expn1=uprv_fmax(uprv_getNaN(), 1.2); + doAssert(expn1, uprv_getNaN(), "uprv_fmax(uprv_getNaN(), 1.2) failed. when one parameter is NaN"); + + log_verbose("Testing the API uprv_fmin()\n"); + doAssert(uprv_fmin(2.4, 1.2), 1.2, "uprv_fmin(2.4, 1.2) failed."); + + log_verbose("Testing the API uprv_fmin() with x value= NaN\n"); + expn1=uprv_fmin(uprv_getNaN(), 1.2); + doAssert(expn1, uprv_getNaN(), "uprv_fmin(uprv_getNaN(), 1.2) failed. when one parameter is NaN"); + + log_verbose("Testing the API uprv_max()\n"); + doAssert(uprv_max(4, 2), 4, "uprv_max(4, 2) failed."); + + log_verbose("Testing the API uprv_min()\n"); + doAssert(uprv_min(-4, 2), -4, "uprv_min(-4, 2) failed."); + + log_verbose("Testing the API uprv_trunc()\n"); + doAssert(uprv_trunc(12.3456), 12, "uprv_trunc(12.3456) failed."); + doAssert(uprv_trunc(12.234E2), 1223, "uprv_trunc(12.234E2) failed."); + doAssert(uprv_trunc(uprv_getNaN()), uprv_getNaN(), "uprv_trunc(uprv_getNaN()) failed. with parameter=NaN"); + doAssert(uprv_trunc(uprv_getInfinity()), uprv_getInfinity(), "uprv_trunc(uprv_getInfinity()) failed. with parameter=Infinity"); + + + log_verbose("Testing the API uprv_pow10()\n"); + doAssert(uprv_pow10(4), 10000, "uprv_pow10(4) failed."); + + log_verbose("Testing the API uprv_isNegativeInfinity()\n"); + isTrue=uprv_isNegativeInfinity(uprv_getInfinity() * -1); + if(isTrue != TRUE){ + log_err("ERROR: uprv_isNegativeInfinity failed.\n"); + } + log_verbose("Testing the API uprv_isPositiveInfinity()\n"); + isTrue=uprv_isPositiveInfinity(uprv_getInfinity()); + if(isTrue != TRUE){ + log_err("ERROR: uprv_isPositiveInfinity failed.\n"); + } + log_verbose("Testing the API uprv_isInfinite()\n"); + isTrue=uprv_isInfinite(uprv_getInfinity()); + if(isTrue != TRUE){ + log_err("ERROR: uprv_isInfinite failed.\n"); + } + +#if 0 + log_verbose("Testing the API uprv_digitsAfterDecimal()....\n"); + doAssert(uprv_digitsAfterDecimal(value1), 3, "uprv_digitsAfterDecimal() failed."); + doAssert(uprv_digitsAfterDecimal(1.2345E2), 2, "uprv_digitsAfterDecimal(1.2345E2) failed."); + doAssert(uprv_digitsAfterDecimal(1.2345E-2), 6, "uprv_digitsAfterDecimal(1.2345E-2) failed."); + doAssert(uprv_digitsAfterDecimal(1.2345E2), 2, "uprv_digitsAfterDecimal(1.2345E2) failed."); + doAssert(uprv_digitsAfterDecimal(-1.2345E-20), 24, "uprv_digitsAfterDecimal(1.2345E-20) failed."); + doAssert(uprv_digitsAfterDecimal(1.2345E20), 0, "uprv_digitsAfterDecimal(1.2345E20) failed."); + doAssert(uprv_digitsAfterDecimal(-0.021), 3, "uprv_digitsAfterDecimal(-0.021) failed."); + doAssert(uprv_digitsAfterDecimal(23.0), 0, "uprv_digitsAfterDecimal(23.0) failed."); + doAssert(uprv_digitsAfterDecimal(0.022223333321), 9, "uprv_digitsAfterDecimal(0.022223333321) failed."); +#endif + + + log_verbose("Testing the API u_versionToString().....\n"); + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "1.0.2.2") != 0){ + log_err("ERROR: u_versionToString() failed. Expected: 1.0.2.2, Got=%s\n", versionString); + } + log_verbose("Testing the API u_versionToString().....with versionArray=NULL\n"); + u_versionToString(NULL, versionString); + if(strcmp(versionString, "") != 0){ + log_err("ERROR: u_versionToString() failed. with versionArray=NULL. It should just return\n"); + } + log_verbose("Testing the API u_versionToString().....with versionArray=NULL\n"); + u_versionToString(NULL, versionString); + if(strcmp(versionString, "") != 0){ + log_err("ERROR: u_versionToString() failed . It should just return\n"); + } + log_verbose("Testing the API u_versionToString().....with versionString=NULL\n"); + u_versionToString(versionArray, NULL); + if(strcmp(versionString, "") != 0){ + log_err("ERROR: u_versionToString() failed. with versionArray=NULL It should just return\n"); + } + versionArray[0] = 0x0a; + log_verbose("Testing the API u_versionToString().....\n"); + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "10.0.2.2") != 0){ + log_err("ERROR: u_versionToString() failed. Expected: 10.0.2.2, Got=%s\n", versionString); + } + versionArray[0] = 0xa0; + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "160.0.2.2") != 0){ + log_err("ERROR: u_versionToString() failed. Expected: 160.0.2.2, Got=%s\n", versionString); + } + versionArray[0] = 0xa0; + versionArray[1] = 0xa0; + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "160.160.2.2") != 0){ + log_err("ERROR: u_versionToString() failed. Expected: 160.160.2.2, Got=%s\n", versionString); + } + versionArray[0] = 0x01; + versionArray[1] = 0x0a; + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "1.10.2.2") != 0){ + log_err("ERROR: u_versionToString() failed. Expected: 160.160.2.2, Got=%s\n", versionString); + } + + log_verbose("Testing the API u_versionFromString() ....\n"); + u_versionFromString(versionArray, "1.3.5.6"); + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "1.3.5.6") != 0){ + log_err("ERROR: u_getVersion() failed. Expected: 1.3.5.6, Got=%s\n", versionString); + } + log_verbose("Testing the API u_versionFromString() where versionArray=NULL....\n"); + u_versionFromString(NULL, "1.3.5.6"); + u_versionToString(versionArray, versionString); + if(strcmp(versionString, "1.3.5.6") != 0){ + log_err("ERROR: u_getVersion() failed. Expected: 1.3.5.6, Got=%s\n", versionString); + } + + log_verbose("Testing the API u_getVersion().....\n"); + u_getVersion(versionArray); + u_versionToString(versionArray, versionString); + if(strcmp(versionString, U_ICU_VERSION) != 0){ + log_err("ERROR: u_getVersion() failed. Got=%s, expected %s\n", versionString, U_ICU_VERSION); + } + log_verbose("Testing the API u_errorName()...\n"); + str=(char*)u_errorName((UErrorCode)0); + if(strcmp(str, "U_ZERO_ERROR") != 0){ + log_err("ERROR: u_getVersion() failed. Expected: U_ZERO_ERROR Got=%s\n", str); + } + log_verbose("Testing the API u_errorName()...\n"); + str=(char*)u_errorName((UErrorCode)-127); + if(strcmp(str, "U_USING_DEFAULT_WARNING") != 0){ + log_err("ERROR: u_getVersion() failed. Expected: U_USING_DEFAULT_WARNING Got=%s\n", str); + } + log_verbose("Testing the API u_errorName().. with BOGUS ERRORCODE...\n"); + str=(char*)u_errorName((UErrorCode)200); + if(strcmp(str, "[BOGUS UErrorCode]") != 0){ + log_err("ERROR: u_getVersion() failed. Expected: [BOGUS UErrorCode] Got=%s\n", str); + } + + { + const char* dataDirectory; + int32_t dataDirectoryLen; + UChar *udataDir=0; + UChar temp[100]; + char *charvalue=0; + log_verbose("Testing chars to UChars\n"); + + /* This cannot really work on a japanese system. u_uastrcpy will have different results than */ + /* u_charsToUChars when there is a backslash in the string! */ + /*dataDirectory=u_getDataDirectory();*/ + + dataDirectory="directory1"; /*no backslashes*/ + dataDirectoryLen=(int32_t)strlen(dataDirectory); + udataDir=(UChar*)malloc(sizeof(UChar) * (dataDirectoryLen + 1)); + u_charsToUChars(dataDirectory, udataDir, (dataDirectoryLen + 1)); + u_uastrcpy(temp, dataDirectory); + + if(u_strcmp(temp, udataDir) != 0){ + log_err("ERROR: u_charsToUChars failed. Expected %s, Got %s\n", austrdup(temp), austrdup(udataDir)); + } + log_verbose("Testing UChars to chars\n"); + charvalue=(char*)malloc(sizeof(char) * (u_strlen(udataDir) + 1)); + + u_UCharsToChars(udataDir, charvalue, (u_strlen(udataDir)+1)); + if(strcmp(charvalue, dataDirectory) != 0){ + log_err("ERROR: u_UCharsToChars failed. Expected %s, Got %s\n", charvalue, dataDirectory); + } + free(charvalue); + free(udataDir); + } + + log_verbose("Testing uprv_timezone()....\n"); + { + int32_t tzoffset = uprv_timezone(); + log_verbose("Value returned from uprv_timezone = %d\n", tzoffset); + if (tzoffset != 28800) { + log_verbose("***** WARNING: If testing in the PST timezone, t_timezone should return 28800! *****"); + } + if ((tzoffset % 1800 != 0)) { + log_err("FAIL: t_timezone may be incorrect. It is not a multiple of 30min."); + } + /*tzoffset=uprv_getUTCtime();*/ + + } +} + +#if 0 +static void testIEEEremainder() +{ + double pinf = uprv_getInfinity(); + double ninf = -uprv_getInfinity(); + double nan = uprv_getNaN(); +/* double pzero = 0.0;*/ +/* double nzero = 0.0; + nzero *= -1;*/ + + /* simple remainder checks*/ + remainderTest(7.0, 2.5, -0.5); + remainderTest(7.0, -2.5, -0.5); + /* this should work + remainderTest(43.7, 2.5, 1.2); + */ + + /* infinity and real*/ + remainderTest(1.0, pinf, 1.0); + remainderTest(1.0, ninf, 1.0); + + /*test infinity and real*/ + remainderTest(nan, 1.0, nan); + remainderTest(1.0, nan, nan); + /*test infinity and nan*/ + remainderTest(ninf, nan, nan); + remainderTest(pinf, nan, nan); + + /* test infinity and zero */ +/* remainderTest(pinf, pzero, 1.25); + remainderTest(pinf, nzero, 1.25); + remainderTest(ninf, pzero, 1.25); + remainderTest(ninf, nzero, 1.25); */ +} + +static void remainderTest(double x, double y, double exp) +{ + double result = uprv_IEEEremainder(x,y); + + if( uprv_isNaN(result) && + ! ( uprv_isNaN(x) || uprv_isNaN(y))) { + log_err("FAIL: got NaN as result without NaN as argument"); + log_err(" IEEEremainder(%f, %f) is %f, expected %f\n", x, y, result, exp); + } + else if(!compareWithNAN(result, exp)) { + log_err("FAIL: IEEEremainder(%f, %f) is %f, expected %f\n", x, y, result, exp); + } else{ + log_verbose("OK: IEEEremainder(%f, %f) is %f\n", x, y, result); + } + +} +#endif + +static UBool compareWithNAN(double x, double y) +{ + if( uprv_isNaN(x) || uprv_isNaN(y) ) { + if(!uprv_isNaN(x) || !uprv_isNaN(y) ) { + return FALSE; + } + } + else if (y != x) { /* no NaN's involved */ + return FALSE; + } + + return TRUE; +} + +static void doAssert(double got, double expect, const char *message) +{ + if(! compareWithNAN(expect, got) ) { + log_err("ERROR : %s. Expected : %lf, Got: %lf\n", message, expect, got); + } +} + + +#define _CODE_ARR_LEN 8 +static const UErrorCode errorCode[_CODE_ARR_LEN] = { + U_USING_FALLBACK_WARNING, + U_STRING_NOT_TERMINATED_WARNING, + U_ILLEGAL_ARGUMENT_ERROR, + U_STATE_TOO_OLD_ERROR, + U_BAD_VARIABLE_DEFINITION, + U_RULE_MASK_ERROR, + U_UNEXPECTED_TOKEN, + U_UNSUPPORTED_ATTRIBUTE +}; + +static const char* str[] = { + "U_USING_FALLBACK_WARNING", + "U_STRING_NOT_TERMINATED_WARNING", + "U_ILLEGAL_ARGUMENT_ERROR", + "U_STATE_TOO_OLD_ERROR", + "U_BAD_VARIABLE_DEFINITION", + "U_RULE_MASK_ERROR", + "U_UNEXPECTED_TOKEN", + "U_UNSUPPORTED_ATTRIBUTE" +}; + +static void TestErrorName(void){ + int32_t code=0; + const char* errorName ; + for(;code<U_ERROR_LIMIT;code++){ + errorName = u_errorName((UErrorCode)code); + } + + for(code=0;code<_CODE_ARR_LEN; code++){ + errorName = u_errorName(errorCode[code]); + if(uprv_strcmp(str[code],errorName )!=0){ + log_err("Error : u_errorName failed. Expected: %s Got: %s \n",str[code],errorName); + } + } +} + +void addPUtilTest(TestNode** root); + +void +addPUtilTest(TestNode** root) +{ + addTest(root, &TestPUtilAPI, "putiltst/TestPUtilAPI"); +/* addTest(root, &testIEEEremainder, "putiltst/testIEEEremainder"); */ + addTest(root, &TestErrorName, "putiltst/TestErrorName"); +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c new file mode 100644 index 00000000000..74fe674f7dc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c @@ -0,0 +1,1038 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2004-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/******************************************************************************** +* +* File reapits.c +* +*********************************************************************************/ +/*C API TEST FOR Regular Expressions */ +/** +* This is an API test for ICU regular expressions in C. It doesn't test very many cases, and doesn't +* try to test the full functionality. It just calls each function and verifies that it +* works on a basic level. +* +* More complete testing of regular expression functionality is done with the C++ tests. +**/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_REGULAR_EXPRESSIONS + +#include <stdlib.h> +#include <string.h> +#include "unicode/uloc.h" +#include "unicode/uregex.h" +#include "unicode/ustring.h" +#include "cintltst.h" + +#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ +log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}} + +#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ +log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}} + +static void test_assert_string(const char *expected, const UChar *actual, UBool nulTerm, const char *file, int line) { + char buf_inside_macro[120]; + int32_t len = (int32_t)strlen(expected); + UBool success; + if (nulTerm) { + u_austrncpy(buf_inside_macro, (actual), len+1); + buf_inside_macro[len+2] = 0; + success = (strcmp((expected), buf_inside_macro) == 0); + } else { + u_austrncpy(buf_inside_macro, (actual), len); + buf_inside_macro[len+1] = 0; + success = (strncmp((expected), buf_inside_macro, len) == 0); + } + if (success == FALSE) { + log_err("Failure at file %s, line %d, expected \"%s\", got \"%s\"\n", + file, line, (expected), buf_inside_macro); + } +} + +#define TEST_ASSERT_STRING(expected, actual, nulTerm) test_assert_string(expected, actual, nulTerm, __FILE__, __LINE__) + + + + + +static void TestRegexCAPI(void); +static void TestBug4315(void); + +void addURegexTest(TestNode** root); + +void addURegexTest(TestNode** root) +{ + addTest(root, &TestRegexCAPI, "regex/TestRegexCAPI"); + addTest(root, &TestBug4315, "regex/TestBug4315"); +} + + +static void TestRegexCAPI(void) { + UErrorCode status = U_ZERO_ERROR; + URegularExpression *re; + UChar pat[200]; + UChar *minus1; + + memset(&minus1, -1, sizeof(minus1)); + + /* Mimimalist open/close */ + u_uastrncpy(pat, "abc*", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + /* Open with all flag values set */ + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, + 0, &status); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + /* Open with an invalid flag */ + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0x40000000, 0, &status); + TEST_ASSERT(status == U_REGEX_INVALID_FLAG); + uregex_close(re); + + /* openC with an invalid parameter */ + status = U_ZERO_ERROR; + re = uregex_openC(NULL, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status); + TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR && re == NULL); + + /* openC with an invalid parameter */ + status = U_USELESS_COLLATOR_ERROR; + re = uregex_openC(NULL, + UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status); + TEST_ASSERT(status == U_USELESS_COLLATOR_ERROR && re == NULL); + + /* openC open from a C string */ + { + const UChar *p; + int32_t len; + status = U_ZERO_ERROR; + re = uregex_openC("abc*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + p = uregex_pattern(re, &len, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if(U_SUCCESS(status)) { + u_uastrncpy(pat, "abc*", sizeof(pat)/2); + TEST_ASSERT(u_strcmp(pat, p) == 0); + TEST_ASSERT(len==(int32_t)strlen("abc*")); + } + + uregex_close(re); + + /* TODO: Open with ParseError parameter */ + } + + /* + * clone + */ + { + URegularExpression *clone1; + URegularExpression *clone2; + URegularExpression *clone3; + UChar testString1[30]; + UChar testString2[30]; + UBool result; + + + status = U_ZERO_ERROR; + re = uregex_openC("abc*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + clone1 = uregex_clone(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone1 != NULL); + + status = U_ZERO_ERROR; + clone2 = uregex_clone(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone2 != NULL); + uregex_close(re); + + status = U_ZERO_ERROR; + clone3 = uregex_clone(clone2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(clone3 != NULL); + + u_uastrncpy(testString1, "abcccd", sizeof(pat)/2); + u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2); + + status = U_ZERO_ERROR; + uregex_setText(clone1, testString1, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_lookingAt(clone1, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==TRUE); + + status = U_ZERO_ERROR; + uregex_setText(clone2, testString2, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_lookingAt(clone2, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==FALSE); + result = uregex_find(clone2, 0, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result==TRUE); + + uregex_close(clone1); + uregex_close(clone2); + uregex_close(clone3); + + } + + /* + * pattern() + */ + { + const UChar *resultPat; + int32_t resultLen; + u_uastrncpy(pat, "hello", sizeof(pat)/2); + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + resultPat = uregex_pattern(re, &resultLen, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if (U_SUCCESS(status)) { + TEST_ASSERT(resultLen == -1); + TEST_ASSERT(u_strcmp(resultPat, pat) == 0); + } + + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, 3, 0, NULL, &status); + resultPat = uregex_pattern(re, &resultLen, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS above should change too... */ + if (U_SUCCESS(status)) { + TEST_ASSERT(resultLen == 3); + TEST_ASSERT(u_strncmp(resultPat, pat, 3) == 0); + TEST_ASSERT(u_strlen(resultPat) == 3); + } + + uregex_close(re); + } + + /* + * flags() + */ + { + int32_t t; + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, 0, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_open(pat, -1, UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL, NULL, &status); + t = uregex_flags(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(t == (UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL)); + uregex_close(re); + } + + /* + * setText() and lookingAt() + */ + { + UChar text1[50]; + UChar text2[50]; + UBool result; + + u_uastrncpy(text1, "abcccd", sizeof(text1)/2); + u_uastrncpy(text2, "abcccxd", sizeof(text2)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Operation before doing a setText should fail... */ + status = U_ZERO_ERROR; + uregex_lookingAt(re, 0, &status); + TEST_ASSERT( status== U_REGEX_INVALID_STATE); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 5, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_lookingAt(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + uregex_close(re); + } + + + /* + * getText() + */ + { + UChar text1[50]; + UChar text2[50]; + const UChar *result; + int32_t textLength; + + u_uastrncpy(text1, "abcccd", sizeof(text1)/2); + u_uastrncpy(text2, "abcccxd", sizeof(text2)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text1); + TEST_ASSERT(textLength == -1); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, 7, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text2); + TEST_ASSERT(textLength == 7); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text2, 4, &status); + result = uregex_getText(re, &textLength, &status); + TEST_ASSERT(result == text2); + TEST_ASSERT(textLength == 4); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + } + + /* + * matches() + */ + { + UChar text1[50]; + UBool result; + int len; + UChar nullString[] = {0,0,0}; + + u_uastrncpy(text1, "abcccde", sizeof(text1)/2); + status = U_ZERO_ERROR; + u_uastrncpy(pat, "abc*d", sizeof(pat)/2); + re = uregex_open(pat, -1, 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, text1, 6, &status); + result = uregex_matches(re, 1, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_openC(".?", 0, NULL, &status); + uregex_setText(re, text1, -1, &status); + len = u_strlen(text1); + result = uregex_matches(re, len, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_setText(re, nullString, -1, &status); + TEST_ASSERT_SUCCESS(status); + result = uregex_matches(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT_SUCCESS(status); + uregex_close(re); + } + + + /* + * lookingAt() Used in setText test. + */ + + + /* + * find(), findNext, start, end, reset + */ + { + UChar text1[50]; + UBool result; + u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2); + status = U_ZERO_ERROR; + re = uregex_openC("rx", 0, NULL, &status); + + uregex_setText(re, text1, -1, &status); + result = uregex_find(re, 0, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 3); + TEST_ASSERT(uregex_end(re, 0, &status) == 5); + TEST_ASSERT_SUCCESS(status); + + result = uregex_find(re, 9, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 11); + TEST_ASSERT(uregex_end(re, 0, &status) == 13); + TEST_ASSERT_SUCCESS(status); + + result = uregex_find(re, 14, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_reset(re, 0, &status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 3); + TEST_ASSERT(uregex_end(re, 0, &status) == 5); + TEST_ASSERT_SUCCESS(status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 6); + TEST_ASSERT(uregex_end(re, 0, &status) == 8); + TEST_ASSERT_SUCCESS(status); + + status = U_ZERO_ERROR; + uregex_reset(re, 12, &status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == TRUE); + TEST_ASSERT(uregex_start(re, 0, &status) == 13); + TEST_ASSERT(uregex_end(re, 0, &status) == 15); + TEST_ASSERT_SUCCESS(status); + + result = uregex_findNext(re, &status); + TEST_ASSERT(result == FALSE); + TEST_ASSERT_SUCCESS(status); + + uregex_close(re); + } + + /* + * groupCount + */ + { + int32_t result; + + status = U_ZERO_ERROR; + re = uregex_openC("abc", 0, NULL, &status); + result = uregex_groupCount(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result == 0); + uregex_close(re); + + status = U_ZERO_ERROR; + re = uregex_openC("abc(def)(ghi(j))", 0, NULL, &status); + result = uregex_groupCount(re, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT(result == 3); + uregex_close(re); + + } + + + /* + * group() + */ + { + UChar text1[80]; + UChar buf[80]; + UBool result; + int32_t resultSz; + u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("abc(.*?)def", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + + uregex_setText(re, text1, -1, &status); + result = uregex_find(re, 0, &status); + TEST_ASSERT(result==TRUE); + + /* Capture Group 0, the full match. Should succeed. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("abc interior def", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Capture group #1. Should succeed. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING(" interior ", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen(" interior ")); + + /* Capture group out of range. Error. */ + status = U_ZERO_ERROR; + uregex_group(re, 2, buf, sizeof(buf)/2, &status); + TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR); + + /* NULL buffer, pure pre-flight */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Too small buffer, truncated string */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_group(re, 0, buf, 5, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT_STRING("abc i", buf, FALSE); + TEST_ASSERT(buf[5] == (UChar)0xffff); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + + /* Output string just fits buffer, no NUL term. */ + status = U_ZERO_ERROR; + resultSz = uregex_group(re, 0, buf, (int32_t)strlen("abc interior def"), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("abc interior def", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def")); + TEST_ASSERT(buf[strlen("abc interior def")] == (UChar)0xffff); + + uregex_close(re); + + } + + /* + * replaceFirst() + */ + { + UChar text1[80]; + UChar text2[80]; + UChar replText[80]; + UChar buf[80]; + int32_t resultSz; + u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + u_uastrncpy(replText, "<$1>", sizeof(replText)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("x(.*?)x", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Normal case, with match */ + uregex_setText(re, text1, -1, &status); + resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* No match. Text should copy to output with no changes. */ + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("No match here.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("No match here.")); + + /* Match, output just fills buffer, no termination warning. */ + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* Do the replaceFirst again, without first resetting anything. + * Should give the same results. + */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* NULL buffer, zero buffer length */ + status = U_ZERO_ERROR; + resultSz = uregex_replaceFirst(re, replText, -1, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* Buffer too small by one */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x.")-1, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT_STRING("Replace <aa> x1x x...x", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + uregex_close(re); + } + + + /* + * replaceAll() + */ + { + UChar text1[80]; + UChar text2[80]; + UChar replText[80]; + UChar buf[80]; + int32_t resultSz; + int32_t expectedResultSize; + int32_t i; + + u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + u_uastrncpy(replText, "<$1>", sizeof(replText)/2); + expectedResultSize = u_strlen(text1); + + status = U_ZERO_ERROR; + re = uregex_openC("x(.*?)x", 0, NULL, &status); + TEST_ASSERT_SUCCESS(status); + + /* Normal case, with match */ + uregex_setText(re, text1, -1, &status); + resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x.")); + + /* No match. Text should copy to output with no changes. */ + status = U_ZERO_ERROR; + uregex_setText(re, text2, -1, &status); + resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("No match here.", buf, TRUE); + TEST_ASSERT(resultSz == (int32_t)strlen("No match here.")); + + /* Match, output just fills buffer, no termination warning. */ + status = U_ZERO_ERROR; + uregex_setText(re, text1, -1, &status); + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* Do the replaceFirst again, without first resetting anything. + * Should give the same results. + */ + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status); + TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING); + TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + TEST_ASSERT(buf[resultSz] == (UChar)0xffff); + + /* NULL buffer, zero buffer length */ + status = U_ZERO_ERROR; + resultSz = uregex_replaceAll(re, replText, -1, NULL, 0, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>.")); + + /* Buffer too small. Try every size, which will tickle edge cases + * in uregex_appendReplacement (used by replaceAll) */ + for (i=0; i<expectedResultSize; i++) { + char expected[80]; + status = U_ZERO_ERROR; + memset(buf, -1, sizeof(buf)); + resultSz = uregex_replaceAll(re, replText, -1, buf, i, &status); + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + strcpy(expected, "Replace <aa> <1> <...>."); + expected[i] = 0; + TEST_ASSERT_STRING(expected, buf, FALSE); + TEST_ASSERT(resultSz == expectedResultSize); + TEST_ASSERT(buf[i] == (UChar)0xffff); + } + + uregex_close(re); + } + + + /* + * appendReplacement() + */ + { + UChar text[100]; + UChar repl[100]; + UChar buf[100]; + UChar *bufPtr; + int32_t bufCap; + + + status = U_ZERO_ERROR; + re = uregex_openC(".*", 0, 0, &status); + TEST_ASSERT_SUCCESS(status); + + u_uastrncpy(text, "whatever", sizeof(text)/2); + u_uastrncpy(repl, "some other", sizeof(repl)/2); + uregex_setText(re, text, -1, &status); + + /* match covers whole target string */ + uregex_find(re, 0, &status); + TEST_ASSERT_SUCCESS(status); + bufPtr = buf; + bufCap = sizeof(buf) / 2; + uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("some other", buf, TRUE); + + /* Match has \u \U escapes */ + uregex_find(re, 0, &status); + TEST_ASSERT_SUCCESS(status); + bufPtr = buf; + bufCap = sizeof(buf) / 2; + u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2); + uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status); + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE); + + uregex_close(re); + } + + + /* + * appendTail(). Checked in ReplaceFirst(), replaceAll(). + */ + + /* + * split() + */ + { + UChar textToSplit[80]; + UChar text2[80]; + UChar buf[200]; + UChar *fields[10]; + int32_t numFields; + int32_t requiredCapacity; + int32_t spaceNeeded; + int32_t sz; + + u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2); + u_uastrncpy(text2, "No match here.", sizeof(text2)/2); + + status = U_ZERO_ERROR; + re = uregex_openC(":", 0, NULL, &status); + + + /* Simple split */ + + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if (U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 3); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second", fields[1], TRUE); + TEST_ASSERT_STRING(" third", fields[2], TRUE); + TEST_ASSERT(fields[3] == NULL); + + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + uregex_close(re); + + + /* Split with too few output strings available */ + status = U_ZERO_ERROR; + re = uregex_openC(":", 0, NULL, &status); + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 2); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second: third", fields[1], TRUE); + TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*))); + + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + TEST_ASSERT(spaceNeeded == requiredCapacity); + + /* Split with a range of output buffer sizes. */ + spaceNeeded = u_strlen(textToSplit) - + (numFields - 1) + /* Field delimiters do not appear in output */ + numFields; /* Each field gets a NUL terminator */ + + for (sz=0; sz < spaceNeeded+1; sz++) { + memset(fields, -1, sizeof(fields)); + status = U_ZERO_ERROR; + numFields = + uregex_split(re, buf, sz, &requiredCapacity, fields, 10, &status); + if (sz >= spaceNeeded) { + TEST_ASSERT_SUCCESS(status); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second", fields[1], TRUE); + TEST_ASSERT_STRING(" third", fields[2], TRUE); + } else { + TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR); + } + TEST_ASSERT(numFields == 3); + TEST_ASSERT(fields[3] == NULL); + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + } + + uregex_close(re); + } + + + + + /* Split(), part 2. Patterns with capture groups. The capture group text + * comes out as additional fields. */ + { + UChar textToSplit[80]; + UChar buf[200]; + UChar *fields[10]; + int32_t numFields; + int32_t requiredCapacity; + int32_t spaceNeeded; + int32_t sz; + + u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2); + + status = U_ZERO_ERROR; + re = uregex_openC("<(.*?)>", 0, NULL, &status); + + uregex_setText(re, textToSplit, -1, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 5); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT_STRING(" third", fields[4], TRUE); + TEST_ASSERT(fields[5] == NULL); + spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + /* Split with too few output strings available (2) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 2); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING(" second<tag-b> third", fields[1], TRUE); + TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first . second<tag-b> third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split with too few output strings available (3) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 3, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 3); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second<tag-b> third", fields[2], TRUE); + TEST_ASSERT(!memcmp(&fields[3],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split with just enough output strings available (5) */ + status = U_ZERO_ERROR; + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 5, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 5); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT_STRING(" third", fields[4], TRUE); + TEST_ASSERT(!memcmp(&fields[5],&minus1,sizeof(UChar*))); + + spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + + /* Split, end of text is a field delimiter. */ + status = U_ZERO_ERROR; + sz = strlen("first <tag-a> second<tag-b>"); + uregex_setText(re, textToSplit, sz, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + memset(fields, -1, sizeof(fields)); + numFields = + uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 9, &status); + TEST_ASSERT_SUCCESS(status); + + /* The TEST_ASSERT_SUCCESS call above should change too... */ + if(U_SUCCESS(status)) { + TEST_ASSERT(numFields == 4); + TEST_ASSERT_STRING("first ", fields[0], TRUE); + TEST_ASSERT_STRING("tag-a", fields[1], TRUE); + TEST_ASSERT_STRING(" second", fields[2], TRUE); + TEST_ASSERT_STRING("tag-b", fields[3], TRUE); + TEST_ASSERT(fields[4] == NULL); + TEST_ASSERT(fields[8] == NULL); + TEST_ASSERT(!memcmp(&fields[9],&minus1,sizeof(UChar*))); + spaceNeeded = strlen("first .tag-a. second.tag-b."); /* "." at NUL positions */ + TEST_ASSERT(spaceNeeded == requiredCapacity); + } + } + + uregex_close(re); + } + +} + +static void TestBug4315(void) { + UErrorCode theICUError = U_ZERO_ERROR; + URegularExpression *theRegEx; + UChar *textBuff; + const char *thePattern; + UChar theString[100]; + UChar *destFields[24]; + int32_t neededLength1; + int32_t neededLength2; + + int32_t wordCount = 0; + int32_t destFieldsSize = 24; + + thePattern = "ck "; + u_uastrcpy(theString, "The quick brown fox jumped over the slow black turtle."); + + /* open a regex */ + theRegEx = uregex_openC(thePattern, 0, NULL, &theICUError); + TEST_ASSERT_SUCCESS(theICUError); + + /* set the input string */ + uregex_setText(theRegEx, theString, u_strlen(theString), &theICUError); + TEST_ASSERT_SUCCESS(theICUError); + + /* split */ + /*explicitly pass NULL and 0 to force the overflow error -> this is where the + * error occurs! */ + wordCount = uregex_split(theRegEx, NULL, 0, &neededLength1, destFields, + destFieldsSize, &theICUError); + + TEST_ASSERT(theICUError == U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(wordCount==3); + + if(theICUError == U_BUFFER_OVERFLOW_ERROR) + { + theICUError = U_ZERO_ERROR; + textBuff = (UChar *) malloc(sizeof(UChar) * (neededLength1 + 1)); + wordCount = uregex_split(theRegEx, textBuff, neededLength1+1, &neededLength2, + destFields, destFieldsSize, &theICUError); + TEST_ASSERT(wordCount==3); + TEST_ASSERT_SUCCESS(theICUError); + TEST_ASSERT(neededLength1 == neededLength2); + TEST_ASSERT_STRING("The qui", destFields[0], TRUE); + TEST_ASSERT_STRING("brown fox jumped over the slow bla", destFields[1], TRUE); + TEST_ASSERT_STRING("turtle.", destFields[2], TRUE); + TEST_ASSERT(destFields[3] == NULL); + free(textBuff); + } + uregex_close(theRegEx); +} + +#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c new file mode 100644 index 00000000000..c99ce507196 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c @@ -0,0 +1,89 @@ +/* +******************************************************************************* +* +* Copyright (C) 2003, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: csorttst.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2003aug04 +* created by: Markus W. Scherer +* +* Test internal sorting functions. +*/ + +#include "unicode/utypes.h" +#include "cmemory.h" +#include "cintltst.h" +#include "uarrsort.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void +SortTest(void) { + uint16_t small[]={ 8, 1, 2, 5, 4, 3, 7, 6 }; + int32_t medium[]={ 10, 8, 1, 2, 5, 5, -1, 6, 4, 3, 9, 7, 5 }; + uint32_t large[]={ 21, 10, 20, 19, 11, 12, 13, 10, 10, 10, 10, + 8, 1, 2, 5, 10, 10, 4, 17, 18, 3, 9, 10, 7, 6, 14, 15, 16 }; + + int32_t i; + UErrorCode errorCode; + + /* sort small array (stable) */ + errorCode=U_ZERO_ERROR; + uprv_sortArray(small, LENGTHOF(small), sizeof(small[0]), uprv_uint16Comparator, NULL, TRUE, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("uprv_sortArray(small) failed - %s\n", u_errorName(errorCode)); + return; + } + for(i=1; i<LENGTHOF(small); ++i) { + if(small[i-1]>small[i]) { + log_err("uprv_sortArray(small) mis-sorted [%d]=%u > [%d]=%u\n", i-1, small[i-1], i, small[i]); + return; + } + } + + /* for medium, add bits that will not be compared, to test stability */ + for(i=0; i<LENGTHOF(medium); ++i) { + medium[i]=(medium[i]<<4)|i; + } + + /* sort medium array (stable) */ + uprv_sortArray(medium, LENGTHOF(medium), sizeof(medium[0]), uprv_int32Comparator, NULL, TRUE, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("uprv_sortArray(medium) failed - %s\n", u_errorName(errorCode)); + return; + } + for(i=1; i<LENGTHOF(medium); ++i) { + if(medium[i-1]>=medium[i]) { + log_err("uprv_sortArray(medium) mis-sorted [%d]=%u > [%d]=%u\n", i-1, medium[i-1], i, medium[i]); + return; + } + } + + /* sort large array (not stable) */ + errorCode=U_ZERO_ERROR; + uprv_sortArray(large, LENGTHOF(large), sizeof(large[0]), uprv_uint32Comparator, NULL, FALSE, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("uprv_sortArray(large) failed - %s\n", u_errorName(errorCode)); + return; + } + for(i=1; i<LENGTHOF(large); ++i) { + if(large[i-1]>large[i]) { + log_err("uprv_sortArray(large) mis-sorted [%d]=%u > [%d]=%u\n", i-1, large[i-1], i, large[i]); + return; + } + } +} + +void +addSortTest(TestNode** root); + +void +addSortTest(TestNode** root) { + addTest(root, &SortTest, "tsutil/sorttest/SortTest"); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c new file mode 100644 index 00000000000..1652984b520 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c @@ -0,0 +1,641 @@ +/* + ******************************************************************************* + * + * Copyright (C) 2003-2006, International Business Machines + * Corporation and others. All Rights Reserved. + * + ******************************************************************************* + * file name: spreptst.c + * encoding: US-ASCII + * tab size: 8 (not used) + * indentation:4 + * + * created on: 2003jul11 + * created by: Ram Viswanadha + */ +#include <stdlib.h> +#include <string.h> +#include "unicode/utypes.h" + +#if !UCONFIG_NO_IDNA + +#include "unicode/ustring.h" +#include "unicode/usprep.h" +#include "cintltst.h" +#include "nfsprep.h" + + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +void addUStringPrepTest(TestNode** root); +void doStringPrepTest(const char* binFileName, const char* txtFileName, + int32_t options, UErrorCode* errorCode); + +static void Test_nfs4_cs_prep_data(void); +static void Test_nfs4_cis_prep_data(void); +static void Test_nfs4_mixed_prep_data(void); +static void Test_nfs4_cs_prep(void); +static void Test_nfs4_cis_prep(void); +static void Test_nfs4_mixed_prep(void); +static void TestBEAMWarning(void); +static void TestCoverage(void); + +void +addUStringPrepTest(TestNode** root) +{ + addTest(root, &Test_nfs4_cs_prep_data, "spreptst/Test_nfs4_cs_prep_data"); + addTest(root, &Test_nfs4_cis_prep_data, "spreptst/Test_nfs4_cis_prep_data"); + addTest(root, &Test_nfs4_mixed_prep_data, "spreptst/Test_nfs4_mixed_prep_data"); + addTest(root, &Test_nfs4_cs_prep, "spreptst/Test_nfs4_cs_prep"); + addTest(root, &Test_nfs4_cis_prep, "spreptst/Test_nfs4_cis_prep"); + addTest(root, &Test_nfs4_mixed_prep, "spreptst/Test_nfs4_mixed_prep"); + addTest(root, &TestBEAMWarning, "spreptst/TestBEAMWarning"); + addTest(root, &TestCoverage, "spreptst/TestCoverage"); +} + +static void +Test_nfs4_cs_prep_data(void){ + UErrorCode errorCode = U_ZERO_ERROR; + loadTestData(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode)); + return; + } + + log_verbose("Testing nfs4_cs_prep_ci.txt\n"); + doStringPrepTest("nfscsi","nfs4_cs_prep_ci.txt", USPREP_DEFAULT, &errorCode); + + log_verbose("Testing nfs4_cs_prep_cs.txt\n"); + errorCode = U_ZERO_ERROR; + doStringPrepTest("nfscss","nfs4_cs_prep_cs.txt", USPREP_DEFAULT, &errorCode); + + +} +static void +Test_nfs4_cis_prep_data(void){ + UErrorCode errorCode = U_ZERO_ERROR; + log_verbose("Testing nfs4_cis_prep.txt\n"); + doStringPrepTest("nfscis","nfs4_cis_prep.txt", USPREP_DEFAULT, &errorCode); +} +static void +Test_nfs4_mixed_prep_data(void){ + UErrorCode errorCode = U_ZERO_ERROR; + loadTestData(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode)); + return; + } + + log_verbose("Testing nfs4_mixed_prep_s.txt\n"); + doStringPrepTest("nfsmxs","nfs4_mixed_prep_s.txt", USPREP_DEFAULT, &errorCode); + + errorCode = U_ZERO_ERROR; + log_verbose("Testing nfs4_mixed_prep_p.txt\n"); + doStringPrepTest("nfsmxp","nfs4_mixed_prep_p.txt", USPREP_DEFAULT, &errorCode); + +} + +static const struct ConformanceTestCases + { + const char *comment; + const char *in; + const char *out; + const char *profile; + UErrorCode expectedStatus; + } + conformanceTestCases[] = + { + + {/*0*/ + "Case folding ASCII U+0043 U+0041 U+0046 U+0045", + "\x43\x41\x46\x45", "\x63\x61\x66\x65", + "nfs4_cis_prep", + U_ZERO_ERROR + + }, + {/*1*/ + "Case folding 8bit U+00DF (german sharp s)", + "\xC3\x9F", "\x73\x73", + "nfs4_cis_prep", + U_ZERO_ERROR + }, + {/*2*/ + "Non-ASCII multibyte space character U+1680", + "\xE1\x9A\x80", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*3*/ + "Non-ASCII 8bit control character U+0085", + "\xC2\x85", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*4*/ + "Non-ASCII multibyte control character U+180E", + "\xE1\xA0\x8E", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*5*/ + "Non-ASCII control character U+1D175", + "\xF0\x9D\x85\xB5", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*6*/ + "Plane 0 private use character U+F123", + "\xEF\x84\xA3", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*7*/ + "Plane 15 private use character U+F1234", + "\xF3\xB1\x88\xB4", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*8*/ + "Plane 16 private use character U+10F234", + "\xF4\x8F\x88\xB4", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*9*/ + "Non-character code point U+8FFFE", + "\xF2\x8F\xBF\xBE", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*10*/ + "Non-character code point U+10FFFF", + "\xF4\x8F\xBF\xBF", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + /* + { + "Surrogate code U+DF42", + "\xED\xBD\x82", NULL, "nfs4_cis_prep", UIDNA_DEFAULT, + U_STRINGPREP_PROHIBITED_ERROR + }, +*/ + {/*11*/ + "Non-plain text character U+FFFD", + "\xEF\xBF\xBD", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*12*/ + "Ideographic description character U+2FF5", + "\xE2\xBF\xB5", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*13*/ + "Display property character U+0341", + "\xCD\x81", "\xCC\x81", + "nfs4_cis_prep", U_ZERO_ERROR + + }, + + {/*14*/ + "Left-to-right mark U+200E", + "\xE2\x80\x8E", "\xCC\x81", + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*15*/ + + "Deprecated U+202A", + "\xE2\x80\xAA", "\xCC\x81", + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*16*/ + "Language tagging character U+E0001", + "\xF3\xA0\x80\x81", "\xCC\x81", + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*17*/ + "Language tagging character U+E0042", + "\xF3\xA0\x81\x82", NULL, + "nfs4_cis_prep", + U_STRINGPREP_PROHIBITED_ERROR + }, + {/*18*/ + "Bidi: RandALCat character U+05BE and LCat characters", + "\x66\x6F\x6F\xD6\xBE\x62\x61\x72", NULL, + "nfs4_cis_prep", + U_STRINGPREP_CHECK_BIDI_ERROR + }, + {/*19*/ + "Bidi: RandALCat character U+FD50 and LCat characters", + "\x66\x6F\x6F\xEF\xB5\x90\x62\x61\x72", NULL, + "nfs4_cis_prep", + U_STRINGPREP_CHECK_BIDI_ERROR + }, + {/*20*/ + "Bidi: RandALCat character U+FB38 and LCat characters", + "\x66\x6F\x6F\xEF\xB9\xB6\x62\x61\x72", "\x66\x6F\x6F\x20\xd9\x8e\x62\x61\x72", + "nfs4_cis_prep", + U_ZERO_ERROR + }, + {/*21*/ + "Bidi: RandALCat without trailing RandALCat U+0627 U+0031", + "\xD8\xA7\x31", NULL, + "nfs4_cis_prep", + U_STRINGPREP_CHECK_BIDI_ERROR + }, + {/*22*/ + "Bidi: RandALCat character U+0627 U+0031 U+0628", + "\xD8\xA7\x31\xD8\xA8", "\xD8\xA7\x31\xD8\xA8", + "nfs4_cis_prep", + U_ZERO_ERROR + }, + {/*23*/ + "Unassigned code point U+E0002", + "\xF3\xA0\x80\x82", NULL, + "nfs4_cis_prep", + U_STRINGPREP_UNASSIGNED_ERROR + }, + +/* // Invalid UTF-8 + { + "Larger test (shrinking)", + "X\xC2\xAD\xC3\xDF\xC4\xB0\xE2\x84\xA1\x6a\xcc\x8c\xc2\xa0\xc2" + "\xaa\xce\xb0\xe2\x80\x80", "xssi\xcc\x87""tel\xc7\xb0 a\xce\xb0 ", + "nfs4_cis_prep", + U_ZERO_ERROR + }, + { + + "Larger test (expanding)", + "X\xC3\xDF\xe3\x8c\x96\xC4\xB0\xE2\x84\xA1\xE2\x92\x9F\xE3\x8c\x80", + "xss\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88" + "\xe3\x83\xab""i\xcc\x87""tel\x28""d\x29\xe3\x82\xa2\xe3\x83\x91" + "\xe3\x83\xbc\xe3\x83\x88" + "nfs4_cis_prep", + U_ZERO_ERROR + }, + */ +}; + +#define MAX_BUFFER_SIZE 1000 + +static int32_t +unescapeData(const char* src, int32_t srcLen, + char* dest, int32_t destCapacity, + UErrorCode* status){ + + UChar b1Stack[MAX_BUFFER_SIZE]; + int32_t b1Capacity = MAX_BUFFER_SIZE, + b1Len = 0, + destLen = 0; + + UChar* b1 = b1Stack; + + b1Len = u_unescape(src,b1,b1Capacity); + + u_strToUTF8(dest, destCapacity, &destLen, b1, b1Len, status); + + return destLen; +} + + +static void Test_nfs4_cis_prep(void){ + int32_t i=0; + UErrorCode loadStatus = U_ZERO_ERROR; + loadTestData(&loadStatus); + if (U_FAILURE(loadStatus)) { + log_err("Test could not initialize. Got %s\n", u_errorName(loadStatus)); + return; + } + + for(i=0;i< (int32_t)(sizeof(conformanceTestCases)/sizeof(conformanceTestCases[0]));i++){ + const char* src = conformanceTestCases[i].in; + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + UErrorCode expectedStatus = conformanceTestCases[i].expectedStatus; + const char* expectedDest = conformanceTestCases[i].out; + char* dest = NULL; + int32_t destLen = 0; + + destLen = nfs4_cis_prepare(src , (int32_t)strlen(src), dest, destLen, &parseError, &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; + dest = (char*) malloc(++destLen); + destLen = nfs4_cis_prepare( src , (int32_t)strlen(src), dest, destLen, &parseError, &status); + } + + if(expectedStatus != status){ + log_err("Did not get the expected status for nfs4_cis_prep at index %i. Expected: %s Got: %s\n",i, u_errorName(expectedStatus), u_errorName(status)); + } + if(U_SUCCESS(status) && (strcmp(expectedDest,dest) !=0)){ + log_err("Did not get the expected output for nfs4_cis_prep at index %i.\n", i); + } + free(dest); + } +} + + + +/* + There are several special identifiers ("who") which need to be + understood universally, rather than in the context of a particular + DNS domain. Some of these identifiers cannot be understood when an + NFS client accesses the server, but have meaning when a local process + accesses the file. The ability to display and modify these + permissions is permitted over NFS, even if none of the access methods + on the server understands the identifiers. + + Who Description + _______________________________________________________________ + + "OWNER" The owner of the file. + "GROUP" The group associated with the file. + "EVERYONE" The world. + "INTERACTIVE" Accessed from an interactive terminal. + "NETWORK" Accessed via the network. + "DIALUP" Accessed as a dialup user to the server. + "BATCH" Accessed from a batch job. + "ANONYMOUS" Accessed without any authentication. + "AUTHENTICATED" Any authenticated user (opposite of + ANONYMOUS) + "SERVICE" Access from a system service. + + To avoid conflict, these special identifiers are distinguish by an + appended "@" and should appear in the form "xxxx@" (note: no domain + name after the "@"). For example: ANONYMOUS@. +*/ +static const char* mixed_prep_data[] ={ + "OWNER@", + "GROUP@", + "EVERYONE@", + "INTERACTIVE@", + "NETWORK@", + "DIALUP@", + "BATCH@", + "ANONYMOUS@", + "AUTHENTICATED@", + "\\u0930\\u094D\\u092E\\u094D\\u0915\\u094D\\u0937\\u0947\\u0924\\u094D@slip129-37-118-146.nc.us.ibm.net", + "\\u0936\\u094d\\u0930\\u0940\\u092e\\u0926\\u094d@saratoga.pe.utexas.edu", + "\\u092d\\u0917\\u0935\\u0926\\u094d\\u0917\\u0940\\u0924\\u093e@dial-120-45.ots.utexas.edu", + "\\u0905\\u0927\\u094d\\u092f\\u093e\\u092f@woo-085.dorms.waller.net", + "\\u0905\\u0930\\u094d\\u091c\\u0941\\u0928@hd30-049.hil.compuserve.com", + "\\u0935\\u093f\\u0937\\u093e\\u0926@pem203-31.pe.ttu.edu", + "\\u092f\\u094b\\u0917@56K-227.MaxTNT3.pdq.net", + "\\u0927\\u0943\\u0924\\u0930\\u093e\\u0937\\u094d\\u091f\\u094d\\u0930@dial-36-2.ots.utexas.edu", + "\\u0909\\u0935\\u093E\\u091A\\u0943@slip129-37-23-152.ga.us.ibm.net", + "\\u0927\\u0930\\u094d\\u092e\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947@ts45ip119.cadvision.com", + "\\u0915\\u0941\\u0930\\u0941\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947@sdn-ts-004txaustP05.dialsprint.net", + "\\u0938\\u092e\\u0935\\u0947\\u0924\\u093e@bar-tnt1s66.erols.com", + "\\u092f\\u0941\\u092f\\u0941\\u0924\\u094d\\u0938\\u0935\\u0903@101.st-louis-15.mo.dial-access.att.net", + "\\u092e\\u093e\\u092e\\u0915\\u093e\\u0903@h92-245.Arco.COM", + "\\u092a\\u093e\\u0923\\u094d\\u0921\\u0935\\u093e\\u0936\\u094d\\u091a\\u0948\\u0935@dial-13-2.ots.utexas.edu", + "\\u0915\\u093f\\u092e\\u0915\\u0941\\u0930\\u094d\\u0935\\u0924@net-redynet29.datamarkets.com.ar", + "\\u0938\\u0902\\u091c\\u0935@ccs-shiva28.reacciun.net.ve", + "\\u0c30\\u0c18\\u0c41\\u0c30\\u0c3e\\u0c2e\\u0c4d@7.houston-11.tx.dial-access.att.net", + "\\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27@ingw129-37-120-26.mo.us.ibm.net", + "\\u0c06\\u0c28\\u0c02\\u0c26\\u0c4d@dialup6.austintx.com", + "\\u0C35\\u0C26\\u0C4D\\u0C26\\u0C3F\\u0C30\\u0C3E\\u0C1C\\u0C41@dns2.tpao.gov.tr", + "\\u0c30\\u0c3e\\u0c1c\\u0c40\\u0c35\\u0c4d@slip129-37-119-194.nc.us.ibm.net", + "\\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26@cs7.dillons.co.uk.203.119.193.in-addr.arpa", + "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c35\\u0c4d@swprd1.innovplace.saskatoon.sk.ca", + "\\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26@bikini.bologna.maraut.it", + "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c2c\\u0c4d@node91.subnet159-198-79.baxter.com", + "\\u0c38\\u0c46\\u0c28\\u0c4d\\u0c17\\u0c41\\u0c2a\\u0c4d\\u0c24@cust19.max5.new-york.ny.ms.uu.net", + "\\u0c05\\u0c2e\\u0c30\\u0c47\\u0c02\\u0c26\\u0c4d\\u0c30@balexander.slip.andrew.cmu.edu", + "\\u0c39\\u0c28\\u0c41\\u0c2e\\u0c3e\\u0c28\\u0c41\\u0c32@pool029.max2.denver.co.dynip.alter.net", + "\\u0c30\\u0c35\\u0c3f@cust49.max9.new-york.ny.ms.uu.net", + "\\u0c15\\u0c41\\u0c2e\\u0c3e\\u0c30\\u0c4d@s61.abq-dialin2.hollyberry.com", + "\\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27@\\u0917\\u0928\\u0947\\u0936.sanjose.ibm.com", + "\\u0c06\\u0c26\\u0c3f\\u0c24\\u0c4d\\u0c2f@www.\\u00E0\\u00B3\\u00AF.com", + "\\u0C15\\u0C02\\u0C26\\u0C4D\\u0C30\\u0C47\\u0C17\\u0C41\\u0c32@www.\\u00C2\\u00A4.com", + "\\u0c36\\u0c4d\\u0c30\\u0c40\\u0C27\\u0C30\\u0C4D@www.\\u00C2\\u00A3.com", + "\\u0c15\\u0c02\\u0c1f\\u0c2e\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f@\\u0025", + "\\u0c2e\\u0c3e\\u0c27\\u0c35\\u0c4d@\\u005C\\u005C", + "\\u0c26\\u0c46\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f@www.\\u0021.com", + "test@www.\\u0024.com", + "help@\\u00C3\\u00BC.com", + +}; + + +static void +Test_nfs4_mixed_prep(void){ + UErrorCode loadStatus = U_ZERO_ERROR; + loadTestData(&loadStatus); + if (U_FAILURE(loadStatus)) { + log_err("Test could not initialize. Got %s\n", u_errorName(loadStatus)); + return; + } + + { + int32_t i=0; + char src[MAX_BUFFER_SIZE]; + int32_t srcLen; + + for(i=0; i< LENGTHOF(mixed_prep_data); i++){ + int32_t destLen=0; + char* dest = NULL; + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + srcLen = unescapeData(mixed_prep_data[i], (int32_t)strlen(mixed_prep_data[i]), src, MAX_BUFFER_SIZE, &status); + if(U_FAILURE(status)){ + log_err("Conversion of data at index %i failed. Error: %s\n", i, u_errorName(status)); + continue; + } + destLen = nfs4_mixed_prepare(src, srcLen, NULL, 0, &parseError, &status); + if(status == U_BUFFER_OVERFLOW_ERROR){ + status = U_ZERO_ERROR; + dest = (char*)malloc(++destLen); + destLen = nfs4_mixed_prepare(src, srcLen, dest, destLen, &parseError, &status); + } + free(dest); + if(U_FAILURE(status)){ + log_err("Preparation of string at index %i failed. Error: %s\n", i, u_errorName(status)); + continue; + } + } + } + /* test the error condition */ + { + const char* source = "OWNER@oss.software.ibm.com"; + char dest[MAX_BUFFER_SIZE]; + char src[MAX_BUFFER_SIZE] = {0}; + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + + int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status); + + nfs4_mixed_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, &parseError, &status); + + if(status != U_PARSE_ERROR){ + log_err("Did not get the expected error.Expected: %s Got: %s\n", u_errorName(U_PARSE_ERROR), u_errorName(status)); + } + } + + +} + +static void +Test_nfs4_cs_prep(void){ + UErrorCode errorCode = U_ZERO_ERROR; + loadTestData(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode)); + return; + } + + { + /* BiDi checking is turned off */ + const char *source = "\\uC138\\uACC4\\uC758\\uBAA8\\uB4E0\\uC0AC\\uB78C\\uB4E4\\uC774\\u0644\\u064A\\u0647\\uD55C\\uAD6D\\uC5B4\\uB97C\\uC774\\uD574\\uD55C\\uB2E4\\uBA74"; + UErrorCode status = U_ZERO_ERROR; + char src[MAX_BUFFER_SIZE]={'\0'}; + UParseError parseError; + int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status); + if(U_SUCCESS(status)){ + char dest[MAX_BUFFER_SIZE] = {'\0'}; + int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status); + if(U_FAILURE(status)){ + log_err("StringPrep failed for case: BiDi Checking Turned OFF with error: %s\n", u_errorName(status)); + } + if(strcmp(dest,src)!=0){ + log_err("Did not get the expected output for case: BiDi Checking Turned OFF\n"); + } + if(destLen != srcLen){ + log_err("Did not get the expected length for the output for case: BiDi Checking Turned OFF. Expected: %i Got: %i\n", srcLen, destLen); + } + }else{ + log_err("Conversion failed for case: BiDi Checking Turned OFF with error: %s\n", u_errorName(status)); + } + } + { + /* Normalization turned off */ + const char *source = "www.\\u00E0\\u00B3\\u00AF.com"; + UErrorCode status = U_ZERO_ERROR; + char src[MAX_BUFFER_SIZE]={'\0'}; + UParseError parseError; + int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status); + if(U_SUCCESS(status)){ + char dest[MAX_BUFFER_SIZE] = {'\0'}; + int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status); + if(U_FAILURE(status)){ + log_err("StringPrep failed for case: Normalization Turned OFF with error: %s\n", u_errorName(status)); + } + if(strcmp(dest,src)!=0){ + log_err("Did not get the expected output for case: Normalization Turned OFF\n"); + } + if(destLen != srcLen){ + log_err("Did not get the expected length for the output for case: Normalization Turned OFF. Expected: %i Got: %i\n", srcLen, destLen); + } + }else{ + log_err("Conversion failed for case: Normalization Turned OFF with error: %s\n", u_errorName(status)); + } + } + { + /* case mapping turned off */ + const char *source = "THISISATEST"; + UErrorCode status = U_ZERO_ERROR; + char src[MAX_BUFFER_SIZE]={'\0'}; + UParseError parseError; + int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status); + if(U_SUCCESS(status)){ + char dest[MAX_BUFFER_SIZE] = {'\0'}; + int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, TRUE, &parseError, &status); + if(U_FAILURE(status)){ + log_err("StringPrep failed for case: Case Mapping Turned OFF with error: %s\n", u_errorName(status)); + } + if(strcmp(dest,src)!=0){ + log_err("Did not get the expected output for case: Case Mapping Turned OFF\n"); + } + if(destLen != srcLen){ + log_err("Did not get the expected length for the output for case: Case Mapping Turned OFF. Expected: %i Got: %i\n", srcLen, destLen); + } + }else{ + log_err("Conversion failed for case: Case Mapping Turned OFF with error: %s\n", u_errorName(status)); + } + } + { + /* case mapping turned on */ + const char *source = "THISISATEST"; + const char *expected = "thisisatest"; + UErrorCode status = U_ZERO_ERROR; + char src[MAX_BUFFER_SIZE]={'\0'}; + char exp[MAX_BUFFER_SIZE]={'\0'}; + UParseError parseError; + int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status); + int32_t expLen = unescapeData(expected, (int32_t)strlen(expected), exp, MAX_BUFFER_SIZE, &status); + if(U_SUCCESS(status)){ + char dest[MAX_BUFFER_SIZE] = {'\0'}; + int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status); + if(U_FAILURE(status)){ + log_err("StringPrep failed for case: Case Mapping Turned On with error: %s\n", u_errorName(status)); + } + if(strcmp(exp, dest)!=0){ + log_err("Did not get the expected output for case: Case Mapping Turned On!\n"); + } + if(destLen != expLen){ + log_err("Did not get the expected length for the outputfor case: Case Mapping Turned On. Expected: %i Got: %i\n", strlen(expected), destLen); + } + }else{ + log_err("Conversion failed for case: Case Mapping Turned ON with error: %s\n", u_errorName(status)); + } + } +} + + + +static void TestBEAMWarning(){ + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + UStringPrepProfile* profile = NULL; + /* get the test data path */ + const char *testdatapath = NULL; + UChar src =0x0000; + testdatapath = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + /* open the profile */ + profile = usprep_open(testdatapath, "nfscis", &status); + usprep_prepare(profile,&src , 0, NULL, 0, USPREP_DEFAULT, &parseError, &status); + + usprep_close(profile); +} + +static void TestCoverage(void) { + UErrorCode status = U_USELESS_COLLATOR_ERROR; + UParseError parseError; + + usprep_open(NULL, NULL, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("usprep_open didn't react correctly to a bad UErrorCode\n"); + } + usprep_prepare(NULL, NULL, 0, NULL, 0, USPREP_DEFAULT, &parseError, &status); + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("usprep_prepare didn't react correctly to a bad UErrorCode\n"); + } + status = U_ZERO_ERROR; + usprep_prepare(NULL, NULL, 0, NULL, 0, USPREP_DEFAULT, &parseError, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("usprep_prepare didn't check its arguments\n"); + } + + /* Don't crash */ + usprep_close(NULL); +} + +#endif + +/* + * Hey, Emacs, please set the following: + * + * Local Variables: + * indent-tabs-mode: nil + * End: + * + */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c b/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c new file mode 100644 index 00000000000..0349541c4be --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c @@ -0,0 +1,312 @@ +/* + ******************************************************************************* + * + * Copyright (C) 2003-2004, International Business Machines + * Corporation and others. All Rights Reserved. + * + ******************************************************************************* + * file name: spreptst.c + * encoding: US-ASCII + * tab size: 8 (not used) + * indentation:4 + * + * created on: 2003jul11 + * created by: Ram Viswanadha + */ +#define USPREP_TYPE_NAMES_ARRAY + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_IDNA + +#include "unicode/ustring.h" +#include "unicode/putil.h" +#include "cintltst.h" +#include "unicode/usprep.h" +#include "sprpimpl.h" +#include "uparse.h" +#include "cmemory.h" +#include "ustr_imp.h" +#include "cstring.h" + +static void +parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode); + +static void +compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping, int32_t mapLength, + UStringPrepType option); + +static void +compareFlagsForRange(UStringPrepProfile* data, uint32_t start, uint32_t end,UStringPrepType option); + +void +doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode); + +static void U_CALLCONV +strprepProfileLineFn(void *context, + char *fields[][2], int32_t fieldCount, + UErrorCode *pErrorCode) { + uint32_t mapping[40]; + char *end, *map; + uint32_t code; + int32_t length; + UStringPrepProfile* data = (UStringPrepProfile*) context; + const char* typeName; + uint32_t rangeStart=0,rangeEnd =0; + + typeName = fields[2][0]; + map = fields[1][0]; + + if(strstr(typeName, usprepTypeNames[USPREP_UNASSIGNED])!=NULL){ + + u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode); + + /* store the range */ + compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_UNASSIGNED); + + }else if(strstr(typeName, usprepTypeNames[USPREP_PROHIBITED])!=NULL){ + + u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode); + + /* store the range */ + compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_PROHIBITED); + + }else if(strstr(typeName, usprepTypeNames[USPREP_MAP])!=NULL){ + /* get the character code, field 0 */ + code=(uint32_t)uprv_strtoul(fields[0][0], &end, 16); + + /* parse the mapping string */ + length=u_parseCodePoints(map, mapping, sizeof(mapping)/4, pErrorCode); + + /* compare the mapping */ + compareMapping(data, code,mapping, length,USPREP_MAP); + }else{ + *pErrorCode = U_INVALID_FORMAT_ERROR; + } + +} + + + +static void +parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode) { + char *fields[3][2]; + + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return; + } + + u_parseDelimitedFile(filename, ';', fields, 3, strprepProfileLineFn, (void*)data, pErrorCode); + + /*fprintf(stdout,"Number of code points that have mappings with length >1 : %i\n",len);*/ + + if(U_FAILURE(*pErrorCode) && (reportError || *pErrorCode!=U_FILE_ACCESS_ERROR)) { + log_err( "testidn error: u_parseDelimitedFile(\"%s\") failed - %s\n", filename, u_errorName(*pErrorCode)); + } +} + + +static UStringPrepType +getValues(uint32_t result, int32_t* value, UBool* isIndex){ + + UStringPrepType type; + if(result == 0){ + /* + * Initial value stored in the mapping table + * just return USPREP_TYPE_LIMIT .. so that + * the source codepoint is copied to the destination + */ + type = USPREP_TYPE_LIMIT; + }else if(result >= _SPREP_TYPE_THRESHOLD){ + type = (UStringPrepType) (result - _SPREP_TYPE_THRESHOLD); + }else{ + /* get the type */ + type = USPREP_MAP; + /* ascertain if the value is index or delta */ + if(result & 0x02){ + *isIndex = TRUE; + *value = result >> 2; + + }else{ + *isIndex = FALSE; + *value = (int16_t)result; + *value = (*value >> 2); + + } + if((result>>2) == _SPREP_MAX_INDEX_VALUE){ + type = USPREP_DELETE; + isIndex =FALSE; + value = 0; + } + } + return type; +} + +static void +compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping,int32_t mapLength, + UStringPrepType type){ + uint32_t result = 0; + int32_t length=0; + UBool isIndex = FALSE; + UStringPrepType retType; + int32_t value=0, index=0, delta=0; + int32_t* indexes = data->indexes; + UTrie trie = data->sprepTrie; + const uint16_t* mappingData = data->mappingData; + int32_t realLength =0; + int32_t j=0; + int8_t i=0; + + UTRIE_GET16(&trie, codepoint, result); + retType = getValues(result,&value,&isIndex); + + + if(type != retType && retType != USPREP_DELETE){ + + log_err( "Did not get the assigned type for codepoint 0x%08X. Expected: %i Got: %i\n",codepoint, USPREP_MAP, type); + + } + + if(isIndex){ + index = value; + if(index >= indexes[_SPREP_ONE_UCHAR_MAPPING_INDEX_START] && + index < indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START]){ + length = 1; + }else if(index >= indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START] && + index < indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START]){ + length = 2; + }else if(index >= indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START] && + index < indexes[_SPREP_FOUR_UCHARS_MAPPING_INDEX_START]){ + length = 3; + }else{ + length = mappingData[index++]; + } + }else{ + delta = value; + length = (retType == USPREP_DELETE)? 0 : 1; + } + + /* figure out the real length */ + for(j=0; j<mapLength; j++){ + if(mapping[j] > 0xFFFF){ + realLength +=2; + }else{ + realLength++; + } + } + + if(realLength != length){ + log_err( "Did not get the expected length. Expected: %i Got: %i\n", mapLength, length); + } + + if(isIndex){ + for(i =0; i< mapLength; i++){ + if(mapping[i] <= 0xFFFF){ + if(mappingData[index+i] != (uint16_t)mapping[i]){ + log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[i], mappingData[index+i]); + } + }else{ + UChar lead = UTF16_LEAD(mapping[i]); + UChar trail = UTF16_TRAIL(mapping[i]); + if(mappingData[index+i] != lead || + mappingData[index+i+1] != trail){ + log_err( "Did not get the expected result. Expected: 0x%04X 0x%04X Got: 0x%04X 0x%04X\n", lead, trail, mappingData[index+i], mappingData[index+i+1]); + } + } + } + }else{ + if(retType!=USPREP_DELETE && (codepoint-delta) != (uint16_t)mapping[0]){ + log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[0],(codepoint-delta)); + } + } + +} + +static void +compareFlagsForRange(UStringPrepProfile* data, + uint32_t start, uint32_t end, + UStringPrepType type){ + + uint32_t result =0 ; + UStringPrepType retType; + UBool isIndex=FALSE; + int32_t value=0; + UTrie trie = data->sprepTrie; +/* + // supplementary code point + UChar __lead16=UTF16_LEAD(0x2323E); + int32_t __offset; + + // get data for lead surrogate + (result)=_UTRIE_GET_RAW((&idnTrie), index, 0, (__lead16)); + __offset=(&idnTrie)->getFoldingOffset(result); + + // get the real data from the folded lead/trail units + if(__offset>0) { + (result)=_UTRIE_GET_RAW((&idnTrie), index, __offset, (0x2323E)&0x3ff); + } else { + (result)=(uint32_t)((&idnTrie)->initialValue); + } + + UTRIE_GET16(&idnTrie,0x2323E, result); +*/ + while(start < end+1){ + UTRIE_GET16(&trie,start, result); + retType = getValues(result, &value, &isIndex); + if(result > _SPREP_TYPE_THRESHOLD){ + if(retType != type){ + log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]); + } + }else{ + if(type == USPREP_PROHIBITED && ((result & 0x01) != 0x01)){ + log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]); + } + } + + start++; + } + +} + +void +doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode){ + + const char *testdatapath = loadTestData(errorCode); + const char *srcdatapath = NULL; + const char *relativepath = NULL; + char *filename = NULL; + UStringPrepProfile* profile = NULL; + +#ifdef U_TOPSRCDIR + srcdatapath = U_TOPSRCDIR; + relativepath = U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; +#else + srcdatapath = ctest_dataOutDir(); + relativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING; +#endif + + filename = (char*) malloc(strlen(srcdatapath)+strlen(relativepath)+strlen(txtFileName)+10 ); + profile = usprep_open(testdatapath, binFileName, errorCode); + + if(U_FAILURE(*errorCode)){ + log_err("Failed to load %s data file. Error: %s \n", binFileName, u_errorName(*errorCode)); + return; + } + /* open and load the txt file */ + strcpy(filename,srcdatapath); + strcat(filename,relativepath); + strcat(filename,txtFileName); + + parseMappings(filename,profile, TRUE,errorCode); + + free(filename); +} +#endif +/* + * Hey, Emacs, please set the following: + * + * Local Variables: + * indent-tabs-mode: nil + * End: + * + */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c new file mode 100644 index 00000000000..2da96145b3c --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c @@ -0,0 +1,297 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2000-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File stdnmtst.c +* +* Modification History: +* +* Date Name Description +* 08/05/2000 Yves Creation +****************************************************************************** +*/ + +#include "unicode/ucnv.h" +#include "unicode/ustring.h" +#include "cstring.h" +#include "cintltst.h" + +#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0]) + +static void TestStandardName(void); +static void TestStandardNames(void); +static void TestCanonicalName(void); + +void addStandardNamesTest(TestNode** root); + + +void +addStandardNamesTest(TestNode** root) +{ + addTest(root, &TestStandardName, "tsconv/stdnmtst/TestStandardName"); + addTest(root, &TestStandardNames, "tsconv/stdnmtst/TestStandardNames"); + addTest(root, &TestCanonicalName, "tsconv/stdnmtst/TestCanonicalName"); +} + +static int dotestname(const char *name, const char *standard, const char *expected) { + int res = 1; + + UErrorCode error; + const char *tag; + + error = U_ZERO_ERROR; + tag = ucnv_getStandardName(name, standard, &error); + if (!tag && expected) { + log_err("FAIL: could not find %s standard name for %s\n", standard, name); + res = 0; + } else if (expected && (name == tag || uprv_strcmp(expected, tag))) { + log_err("FAIL: expected %s for %s standard name for %s, got %s\n", expected, standard, name, tag); + res = 0; + } + + return res; +} + +static void TestStandardName() +{ + int res = 1; + + uint16_t i, count; + UErrorCode err; + + /* Iterate over all standards. */ + for (i = 0, count = ucnv_countStandards(); i < count-1; ++i) { + const char *standard; + + err = U_ZERO_ERROR; + standard = ucnv_getStandard(i, &err); + if (U_FAILURE(err)) { + log_err("FAIL: ucnv_getStandard(%d), error=%s\n", i, u_errorName(err)); + res = 0; + } else if (!standard || !*standard) { + log_err("FAIL: %s standard name at index %d\n", (standard ? "empty" : + "null"), i); + res = 0; + } + } + err = U_ZERO_ERROR; + /* "" must be last */ + if(!count) { + log_data_err("No standards. You probably have no data.\n"); + } else if (*ucnv_getStandard((uint16_t)(count-1), &err) != 0) { + log_err("FAIL: ucnv_getStandard(%d) should return ""\n", count-1); + res = 0; + } + err = U_ZERO_ERROR; + if (ucnv_getStandard(++i, &err)) { + log_err("FAIL: ucnv_getStandard(%d) should return NULL\n", i); + res = 0; + } + + if (res) { + log_verbose("PASS: iterating over standard names works\n"); + } + + /* Test for some expected results. */ + + if (dotestname("ibm-1208", "MIME", "UTF-8") && + /*dotestname("cp1252", "MIME", "windows-1252") &&*/ + dotestname("ascii", "MIME", "US-ASCII") && + dotestname("csiso2022jp2", "MIME", "ISO-2022-JP-2") && + dotestname("Iso20-22__cN", "IANA", "ISO-2022-CN") && + dotestname("ascii", "IANA", "ANSI_X3.4-1968") && + dotestname("cp850", "IANA", "IBM850") && + dotestname("crazy", "MIME", NULL) && + dotestname("ASCII", "crazy", NULL) && + dotestname("LMBCS-1", "MIME", NULL)) + { + log_verbose("PASS: getting IANA and MIME standard names works\n"); + } +} + +static int dotestconv(const char *name, const char *standard, const char *expected) { + int res = 1; + + UErrorCode error; + const char *tag; + + error = U_ZERO_ERROR; + tag = ucnv_getCanonicalName(name, standard, &error); + if (tag && !expected) { + log_err("FAIL: Unexpectedly found %s canonical name for %s, got %s\n", standard, name, tag); + res = 0; + } + else if (!tag && expected) { + log_err("FAIL: could not find %s canonical name for %s\n", (standard ? "\"\"" : standard), name); + res = 0; + } + else if (expected && (name == tag || uprv_strcmp(expected, tag) != 0)) { + log_err("FAIL: expected %s for %s canonical name for %s, got %s\n", expected, standard, name, tag); + res = 0; + } + else { + log_verbose("PASS: (\"%s\", \"%s\") -> %s == %s \n", name, standard, tag, expected); + } + + return res; +} + +static void TestCanonicalName() +{ + /* Test for some expected results. */ + + if (dotestconv("UTF-8", "IANA", "UTF-8") && /* default name */ + dotestconv("UTF-8", "MIME", "UTF-8") && /* default name */ + dotestconv("ibm-1208", "IBM", "UTF-8") && /* default name */ + dotestconv("ibm-5305", "IBM", "UTF-8") && /* non-default name */ + dotestconv("ibm-5305", "MIME", NULL) && /* mapping does not exist */ + dotestconv("ascii", "MIME", NULL) && /* mapping does not exist */ + dotestconv("ibm-1208", "IANA", NULL) && /* mapping does not exist */ + dotestconv("ibm-5305", "IANA", NULL) && /* mapping does not exist */ + dotestconv("cp1208", "", "UTF-8") && /* default name due to ordering */ + dotestconv("UTF16_BigEndian", "", "UTF-16BE") && /* non-default name due to ordering */ + dotestconv("ISO-2022-CN", "IANA", "ISO_2022,locale=zh,version=0") &&/* default name */ + dotestconv("Shift_JIS", "MIME", "ibm-943_P15A-2003") &&/* ambiguous alias */ + dotestconv("Shift_JIS", "", "ibm-943_P130-1999") &&/* ambiguous alias */ + dotestconv("ibm-943", "", "ibm-943_P15A-2003") &&/* ambiguous alias */ + dotestconv("ibm-943", "IBM", "ibm-943_P130-1999") &&/* ambiguous alias */ + dotestconv("ibm-1363", "", "ibm-1363_P11B-1998") &&/* ambiguous alias */ + dotestconv("ibm-1363", "IBM", "ibm-1363_P110-1997") &&/* ambiguous alias */ + dotestconv("crazy", "MIME", NULL) && + dotestconv("ASCII", "crazy", NULL)) + { + log_verbose("PASS: getting IANA and MIME canonical names works\n"); + } +} + + +static UBool doTestNames(const char *name, const char *standard, const char **expected, int32_t size) { + UErrorCode err = U_ZERO_ERROR; + UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err); + const char *enumName, *testName; + int32_t enumCount = uenum_count(myEnum, &err); + int32_t idx, len, repeatTimes = 3; + if (size != enumCount) { + log_err("FAIL: different size arrays for %s. Got %d. Expected %d\n", name, enumCount, size); + return 0; + } + if (size < 0 && myEnum) { + log_err("FAIL: size < 0, but recieved an actual object\n"); + return 0; + } + log_verbose("\n%s %s\n", name, standard); + while (repeatTimes-- > 0) { + for (idx = 0; idx < enumCount; idx++) { + enumName = uenum_next(myEnum, &len, &err); + testName = expected[idx]; + if (uprv_strcmp(enumName, testName) != 0 || U_FAILURE(err) + || len != (int32_t)uprv_strlen(expected[idx])) + { + log_err("FAIL: uenum_next(%d) == \"%s\". expected \"%s\", len=%d, error=%s\n", + idx, enumName, testName, len, u_errorName(err)); + } + log_verbose("%s\n", enumName); + err = U_ZERO_ERROR; + } + if (enumCount >= 0) { + /* one past the list of all names must return NULL */ + enumName = uenum_next(myEnum, &len, &err); + if (enumName != NULL || len != 0 || U_FAILURE(err)) { + log_err("FAIL: uenum_next(past the list) did not return NULL[0] with U_SUCCESS(). name=%s standard=%s len=%d err=%s\n", name, standard, len, u_errorName(err)); + } + } + log_verbose("\n reset\n"); + uenum_reset(myEnum, &err); + if (U_FAILURE(err)) { + log_err("FAIL: uenum_reset() for %s{%s} failed with %s\n", + name, standard, u_errorName(err)); + err = U_ZERO_ERROR; + } + } + uenum_close(myEnum); + return 1; +} + +static UBool doTestUCharNames(const char *name, const char *standard, const char **expected, int32_t size) { + UErrorCode err = U_ZERO_ERROR; + UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err); + int32_t enumCount = uenum_count(myEnum, &err); + int32_t idx, repeatTimes = 3; + if (size != enumCount) { + log_err("FAIL: different size arrays. Got %d. Expected %d\n", enumCount, size); + return 0; + } + if (size < 0 && myEnum) { + log_err("FAIL: size < 0, but recieved an actual object\n"); + return 0; + } + log_verbose("\n%s %s\n", name, standard); + while (repeatTimes-- > 0) { + for (idx = 0; idx < enumCount; idx++) { + UChar testName[256]; + int32_t len; + const UChar *enumName = uenum_unext(myEnum, &len, &err); + u_uastrncpy(testName, expected[idx], sizeof(testName)/sizeof(testName[0])); + if (u_strcmp(enumName, testName) != 0 || U_FAILURE(err) + || len != (int32_t)uprv_strlen(expected[idx])) + { + log_err("FAIL: uenum_next(%d) == \"%s\". expected \"%s\", len=%d, error=%s\n", + idx, enumName, testName, len, u_errorName(err)); + } + log_verbose("%s\n", expected[idx]); + err = U_ZERO_ERROR; + } + log_verbose("\n reset\n"); + uenum_reset(myEnum, &err); + if (U_FAILURE(err)) { + log_err("FAIL: uenum_reset() for %s{%s} failed with %s\n", + name, standard, u_errorName(err)); + err = U_ZERO_ERROR; + } + } + uenum_close(myEnum); + return 1; +} + +static void TestStandardNames() +{ + static const char *asciiIANA[] = { + "ANSI_X3.4-1968", + "US-ASCII", + "ASCII", + "ANSI_X3.4-1986", + "ISO_646.irv:1991", + "ISO646-US", + "us", + "csASCII", + "iso-ir-6", + "cp367", + "IBM367", + }; + static const char *asciiMIME[] = { + "US-ASCII" + }; + + static const char *iso2022MIME[] = { + "ISO-2022-KR", + }; + + doTestNames("ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA)); + doTestNames("US-ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA)); + doTestNames("ASCII", "MIME", asciiMIME, ARRAY_SIZE(asciiMIME)); + doTestNames("ascii", "mime", asciiMIME, ARRAY_SIZE(asciiMIME)); + + doTestNames("ASCII", "crazy", asciiMIME, -1); + doTestNames("crazy", "MIME", asciiMIME, -1); + + doTestNames("LMBCS-1", "MIME", asciiMIME, 0); + + doTestNames("ISO_2022,locale=ko,version=0", "MIME", iso2022MIME, ARRAY_SIZE(iso2022MIME)); + doTestNames("csiso2022kr", "MIME", iso2022MIME, ARRAY_SIZE(iso2022MIME)); + + log_verbose(" Testing unext()\n"); + doTestUCharNames("ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA)); + +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c new file mode 100644 index 00000000000..d61804482a1 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c @@ -0,0 +1,379 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2003-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* + * File tracetst.c + * + */ + + +#include "unicode/utypes.h" +#include "unicode/utrace.h" +#include "unicode/uclean.h" +#include "unicode/uchar.h" +#include "unicode/ures.h" +#include "unicode/ucnv.h" +#include "cintltst.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/* We define the following to always test tracing, even when it's off in the library. */ +#if U_ENABLE_TRACING +#define ENABLE_TRACING_ORIG_VAL 1 +#else +#define ENABLE_TRACING_ORIG_VAL 0 +#endif +#undef U_ENABLE_TRACING +#define U_ENABLE_TRACING 1 +#include "utracimp.h" + + +static void TestTraceAPI(void); + + +void +addUTraceTest(TestNode** root); + +void +addUTraceTest(TestNode** root) +{ + addTest(root, &TestTraceAPI, "tsutil/TraceTest/TestTraceAPI" ); +} + + +/* + * Macro for assert style tests. + */ +#define TEST_ASSERT(expr) \ +if (!(expr)) { \ + log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \ +} + + +/* + * test_format. Helper function for checking the results of a formatting + * operation. Executes the format op and compares actual + * results with the expected results. + * + * params: format: the format to be applied. + * bufCap buffer size to pass to formatter. + * indent: indent value to give to formatter + * result expected result. Do not truncate for short bufCap - + * this function will do it. + * line __LINE__, so we can report where failure happened. + * ... variable args to pass to formatter + * + */ +static void test_format(const char *format, int32_t bufCap, int32_t indent, + const char *result, int32_t line, ...) { + int32_t len; + va_list args; + char buf[300]; + char expectedResult[300]; + + /* check that local buffers are big enough for the test case */ + if (sizeof(buf) <= bufCap) { + log_err("At file:line %s:%d, requested bufCap too large.\n"); + return; + } + if (strlen(result) >= sizeof(expectedResult)) { + log_err("At file:line %s:%d, expected result too large.\n"); + return; + } + + /* Guarantee a nul term if buffer is smaller than output */ + strcpy(expectedResult, result); + expectedResult[bufCap] = 0; + + /* run the formatter */ + va_start(args, line); + memset(buf, 0, sizeof(buf)); + len = utrace_vformat(buf, bufCap, indent, format, args); + + /* Check results. */ + if (strcmp(expectedResult, buf) != 0) { + log_err("At file:line %s:%d Expected \"%s\", got \"%s\" \n", + __FILE__, line, expectedResult, buf); + } + va_end(args); +} + + +/* + * define trace functions for use in this test. + */ +static int gTraceEntryCount; +static int gTraceExitCount; +static int gTraceDataCount; +static UBool gFnNameError = FALSE; +static UBool gFnFormatError = FALSE; + +static void U_CALLCONV testTraceEntry(const void *context, int32_t fnNumber) { + const char *fnName; + const char *bogusFnName; + + gTraceEntryCount++; + + /* Verify that a name is available for the fnNumber passed to us */ + bogusFnName = utrace_functionName(-1); + fnName = utrace_functionName(fnNumber); + if (strcmp(fnName, bogusFnName) == 0) { + gFnNameError = TRUE; + } + /* printf("%s() Enter\n", fnName); */ + +} + +static void U_CALLCONV testTraceExit(const void *context, int32_t fnNumber, + const char *fmt, va_list args) { + char buf[1000]; + const char *fnName; + const char *bogusFnName; + + gTraceExitCount++; + + /* Verify that a name is available for the fnNumber passed to us */ + bogusFnName = utrace_functionName(-1); + fnName = utrace_functionName(fnNumber); + if (strcmp(fnName, bogusFnName) == 0) { + gFnNameError = TRUE; + } + + /* Verify that the format can be used. */ + buf[0] = 0; + utrace_vformat(buf, sizeof(buf), 0, fmt, args); + if (strlen(buf) == 0) { + gFnFormatError = TRUE; + } + + /* printf("%s() %s\n", fnName, buf); */ + +} + +static void U_CALLCONV testTraceData(const void *context, int32_t fnNumber, int32_t level, + const char *fmt, va_list args) { + char buf[1000]; + const char *fnName; + const char *bogusFnName; + + gTraceDataCount++; + + /* Verify that a name is available for the fnNumber passed to us */ + bogusFnName = utrace_functionName(-1); + fnName = utrace_functionName(fnNumber); + if (strcmp(fnName, bogusFnName) == 0) { + gFnNameError = TRUE; + } + + /* Verify that the format can be used. */ + buf[0] = 0; + utrace_vformat(buf, sizeof(buf), 0, fmt, args); + if (strlen(buf) == 0) { + gFnFormatError = TRUE; + } + + /* printf(" %s() %s\n", fnName, buf); */ +} + +static UConverter * psuedo_ucnv_open(const char *name, UErrorCode * err) +{ + UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD); + + UTRACE_DATA2(UTRACE_OPEN_CLOSE, "error code is %s for %s", u_errorName(*err), name); + + UTRACE_EXIT_PTR_STATUS(NULL, *err); + return NULL; +} +static void psuedo_ucnv_close(UConverter * cnv) +{ + UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD); + UTRACE_DATA1(UTRACE_OPEN_CLOSE, "unload converter %p", cnv); + UTRACE_EXIT_VALUE((int32_t)TRUE); +} + + +/* + * TestTraceAPI + */ +static void TestTraceAPI() { + + + UTraceEntry *originalTEntryFunc; + UTraceExit *originalTExitFunc; + UTraceData *originalTDataFunc; + const void *originalTContext; + int32_t originalLevel; + + /* + * Save the original tracing state so that we can restore it after the test. + */ + utrace_getFunctions(&originalTContext, &originalTEntryFunc, &originalTExitFunc, + &originalTDataFunc); + originalLevel = utrace_getLevel(); + + + /* verify that set/get of tracing functions returns what was set. */ + { + UTraceEntry *e; + UTraceExit *x; + UTraceData *d; + const void *context; + const void *newContext = (const char *)originalTContext + 1; + + TEST_ASSERT(originalTEntryFunc != testTraceEntry); + TEST_ASSERT(originalTExitFunc != testTraceExit); + TEST_ASSERT(originalTDataFunc != testTraceData); + + utrace_setFunctions(newContext, testTraceEntry, testTraceExit, testTraceData); + utrace_getFunctions(&context, &e, &x, &d); + TEST_ASSERT(e == testTraceEntry); + TEST_ASSERT(x == testTraceExit); + TEST_ASSERT(d == testTraceData); + TEST_ASSERT(context == newContext); + } + + /* verify that set/get level work as a pair, and that the level + * identifiers all exist. + */ + + { + int32_t level; + + utrace_setLevel(UTRACE_OFF); + level = utrace_getLevel(); + TEST_ASSERT(level==UTRACE_OFF); + utrace_setLevel(UTRACE_VERBOSE); + level = utrace_getLevel(); + TEST_ASSERT(level==UTRACE_VERBOSE); + utrace_setLevel(UTRACE_ERROR); + utrace_setLevel(UTRACE_WARNING); + utrace_setLevel(UTRACE_OPEN_CLOSE); + utrace_setLevel(UTRACE_INFO); + } + + /* + * Open and close a converter with tracing enabled. + * Verify that our tracing callback functions get called. + */ + { + UErrorCode status = U_ZERO_ERROR; + UConverter *cnv; + + gTraceEntryCount = 0; + gTraceExitCount = 0; + gTraceDataCount = 0; + gFnNameError = FALSE; + gFnFormatError = FALSE; + utrace_setLevel(UTRACE_OPEN_CLOSE); +#if ENABLE_TRACING_ORIG_VAL + cnv = ucnv_open(NULL, &status); + TEST_ASSERT(U_SUCCESS(status)); + ucnv_close(cnv); +#else + cnv = psuedo_ucnv_open(NULL, &status); + TEST_ASSERT(U_SUCCESS(status)); + psuedo_ucnv_close(cnv); +#endif + TEST_ASSERT(gTraceEntryCount > 0); + TEST_ASSERT(gTraceExitCount > 0); + TEST_ASSERT(gTraceDataCount > 0); + TEST_ASSERT(gFnNameError == FALSE); + TEST_ASSERT(gFnFormatError == FALSE); + } + + + + /* + * trace data formatter operation. + */ + { + UChar s1[] = {0x41fe, 0x42, 0x43, 00}; + const char *a1[] = {"s1", "s2", "s3"}; + void *ptr; + + test_format("hello, world", 50, 0, "hello, world", __LINE__); + test_format("hello, world", 50, 4, " hello, world", __LINE__); + test_format("hello, world", 3, 0, "hello, world", __LINE__); + + test_format("a character %c", 50, 0, "a character x", __LINE__, 'x'); + test_format("a string %s ", 50, 0, "a string hello ", __LINE__, "hello"); + test_format("uchars %S ", 50, 0, "uchars 41fe 0042 0043 0000 ", __LINE__, s1, -1); + test_format("uchars %S ", 50, 0, "uchars 41fe 0042 ", __LINE__, s1, 2); + + test_format("a byte %b--", 50, 0, "a byte dd--", __LINE__, 0xdd); + test_format("a 16 bit val %h", 50, 0, "a 16 bit val 1234", __LINE__, 0x1234); + test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd); + test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0" + , __LINE__, INT64_C(0x123456780abcdef0)); + + if (sizeof(void *) == 4) { + ptr = (void *)0xdeadbeef; + test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr); + } else if (sizeof(void *) == 8) { + ptr = (void *) INT64_C(0x1000200030004000); + test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr); + } else if (sizeof(void *) == 16) { + /* iSeries */ + union { + int32_t arr[4]; + void *ptr; + } massiveBigEndianPtr = {{ 0x10002000, 0x30004000, 0x50006000, 0x70008000 }}; + ptr = massiveBigEndianPtr.ptr; + test_format("a 128 bit ptr %p", 50, 0, "a 128 bit ptr 10002000300040005000600070008000", __LINE__, ptr); + } else { + TEST_ASSERT(FALSE); + /* TODO: others? */ + } + + test_format("%vc", 100, 0, "abc[ffffffff]", __LINE__, "abc", -1); + test_format("%vs", 100, 0, "s1\ns2\n[00000002]", __LINE__, a1, 2); + test_format("%vs", 100, 4, " s1\n s2\n [00000002]", __LINE__, a1, 2); + + test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "\x41\x42\x43", 3); + + /* Null ptrs for strings, vectors */ + test_format("Null string - %s", 50, 0, "Null string - *NULL*", __LINE__, NULL); + test_format("Null string - %S", 50, 0, "Null string - *NULL*", __LINE__, NULL); + test_format("Null vector - %vc", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2); + test_format("Null vector - %vC", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2); + test_format("Null vector - %vd", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2); + + } + + /* + * utrace_format. Only need a minimal test to see that the function works at all. + * Full functionality is tested via utrace_vformat. + */ + { + char buf[100]; + int32_t x; + x = utrace_format(buf, 100, 0, "%s", "Hello, World."); + TEST_ASSERT(strcmp(buf, "Hello, World.") == 0); + TEST_ASSERT(x == 14); + } + + /* + * utrace_functionName. Just spot-check a couple of them. + */ + { + const char *name; + name = utrace_functionName(UTRACE_U_INIT); + TEST_ASSERT(strcmp(name, "u_init") == 0); + name = utrace_functionName(UTRACE_UCNV_OPEN); + TEST_ASSERT(strcmp(name, "ucnv_open") == 0); + name = utrace_functionName(UTRACE_UCOL_GET_SORTKEY); + TEST_ASSERT(strcmp(name, "ucol_getSortKey") == 0); + } + + + + /* Restore the trace function settings to their original values. */ + utrace_setFunctions(originalTContext, originalTEntryFunc, originalTExitFunc, originalTDataFunc); + utrace_setLevel(originalLevel); +} + + + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c new file mode 100644 index 00000000000..c4a7c1733fc --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c @@ -0,0 +1,877 @@ +/* +****************************************************************************** +* +* Copyright (C) 2001-2006, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* file name: trietest.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2001nov20 +* created by: Markus W. Scherer +*/ + +#include <stdio.h> +#include "unicode/utypes.h" +#include "utrie.h" +#include "cstring.h" +#include "cmemory.h" + +#if 1 +#include "cintltst.h" +#else +/* definitions from standalone utrie development */ +#define log_err printf +#define log_verbose printf + +#undef u_errorName +#define u_errorName(errorCode) "some error code" +#endif + +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) + +/* Values for setting possibly overlapping, out-of-order ranges of values */ +typedef struct SetRange { + UChar32 start, limit; + uint32_t value; + UBool overwrite; +} SetRange; + +/* + * Values for testing: + * value is set from the previous boundary's limit to before + * this boundary's limit + */ +typedef struct CheckRange { + UChar32 limit; + uint32_t value; +} CheckRange; + + +static uint32_t U_CALLCONV +_testFoldedValue32(UNewTrie *trie, UChar32 start, int32_t offset) { + uint32_t foldedValue, value; + UChar32 limit; + UBool inBlockZero; + + foldedValue=0; + + limit=start+0x400; + while(start<limit) { + value=utrie_get32(trie, start, &inBlockZero); + if(inBlockZero) { + start+=UTRIE_DATA_BLOCK_LENGTH; + } else { + foldedValue|=value; + ++start; + } + } + + if(foldedValue!=0) { + return ((uint32_t)offset<<16)|foldedValue; + } else { + return 0; + } +} + +static int32_t U_CALLCONV +_testFoldingOffset32(uint32_t data) { + return (int32_t)(data>>16); +} + +static uint32_t U_CALLCONV +_testFoldedValue16(UNewTrie *trie, UChar32 start, int32_t offset) { + uint32_t foldedValue, value; + UChar32 limit; + UBool inBlockZero; + + foldedValue=0; + + limit=start+0x400; + while(start<limit) { + value=utrie_get32(trie, start, &inBlockZero); + if(inBlockZero) { + start+=UTRIE_DATA_BLOCK_LENGTH; + } else { + foldedValue|=value; + ++start; + } + } + + if(foldedValue!=0) { + return (uint32_t)(offset|0x8000); + } else { + return 0; + } +} + +static int32_t U_CALLCONV +_testFoldingOffset16(uint32_t data) { + if(data&0x8000) { + return (int32_t)(data&0x7fff); + } else { + return 0; + } +} + +static uint32_t U_CALLCONV +_testEnumValue(const void *context, uint32_t value) { + return value^0x5555; +} + +static UBool U_CALLCONV +_testEnumRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) { + const CheckRange **pb=(const CheckRange **)context; + const CheckRange *b=(*pb)++; + + value^=0x5555; + if(start!=(b-1)->limit || limit!=b->limit || value!=b->value) { + log_err("error: utrie_enum() delivers wrong range [U+%04lx..U+%04lx[.0x%lx instead of [U+%04lx..U+%04lx[.0x%lx\n", + start, limit, value, + (b-1)->limit, b->limit, b->value); + } + return TRUE; +} + +static void +testTrieIteration(const char *testName, + const UTrie *trie, + const CheckRange checkRanges[], int32_t countCheckRanges) { + UChar s[100]; + uint32_t values[30]; + + const UChar *p, *limit; + + uint32_t value; + UChar32 c; + int32_t i, length, countValues; + UChar c2; + + /* write a string */ + length=countValues=0; + for(i=0; i<countCheckRanges; ++i) { + c=checkRanges[i].limit; + if(c!=0) { + --c; + UTF_APPEND_CHAR_UNSAFE(s, length, c); + values[countValues++]=checkRanges[i].value; + } + } + limit=s+length; + + /* try forward */ + p=s; + i=0; + while(p<limit) { + c=c2=0x33; + if(trie->data32!=NULL) { + UTRIE_NEXT32(trie, p, limit, c, c2, value); + } else { + UTRIE_NEXT16(trie, p, limit, c, c2, value); + } + if(value!=values[i]) { + log_err("error: wrong value from UTRIE_NEXT(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n", + testName, c, c2, value, values[i]); + } + if( + c2==0 ? + c!=*(p-1) : + !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*(p-2) || c2!=*(p-1) + ) { + log_err("error: wrong (c, c2) from UTRIE_NEXT(%s): (U+%04lx, U+%04lx)\n", + testName, c, c2); + continue; + } + if(c2!=0) { + int32_t offset; + + if(trie->data32==NULL) { + value=UTRIE_GET16_FROM_LEAD(trie, c); + offset=trie->getFoldingOffset(value); + if(offset>0) { + value=UTRIE_GET16_FROM_OFFSET_TRAIL(trie, offset, c2); + } else { + value=trie->initialValue; + } + } else { + value=UTRIE_GET32_FROM_LEAD(trie, c); + offset=trie->getFoldingOffset(value); + if(offset>0) { + value=UTRIE_GET32_FROM_OFFSET_TRAIL(trie, offset, c2); + } else { + value=trie->initialValue; + } + } + if(value!=values[i]) { + log_err("error: wrong value from UTRIE_GETXX_FROM_OFFSET_TRAIL(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n", + testName, c, c2, value, values[i]); + } + } + if(c2!=0) { + value=0x44; + if(trie->data32==NULL) { + UTRIE_GET16_FROM_PAIR(trie, c, c2, value); + } else { + UTRIE_GET32_FROM_PAIR(trie, c, c2, value); + } + if(value!=values[i]) { + log_err("error: wrong value from UTRIE_GETXX_FROM_PAIR(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n", + testName, c, c2, value, values[i]); + } + } + ++i; + } + + /* try backward */ + p=limit; + i=countValues; + while(s<p) { + --i; + c=c2=0x33; + if(trie->data32!=NULL) { + UTRIE_PREVIOUS32(trie, s, p, c, c2, value); + } else { + UTRIE_PREVIOUS16(trie, s, p, c, c2, value); + } + if(value!=values[i]) { + log_err("error: wrong value from UTRIE_PREVIOUS(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n", + testName, c, c2, value, values[i]); + } + if( + c2==0 ? + c!=*p: + !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*p || c2!=*(p+1) + ) { + log_err("error: wrong (c, c2) from UTRIE_PREVIOUS(%s): (U+%04lx, U+%04lx)\n", + testName, c, c2); + } + } +} + +static void +testTrieRangesWithMalloc(const char *testName, + const SetRange setRanges[], int32_t countSetRanges, + const CheckRange checkRanges[], int32_t countCheckRanges, + UBool dataIs32, UBool latin1Linear) { + UTrieGetFoldingOffset *getFoldingOffset; + const CheckRange *enumRanges; + UNewTrie *newTrie; + UTrie trie={ 0 }; + uint32_t value, value2; + UChar32 start, limit; + int32_t i, length; + UErrorCode errorCode; + UBool overwrite, ok; + uint8_t* storage =NULL; + static const int32_t DEFAULT_STORAGE_SIZE = 32768; + storage = (uint8_t*) uprv_malloc(sizeof(uint8_t)*DEFAULT_STORAGE_SIZE); + + log_verbose("\ntesting Trie '%s'\n", testName); + newTrie=utrie_open(NULL, NULL, 2000, + checkRanges[0].value, checkRanges[0].value, + latin1Linear); + + /* set values from setRanges[] */ + ok=TRUE; + for(i=0; i<countSetRanges; ++i) { + start=setRanges[i].start; + limit=setRanges[i].limit; + value=setRanges[i].value; + overwrite=setRanges[i].overwrite; + if((limit-start)==1 && overwrite) { + ok&=utrie_set32(newTrie, start, value); + } else { + ok&=utrie_setRange32(newTrie, start, limit, value, overwrite); + } + } + if(!ok) { + log_err("error: setting values into a trie failed (%s)\n", testName); + return; + } + + /* verify that all these values are in the new Trie */ + start=0; + for(i=0; i<countCheckRanges; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + while(start<limit) { + if(value!=utrie_get32(newTrie, start, NULL)) { + log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n", + testName, start, utrie_get32(newTrie, start, NULL), value); + } + ++start; + } + } + + if(dataIs32) { + getFoldingOffset=_testFoldingOffset32; + } else { + getFoldingOffset=_testFoldingOffset16; + } + + errorCode=U_ZERO_ERROR; + length=utrie_serialize(newTrie, storage, DEFAULT_STORAGE_SIZE, + dataIs32 ? _testFoldedValue32 : _testFoldedValue16, + (UBool)!dataIs32, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode)); + utrie_close(newTrie); + return; + } + + /* test linear Latin-1 range from utrie_getData() */ + if(latin1Linear) { + uint32_t *data; + int32_t dataLength; + + data=utrie_getData(newTrie, &dataLength); + start=0; + for(i=0; i<countCheckRanges && start<=0xff; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + while(start<limit && start<=0xff) { + if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) { + log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n", + testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value); + } + ++start; + } + } + } + + utrie_close(newTrie); + + errorCode=U_ZERO_ERROR; + if(!utrie_unserialize(&trie, storage, length, &errorCode)) { + log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode)); + return; + } + trie.getFoldingOffset=getFoldingOffset; + + if(dataIs32!=(trie.data32!=NULL)) { + log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName); + } + if(latin1Linear!=trie.isLatin1Linear) { + log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName); + } + + /* verify that all these values are in the unserialized Trie */ + start=0; + for(i=0; i<countCheckRanges; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + if(start==0xd800) { + /* skip surrogates */ + start=limit; + continue; + } + + while(start<limit) { + if(start<=0xffff) { + if(dataIs32) { + value2=UTRIE_GET32_FROM_BMP(&trie, start); + } else { + value2=UTRIE_GET16_FROM_BMP(&trie, start); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + if(!UTF_IS_LEAD(start)) { + if(dataIs32) { + value2=UTRIE_GET32_FROM_LEAD(&trie, start); + } else { + value2=UTRIE_GET16_FROM_LEAD(&trie, start); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + } + } + if(dataIs32) { + UTRIE_GET32(&trie, start, value2); + } else { + UTRIE_GET16(&trie, start, value2); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + ++start; + } + } + + /* enumerate and verify all ranges */ + enumRanges=checkRanges+1; + utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges); + + /* test linear Latin-1 range */ + if(trie.isLatin1Linear) { + if(trie.data32!=NULL) { + const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie); + + for(start=0; start<0x100; ++start) { + if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) { + log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n", + testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start); + } + } + } else { + const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie); + + for(start=0; start<0x100; ++start) { + if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) { + log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n", + testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start); + } + } + } + } + + testTrieIteration(testName, &trie, checkRanges, countCheckRanges); + uprv_free(storage); +} + +static void +testTrieRanges(const char *testName, + const SetRange setRanges[], int32_t countSetRanges, + const CheckRange checkRanges[], int32_t countCheckRanges, + UBool dataIs32, UBool latin1Linear) { + union{ + double bogus; /* needed for aligining the storage */ + uint8_t storage[32768]; + } storageHolder; + UTrieGetFoldingOffset *getFoldingOffset; + UNewTrieGetFoldedValue *getFoldedValue; + const CheckRange *enumRanges; + UNewTrie *newTrie; + UTrie trie={ 0 }; + uint32_t value, value2; + UChar32 start, limit; + int32_t i, length; + UErrorCode errorCode; + UBool overwrite, ok; + + log_verbose("\ntesting Trie '%s'\n", testName); + newTrie=utrie_open(NULL, NULL, 2000, + checkRanges[0].value, checkRanges[0].value, + latin1Linear); + + /* set values from setRanges[] */ + ok=TRUE; + for(i=0; i<countSetRanges; ++i) { + start=setRanges[i].start; + limit=setRanges[i].limit; + value=setRanges[i].value; + overwrite=setRanges[i].overwrite; + if((limit-start)==1 && overwrite) { + ok&=utrie_set32(newTrie, start, value); + } else { + ok&=utrie_setRange32(newTrie, start, limit, value, overwrite); + } + } + if(!ok) { + log_err("error: setting values into a trie failed (%s)\n", testName); + return; + } + + /* verify that all these values are in the new Trie */ + start=0; + for(i=0; i<countCheckRanges; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + while(start<limit) { + if(value!=utrie_get32(newTrie, start, NULL)) { + log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n", + testName, start, utrie_get32(newTrie, start, NULL), value); + } + ++start; + } + } + + if(dataIs32) { + getFoldingOffset=_testFoldingOffset32; + getFoldedValue=_testFoldedValue32; + } else { + getFoldingOffset=_testFoldingOffset16; + getFoldedValue=_testFoldedValue16; + } + + /* + * code coverage for utrie.c/defaultGetFoldedValue(), + * pick some combination of parameters for selecting the UTrie defaults + */ + if(!dataIs32 && latin1Linear) { + getFoldingOffset=NULL; + getFoldedValue=NULL; + } + + errorCode=U_ZERO_ERROR; + length=utrie_serialize(newTrie, storageHolder.storage, sizeof(storageHolder.storage), + getFoldedValue, + (UBool)!dataIs32, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode)); + utrie_close(newTrie); + return; + } + if (length >= (int32_t)sizeof(storageHolder.storage)) { + log_err("error: utrie_serialize(%s) needs more memory\n", testName); + utrie_close(newTrie); + return; + } + + /* test linear Latin-1 range from utrie_getData() */ + if(latin1Linear) { + uint32_t *data; + int32_t dataLength; + + data=utrie_getData(newTrie, &dataLength); + start=0; + for(i=0; i<countCheckRanges && start<=0xff; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + while(start<limit && start<=0xff) { + if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) { + log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n", + testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value); + } + ++start; + } + } + } + + utrie_close(newTrie); + + errorCode=U_ZERO_ERROR; + if(!utrie_unserialize(&trie, storageHolder.storage, length, &errorCode)) { + log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode)); + return; + } + if(getFoldingOffset!=NULL) { + trie.getFoldingOffset=getFoldingOffset; + } + + if(dataIs32!=(trie.data32!=NULL)) { + log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName); + } + if(latin1Linear!=trie.isLatin1Linear) { + log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName); + } + + /* verify that all these values are in the unserialized Trie */ + start=0; + for(i=0; i<countCheckRanges; ++i) { + limit=checkRanges[i].limit; + value=checkRanges[i].value; + + if(start==0xd800) { + /* skip surrogates */ + start=limit; + continue; + } + + while(start<limit) { + if(start<=0xffff) { + if(dataIs32) { + value2=UTRIE_GET32_FROM_BMP(&trie, start); + } else { + value2=UTRIE_GET16_FROM_BMP(&trie, start); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + if(!UTF_IS_LEAD(start)) { + if(dataIs32) { + value2=UTRIE_GET32_FROM_LEAD(&trie, start); + } else { + value2=UTRIE_GET16_FROM_LEAD(&trie, start); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + } + } + if(dataIs32) { + UTRIE_GET32(&trie, start, value2); + } else { + UTRIE_GET16(&trie, start, value2); + } + if(value!=value2) { + log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n", + testName, start, value2, value); + } + ++start; + } + } + + /* enumerate and verify all ranges */ + enumRanges=checkRanges+1; + utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges); + + /* test linear Latin-1 range */ + if(trie.isLatin1Linear) { + if(trie.data32!=NULL) { + const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie); + + for(start=0; start<0x100; ++start) { + if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) { + log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n", + testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start); + } + } + } else { + const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie); + + for(start=0; start<0x100; ++start) { + if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) { + log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n", + testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start); + } + } + } + } + + testTrieIteration(testName, &trie, checkRanges, countCheckRanges); +} + +static void +testTrieRanges2(const char *testName, + const SetRange setRanges[], int32_t countSetRanges, + const CheckRange checkRanges[], int32_t countCheckRanges, + UBool dataIs32) { + char name[40]; + + testTrieRanges(testName, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + dataIs32, FALSE); + testTrieRangesWithMalloc(testName, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + dataIs32, FALSE); + + uprv_strcpy(name, testName); + uprv_strcat(name, "-latin1Linear"); + testTrieRanges(name, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + dataIs32, TRUE); + testTrieRangesWithMalloc(name, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + dataIs32, TRUE); +} + +static void +testTrieRanges4(const char *testName, + const SetRange setRanges[], int32_t countSetRanges, + const CheckRange checkRanges[], int32_t countCheckRanges) { + char name[40]; + + uprv_strcpy(name, testName); + uprv_strcat(name, ".32"); + testTrieRanges2(name, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + TRUE); + + uprv_strcpy(name, testName); + uprv_strcat(name, ".16"); + testTrieRanges2(name, + setRanges, countSetRanges, + checkRanges, countCheckRanges, + FALSE); +} + +/* test data ----------------------------------------------------------------*/ + +/* set consecutive ranges, even with value 0 */ +static const SetRange +setRanges1[]={ + {0, 0x20, 0, FALSE}, + {0x20, 0xa7, 0x1234, FALSE}, + {0xa7, 0x3400, 0, FALSE}, + {0x3400, 0x9fa6, 0x6162, FALSE}, + {0x9fa6, 0xda9e, 0x3132, FALSE}, + {0xdada, 0xeeee, 0x87ff, FALSE}, /* try to disrupt _testFoldingOffset16() */ + {0xeeee, 0x11111, 1, FALSE}, + {0x11111, 0x44444, 0x6162, FALSE}, + {0x44444, 0x60003, 0, FALSE}, + {0xf0003, 0xf0004, 0xf, FALSE}, + {0xf0004, 0xf0006, 0x10, FALSE}, + {0xf0006, 0xf0007, 0x11, FALSE}, + {0xf0007, 0xf0020, 0x12, FALSE}, + {0xf0020, 0x110000, 0, FALSE} +}; + +static const CheckRange +checkRanges1[]={ + {0, 0}, /* dummy start range to make _testEnumRange() simpler */ + {0x20, 0}, + {0xa7, 0x1234}, + {0x3400, 0}, + {0x9fa6, 0x6162}, + {0xda9e, 0x3132}, + {0xdada, 0}, + {0xeeee, 0x87ff}, + {0x11111,1}, + {0x44444,0x6162}, + {0xf0003,0}, + {0xf0004,0xf}, + {0xf0006,0x10}, + {0xf0007,0x11}, + {0xf0020,0x12}, + {0x110000, 0} +}; + +/* set some interesting overlapping ranges */ +static const SetRange +setRanges2[]={ + {0x21, 0x7f, 0x5555, TRUE}, + {0x2f800,0x2fedc, 0x7a, TRUE}, + {0x72, 0xdd, 3, TRUE}, + {0xdd, 0xde, 4, FALSE}, + {0x2f987,0x2fa98, 5, TRUE}, + {0x2f777,0x2f833, 0, TRUE}, + {0x2f900,0x2ffee, 1, FALSE}, + {0x2ffee,0x2ffef, 2, TRUE} +}; + +static const CheckRange +checkRanges2[]={ + {0, 0}, /* dummy start range to make _testEnumRange() simpler */ + {0x21, 0}, + {0x72, 0x5555}, + {0xdd, 3}, + {0xde, 4}, + {0x2f833,0}, + {0x2f987,0x7a}, + {0x2fa98,5}, + {0x2fedc,0x7a}, + {0x2ffee,1}, + {0x2ffef,2}, + {0x110000, 0} +}; + +/* use a non-zero initial value */ +static const SetRange +setRanges3[]={ + {0x31, 0xa4, 1, FALSE}, + {0x3400, 0x6789, 2, FALSE}, + {0x30000,0x34567,9, TRUE}, + {0x45678,0x56789,3, TRUE} +}; + +static const CheckRange +checkRanges3[]={ + {0, 9}, /* dummy start range, also carries the initial value */ + {0x31, 9}, + {0xa4, 1}, + {0x3400, 9}, + {0x6789, 2}, + {0x45678,9}, + {0x56789,3}, + {0x110000,9} +}; + +static void +TrieTest(void) { + testTrieRanges4("set1", + setRanges1, ARRAY_LENGTH(setRanges1), + checkRanges1, ARRAY_LENGTH(checkRanges1)); + testTrieRanges4("set2-overlap", + setRanges2, ARRAY_LENGTH(setRanges2), + checkRanges2, ARRAY_LENGTH(checkRanges2)); + testTrieRanges4("set3-initial-9", + setRanges3, ARRAY_LENGTH(setRanges3), + checkRanges3, ARRAY_LENGTH(checkRanges3)); +} + +/* test utrie_unserializeDummy() -------------------------------------------- */ + +static int32_t U_CALLCONV +dummyGetFoldingOffset(uint32_t data) { + return -1; /* never get non-initialValue data for supplementary code points */ +} + +static void +dummyTest(UBool make16BitTrie) { + int32_t mem[UTRIE_DUMMY_SIZE/4]; + + UTrie trie; + UErrorCode errorCode; + UChar32 c; + + uint32_t value, initialValue, leadUnitValue; + + if(make16BitTrie) { + initialValue=0x313; + leadUnitValue=0xaffe; + } else { + initialValue=0x01234567; + leadUnitValue=0x89abcdef; + } + + errorCode=U_ZERO_ERROR; + utrie_unserializeDummy(&trie, mem, sizeof(mem), initialValue, leadUnitValue, make16BitTrie, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("utrie_unserializeDummy(make16BitTrie=%d) failed - %s\n", make16BitTrie, u_errorName(errorCode)); + return; + } + trie.getFoldingOffset=dummyGetFoldingOffset; + + /* test that all code points have initialValue */ + for(c=0; c<=0x10ffff; ++c) { + if(make16BitTrie) { + UTRIE_GET16(&trie, c, value); + } else { + UTRIE_GET32(&trie, c, value); + } + if(value!=initialValue) { + log_err("UTRIE_GET%s(dummy, U+%04lx)=0x%lx instead of 0x%lx\n", + make16BitTrie ? "16" : "32", (long)c, (long)value, (long)initialValue); + } + } + + /* test that the lead surrogate code units have leadUnitValue */ + for(c=0xd800; c<=0xdbff; ++c) { + if(make16BitTrie) { + value=UTRIE_GET16_FROM_LEAD(&trie, c); + } else { + value=UTRIE_GET32_FROM_LEAD(&trie, c); + } + if(value!=leadUnitValue) { + log_err("UTRIE_GET%s_FROM_LEAD(dummy, U+%04lx)=0x%lx instead of 0x%lx\n", + make16BitTrie ? "16" : "32", (long)c, (long)value, (long)leadUnitValue); + } + } +} + +static void +DummyTrieTest(void) { + dummyTest(TRUE); + dummyTest(FALSE); +} + +void +addTrieTest(TestNode** root); + +void +addTrieTest(TestNode** root) { + addTest(root, &TrieTest, "tsutil/trietest/TrieTest"); + addTest(root, &DummyTrieTest, "tsutil/trietest/DummyTrieTest"); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c new file mode 100644 index 00000000000..9bc18d329ea --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c @@ -0,0 +1,355 @@ +/* + **************************************************************************** + * Copyright (c) 2005-2006, International Business Machines Corporation and * + * others. All Rights Reserved. * + **************************************************************************** + */ + +#include "unicode/utypes.h" + +#include "unicode/ucsdet.h" +#include "unicode/ucnv.h" +#include "unicode/ustring.h" + +#include "cintltst.h" + +#include <stdlib.h> +#include <string.h> + +#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) + +#define NEW_ARRAY(type,count) (type *) malloc((count) * sizeof(type)) +#define DELETE_ARRAY(array) free(array) + +static void TestConstruction(void); +static void TestUTF8(void); +static void TestUTF16(void); +static void TestC1Bytes(void); +static void TestInputFilter(void); +static void TestChaining(void); + +void addUCsdetTest(TestNode** root); + +void addUCsdetTest(TestNode** root) +{ + addTest(root, &TestConstruction, "ucsdetst/TestConstruction"); + addTest(root, &TestUTF8, "ucsdetst/TestUTF8"); + addTest(root, &TestUTF16, "ucsdetst/TestUTF16"); + addTest(root, &TestC1Bytes, "ucsdetst/TestC1Bytes"); + addTest(root, &TestInputFilter, "ucsdetst/TestInputFilter"); + addTest(root, &TestChaining, "ucsdetst/TestErrorChaining"); +} + +static int32_t preflight(const UChar *src, int32_t length, UConverter *cnv) +{ + UErrorCode status; + char buffer[1024]; + char *dest, *destLimit = buffer + sizeof(buffer); + const UChar *srcLimit = src + length; + int32_t result = 0; + + do { + dest = buffer; + status = U_ZERO_ERROR; + ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &status); + result += (int32_t) (dest - buffer); + } while (status == U_BUFFER_OVERFLOW_ERROR); + + return result; +} + +static char *extractBytes(const UChar *src, int32_t length, const char *codepage, int32_t *byteLength) +{ + UErrorCode status = U_ZERO_ERROR; + UConverter *cnv = ucnv_open(codepage, &status); + int32_t byteCount = preflight(src, length, cnv); + const UChar *srcLimit = src + length; + char *bytes = NEW_ARRAY(char, byteCount + 1); + char *dest = bytes, *destLimit = bytes + byteCount + 1; + + ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &status); + ucnv_close(cnv); + + *byteLength = byteCount; + return bytes; +} + +static void freeBytes(char *bytes) +{ + DELETE_ARRAY(bytes); +} + +static void TestConstruction(void) +{ + UErrorCode status = U_ZERO_ERROR; + UCharsetDetector *csd = ucsdet_open(&status); + UEnumeration *e = ucsdet_getAllDetectableCharsets(csd, &status); + const char *name; + int32_t count = uenum_count(e, &status); + int32_t i, length; + + for(i = 0; i < count; i += 1) { + name = uenum_next(e, &length, &status); + + if(name == NULL || length <= 0) { + log_err("ucsdet_getAllDetectableCharsets() returned a null or empty name!\n"); + } + } + /* one past the list of all names must return NULL */ + name = uenum_next(e, &length, &status); + if(name != NULL || length != 0 || U_FAILURE(status)) { + log_err("ucsdet_getAllDetectableCharsets(past the list) returned a non-null name!\n"); + } + + uenum_close(e); + ucsdet_close(csd); +} + +static void TestUTF8(void) +{ + UErrorCode status = U_ZERO_ERROR; + static const char ss[] = "This is a string with some non-ascii characters that will " + "be converted to UTF-8, then shoved through the detection process. " + "\\u0391\\u0392\\u0393\\u0394\\u0395" + "Sure would be nice if our source could contain Unicode directly!"; + int32_t byteLength = 0, sLength = 0, dLength = 0; + UChar s[sizeof(ss)]; + char *bytes; + UCharsetDetector *csd = ucsdet_open(&status); + const UCharsetMatch *match; + UChar detected[sizeof(ss)]; + + sLength = u_unescape(ss, s, sizeof(ss)); + bytes = extractBytes(s, sLength, "UTF-8", &byteLength); + + ucsdet_setText(csd, bytes, byteLength, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("Detection failure for UTF-8: got no matches.\n"); + goto bail; + } + + dLength = ucsdet_getUChars(match, detected, sLength, &status); + + if (u_strCompare(detected, dLength, s, sLength, FALSE) != 0) { + log_err("Round-trip test failed!\n"); + } + + ucsdet_setDeclaredEncoding(csd, "UTF-8", 5, &status); /* for coverage */ + +bail: + freeBytes(bytes); + ucsdet_close(csd); +} + +static void TestUTF16(void) +{ + UErrorCode status = U_ZERO_ERROR; + /* Notice the BOM on the start of this string */ + static const UChar chars[] = { + 0xFEFF, 0x0623, 0x0648, 0x0631, 0x0648, 0x0628, 0x0627, 0x002C, + 0x0020, 0x0628, 0x0631, 0x0645, 0x062c, 0x064a, 0x0627, 0x062a, + 0x0020, 0x0627, 0x0644, 0x062d, 0x0627, 0x0633, 0x0648, 0x0628, + 0x0020, 0x002b, 0x0020, 0x0627, 0x0646, 0x062a, 0x0631, 0x0646, + 0x064a, 0x062a, 0x0000}; + int32_t beLength = 0, leLength = 0, cLength = ARRAY_SIZE(chars); + char *beBytes = extractBytes(chars, cLength, "UTF-16BE", &beLength); + char *leBytes = extractBytes(chars, cLength, "UTF-16LE", &leLength); + UCharsetDetector *csd = ucsdet_open(&status); + const UCharsetMatch *match; + const char *name; + int32_t conf; + + ucsdet_setText(csd, beBytes, beLength, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("Encoding detection failure for UTF-16BE: got no matches.\n"); + goto try_le; + } + + name = ucsdet_getName(match, &status); + conf = ucsdet_getConfidence(match, &status); + + if (strcmp(name, "UTF-16BE") != 0) { + log_err("Encoding detection failure for UTF-16BE: got %s\n", name); + } + + if (conf != 100) { + log_err("Did not get 100%% confidence for UTF-16BE: got %d\n", conf); + } + +try_le: + ucsdet_setText(csd, leBytes, leLength, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("Encoding detection failure for UTF-16LE: got no matches.\n"); + goto bail; + } + + name = ucsdet_getName(match, &status); + conf = ucsdet_getConfidence(match, &status); + + + if (strcmp(name, "UTF-16LE") != 0) { + log_err("Enconding detection failure for UTF-16LE: got %s\n", name); + } + + if (conf != 100) { + log_err("Did not get 100%% confidence for UTF-16LE: got %d\n", conf); + } + +bail: + freeBytes(leBytes); + freeBytes(beBytes); + ucsdet_close(csd); +} + +static void TestC1Bytes(void) +{ +#if !UCONFIG_NO_LEGACY_CONVERSION + UErrorCode status = U_ZERO_ERROR; + static const char ssISO[] = "This is a small sample of some English text. Just enough to be sure that it detects correctly."; + static const char ssWindows[] = "This is another small sample of some English text. Just enough to be sure that it detects correctly. It also includes some \\u201CC1\\u201D bytes."; + int32_t sISOLength = 0, sWindowsLength = 0; + UChar sISO[sizeof(ssISO)]; + UChar sWindows[sizeof(ssWindows)]; + int32_t lISO = 0, lWindows = 0; + char *bISO; + char *bWindows; + UCharsetDetector *csd = ucsdet_open(&status); + const UCharsetMatch *match; + const char *name; + + sISOLength = u_unescape(ssISO, sISO, sizeof(ssISO)); + sWindowsLength = u_unescape(ssWindows, sWindows, sizeof(ssWindows)); + bISO = extractBytes(sISO, sISOLength, "ISO-8859-1", &lISO); + bWindows = extractBytes(sWindows, sWindowsLength, "windows-1252", &lWindows); + + ucsdet_setText(csd, bWindows, lWindows, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("English test with C1 bytes got no matches.\n"); + goto bail; + } + + name = ucsdet_getName(match, &status); + + if (strcmp(name, "windows-1252") != 0) { + log_err("English text with C1 bytes does not detect as windows-1252, but as %s\n", name); + } + + ucsdet_setText(csd, bISO, lISO, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("English text without C1 bytes got no matches.\n"); + goto bail; + } + + name = ucsdet_getName(match, &status); + + if (strcmp(name, "ISO-8859-1") != 0) { + log_err("English text without C1 bytes does not detect as ISO-8859-1, but as %s\n", name); + } + +bail: + freeBytes(bWindows); + freeBytes(bISO); + + ucsdet_close(csd); +#endif +} + +static void TestInputFilter(void) +{ + UErrorCode status = U_ZERO_ERROR; + static const char ss[] = "<a> <lot> <of> <English> <inside> <the> <markup> Un tr\\u00E8s petit peu de Fran\\u00E7ais. <to> <confuse> <the> <detector>"; + int32_t sLength = 0; + UChar s[sizeof(ss)]; + int32_t byteLength = 0; + char *bytes; + UCharsetDetector *csd = ucsdet_open(&status); + const UCharsetMatch *match; + const char *lang, *name; + + sLength = u_unescape(ss, s, sizeof(ss)); + bytes = extractBytes(s, sLength, "ISO-8859-1", &byteLength); + + ucsdet_enableInputFilter(csd, TRUE); + + if (!ucsdet_isInputFilterEnabled(csd)) { + log_err("ucsdet_enableInputFilter(csd, TRUE) did not enable input filter!\n"); + } + + + ucsdet_setText(csd, bytes, byteLength, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("Turning on the input filter resulted in no matches.\n"); + goto turn_off; + } + + name = ucsdet_getName(match, &status); + + if (name == NULL || strcmp(name, "ISO-8859-1") != 0) { + log_err("Turning on the input filter resulted in %s rather than ISO-8859-1\n", name); + } else { + lang = ucsdet_getLanguage(match, &status); + + if (lang == NULL || strcmp(lang, "fr") != 0) { + log_err("Input filter did not strip markup!\n"); + } + } + +turn_off: + ucsdet_enableInputFilter(csd, FALSE); + ucsdet_setText(csd, bytes, byteLength, &status); + match = ucsdet_detect(csd, &status); + + if (match == NULL) { + log_err("Turning off the input filter resulted in no matches.\n"); + goto bail; + } + + name = ucsdet_getName(match, &status); + + if (name == NULL || strcmp(name, "ISO-8859-1") != 0) { + log_err("Turning off the input filter resulted in %s rather than ISO-8859-1\n", name); + } else { + lang = ucsdet_getLanguage(match, &status); + + if (lang == NULL || strcmp(lang, "en") != 0) { + log_err("Unfiltered input did not detect as English!\n"); + } + } + +bail: + freeBytes(bytes); + ucsdet_close(csd); +} + +static void TestChaining(void) { + UErrorCode status = U_USELESS_COLLATOR_ERROR; + + ucsdet_open(&status); + ucsdet_setText(NULL, NULL, 0, &status); + ucsdet_getName(NULL, &status); + ucsdet_getConfidence(NULL, &status); + ucsdet_getLanguage(NULL, &status); + ucsdet_detect(NULL, &status); + ucsdet_setDeclaredEncoding(NULL, NULL, 0, &status); + ucsdet_detectAll(NULL, NULL, &status); + ucsdet_getUChars(NULL, NULL, 0, &status); + ucsdet_getUChars(NULL, NULL, 0, &status); + ucsdet_close(NULL); + + /* All of this code should have done nothing. */ + if (status != U_USELESS_COLLATOR_ERROR) { + log_err("Status got changed to %s\n", u_errorName(status)); + } +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c new file mode 100644 index 00000000000..73b8f089ca3 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c @@ -0,0 +1,1761 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1998-2007, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File test.c +* +* Modification History: +* +* Date Name Description +* 02/22/2000 Madhu Creation +****************************************************************************** +*/ + +#include "unicode/utypes.h" +#include "unicode/putil.h" +#include "unicode/udata.h" +#include "unicode/uchar.h" +#include "unicode/ucnv.h" +#include "unicode/ures.h" +#include "unicode/ustring.h" +#include "unicode/uclean.h" +#include "cmemory.h" +#include "cstring.h" +#include "filestrm.h" +#include "udatamem.h" +#include "cintltst.h" +#include "ubrkimpl.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef U_WINDOWS +#include <io.h> +#else +#include <unistd.h> +#endif + +/* includes for TestSwapData() */ +#include "udataswp.h" + +/* swapping implementations in common */ +#include "uresdata.h" +#include "ucnv_io.h" +#include "uprops.h" +#include "ucase.h" +#include "ucol_swp.h" +#include "ucnv_bld.h" +#include "unormimp.h" +#include "sprpimpl.h" +#include "propname.h" +#include "rbbidata.h" + +/* other definitions and prototypes */ + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +static void TestUDataOpen(void); +static void TestUDataOpenChoiceDemo1(void); +static void TestUDataOpenChoiceDemo2(void); +static void TestUDataGetInfo(void); +static void TestUDataGetMemory(void); +static void TestUDataSetAppData(void); +static void TestErrorConditions(void); +static void TestAppData(void); +static void TestICUDataName(void); +static void TestSwapData(void); +static void PointerTableOfContents(void); +static void SetBadCommonData(void); +static void TestUDataFileAccess(void); + + +void addUDataTest(TestNode** root); + +void +addUDataTest(TestNode** root) +{ + addTest(root, &TestUDataOpen, "udatatst/TestUDataOpen" ); + addTest(root, &TestUDataOpenChoiceDemo1, "udatatst/TestUDataOpenChoiceDemo1"); + addTest(root, &TestUDataOpenChoiceDemo2, "udatatst/TestUDataOpenChoiceDemo2"); + addTest(root, &TestUDataGetInfo, "udatatst/TestUDataGetInfo" ); + addTest(root, &TestUDataGetMemory, "udatatst/TestUDataGetMemory" ); + addTest(root, &TestUDataSetAppData, "udatatst/TestUDataSetAppData" ); + addTest(root, &TestErrorConditions, "udatatst/TestErrorConditions"); + addTest(root, &TestAppData, "udatatst/TestAppData" ); + addTest(root, &TestICUDataName, "udatatst/TestICUDataName" ); + addTest(root, &TestSwapData, "udatatst/TestSwapData" ); + addTest(root, &PointerTableOfContents, "udatatst/PointerTableOfContents" ); + addTest(root, &SetBadCommonData, "udatatst/SetBadCommonData" ); + addTest(root, &TestUDataFileAccess, "udatatst/TestUDataFileAccess" ); +} + +#if 0 +static void lots_of_mallocs() +{ + int q; + for(q=1;q<100;q++) + { + free(malloc(q)); + malloc(q*2); + } + +} +#endif + +static void TestUDataOpen(){ + UDataMemory *result; + UErrorCode status=U_ZERO_ERROR; + const char* memMap[][2]={ + {"root", "res"}, + {"pnames", "icu"}, + {"cnvalias", "icu"}, + {"unames", "icu"}, + {"ibm-37_P100-1995", "cnv"} + }; + const char* name = "test"; + const char* type = "icu"; + const char dirSepString[] = {U_FILE_SEP_CHAR, 0}; + const char pathSepString[] = {U_PATH_SEP_CHAR, 0}; + + + char* path=(char*)malloc(sizeof(char) * (strlen(ctest_dataOutDir()) + + strlen(U_ICUDATA_NAME) + + strlen("/build")+1 ) ); + + char *icuDataFilePath = 0; + struct stat stat_buf; + + const char* testPath=loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + /* lots_of_mallocs(); */ + + strcat(strcpy(path, ctest_dataOutDir()), U_ICUDATA_NAME); + + log_verbose("Testing udata_open()\n"); + result=udata_open(testPath, type, name, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", testPath, name, type, myErrorName(status)); + } else { + log_verbose("PASS: udata_open worked\n"); + udata_close(result); + } + + /* If the ICU system common data file is present in this confiugration, + * verify that udata_open can explicitly fetch items from it. + * If packaging mode == dll, the file may not exist. So, if the file is + * missing, skip this test without error. + */ + icuDataFilePath = (char *)malloc(strlen(path) + 10); + strcpy(icuDataFilePath, path); + strcat(icuDataFilePath, ".dat"); + /* lots_of_mallocs(); */ + if (stat(icuDataFilePath, &stat_buf) == 0) + { + int i; + log_verbose("Testing udata_open() on %s\n", icuDataFilePath); + for(i=0; i<sizeof(memMap)/sizeof(memMap[0]); i++){ + /* lots_of_mallocs(); */ + status=U_ZERO_ERROR; + result=udata_open(path, memMap[i][1], memMap[i][0], &status); + if(U_FAILURE(status)) { + log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status)); + } else { + log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", path, memMap[i][0], memMap[i][1]); + udata_close(result); + } + } + } + else + { + /* lots_of_mallocs(); */ + log_verbose("Skipping tests of udata_open() on %s. File not present in this configuration.\n", + icuDataFilePath); + } + free(icuDataFilePath); + icuDataFilePath = NULL; + /* lots_of_mallocs(); */ + + /* If the ICU individual files used to build the ICU system common data are + * present in this configuration, + * verify that udata_open can explicitly open them. + * These data files are present in the ICU data/build directory after a build + * completes. Tests are most commonly run with the data directory pointing + * back into this directory structure, but this is not required. Soooo, if + * the files are missing, skip this test without error. + */ + /* lots_of_mallocs(); */ + icuDataFilePath = (char *)malloc(strlen(ctest_dataOutDir()) + 50); + strcpy(icuDataFilePath, ctest_dataOutDir()); + strcat(icuDataFilePath, "build"); + strcat(icuDataFilePath, dirSepString); + strcat(icuDataFilePath, U_ICUDATA_NAME); + strcat(icuDataFilePath, "_"); + strcat(icuDataFilePath, "cnvalias.icu"); + + /* lots_of_mallocs(); */ + if (stat(icuDataFilePath, &stat_buf) == 0) + { + int i; + log_verbose("%s exists, so..\n", icuDataFilePath); + strcpy(icuDataFilePath, ctest_dataOutDir()); + strcat(icuDataFilePath, "build"); + strcat(icuDataFilePath, dirSepString); + strcat(icuDataFilePath, U_ICUDATA_NAME); + log_verbose("Testing udata_open() on %s\n", icuDataFilePath); + for(i=0; i<sizeof(memMap)/sizeof(memMap[0]); i++){ + status=U_ZERO_ERROR; + result=udata_open(icuDataFilePath, memMap[i][1], memMap[i][0], &status); + if(U_FAILURE(status)) { + log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1], myErrorName(status)); + } else { + log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1]); + udata_close(result); + } + } + } + else + { + log_verbose("Skipping tests of udata_open() on %s. File not present in this configuration.\n", + icuDataFilePath); + } + + free(icuDataFilePath); + icuDataFilePath = NULL; + + /* + * Test fallback file names for open of separate data files. + * With these params to udata_open: + * path = wherever/testdata + * type = typ + * name = nam + * these files will be tried first: + * wherever/testudata_nam.typ + * testudata_nam.typ + * A test data file named testudata_nam.typ exists for the purpose of testing this. + */ + log_verbose("Testing udata_open, with base_name.type style fallback to individual file.\n"); + + status = U_ZERO_ERROR; + result = udata_open( testPath, "typ", "nam", &status); + if (status != U_ZERO_ERROR) { + log_err("FAIL: udata_open( \"%s\", \"typ\", \"nam\") returned status %s\n", testPath, u_errorName(status)); + } + udata_close(result); + free(icuDataFilePath); + + + /* This type of path is deprecated */ + /* + * Another fallback test. Paths ending with a trailing directory separator + * take a slightly different code path, with the "base name" from the path + * being empty in the internal udata_open logic. + */ + +/* log_verbose("Testing udata_open, with path containing a trailing directory separator.\n"); */ +/* icuDataFilePath = (char *)malloc(strlen(u_getDataDirectory()) + 50); */ +/* strcpy(icuDataFilePath, testPath); */ +/* status = U_ZERO_ERROR; */ +/* result = udata_open( icuDataFilePath, "cnv", "test1", &status); */ +/* if (status != U_ZERO_ERROR) { */ +/* log_err("FAIL: udata_open( \"%s\", \"cnv\", \"test1\") returned status %s\n", icuDataFilePath, u_errorName(status)); */ +/* } */ +/* udata_close(result); */ +/* free(icuDataFilePath); */ + + + log_verbose("Testing udata_open() with a non existing binary file\n"); + result=udata_open("testdata", "tst", "nonexist", &status); + if(status==U_FILE_ACCESS_ERROR){ + log_verbose("Opening udata_open with non-existing file handled correctly.\n"); + status=U_ZERO_ERROR; + } else { + log_err("calling udata_open with non-existing file [testdata | nonexist.tst] not handled correctly\n. Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status)); + if(U_SUCCESS(status)) { + udata_close(result); + } + } + + if(result != NULL){ + log_err("calling udata_open with non-existing file didn't return a null value\n"); + } else { + log_verbose("calling udat_open with non-existing file returned null as expected\n"); + } + + /* + * Try opening data with absurdly long path and name, to trigger buffer size + * overflow handling code. + */ + { + char longTestPath[1024]; /* Implementation goes to heap at length of 128. */ + char longName[1024]; + + /* Try a very long nonexistent directory path. + * udata_open should still succeed. Opening with the path will fail, + * then fall back to skipping the directory portion of the path. + */ + log_verbose("Testing udata_open() with really long names\n"); + longTestPath[0] = 0; + strcat(longTestPath, "bogus_directory_name"); + while (strlen(longTestPath) < 500) { + strcat(longTestPath, dirSepString); + strcat(longTestPath, "bogus_directory_name"); + } + strcat(longTestPath, pathSepString); + strcat(longTestPath, testPath); + result=udata_open(longTestPath, type, name, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n", + longTestPath, name, type, myErrorName(status)); + } else { + log_verbose("PASS: udata_open worked\n"); + udata_close(result); + } + + /* Try a very long name. Won't open, but shouldn't blow up. + */ + longName[0] = 0; + while (strlen(longName) < 500) { + strcat(longName, name); + strcat(longName, "_"); + } + strcat(longName, dirSepString); + strcat(longName, name); + + result=udata_open(longTestPath, type, longName, &status); + if (status != U_FILE_ACCESS_ERROR) { + log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n", + longTestPath, longName, type, myErrorName(status)); + } + udata_close(result); + } + + free(path); +} + +typedef struct { + uint16_t headerSize; + uint8_t magic1, magic2; + UDataInfo info; + char padding[8]; + uint32_t count, reserved; + /* + const struct { + const char *const name; + const void *const data; + } toc[1]; + */ + int32_t fakeNameAndData[4]; +} ICU_COMMON_Data_Header; + +static const ICU_COMMON_Data_Header gEmptyHeader = { + 32, /* headerSize */ + 0xda, /* magic1, (see struct MappedData in udata.c) */ + 0x27, /* magic2 */ + { /*UDataInfo */ + sizeof(UDataInfo), /* size */ + 0, /* reserved */ + +#if U_IS_BIG_ENDIAN + 1, +#else + 0, +#endif + + U_CHARSET_FAMILY, + sizeof(UChar), + 0, /* reserved */ + { /* data format identifier */ + 0x43, 0x6d, 0x6e, 0x44}, /* "CmnD" */ + {1, 0, 0, 0}, /* format version major, minor, milli, micro */ + {0, 0, 0, 0} /* dataVersion */ + }, + {0,0,0,0,0,0,0,0}, /* Padding[8] */ + 0, /* count */ + 0, /* Reserved */ + { /* TOC structure */ +/* { */ + 0 , 0 , 0, 0 /* name and data entries. Count says there are none, */ + /* but put one in just in case. */ +/* } */ + } +}; + + +static void TestUDataSetAppData(){ +/* UDataMemory *dataItem;*/ + + UErrorCode status=U_ZERO_ERROR; + + /* + * First we try some monkey business and try to do bad things. + */ + + status=U_ZERO_ERROR; + udata_setAppData("appData1", NULL, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", NULL, status) should have failed." + " It returned status of %s\n", u_errorName(status)); + return; + } + /* The following call should fail. + If the following works with a bad UErrorCode, then later calls to appData1 should fail. */ + udata_setAppData("appData1", &gEmptyHeader, &status); + + /* + * Got testdata.dat into memory, now we try setAppData using the memory image. + */ + + status=U_ZERO_ERROR; + udata_setAppData("appData1", &gEmptyHeader, &status); + if (status != U_ZERO_ERROR) { + log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) " + " returned status of %s\n", u_errorName(status)); + return; + } + + udata_setAppData("appData2", &gEmptyHeader, &status); + if (status != U_ZERO_ERROR) { + log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) " + " returned status of %s\n", u_errorName(status)); + return; + } + + /* If we try to setAppData with the same name a second time, we should get a + * a using default warning. + */ + udata_setAppData("appData2", &gEmptyHeader, &status); + if (status != U_USING_DEFAULT_WARNING) { + log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) " + " returned status of %s, expected U_USING_DEFAULT_WARNING.\n", u_errorName(status)); + } + + + /** It is no longer correct to use udata_setAppData to change the + package of a contained item. + + dataItem = udata_open("appData1", "res", "te_IN", &status); **/ +} + +static char *safeGetICUDataDirectory() { + const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */ + char *retStr = NULL; + if (dataDir != NULL) { + retStr = (char *)malloc(strlen(dataDir)+1); + strcpy(retStr, dataDir); + } + return retStr; +} + +static void TestUDataFileAccess(){ + UErrorCode status; + char *icuDataDir; + icuDataDir = safeGetICUDataDirectory(); /* save icu data dir, so we can put it back + * after doing u_cleanup(). */ + + /** UDATA_NO_FILES, ICU does not access the file system for data loading. */ + status=U_ZERO_ERROR; + u_cleanup(); + udata_setFileAccess(UDATA_NO_FILES,&status); + u_init(&status); + if(U_FAILURE(status) && *icuDataDir == 0){ + log_data_err("udata_setFileAccess(UDATA_NO_FILES) failed with ICU_DATA=\"\" err=%s\n", u_errorName(status)); + } + + /** UDATA_ONLY_PACKAGES, ICU only loads data from packages, not from single files. */ + status=U_ZERO_ERROR; + u_cleanup(); + udata_setFileAccess(UDATA_ONLY_PACKAGES,&status); + u_init(&status); + + /** UDATA_PACKAGES_FIRST, ICU loads data from packages first, and only from single files + if the data cannot be found in a package. */ + status=U_ZERO_ERROR; + u_cleanup(); + udata_setFileAccess(UDATA_PACKAGES_FIRST,&status); + u_init(&status); + + /** UDATA_FILES_FIRST, ICU looks for data in single files first, then in packages. (default) */ + status=U_ZERO_ERROR; + u_cleanup(); + udata_setFileAccess(UDATA_FILES_FIRST,&status); + u_init(&status); + + /** An alias for the default access mode. */ + status=U_ZERO_ERROR; + u_cleanup(); + udata_setFileAccess(UDATA_DEFAULT_ACCESS,&status); + u_setDataDirectory(icuDataDir); + u_init(&status); + if(U_FAILURE(status)){ + log_err("%s\n", u_errorName(status)); + } + free(icuDataDir); +} + + +static UBool U_CALLCONV +isAcceptable1(void *context, + const char *type, const char *name, + const UDataInfo *pInfo) { + + if( pInfo->size>=20 && + pInfo->isBigEndian==U_IS_BIG_ENDIAN && + pInfo->charsetFamily==U_CHARSET_FAMILY && + pInfo->dataFormat[0]==0x43 && /* dataFormat="CvAl" */ + pInfo->dataFormat[1]==0x76 && + pInfo->dataFormat[2]==0x41 && + pInfo->dataFormat[3]==0x6c && + pInfo->formatVersion[0]==3 ) + { + log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable1()\n", name, type); + return TRUE; + } else { + log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable1():-\n" + "\tsize = %d\n" + "\tisBigEndian = %d\n" + "\tcharsetFamily = %d\n" + "\tformatVersion[0] = %d\n" + "\tdataVersion[0] = %d\n" + "\tdataFormat = %c%c%c%c\n", + name, type, pInfo->size, pInfo->isBigEndian, pInfo->charsetFamily, pInfo->formatVersion[0], + pInfo->dataVersion[0], pInfo->dataFormat[0], pInfo->dataFormat[1], pInfo->dataFormat[2], + pInfo->dataFormat[3]); + log_verbose("Call another verifing function to accept the data\n"); + return FALSE; + } +} + +static UBool U_CALLCONV +isAcceptable2(void *context, + const char *type, const char *name, + const UDataInfo *pInfo){ + UVersionInfo unicodeVersion; + + u_getUnicodeVersion(unicodeVersion); + + if( pInfo->size>=20 && + pInfo->isBigEndian==U_IS_BIG_ENDIAN && + pInfo->charsetFamily==U_CHARSET_FAMILY && + pInfo->dataFormat[0]==0x75 && /* dataFormat="unam" */ + pInfo->dataFormat[1]==0x6e && + pInfo->dataFormat[2]==0x61 && + pInfo->dataFormat[3]==0x6d && + pInfo->formatVersion[0]==1 && + pInfo->dataVersion[0]==unicodeVersion[0] ) + { + log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable2()\n", name, type); + return TRUE; + } else { + log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable2()\n", name, type); + + return FALSE; + } + + +} +static UBool U_CALLCONV +isAcceptable3(void *context, + const char *type, const char *name, + const UDataInfo *pInfo){ + + if( pInfo->size>=20 && + pInfo->isBigEndian==U_IS_BIG_ENDIAN && + pInfo->charsetFamily==U_CHARSET_FAMILY && + pInfo->dataFormat[0]==0x54 && /* dataFormat="test" */ + pInfo->dataFormat[1]==0x65 && + pInfo->dataFormat[2]==0x73 && + pInfo->dataFormat[3]==0x74 && + pInfo->formatVersion[0]==1 && + pInfo->dataVersion[0]==1 ) { + log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable3()\n", name, type); + + return TRUE; + } else { + log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable3()\n", name, type); + return FALSE; + } + + +} + +static void TestUDataOpenChoiceDemo1() { + UDataMemory *result; + UErrorCode status=U_ZERO_ERROR; + + const char* name[]={ + "cnvalias", + "unames", + "test", + "nam" + }; + const char* type="icu"; + const char* testPath="testdata"; + const char* fullTestDataPath = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + result=udata_openChoice(NULL, "icu", name[0], isAcceptable1, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[0], type, myErrorName(status)); + } else { + log_verbose("PASS: udata_openChoice worked\n"); + udata_close(result); + } + + status=U_ZERO_ERROR; + result=udata_openChoice(NULL, type, name[1], isAcceptable1, NULL, &status); + if(U_FAILURE(status)){ + status=U_ZERO_ERROR; + result=udata_openChoice(NULL, type, name[1], isAcceptable2, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status)); + } + } + else { + log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status)); + } + + if(U_SUCCESS(status)){ + udata_close(result); + } + + status=U_ZERO_ERROR; + result=udata_openChoice(testPath, type, name[2], isAcceptable1, NULL, &status); + if(U_FAILURE(status)){ + status=U_ZERO_ERROR; + result=udata_openChoice(testPath, type, name[2], isAcceptable3, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_openChoice() failed path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name[2], type, myErrorName(status)); + } + } + else { + log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[2], type, myErrorName(status)); + } + + if(U_SUCCESS(status)){ + udata_close(result); + } + + status=U_ZERO_ERROR; + type="typ"; + result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status); + if(status != U_INVALID_FORMAT_ERROR){ + log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status)); + } + + status=U_USELESS_COLLATOR_ERROR; + result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status); + if(status != U_USELESS_COLLATOR_ERROR){ + log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status)); + } +} + +static UBool U_CALLCONV +isAcceptable(void *context, + const char *type, const char *name, + const UDataInfo *pInfo){ + if( pInfo->size>=20 && + pInfo->isBigEndian==U_IS_BIG_ENDIAN && + pInfo->charsetFamily==U_CHARSET_FAMILY && + pInfo->dataFormat[0]==0x54 && /* dataFormat="test" */ + pInfo->dataFormat[1]==0x65 && + pInfo->dataFormat[2]==0x73 && + pInfo->dataFormat[3]==0x74 && + pInfo->formatVersion[0]==1 && + pInfo->dataVersion[0]==1 && + *((int*)context) == 2 ) { + log_verbose("The data from\"%s.%s\" IS acceptable using the verifing function isAcceptable()\n", name, type); + + return TRUE; + } else { + log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable()\n", name, type); + return FALSE; + } +} + + +/* This test checks to see if the isAcceptable function is being called correctly. */ + +static void TestUDataOpenChoiceDemo2() { + UDataMemory *result; + UErrorCode status=U_ZERO_ERROR; + int i; + int p=2; + + const char* name="test"; + const char* type="icu"; + const char* path = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + result=udata_openChoice(path, type, name, isAcceptable, &p, &status); + if(U_FAILURE(status)){ + log_err("failed to load data at p=%s t=%s n=%s, isAcceptable", path, type, name); + } + if(U_SUCCESS(status) ) { + udata_close(result); + } + + p=0; + for(i=0;i<2; i++){ + result=udata_openChoice(path, type, name, isAcceptable, &p, &status); + if(p<2) { + if(U_FAILURE(status) && status==U_INVALID_FORMAT_ERROR){ + log_verbose("Loads the data but rejects it as expected %s\n", myErrorName(status)); + status=U_ZERO_ERROR; + p++; + } + else { + log_err("FAIL: failed to either load the data or to reject the loaded data. ERROR=%s\n", myErrorName(status) ); + } + } + else if(p == 2) { + if(U_FAILURE(status)) { + log_err("FAIL: failed to load the data and accept it. ERROR=%s\n", myErrorName(status) ); + } + else { + log_verbose("Loads the data and accepts it for p==2 as expected\n"); + udata_close(result); + } + } + } +} + + +static void TestUDataGetInfo() { + + UDataMemory *result; + /* UDataInfo cf. udata.h */ + static UDataInfo dataInfo={ + 30, /*sizeof(UDataInfo),*/ + 0, + + U_IS_BIG_ENDIAN, + U_CHARSET_FAMILY, + sizeof(UChar), + 0, + + {0x54, 0x65, 0x73, 0x74}, /* dataFormat="Test" */ + {9, 0, 0, 0}, /* formatVersion */ + {4, 0, 0, 0} /* dataVersion */ + }; + UErrorCode status=U_ZERO_ERROR; + const char* name="cnvalias"; + const char* name2="test"; + const char* type="icu"; + + const char* testPath=loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + log_verbose("Testing udata_getInfo() for cnvalias.icu\n"); + result=udata_open(NULL, "icu", name, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_open() failed for path = NULL, name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status)); + return; + } + udata_getInfo(result, &dataInfo); + if(dataInfo.size==20 && dataInfo.size!=30 && + dataInfo.isBigEndian==U_IS_BIG_ENDIAN && + dataInfo.charsetFamily==U_CHARSET_FAMILY && + dataInfo.dataFormat[0]==0x43 && dataInfo.dataFormat[0]!=0x54 && /* dataFormat="CvAl" and not "Test". The values are set for cnvalias.dat*/ + dataInfo.dataFormat[1]==0x76 && dataInfo.dataFormat[1]!=0x65 && + dataInfo.dataFormat[2]==0x41 && dataInfo.dataFormat[2]!=0x73 && + dataInfo.dataFormat[3]==0x6c && dataInfo.dataFormat[3]!=0x74 && + dataInfo.formatVersion[0]!=9 && /*formatVersion is also set to the one for cnvalias*/ + dataInfo.dataVersion[0]!=4 && /*dataVersion*/ + dataInfo.dataVersion[1]!=0 ){ + log_verbose("PASS: udata_getInfo() filled in the right values\n"); + } else { + log_err("FAIL: udata_getInfo() filled in the wrong values\n"); + } + udata_close(result); + + + log_verbose("Testing udata_getInfo() for test.icu\n"); + result=udata_open(testPath, type, name2, &status); + if(U_FAILURE(status)) { + log_err("FAIL: udata_open() failed for path=%s name2=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status)); + return; + } + udata_getInfo(result, &dataInfo); + if(dataInfo.size==20 && + dataInfo.isBigEndian==U_IS_BIG_ENDIAN && + dataInfo.charsetFamily==U_CHARSET_FAMILY && + dataInfo.dataFormat[0]==0x54 && /* dataFormat="Test". The values are set for test.dat*/ + dataInfo.dataFormat[1]==0x65 && + dataInfo.dataFormat[2]==0x73 && + dataInfo.dataFormat[3]==0x74 && + dataInfo.formatVersion[0]==1 && /*formatVersion is also set to the one for test*/ + dataInfo.dataVersion[0]==1 && /*dataVersion*/ + dataInfo.dataVersion[1]==0 ) + { + log_verbose("PASS: udata_getInfo() filled in the right values\n"); + } else { + log_err("FAIL: udata_getInfo() filled in the wrong values\n"); + } + udata_close(result); +} + +static void TestUDataGetMemory() { + + UDataMemory *result; + const int32_t *table=NULL; + uint16_t* intValue=0; + UErrorCode status=U_ZERO_ERROR; + const char* name="cnvalias"; + const char* type; + + const char* name2="test"; + + const char* testPath = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + type="icu"; + log_verbose("Testing udata_getMemory() for \"cnvalias.icu\"\n"); + result=udata_openChoice(NULL, type, name, isAcceptable1, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_openChoice() failed for name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status)); + return; + } + table=(const int32_t *)udata_getMemory(result); + + /* The alias table may list more converters than what's actually available now. [grhoten] */ + if(ucnv_countAvailable() > table[1]) /*???*/ + log_err("FAIL: udata_getMemory() failed ucnv_countAvailable returned = %d, expected = %d\n", ucnv_countAvailable(), table[1+2*(*table)]); + + udata_close(result); + + type="icu"; + log_verbose("Testing udata_getMemory for \"test.icu\"()\n"); + result=udata_openChoice(testPath, type, name2, isAcceptable3, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: udata_openChoice() failed for path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status)); + return; + } + intValue=(uint16_t *)udata_getMemory(result); + /*printf("%d ..... %s", *(intValue), intValue+1));*/ + if( *intValue != 2000 || strcmp((char*)(intValue+1), "YEAR") != 0 ) + log_err("FAIL: udata_getMemory() failed: intValue :- Expected:2000 Got:%d \n\tstringValue:- Expected:YEAR Got:%s\n", *intValue, (intValue+1)); + + udata_close(result); + +} + +static void TestErrorConditions(){ + + UDataMemory *result=NULL; + UErrorCode status=U_ZERO_ERROR; + uint16_t* intValue=0; + static UDataInfo dataInfo={ + 30, /*sizeof(UDataInfo),*/ + 0, + + U_IS_BIG_ENDIAN, + U_CHARSET_FAMILY, + sizeof(UChar), + 0, + + {0x54, 0x65, 0x73, 0x74}, /* dataFormat="Test" */ + {9, 0, 0, 0}, /* formatVersion */ + {4, 0, 0, 0} /* dataVersion */ + }; + + const char* name = "test"; + const char* type="icu"; + + const char *testPath = loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + status = U_ILLEGAL_ARGUMENT_ERROR; + /*Try udata_open with status != U_ZERO_ERROR*/ + log_verbose("Testing udata_open() with status != U_ZERO_ERROR\n"); + result=udata_open(testPath, type, name, &status); + if(result != NULL){ + log_err("FAIL: udata_open() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode !=U_ZERO_ERROR\n", testPath, name, type); + udata_close(result); + + } else { + log_verbose("PASS: udata_open with errorCode != U_ZERO_ERROR failed as expected\n"); + } + + /*Try udata_open with data name=NULL*/ + log_verbose("Testing udata_open() with data name=NULL\n"); + status=U_ZERO_ERROR; + result=udata_open(testPath, type, NULL, &status); + if(U_FAILURE(status)){ + if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){ + log_err("FAIL: udata_open() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status)); + }else{ + log_verbose("PASS: udata_open with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status)); + } + }else{ + log_err("FAIL: udata_open() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type); + udata_close(result); + } + + + /*Try udata_openChoice with status != U_ZERO_ERROR*/ + log_verbose("Testing udata_openChoice() with status != U_ZERO_ERROR\n"); + status=U_ILLEGAL_ARGUMENT_ERROR; + result=udata_openChoice(testPath, type, name, isAcceptable3, NULL, &status); + if(result != NULL){ + log_err("FAIL: udata_openChoice() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode != U_ZERO_ERROR\n", testPath, name, type); + udata_close(result); + } else { + log_verbose("PASS: udata_openChoice() with errorCode != U_ZERO_ERROR failed as expected\n"); + } + + /*Try udata_open with data name=NULL*/ + log_verbose("Testing udata_openChoice() with data name=NULL\n"); + status=U_ZERO_ERROR; + result=udata_openChoice(testPath, type, NULL, isAcceptable3, NULL, &status); + if(U_FAILURE(status)){ + if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){ + log_err("FAIL: udata_openChoice() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status)); + }else{ + log_verbose("PASS: udata_openChoice with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status)); + } + }else{ + log_err("FAIL: udata_openChoice() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type); + udata_close(result); + } + + /*Try udata_getMemory with UDataMemory=NULL*/ + log_verbose("Testing udata_getMemory with UDataMemory=NULL\n"); + intValue=(uint16_t*)udata_getMemory(NULL); + if(intValue != NULL){ + log_err("FAIL: udata_getMemory with UDataMemory = NULL is supposed to fail\n"); + } + + /*Try udata_getInfo with UDataMemory=NULL*/ + status=U_ZERO_ERROR; + udata_getInfo(NULL, &dataInfo); + if(dataInfo.size != 0){ + log_err("FAIL : udata_getInfo with UDataMemory = NULL us supposed to fail\n"); + } + + /*Try udata_openChoice with a non existing binary file*/ + log_verbose("Testing udata_openChoice() with a non existing binary file\n"); + result=udata_openChoice(testPath, "tst", "nonexist", isAcceptable3, NULL, &status); + if(status==U_FILE_ACCESS_ERROR){ + log_verbose("Opening udata_openChoice with non-existing file handled correctly.\n"); + status=U_ZERO_ERROR; + } else { + log_err("calling udata_open with non-existing file not handled correctly\n. Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status)); + if(U_SUCCESS(status)) { + udata_close(result); + } + } + + if(result != NULL){ + log_err("calling udata_open with non-existing file didn't return a null value\n"); + } else { + log_verbose("calling udat_open with non-existing file returned null as expected\n"); + } +} + +/* Test whether apps and ICU can each have their own root.res */ +static void TestAppData() +{ + UResourceBundle *icu, *app; + UResourceBundle *tmp = NULL; + UResourceBundle *tmp2 = NULL; + + const UChar *appString; + const UChar *icuString; + + int32_t len; + + UErrorCode status = U_ZERO_ERROR; + char testMsgBuf[256]; + + const char* testPath=loadTestData(&status); + if(U_FAILURE(status)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(status)); + return; + } + + icu = ures_open(NULL, "root", &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't open root ICU bundle- %s", __FILE__, __LINE__, u_errorName(status)); + return; + } + /* log_info("Open icu root: %s size_%d\n", u_errorName(status), ures_getSize(icu)); */ + status = U_ZERO_ERROR; + + app = ures_open(testPath, "root", &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't open app ICU bundle [%s]- %s", __FILE__, __LINE__, testPath, u_errorName(status)); + return; + } + /* log_info("Open app: %s, size %d\n", u_errorName(status), ures_getSize(app)); */ + + tmp = ures_getByKey(icu, "Version", tmp, &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't get Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status)); + return; + } + + icuString = ures_getString(tmp, &len, &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't get string from Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status)); + return; + } + /* log_info("icuString=%p - %s\n", icuString, austrdup(icuString)); */ + + + tmp2 = ures_getByKey(app, "Version", tmp2, &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't get Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status)); + return; + } + + appString = ures_getString(tmp2, &len, &status); + if(U_FAILURE(status)) + { + log_err("%s:%d: Couldn't get string from Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status)); + return; + } + + /* log_info("appString=%p - %s\n", appString, austrdup(appString)); */ + + + if(!u_strcmp(icuString, appString)) + { + log_err("%s:%d: Error! Expected ICU and App root version strings to be DIFFERENT but they are both %s and %s\n", __FILE__, __LINE__, austrdup(icuString), + austrdup(appString)); + } + else + { + log_verbose("%s:%d: appstr=%s, icustr=%s\n", __FILE__, + __LINE__, u_austrcpy(testMsgBuf, appString), u_austrcpy(testMsgBuf, icuString)); + } + + ures_close(tmp); + ures_close(tmp2); + ures_close(icu); + ures_close(app); +} + +static void TestICUDataName() +{ + UVersionInfo icuVersion; + char expectDataName[20]; + unsigned int expectLen = 8; + + char typeChar = '?'; + + /* Print out the version # we have .. */ + log_verbose("utypes.h says U_ICUDATA_NAME = %s\n", U_ICUDATA_NAME); + + /* Build up the version # we expect to get */ + u_getVersion(icuVersion); + + switch(U_CHARSET_FAMILY) + { + case U_ASCII_FAMILY: + switch(U_IS_BIG_ENDIAN) + { + case 1: + typeChar = 'b'; + break; + case 0: + typeChar = 'l'; + break; + default: + log_err("Expected 1 or 0 for U_IS_BIG_ENDIAN, got %d!\n", (int)U_IS_BIG_ENDIAN); + /* return; */ + } + break; + case U_EBCDIC_FAMILY: + typeChar = 'e'; + break; + } + + sprintf(expectDataName, "%s%d%d%c", + "icudt", + (int)icuVersion[0], + (int)icuVersion[1], + typeChar); + + log_verbose("Expected: %s\n", expectDataName); + if(uprv_strlen(expectDataName) != expectLen) + { + log_err("*Expected* length is wrong (test err?), should be %d is %d\n", + expectLen, uprv_strlen(expectDataName)); + } + + if(uprv_strlen(U_ICUDATA_NAME) != expectLen) + { + log_err("U_ICUDATA_NAME length should be %d is %d\n", + expectLen, uprv_strlen(U_ICUDATA_NAME)); + } + + if(uprv_strcmp(U_ICUDATA_NAME, expectDataName)) + { + log_err("U_ICUDATA_NAME should be %s but is %s\n", + expectDataName, U_ICUDATA_NAME); + } + + /* ICUDATA_NAME comes from the build system on *nix */ +#ifdef ICUDATA_NAME + if(uprv_strcmp(U_ICUDATA_NAME, ICUDATA_NAME)) + { + log_err("ICUDATA_NAME and U_ICUDATA_NAME don't match: " + "ICUDATA_NAME=%s, U_ICUDATA_NAME=%s. Check configure.in, icudefs.mk.in, utypes.h...\n", ICUDATA_NAME, U_ICUDATA_NAME); + } + else + { + log_verbose("ICUDATA_NAME=%s (from icudefs.mk), U_ICUDATA_NAME=%s (from utypes.h)\n", ICUDATA_NAME, U_ICUDATA_NAME); + } +#endif + +} + +/* test data swapping ------------------------------------------------------- */ + +#ifdef OS400 +/* See comments in genccode.c on when this special implementation can be removed. */ +static const struct { + double bogus; + const char *bytes; +} gOffsetTOCAppDataItem1={ 0.0, /* alignment bytes */ + "\x00\x14" /* sizeof(UDataInfo) *//* MappedData { */ + "\xda" + "\x27" /* } */ + "\x00\x14" /* sizeof(UDataInfo) *//* UDataInfo { */ + "\0\0" + "\1" /* U_IS_BIG_ENDIAN */ + "\1" /* U_CHARSET_FAMILY */ + "\2" /* U_SIZEOF_WHAR_T */ + "\0" + "\x31\x31\x31\x31" + "\0\0\0\0" + "\0\0\0\0" /* } */ +}; +#else +static const struct { + double bogus; + MappedData bytes1; + UDataInfo bytes2; + uint8_t bytes3; +} gOffsetTOCAppDataItem1={ + 0.0, /* alignment bytes */ + { sizeof(UDataInfo), 0xda, 0x27 }, /* MappedData */ + + {sizeof(UDataInfo), + 0, + + U_IS_BIG_ENDIAN, + U_CHARSET_FAMILY, + sizeof(UChar), + 0, + + {0x31, 0x31, 0x31, 0x31}, /* dataFormat="1111" */ + {0, 0, 0, 0}, /* formatVersion */ + {0, 0, 0, 0}} /* dataVersion */ +}; +#endif + +static const UChar gOffsetTOCGarbage[] = { /* "I have been very naughty!" */ + 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, + 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6E, 0x61, 0x75, 0x67, 0x68, 0x74, 0x79, 0x21 +}; + +/* Original source: icu/source/tools/genccode */ +static const struct { + uint16_t headerSize; + uint8_t magic1, magic2; + UDataInfo info; + char padding[8]; + uint32_t count, reserved; + const struct { + const char *const name; + const void *const data; + } toc[3]; +} gOffsetTOCAppData_dat = { + 32, /* headerSize */ + 0xda, /* magic1, (see struct MappedData in udata.c) */ + 0x27, /* magic2 */ + { /*UDataInfo */ + sizeof(UDataInfo), /* size */ + 0, /* reserved */ + U_IS_BIG_ENDIAN, + U_CHARSET_FAMILY, + sizeof(UChar), + 0, /* reserved */ + { /* data format identifier */ + 0x54, 0x6f, 0x43, 0x50}, /* "ToCP" */ + {1, 0, 0, 0}, /* format version major, minor, milli, micro */ + {0, 0, 0, 0} /* dataVersion */ + }, + {0,0,0,0,0,0,0,0}, /* Padding[8] */ + 3, /* count */ + 0, /* Reserved */ + { /* TOC structure */ + { "OffsetTOCAppData/a/b", &gOffsetTOCAppDataItem1 }, + { "OffsetTOCAppData/gOffsetTOCAppDataItem1", &gOffsetTOCAppDataItem1 }, + { "OffsetTOCAppData/gOffsetTOCGarbage", &gOffsetTOCGarbage } + } +}; + +/* Unfortunately, trie dictionaries are in a C++ header */ +int32_t +triedict_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode); + +/* test cases for maximum data swapping code coverage */ +static const struct { + const char *name, *type; + UDataSwapFn *swapFn; +} swapCases[]={ + /* resource bundles */ + + /* resource bundle with many data types */ + {"*testtypes", "res", ures_swap}, + /* resource bundle with collation data */ + {"ja", "res", ures_swap}, + /* resource bundle with options-only collation data */ + {"ru", "res", ures_swap}, + {"el", "res", ures_swap}, + /* ICU's root */ + {"root", "res", ures_swap}, + /* Test a 32-bit key table. This is large. */ + {"*testtable32", "res", ures_swap}, + + /* ICU 2.6 resource bundle - data format 1.0, without indexes[] (little-endian ASCII) */ + {"*icu26_testtypes", "res", ures_swap}, + /* same for big-endian EBCDIC */ + {"*icu26e_testtypes", "res", ures_swap}, + +#if !UCONFIG_NO_COLLATION + /* standalone collation data files */ + {"ucadata", "icu", ucol_swap}, + {"invuca", "icu", ucol_swapInverseUCA}, +#endif + +#if !UCONFIG_NO_LEGACY_CONVERSION + /* conversion table files */ + + /* SBCS conversion table file without extension */ + {"ibm-913_P100-2000", "cnv", ucnv_swap}, + /* EBCDIC_STATEFUL conversion table file with extension */ + {"ibm-1390_P110-2003", "cnv", ucnv_swap}, + /* DBCS extension-only conversion table file */ + {"ibm-16684_P110-2003", "cnv", ucnv_swap}, + /* EUC-TW (3-byte) conversion table file without extension */ + {"ibm-964_P110-1999", "cnv", ucnv_swap}, + /* GB 18030 (4-byte) conversion table file without extension */ + {"gb18030", "cnv", ucnv_swap}, + /* MBCS conversion table file with extension */ + {"*test4x", "cnv", ucnv_swap}, + /* + * MBCS conversion table file without extension, + * to test swapping and preflighting of UTF-8-friendly mbcsIndex[]. + */ + {"jisx-208", "cnv", ucnv_swap}, +#endif + +#if !UCONFIG_NO_CONVERSION + /* alias table */ + {"cnvalias", "icu", ucnv_swapAliases}, +#endif + +#if !UCONFIG_NO_IDNA + {"uidna", "spp", usprep_swap}, +#endif + +#if !UCONFIG_NO_BREAK_ITERATION + {"char", "brk", ubrk_swap}, + {"thaidict", "ctd", triedict_swap}, +#endif + + /* the last item should not be #if'ed so that it can reliably omit the last comma */ + + /* Unicode properties */ + {"pnames", "icu", upname_swap}, +#if 0 + /* + * Starting with ICU4C 3.4, the core Unicode properties files + * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu) + * are hardcoded in the common DLL and therefore not included + * in the data package any more. + * Their swapping code is moved from the common DLL to the icuswap tool so that + * we need not jump through hoops (like adding snapshots of these files + * to testdata) for code coverage in tests. + * See Jitterbug 4497. + */ +#if !UCONFIG_NO_NORMALIZATION + {"unorm", "icu", unorm_swap}, +#endif + {"uprops", "icu", uprops_swap}, + {"ucase", "icu", ucase_swap}, + {"ubidi", "icu", ubidi_swap}, +#endif + {"unames", "icu", uchar_swapNames} +}; + +/* Large enough for the largest swappable data item. */ +#define SWAP_BUFFER_SIZE 1800000 + +static void U_CALLCONV +printError(void *context, const char *fmt, va_list args) { + vlog_info("[swap] ", fmt, args); + log_err("\n"); /* Register error */ +} + +static void +TestSwapCase(UDataMemory *pData, const char *name, + UDataSwapFn *swapFn, + uint8_t *buffer, uint8_t *buffer2) { + UDataSwapper *ds; + const void *inData, *inHeader; + int32_t length, dataLength, length2, headerLength; + + UErrorCode errorCode; + UErrorCode badStatus; + + UBool inEndian, oppositeEndian; + uint8_t inCharset, oppositeCharset; + + /* First we check that swapFn handles failures as expected. */ + errorCode = U_UNSUPPORTED_ERROR; + length = swapFn(NULL, NULL, 0, buffer, &errorCode); + if (length != 0 || errorCode != U_UNSUPPORTED_ERROR) { + log_err("%s() did not fail as expected - %s\n", name, u_errorName(errorCode)); + } + errorCode = U_ZERO_ERROR; + length = swapFn(NULL, NULL, 0, buffer, &errorCode); + if (length != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("%s() did not fail as expected with bad arguments - %s\n", name, u_errorName(errorCode)); + } + + + /* Continue with the rest of the tests. */ + errorCode = U_ZERO_ERROR; + inData=udata_getMemory(pData); + + /* + * get the data length if possible, to verify that swapping and preflighting + * handles the entire data + */ + dataLength=udata_getLength(pData); + + /* + * get the header and its length + * all of the swap implementation functions require the header to be included + */ + inHeader=udata_getRawMemory(pData); + headerLength=(int32_t)((const char *)inData-(const char *)inHeader); + + /* first swap to opposite endianness but same charset family */ + errorCode=U_ZERO_ERROR; + ds=udata_openSwapperForInputData(inHeader, headerLength, + !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udata_openSwapperForInputData(%s->!isBig+same charset) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + + inEndian=ds->inIsBigEndian; + inCharset=ds->inCharset; + + oppositeEndian=!inEndian; + oppositeCharset= inCharset==U_ASCII_FAMILY ? U_EBCDIC_FAMILY : U_ASCII_FAMILY; + + /* make this test work with data files that are built for a different platform */ + if(inEndian!=U_IS_BIG_ENDIAN || inCharset!=U_CHARSET_FAMILY) { + udata_closeSwapper(ds); + ds=udata_openSwapper(inEndian, inCharset, oppositeEndian, inCharset, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udata_openSwapper(%s->!isBig+same charset) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + } + + /* + Check error checking of swappable data not specific to this swapper. + This should always fail. + */ + badStatus = U_ZERO_ERROR; + length=swapFn(ds, &gOffsetTOCAppData_dat, -1, NULL, &badStatus); + if(badStatus != U_UNSUPPORTED_ERROR) { + log_err("swapFn(%s->!isBig+same charset) unexpectedly succeeded on bad data - %s\n", + name, u_errorName(errorCode)); + udata_closeSwapper(ds); + return; + } + + /* Now allow errors to be printed */ + ds->printError=printError; + + /* preflight the length */ + length=swapFn(ds, inHeader, -1, NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("swapFn(preflight %s->!isBig+same charset) failed - %s\n", + name, u_errorName(errorCode)); + udata_closeSwapper(ds); + return; + } + + /* compare the preflighted length against the data length */ + if(dataLength>=0 && (length+15)<(headerLength+dataLength)) { + log_err("swapFn(preflight %s->!isBig+same charset) length too small: %d < data length %d\n", + name, length, (headerLength+dataLength)); + udata_closeSwapper(ds); + return; + } + + /* swap, not in-place */ + length2=swapFn(ds, inHeader, length, buffer, &errorCode); + udata_closeSwapper(ds); + if(U_FAILURE(errorCode)) { + log_err("swapFn(%s->!isBig+same charset) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + + /* compare the swap length against the preflighted length */ + if(length2!=length) { + log_err("swapFn(%s->!isBig+same charset) length differs from preflighting: %d != preflighted %d\n", + name, length2, length); + return; + } + + /* next swap to opposite charset family */ + ds=udata_openSwapper(oppositeEndian, inCharset, + oppositeEndian, oppositeCharset, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udata_openSwapper(%s->!isBig+other charset) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + ds->printError=printError; + + /* swap in-place */ + length2=swapFn(ds, buffer, length, buffer, &errorCode); + udata_closeSwapper(ds); + if(U_FAILURE(errorCode)) { + log_err("swapFn(%s->!isBig+other charset) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + + /* compare the swap length against the original length */ + if(length2!=length) { + log_err("swapFn(%s->!isBig+other charset) length differs from original: %d != original %d\n", + name, length2, length); + return; + } + + /* finally swap to original platform values */ + ds=udata_openSwapper(oppositeEndian, oppositeCharset, + inEndian, inCharset, + &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udata_openSwapper(%s->back to original) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + ds->printError=printError; + + /* swap, not in-place */ + length2=swapFn(ds, buffer, length, buffer2, &errorCode); + udata_closeSwapper(ds); + if(U_FAILURE(errorCode)) { + log_err("swapFn(%s->back to original) failed - %s\n", + name, u_errorName(errorCode)); + return; + } + + /* compare the swap length against the original length */ + if(length2!=length) { + log_err("swapFn(%s->back to original) length differs from original: %d != original %d\n", + name, length2, length); + return; + } + + /* compare the final contents with the original */ + if(0!=uprv_memcmp(inHeader, buffer2, length)) { + const uint8_t *original; + uint8_t diff[8]; + int32_t i, j; + + log_err("swapFn(%s->back to original) contents differs from original\n", + name); + + /* find the first difference */ + original=(const uint8_t *)inHeader; + for(i=0; i<length && original[i]==buffer2[i]; ++i) {} + + /* find the next byte that is the same */ + for(j=i+1; j<length && original[j]!=buffer2[j]; ++j) {} + log_info(" difference at index %d=0x%x, until index %d=0x%x\n", i, i, j, j); + + /* round down to the last 4-boundary for better result output */ + i&=~3; + log_info("showing bytes from index %d=0x%x (length %d=0x%x):\n", i, i, length, length); + + /* print 8 bytes but limit to the buffer contents */ + length2=i+sizeof(diff); + if(length2>length) { + length2=length; + } + + /* print the original bytes */ + uprv_memset(diff, 0, sizeof(diff)); + for(j=i; j<length2; ++j) { + diff[j-i]=original[j]; + } + log_info(" original: %02x %02x %02x %02x %02x %02x %02x %02x\n", + diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]); + + /* print the swapped bytes */ + uprv_memset(diff, 0, sizeof(diff)); + for(j=i; j<length2; ++j) { + diff[j-i]=buffer2[j]; + } + log_info(" swapped: %02x %02x %02x %02x %02x %02x %02x %02x\n", + diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]); + } +} + +static void U_CALLCONV +printErrorToString(void *context, const char *fmt, va_list args) { + vsprintf((char *)context, fmt, args); +} + +static void +TestSwapData() { + char name[100]; + UDataSwapper *ds; + UDataMemory *pData; + uint8_t *buffer; + const char *pkg, *nm, *testPath; + UErrorCode errorCode = U_ZERO_ERROR; + int32_t i; + + buffer=(uint8_t *)uprv_malloc(2*SWAP_BUFFER_SIZE); + if(buffer==NULL) { + log_err("unable to allocate %d bytes\n", 2*SWAP_BUFFER_SIZE); + return; + } + + testPath=loadTestData(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode)); + } + + /* Test that printError works as expected. */ + errorCode=U_USELESS_COLLATOR_ERROR; + ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + !U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + &errorCode); + if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) { + log_err("udata_openSwapper should have returned NULL with bad argument\n", name); + } + errorCode=U_ZERO_ERROR; + ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + !U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + &errorCode); + ds->printError=printErrorToString; + ds->printErrorContext=name; + udata_printError(ds, "This %s a %s", "is", "test"); + udata_closeSwapper(ds); + if (strcmp(name, "This is a test") != 0) { + log_err("udata_printError can't properly print error messages. Got = %s\n", name); + } + errorCode = U_USELESS_COLLATOR_ERROR; + ds=udata_openSwapperForInputData(NULL, 0, + !U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + &errorCode); + if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) { + log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name); + } + errorCode=U_ZERO_ERROR; + ds=udata_openSwapperForInputData(NULL, 0, + !U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + &errorCode); + if (ds != NULL || errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name); + } + errorCode=U_ZERO_ERROR; + memset(buffer, 0, sizeof(2*SWAP_BUFFER_SIZE)); + ds=udata_openSwapperForInputData(buffer, 2*SWAP_BUFFER_SIZE, + !U_IS_BIG_ENDIAN, U_ASCII_FAMILY, + &errorCode); + if (ds != NULL || errorCode != U_UNSUPPORTED_ERROR) { + log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name); + } + errorCode=U_ZERO_ERROR; + + /* Test argument checking. ucol_swapBinary is normally tested via ures_swap, and isn't normally called directly. */ +#if !UCONFIG_NO_COLLATION + ucol_swapBinary(NULL, NULL, -1, NULL, NULL); + ucol_swapBinary(NULL, NULL, -1, NULL, &errorCode); + if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("ucol_swapBinary did not fail as expected\n", name); + } + errorCode=U_ZERO_ERROR; +#endif + + for(i=0; i<LENGTHOF(swapCases); ++i) { + /* build the name for logging */ + errorCode=U_ZERO_ERROR; + if(swapCases[i].name[0]=='*') { + pkg=testPath; + nm=swapCases[i].name+1; + uprv_strcpy(name, "testdata"); + } else if (uprv_strcmp(swapCases[i].type, "brk")==0 + || uprv_strcmp(swapCases[i].type, "ctd")==0) { + pkg=U_ICUDATA_BRKITR; + nm=swapCases[i].name; + uprv_strcpy(name, U_ICUDATA_BRKITR); + } else { + pkg=NULL; + nm=swapCases[i].name; + uprv_strcpy(name, "NULL"); + } + uprv_strcat(name, "/"); + uprv_strcat(name, nm); + uprv_strcat(name, "."); + uprv_strcat(name, swapCases[i].type); + + pData=udata_open(pkg, swapCases[i].type, nm, &errorCode); + if(U_SUCCESS(errorCode)) { + TestSwapCase(pData, name, swapCases[i].swapFn, buffer, buffer+SWAP_BUFFER_SIZE); + udata_close(pData); + } else { + log_data_err("udata_open(%s) failed - %s\n", + name, u_errorName(errorCode)); + } + } + + uprv_free(buffer); +} + + +static void PointerTableOfContents() { + UDataMemory *dataItem; + UErrorCode status=U_ZERO_ERROR; + + /* + * Got testdata.dat into memory, now we try setAppData using the memory image. + */ + + status=U_ZERO_ERROR; + udata_setAppData("OffsetTOCAppData", &gOffsetTOCAppData_dat, &status); + if (status != U_ZERO_ERROR) { + log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) \n" + " returned status of %s\n", u_errorName(status)); + return; + } + + dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCAppDataItem1", &status); + if (U_FAILURE(status)) { + log_err("FAIL: gOffsetTOCAppDataItem1 could not be opened. status = %s\n", u_errorName(status)); + } + if (udata_getMemory(dataItem) != NULL) { + log_verbose("FAIL: udata_getMemory(dataItem) passed\n"); + } + else { + log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status)); + } + udata_close(dataItem); + + dataItem = udata_open("OffsetTOCAppData-a", "", "b", &status); + if (U_FAILURE(status)) { + log_err("FAIL: gOffsetTOCAppDataItem1 in tree \"a\" could not be opened. status = %s\n", u_errorName(status)); + } + if (udata_getMemory(dataItem) != NULL) { + log_verbose("FAIL: udata_getMemory(dataItem) in tree \"a\" passed\n"); + } + else { + log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status)); + } + udata_close(dataItem); + + dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCGarbage", &status); + if (U_SUCCESS(status)) { + log_err("FAIL: gOffsetTOCGarbage should not be opened. status = %s\n", u_errorName(status)); + } + dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCNonExistent", &status); + if (U_SUCCESS(status)) { + log_err("FAIL: gOffsetTOCNonExistent should not be found. status = %s\n", u_errorName(status)); + } + +} + +static void SetBadCommonData(void) { + /* It's difficult to test that udata_setCommonData really works within the test framework. + So we just test that foolish people can't do bad things. */ + UErrorCode status; + char badBuffer[sizeof(gOffsetTOCAppData_dat)]; + + memset(badBuffer, 0, sizeof(badBuffer)); + strcpy(badBuffer, "Hello! I'm not good data."); + + /* Check that we don't do anything */ + status = U_FILE_ACCESS_ERROR; + udata_setCommonData(&gOffsetTOCAppData_dat, &status); + if (status != U_FILE_ACCESS_ERROR) { + log_err("FAIL: udata_setCommonData changed the failure code.\n"); + } + /* Check that we fail correctly */ + status = U_ZERO_ERROR; + udata_setCommonData(NULL, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("FAIL: udata_setCommonData did not fail with bad arguments.\n"); + } + if (u_getDataDirectory() == NULL || u_getDataDirectory()[0] == 0) { + /* Check that we don't change the common data. Many ICU tests will fail after this test, if this works. */ + /* We could do a better test, if we called u_cleanup and udata_setCommonData returned the last value. */ + status = U_ZERO_ERROR; + udata_setCommonData(&gOffsetTOCAppData_dat, &status); + if (status != U_USING_DEFAULT_WARNING) { + log_err("FAIL: udata_setCommonData allowed the data to be changed after initialization!\n"); + } + } + else { + log_verbose("Can't test setting common data because files mode may have been used.\n"); + } + + /* Check that we verify that the data isn't bad */ + status = U_ZERO_ERROR; + udata_setAppData("invalid path", badBuffer, &status); + if (status != U_INVALID_FORMAT_ERROR) { + log_err("FAIL: udata_setAppData doesn't verify data validity.\n"); + } +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c b/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c new file mode 100644 index 00000000000..34542b0bcda --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c @@ -0,0 +1,307 @@ +/* +******************************************************************************* +* +* Copyright (C) 2007, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: udatpg_test.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:4 +* +* created on: 2007aug01 +* created by: Markus W. Scherer +* +* Test of the C wrapper for the DateTimePatternGenerator. +* Calls each C API function and exercises code paths in the wrapper, +* but the full functionality is tested in the C++ intltest. +* +* One item to note: C API functions which return a const UChar * +* should return a NUL-terminated string. +* (The C++ implementation needs to use getTerminatedBuffer() +* on UnicodeString objects which end up being returned this way.) +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/udatpg.h" +#include "unicode/ustring.h" +#include "cintltst.h" + +void addDateTimePatternGeneratorTest(TestNode** root); + +#define TESTCASE(x) addTest(root, &x, "tsformat/udatpg_test/" #x) + +static void TestOpenClose(void); +static void TestUsage(void); +static void TestBuilder(void); + +void addDateTimePatternGeneratorTest(TestNode** root) { + TESTCASE(TestOpenClose); + TESTCASE(TestUsage); + TESTCASE(TestBuilder); +} + +/* + * Pipe symbol '|'. We pass only the first UChar without NUL-termination. + * The second UChar is just to verify that the API does not pick that up. + */ +static const UChar pipeString[]={ 0x7c, 0x0a }; + +static const UChar testSkeleton1[]={ 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */ +static const UChar expectingBestPattern[]={ 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0 }; /* HH.mm */ +static const UChar testPattern[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0 }; /* HH:mm */ +static const UChar expectingSkeleton[]= { 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */ +static const UChar expectingBaseSkeleton[]= { 0x48, 0x6d, 0 }; /* HHmm */ +static const UChar redundantPattern[]={ 0x79, 0x79, 0x4d, 0x4d, 0x4d, 0 }; /* yyMMM */ +static const UChar testFormat[]= {0x7B, 0x31, 0x7D, 0x20, 0x7B, 0x30, 0x7D, 0}; /* {1} {0} */ +static const UChar appendItemName[]= {0x68, 0x72, 0}; /* hr */ +static const UChar testPattern2[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x76, 0 }; /* HH:mm v */ +static const UChar replacedStr[]={ 0x76, 0x76, 0x76, 0x76, 0 }; /* vvvv */ +/* results for getBaseSkeletons() - {Hmv}, {yMMM} */ +static const UChar resultBaseSkeletons[2][10] = {{0x48,0x6d, 0x76, 0}, {0x79, 0x4d, 0x4d, 0x4d, 0 } }; + + +static void TestOpenClose() { + UErrorCode errorCode=U_ZERO_ERROR; + UDateTimePatternGenerator *dtpg, *dtpg2; + const UChar *s; + int32_t length; + + /* Open a DateTimePatternGenerator for the default locale. */ + dtpg=udatpg_open(NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_open(NULL) failed - %s\n", u_errorName(errorCode)); + return; + } + udatpg_close(dtpg); + + /* Now one for German. */ + dtpg=udatpg_open("de", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_open(de) failed - %s\n", u_errorName(errorCode)); + return; + } + + /* Make some modification which we verify gets passed on to the clone. */ + udatpg_setDecimal(dtpg, pipeString, 1); + + /* Clone the generator. */ + dtpg2=udatpg_clone(dtpg, &errorCode); + if(U_FAILURE(errorCode) || dtpg2==NULL) { + log_err("udatpg_clone() failed - %s\n", u_errorName(errorCode)); + return; + } + + /* Verify that the clone has the custom decimal symbol. */ + s=udatpg_getDecimal(dtpg2, &length); + if(s==pipeString || length!=1 || 0!=u_memcmp(s, pipeString, length) || s[length]!=0) { + log_err("udatpg_getDecimal(cloned object) did not return the expected string\n"); + return; + } + + udatpg_close(dtpg); + udatpg_close(dtpg2); +} + +static void TestUsage() { + UErrorCode errorCode=U_ZERO_ERROR; + UDateTimePatternGenerator *dtpg; + UChar bestPattern[20]; + UChar result[20]; + int32_t length; + UChar *s; + const UChar *r; + + dtpg=udatpg_open("fi", &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_open(fi) failed - %s\n", u_errorName(errorCode)); + return; + } + length = udatpg_getBestPattern(dtpg, testSkeleton1, 4, + bestPattern, 20, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_getBestPattern failed - %s\n", u_errorName(errorCode)); + return; + } + if((u_memcmp(bestPattern, expectingBestPattern, length)!=0) || bestPattern[length]!=0) { + log_err("udatpg_getBestPattern did not return the expected string\n"); + return; + } + + + /* Test skeleton == NULL */ + s=NULL; + length = udatpg_getBestPattern(dtpg, s, 0, bestPattern, 20, &errorCode); + if(!U_FAILURE(errorCode)&&(length!=0) ) { + log_err("udatpg_getBestPattern failed in illegal argument - skeleton is NULL.\n"); + return; + } + + /* Test udatpg_getSkeleton */ + length = udatpg_getSkeleton(dtpg, testPattern, 5, result, 20, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_getSkeleton failed - %s\n", u_errorName(errorCode)); + return; + } + if((u_memcmp(result, expectingSkeleton, length)!=0) || result[length]!=0) { + log_err("udatpg_getSkeleton did not return the expected string\n"); + return; + } + + /* Test pattern == NULL */ + s=NULL; + length = udatpg_getSkeleton(dtpg, s, 0, result, 20, &errorCode); + if(!U_FAILURE(errorCode)&&(length!=0) ) { + log_err("udatpg_getSkeleton failed in illegal argument - pattern is NULL.\n"); + return; + } + + /* Test udatpg_getBaseSkeleton */ + length = udatpg_getBaseSkeleton(dtpg, testPattern, 5, result, 20, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_getBaseSkeleton failed - %s\n", u_errorName(errorCode)); + return; + } + if((u_memcmp(result, expectingBaseSkeleton, length)!=0) || result[length]!=0) { + log_err("udatpg_getBaseSkeleton did not return the expected string\n"); + return; + } + + /* Test pattern == NULL */ + s=NULL; + length = udatpg_getBaseSkeleton(dtpg, s, 0, result, 20, &errorCode); + if(!U_FAILURE(errorCode)&&(length!=0) ) { + log_err("udatpg_getBaseSkeleton failed in illegal argument - pattern is NULL.\n"); + return; + } + + /* set append format to {1}{0} */ + udatpg_setAppendItemFormat( dtpg, UDATPG_MONTH_FIELD, testFormat, 7 ); + r = udatpg_getAppendItemFormat(dtpg, UDATPG_MONTH_FIELD, &length); + + + if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) { + log_err("udatpg_setAppendItemFormat did not return the expected string\n"); + return; + } + + /* set append name to hr */ + udatpg_setAppendItemName( dtpg, UDATPG_HOUR_FIELD, appendItemName, 7 ); + r = udatpg_getAppendItemName(dtpg, UDATPG_HOUR_FIELD, &length); + + if(length!=7 || 0!=u_memcmp(r, appendItemName, length) || r[length]!=0) { + log_err("udatpg_setAppendItemName did not return the expected string\n"); + return; + } + + /* set date time format to {1}{0} */ + udatpg_setDateTimeFormat( dtpg, testFormat, 7 ); + r = udatpg_getDateTimeFormat(dtpg, &length); + + if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) { + log_err("udatpg_setDateTimeFormat did not return the expected string\n"); + return; + } + udatpg_close(dtpg); +} + +static void TestBuilder() { + UErrorCode errorCode=U_ZERO_ERROR; + UDateTimePatternGenerator *dtpg; + UDateTimePatternConflict conflict; + UEnumeration *en; + UChar result[20]; + int32_t length, pLength; + const UChar *s, *p; + const UChar* ptrResult[2]; + int32_t count=0; + + /* test create an empty DateTimePatternGenerator */ + dtpg=udatpg_openEmpty(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_openEmpty() failed - %s\n", u_errorName(errorCode)); + return; + } + + /* Add a pattern */ + conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20, + &length, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("udatpg_addPattern() failed - %s\n", u_errorName(errorCode)); + return; + } + /* Add a redundant pattern */ + conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20, + &length, &errorCode); + if(conflict == UDATPG_NO_CONFLICT) { + log_err("udatpg_addPattern() failed to find the duplicate pattern.\n"); + return; + } + /* Test pattern == NULL */ + s=NULL; + length = udatpg_addPattern(dtpg, s, 0, FALSE, result, 20, + &length, &errorCode); + if(!U_FAILURE(errorCode)&&(length!=0) ) { + log_err("udatpg_addPattern failed in illegal argument - pattern is NULL.\n"); + return; + } + + /* replace field type */ + errorCode=U_ZERO_ERROR; + conflict = udatpg_addPattern(dtpg, testPattern2, 7, FALSE, result, 20, + &length, &errorCode); + if((conflict != UDATPG_NO_CONFLICT)||U_FAILURE(errorCode)) { + log_err("udatpg_addPattern() failed to add HH:mm v. - %s\n", u_errorName(errorCode)); + return; + } + length = udatpg_replaceFieldTypes(dtpg, testPattern2, 7, replacedStr, 4, + result, 20, &errorCode); + if (U_FAILURE(errorCode) || (length==0) ) { + log_err("udatpg_replaceFieldTypes failed!\n"); + return; + } + + /* Get all skeletons and the crroespong pattern for each skeleton. */ + ptrResult[0] = testPattern2; + ptrResult[1] = redundantPattern; + count=0; + en = udatpg_openSkeletons(dtpg, &errorCode); + if (U_FAILURE(errorCode) || (length==0) ) { + log_err("udatpg_openSkeletons failed!\n"); + return; + } + while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) { + p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength); + if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, ptrResult[count], pLength)!=0 ) { + log_err("udatpg_getPatternForSkeleton failed!\n"); + return; + } + count++; + } + uenum_close(en); + + /* Get all baseSkeletons */ + en = udatpg_openBaseSkeletons(dtpg, &errorCode); + count=0; + while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) { + p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength); + if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, resultBaseSkeletons[count], pLength)!=0 ) { + log_err("udatpg_getPatternForSkeleton failed!\n"); + return; + } + count++; + } + if (U_FAILURE(errorCode) || (length==0) ) { + log_err("udatpg_openSkeletons failed!\n"); + return; + } + uenum_close(en); + + udatpg_close(dtpg); +} + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c new file mode 100644 index 00000000000..2d9ed6c0ab8 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c @@ -0,0 +1,307 @@ +/* +******************************************************************************* +* +* Copyright (C) 2002-2003, International Business Machines +* Corporation and others. All Rights Reserved. +* +******************************************************************************* +* file name: uenumtst.c +* encoding: US-ASCII +* tab size: 8 (not used) +* indentation:2 +* +* created on: 2002jul08 +* created by: Vladimir Weinstein +*/ + +#include "cintltst.h" +#include "uenumimp.h" +#include "cmemory.h" +#include "cstring.h" +#include "unicode/ustring.h" + +static char quikBuf[256]; +static char* quikU2C(const UChar* str, int32_t len) { + u_UCharsToChars(str, quikBuf, len); + quikBuf[len] = 0; + return quikBuf; +} + +static const char* test1[] = { + "first", + "second", + "third", + "fourth" +}; + +struct chArrayContext { + int32_t currIndex; + int32_t maxIndex; + char *currChar; + UChar *currUChar; + char **array; +}; + +typedef struct chArrayContext chArrayContext; + +#define cont ((chArrayContext *)en->context) + +static void U_CALLCONV +chArrayClose(UEnumeration *en) { + if(cont->currUChar != NULL) { + free(cont->currUChar); + cont->currUChar = NULL; + } + free(en); +} + +static int32_t U_CALLCONV +chArrayCount(UEnumeration *en, UErrorCode *status) { + return cont->maxIndex; +} + +static const UChar* U_CALLCONV +chArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + if(cont->currIndex >= cont->maxIndex) { + return NULL; + } + + if(cont->currUChar == NULL) { + cont->currUChar = (UChar *)malloc(1024*sizeof(UChar)); + } + + cont->currChar = (cont->array)[cont->currIndex]; + *resultLength = (int32_t)strlen(cont->currChar); + u_charsToUChars(cont->currChar, cont->currUChar, *resultLength); + cont->currIndex++; + return cont->currUChar; +} + +static const char* U_CALLCONV +chArrayNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + if(cont->currIndex >= cont->maxIndex) { + return NULL; + } + + cont->currChar = (cont->array)[cont->currIndex]; + *resultLength = (int32_t)strlen(cont->currChar); + cont->currIndex++; + return cont->currChar; +} + +static void U_CALLCONV +chArrayReset(UEnumeration *en, UErrorCode *status) { + cont->currIndex = 0; +} + +chArrayContext myCont = { + 0, 0, + NULL, NULL, + NULL +}; + +UEnumeration chEnum = { + NULL, + &myCont, + chArrayClose, + chArrayCount, + chArrayUNext, + chArrayNext, + chArrayReset +}; + +static const UEnumeration emptyEnumerator = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static const UEnumeration emptyPartialEnumerator = { + NULL, + NULL, + NULL, + NULL, + uenum_unextDefault, + NULL, + NULL, +}; + +/********************************************************************/ +static const UChar _first[] = {102,105,114,115,116,0}; /* "first" */ +static const UChar _second[]= {115,101,99,111,110,100,0}; /* "second" */ +static const UChar _third[] = {116,104,105,114,100,0}; /* "third" */ +static const UChar _fourth[]= {102,111,117,114,116,104,0};/* "fourth" */ + +static const UChar* test2[] = { + _first, _second, _third, _fourth +}; + +struct uchArrayContext { + int32_t currIndex; + int32_t maxIndex; + UChar *currUChar; + UChar **array; +}; + +typedef struct uchArrayContext uchArrayContext; + +#define ucont ((uchArrayContext *)en->context) + +static void U_CALLCONV +uchArrayClose(UEnumeration *en) { + free(en); +} + +static int32_t U_CALLCONV +uchArrayCount(UEnumeration *en, UErrorCode *status) { + return ucont->maxIndex; +} + +static const UChar* U_CALLCONV +uchArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { + if(ucont->currIndex >= ucont->maxIndex) { + return NULL; + } + + ucont->currUChar = (ucont->array)[ucont->currIndex]; + *resultLength = u_strlen(ucont->currUChar); + ucont->currIndex++; + return ucont->currUChar; +} + +static void U_CALLCONV +uchArrayReset(UEnumeration *en, UErrorCode *status) { + ucont->currIndex = 0; +} + +uchArrayContext myUCont = { + 0, 0, + NULL, NULL +}; + +UEnumeration uchEnum = { + NULL, + &myUCont, + uchArrayClose, + uchArrayCount, + uchArrayUNext, + uenum_nextDefault, + uchArrayReset +}; + +/********************************************************************/ + +static UEnumeration *getchArrayEnum(const char** source, int32_t size) { + UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration)); + memcpy(en, &chEnum, sizeof(UEnumeration)); + cont->array = (char **)source; + cont->maxIndex = size; + return en; +} + +static void EnumerationTest(void) { + UErrorCode status = U_ZERO_ERROR; + int32_t len = 0; + UEnumeration *en = getchArrayEnum(test1, sizeof(test1)/sizeof(test1[0])); + const char *string = NULL; + const UChar *uString = NULL; + while ((string = uenum_next(en, &len, &status))) { + log_verbose("read \"%s\", length %i\n", string, len); + } + uenum_reset(en, &status); + while ((uString = uenum_unext(en, &len, &status))) { + log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len); + } + + uenum_close(en); +} + +static void EmptyEnumerationTest(void) { + UErrorCode status = U_ZERO_ERROR; + UEnumeration *emptyEnum = uprv_malloc(sizeof(UEnumeration)); + + uprv_memcpy(emptyEnum, &emptyEnumerator, sizeof(UEnumeration)); + if (uenum_count(emptyEnum, &status) != -1 || status != U_UNSUPPORTED_ERROR) { + log_err("uenum_count failed\n"); + } + status = U_ZERO_ERROR; + if (uenum_next(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) { + log_err("uenum_next failed\n"); + } + status = U_ZERO_ERROR; + if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) { + log_err("uenum_unext failed\n"); + } + status = U_ZERO_ERROR; + uenum_reset(emptyEnum, &status); + if (status != U_UNSUPPORTED_ERROR) { + log_err("uenum_reset failed\n"); + } + uenum_close(emptyEnum); + + status = U_ZERO_ERROR; + if (uenum_next(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) { + log_err("uenum_next(NULL) failed\n"); + } + status = U_ZERO_ERROR; + if (uenum_unext(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) { + log_err("uenum_unext(NULL) failed\n"); + } + status = U_ZERO_ERROR; + uenum_reset(NULL, &status); + if (status != U_ZERO_ERROR) { + log_err("uenum_reset(NULL) failed\n"); + } + + emptyEnum = uprv_malloc(sizeof(UEnumeration)); + uprv_memcpy(emptyEnum, &emptyPartialEnumerator, sizeof(UEnumeration)); + status = U_ZERO_ERROR; + if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) { + log_err("partial uenum_unext failed\n"); + } + uenum_close(emptyEnum); +} + +static UEnumeration *getuchArrayEnum(const UChar** source, int32_t size) { + UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration)); + memcpy(en, &uchEnum, sizeof(UEnumeration)); + ucont->array = (UChar **)source; + ucont->maxIndex = size; + return en; +} + +static void DefaultNextTest(void) { + UErrorCode status = U_ZERO_ERROR; + int32_t len = 0; + UEnumeration *en = getuchArrayEnum(test2, sizeof(test2)/sizeof(test2[0])); + const char *string = NULL; + const UChar *uString = NULL; + while ((uString = uenum_unext(en, &len, &status))) { + log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len); + } + if (U_FAILURE(status)) { + log_err("FAIL: uenum_unext => %s\n", u_errorName(status)); + } + uenum_reset(en, &status); + while ((string = uenum_next(en, &len, &status))) { + log_verbose("read \"%s\", length %i\n", string, len); + } + if (U_FAILURE(status)) { + log_err("FAIL: uenum_next => %s\n", u_errorName(status)); + } + + uenum_close(en); +} + +void addEnumerationTest(TestNode** root); + +void addEnumerationTest(TestNode** root) +{ + addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest"); + addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest"); + addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest"); +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c new file mode 100644 index 00000000000..fc2a3e9b055 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c @@ -0,0 +1,646 @@ +/* +********************************************************************** +* Copyright (c) 2002-2007, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +#include "unicode/uset.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include <stdlib.h> +#include <string.h> + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +#define TEST(x) addTest(root, &x, "uset/" # x) + +static void TestAPI(void); +static void Testj2269(void); +static void TestSerialized(void); +static void TestNonInvariantPattern(void); +static void TestBadPattern(void); +static void TestFreezable(void); +static void TestSpan(void); + +void addUSetTest(TestNode** root); + +static void expect(const USet* set, + const char* inList, + const char* outList, + UErrorCode* ec); +static void expectContainment(const USet* set, + const char* list, + UBool isIn); +static char oneUCharToChar(UChar32 c); +static void expectItems(const USet* set, + const char* items); + +void +addUSetTest(TestNode** root) { + TEST(TestAPI); + TEST(Testj2269); + TEST(TestSerialized); + TEST(TestNonInvariantPattern); + TEST(TestBadPattern); + TEST(TestFreezable); + TEST(TestSpan); +} + +/*------------------------------------------------------------------ + * Tests + *------------------------------------------------------------------*/ + +static void Testj2269() { + UErrorCode status = U_ZERO_ERROR; + UChar a[4] = { 0x61, 0x62, 0x63, 0 }; + USet *s = uset_open(1, 0); + uset_addString(s, a, 3); + a[0] = 0x63; a[1] = 0x63; + expect(s, "{abc}", "{ccc}", &status); + uset_close(s); +} + +static const UChar PAT[] = {91,97,45,99,123,97,98,125,93,0}; /* "[a-c{ab}]" */ +static const int32_t PAT_LEN = (sizeof(PAT) / sizeof(PAT[0])) - 1; + +static const UChar PAT_lb[] = {0x6C, 0x62, 0}; /* "lb" */ +static const int32_t PAT_lb_LEN = (sizeof(PAT_lb) / sizeof(PAT_lb[0])) - 1; + +static const UChar VAL_SP[] = {0x53, 0x50, 0}; /* "SP" */ +static const int32_t VAL_SP_LEN = (sizeof(VAL_SP) / sizeof(VAL_SP[0])) - 1; + +static const UChar STR_bc[] = {98,99,0}; /* "bc" */ +static const int32_t STR_bc_LEN = (sizeof(STR_bc) / sizeof(STR_bc[0])) - 1; + +static const UChar STR_ab[] = {97,98,0}; /* "ab" */ +static const int32_t STR_ab_LEN = (sizeof(STR_ab) / sizeof(STR_ab[0])) - 1; + +/** + * Basic API test for uset.x + */ +static void TestAPI() { + USet* set; + USet* set2; + UErrorCode ec; + + /* [] */ + set = uset_open(1, 1); + uset_clear(set); + expect(set, "", "abc{ab}", NULL); + uset_close(set); + + /* [ABC] */ + set = uset_open(0x0041, 0x0043); + expect(set, "ABC", "DEF{ab}", NULL); + uset_close(set); + + /* [a-c{ab}] */ + ec = U_ZERO_ERROR; + set = uset_openPattern(PAT, PAT_LEN, &ec); + if(U_FAILURE(ec)) { + log_err("uset_openPattern([a-c{ab}]) failed - %s\n", u_errorName(ec)); + return; + } + if(!uset_resemblesPattern(PAT, PAT_LEN, 0)) { + log_err("uset_resemblesPattern of PAT failed\n"); + } + expect(set, "abc{ab}", "def{bc}", &ec); + + /* [a-d{ab}] */ + uset_add(set, 0x64); + expect(set, "abcd{ab}", "ef{bc}", NULL); + + /* [acd{ab}{bc}] */ + uset_remove(set, 0x62); + uset_addString(set, STR_bc, STR_bc_LEN); + expect(set, "acd{ab}{bc}", "bef{cd}", NULL); + + /* [acd{bc}] */ + uset_removeString(set, STR_ab, STR_ab_LEN); + expect(set, "acd{bc}", "bfg{ab}", NULL); + + /* [^acd{bc}] */ + uset_complement(set); + expect(set, "bef{bc}", "acd{ac}", NULL); + + /* [a-e{bc}] */ + uset_complement(set); + uset_addRange(set, 0x0062, 0x0065); + expect(set, "abcde{bc}", "fg{ab}", NULL); + + /* [de{bc}] */ + uset_removeRange(set, 0x0050, 0x0063); + expect(set, "de{bc}", "bcfg{ab}", NULL); + + /* [g-l] */ + uset_set(set, 0x0067, 0x006C); + expect(set, "ghijkl", "de{bc}", NULL); + + if (uset_indexOf(set, 0x0067) != 0) { + log_err("uset_indexOf failed finding correct index of 'g'\n"); + } + + if (uset_charAt(set, 0) != 0x0067) { + log_err("uset_charAt failed finding correct char 'g' at index 0\n"); + } + + /* How to test this one...? */ + uset_compact(set); + + /* [g-i] */ + uset_retain(set, 0x0067, 0x0069); + expect(set, "ghi", "dejkl{bc}", NULL); + + /* UCHAR_ASCII_HEX_DIGIT */ + uset_applyIntPropertyValue(set, UCHAR_ASCII_HEX_DIGIT, 1, &ec); + if(U_FAILURE(ec)) { + log_err("uset_applyIntPropertyValue([UCHAR_ASCII_HEX_DIGIT]) failed - %s\n", u_errorName(ec)); + return; + } + expect(set, "0123456789ABCDEFabcdef", "GHIjkl{bc}", NULL); + + /* [ab] */ + uset_clear(set); + uset_addAllCodePoints(set, STR_ab, STR_ab_LEN); + expect(set, "ab", "def{ab}", NULL); + if (uset_containsAllCodePoints(set, STR_bc, STR_bc_LEN)){ + log_err("set should not conatin all characters of \"bc\" \n"); + } + + /* [] */ + set2 = uset_open(1, 1); + uset_clear(set2); + + /* space */ + uset_applyPropertyAlias(set2, PAT_lb, PAT_lb_LEN, VAL_SP, VAL_SP_LEN, &ec); + expect(set2, " ", "abcdefghi{bc}", NULL); + + /* [a-c] */ + uset_set(set2, 0x0061, 0x0063); + /* [g-i] */ + uset_set(set, 0x0067, 0x0069); + + /* [a-c g-i] */ + if (uset_containsSome(set, set2)) { + log_err("set should not contain some of set2 yet\n"); + } + uset_complementAll(set, set2); + if (!uset_containsSome(set, set2)) { + log_err("set should contain some of set2\n"); + } + expect(set, "abcghi", "def{bc}", NULL); + + /* [g-i] */ + uset_removeAll(set, set2); + expect(set, "ghi", "abcdef{bc}", NULL); + + /* [a-c g-i] */ + uset_addAll(set2, set); + expect(set2, "abcghi", "def{bc}", NULL); + + /* [g-i] */ + uset_retainAll(set2, set); + expect(set2, "ghi", "abcdef{bc}", NULL); + + uset_close(set); + uset_close(set2); +} + +/*------------------------------------------------------------------ + * Support + *------------------------------------------------------------------*/ + +/** + * Verifies that the given set contains the characters and strings in + * inList, and does not contain those in outList. Also verifies that + * 'set' is not NULL and that 'ec' succeeds. + * @param set the set to test, or NULL (on error) + * @param inList list of set contents, in iteration order. Format is + * list of individual strings, in iteration order, followed by sorted + * list of strings, delimited by {}. This means we do not test + * characters '{' or '}' and we do not test strings containing those + * characters either. + * @param outList list of things not in the set. Same format as + * inList. + * @param ec an error code, checked for success. May be NULL in which + * case it is ignored. + */ +static void expect(const USet* set, + const char* inList, + const char* outList, + UErrorCode* ec) { + if (ec!=NULL && U_FAILURE(*ec)) { + log_err("FAIL: %s\n", u_errorName(*ec)); + return; + } + if (set == NULL) { + log_err("FAIL: USet is NULL\n"); + return; + } + expectContainment(set, inList, TRUE); + expectContainment(set, outList, FALSE); + expectItems(set, inList); +} + +static void expectContainment(const USet* set, + const char* list, + UBool isIn) { + const char* p = list; + UChar ustr[4096]; + char *pat; + UErrorCode ec; + int32_t rangeStart = -1, rangeEnd = -1, length; + + ec = U_ZERO_ERROR; + length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec); + if(U_FAILURE(ec)) { + log_err("FAIL: uset_toPattern() fails in expectContainment() - %s\n", u_errorName(ec)); + return; + } + pat=aescstrdup(ustr, length); + + while (*p) { + if (*p=='{') { + const char* stringStart = ++p; + int32_t stringLength = 0; + char strCopy[64]; + + while (*p++ != '}') { + } + stringLength = (int32_t)(p - stringStart - 1); + strncpy(strCopy, stringStart, stringLength); + strCopy[stringLength] = 0; + + u_charsToUChars(stringStart, ustr, stringLength); + + if (uset_containsString(set, ustr, stringLength) == isIn) { + log_verbose("Ok: %s %s \"%s\"\n", pat, + (isIn ? "contains" : "does not contain"), + strCopy); + } else { + log_err("FAIL: %s %s \"%s\"\n", pat, + (isIn ? "does not contain" : "contains"), + strCopy); + } + } + + else { + UChar32 c; + + u_charsToUChars(p, ustr, 1); + c = ustr[0]; + + if (uset_contains(set, c) == isIn) { + log_verbose("Ok: %s %s '%c'\n", pat, + (isIn ? "contains" : "does not contain"), + *p); + } else { + log_err("FAIL: %s %s '%c'\n", pat, + (isIn ? "does not contain" : "contains"), + *p); + } + + /* Test the range API too by looking for ranges */ + if (c == rangeEnd+1) { + rangeEnd = c; + } else { + if (rangeStart >= 0) { + if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) { + log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat, + (isIn ? "contains" : "does not contain"), + rangeStart, rangeEnd); + } else { + log_err("FAIL: %s %s U+%04X-U+%04X\n", pat, + (isIn ? "does not contain" : "contains"), + rangeStart, rangeEnd); + } + } + rangeStart = rangeEnd = c; + } + + ++p; + } + } + + if (rangeStart >= 0) { + if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) { + log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat, + (isIn ? "contains" : "does not contain"), + rangeStart, rangeEnd); + } else { + log_err("FAIL: %s %s U+%04X-U+%04X\n", pat, + (isIn ? "does not contain" : "contains"), + rangeStart, rangeEnd); + } + } +} + +/* This only works for invariant BMP chars */ +static char oneUCharToChar(UChar32 c) { + UChar ubuf[1]; + char buf[1]; + ubuf[0] = (UChar) c; + u_UCharsToChars(ubuf, buf, 1); + return buf[0]; +} + +static void expectItems(const USet* set, + const char* items) { + const char* p = items; + UChar ustr[4096], itemStr[4096]; + char buf[4096]; + char *pat; + UErrorCode ec; + int32_t expectedSize = 0; + int32_t itemCount = uset_getItemCount(set); + int32_t itemIndex = 0; + UChar32 start = 1, end = 0; + int32_t itemLen = 0, length; + + ec = U_ZERO_ERROR; + length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec); + if (U_FAILURE(ec)) { + log_err("FAIL: uset_toPattern => %s\n", u_errorName(ec)); + return; + } + pat=aescstrdup(ustr, length); + + if (uset_isEmpty(set) != (strlen(items)==0)) { + log_err("FAIL: %s should return %s from isEmpty\n", + pat, + strlen(items)==0 ? "TRUE" : "FALSE"); + } + + /* Don't test patterns starting with "[^" */ + if (u_strlen(ustr) > 2 && ustr[1] == 0x5e /*'^'*/) { + return; + } + + while (*p) { + + ++expectedSize; + + if (start > end || start == -1) { + /* Fetch our next item */ + if (itemIndex >= itemCount) { + log_err("FAIL: ran out of items iterating %s\n", pat); + return; + } + + itemLen = uset_getItem(set, itemIndex, &start, &end, + itemStr, sizeof(itemStr), &ec); + if (U_FAILURE(ec) || itemLen < 0) { + log_err("FAIL: uset_getItem => %s\n", u_errorName(ec)); + return; + } + + if (itemLen == 0) { + log_verbose("Ok: %s item %d is %c-%c\n", pat, + itemIndex, oneUCharToChar(start), + oneUCharToChar(end)); + } else { + itemStr[itemLen] = 0; + u_UCharsToChars(itemStr, buf, itemLen+1); + log_verbose("Ok: %s item %d is \"%s\"\n", pat, itemIndex, buf); + } + + ++itemIndex; + } + + if (*p=='{') { + const char* stringStart = ++p; + int32_t stringLength = 0; + char strCopy[64]; + + while (*p++ != '}') { + } + stringLength = (int32_t)(p - stringStart - 1); + strncpy(strCopy, stringStart, stringLength); + strCopy[stringLength] = 0; + + u_charsToUChars(stringStart, ustr, stringLength); + ustr[stringLength] = 0; + + if (itemLen == 0) { + log_err("FAIL: for %s expect \"%s\" next, but got a char\n", + pat, strCopy); + return; + } + + if (u_strcmp(ustr, itemStr) != 0) { + log_err("FAIL: for %s expect \"%s\" next\n", + pat, strCopy); + return; + } + } + + else { + UChar32 c; + + u_charsToUChars(p, ustr, 1); + c = ustr[0]; + + if (itemLen != 0) { + log_err("FAIL: for %s expect '%c' next, but got a string\n", + pat, *p); + return; + } + + if (c != start++) { + log_err("FAIL: for %s expect '%c' next\n", + pat, *p); + return; + } + + ++p; + } + } + + if (uset_size(set) == expectedSize) { + log_verbose("Ok: %s size is %d\n", pat, expectedSize); + } else { + log_err("FAIL: %s size is %d, expected %d\n", + pat, uset_size(set), expectedSize); + } +} + +static void +TestSerialized() { + uint16_t buffer[1000]; + USerializedSet sset; + USet *set; + UErrorCode errorCode; + UChar32 c; + int32_t length; + + /* use a pattern that generates both BMP and supplementary code points */ + U_STRING_DECL(pattern, "[:Cf:]", 6); + U_STRING_INIT(pattern, "[:Cf:]", 6); + + errorCode=U_ZERO_ERROR; + set=uset_openPattern(pattern, -1, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("uset_openPattern([:Cf:]) failed - %s\n", u_errorName(errorCode)); + return; + } + + length=uset_serialize(set, buffer, LENGTHOF(buffer), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("unable to uset_serialize([:Cf:]) - %s\n", u_errorName(errorCode)); + uset_close(set); + return; + } + + uset_getSerializedSet(&sset, buffer, length); + for(c=0; c<=0x10ffff; ++c) { + if(uset_contains(set, c)!=uset_serializedContains(&sset, c)) { + log_err("uset_contains(U+%04x)!=uset_serializedContains(U+%04x)\n", c); + break; + } + } + + uset_close(set); +} + +/** + * Make sure that when non-invariant chars are passed to uset_openPattern + * they do not cause an ugly failure mode (e.g. assertion failure). + * JB#3795. + */ +static void +TestNonInvariantPattern() { + UErrorCode ec = U_ZERO_ERROR; + /* The critical part of this test is that the following pattern + must contain a non-invariant character. */ + static const char *pattern = "[:ccc!=0:]"; + UChar buf[256]; + int32_t len = u_unescape(pattern, buf, 256); + /* This test 'fails' by having an assertion failure within the + following call. It passes by running to completion with no + assertion failure. */ + USet *set = uset_openPattern(buf, len, &ec); + uset_close(set); +} + +static void TestBadPattern(void) { + UErrorCode status = U_ZERO_ERROR; + USet *pat; + U_STRING_DECL(pattern, "[", 1); + U_STRING_INIT(pattern, "[", 1); + pat = uset_openPatternOptions(pattern, u_strlen(pattern), 0, &status); + if (pat != NULL || U_SUCCESS(status)) { + log_err("uset_openPatternOptions did not fail as expected %s\n", u_errorName(status)); + } +} + +static USet *openIDSet() { + UErrorCode errorCode = U_ZERO_ERROR; + U_STRING_DECL(pattern, "[:ID_Continue:]", 15); + U_STRING_INIT(pattern, "[:ID_Continue:]", 15); + return uset_openPattern(pattern, 15, &errorCode); +} + +static void TestFreezable() { + USet *idSet; + USet *frozen; + USet *thawed; + + idSet=openIDSet(); + + if (idSet == NULL) { + log_err("openIDSet() returned NULL"); + uset_close(idSet); + return; + } + + frozen=uset_clone(idSet); + + if (frozen == NULL) { + log_err("uset_Clone() returned NULL"); + return; + } + + if(!uset_equals(frozen, idSet)) { + log_err("uset_clone() did not make an equal copy\n"); + } + + uset_freeze(frozen); + uset_addRange(frozen, 0xd802, 0xd805); + + if(uset_isFrozen(idSet) || !uset_isFrozen(frozen) || !uset_equals(frozen, idSet)) { + log_err("uset_freeze() or uset_isFrozen() does not work\n"); + } + + thawed=uset_cloneAsThawed(frozen); + + if (thawed == NULL) { + log_err("uset_cloneAsThawed(frozen) returned NULL"); + uset_close(frozen); + uset_close(idSet); + return; + } + + uset_addRange(thawed, 0xd802, 0xd805); + + if(uset_isFrozen(thawed) || uset_equals(thawed, idSet) || !uset_containsRange(thawed, 0xd802, 0xd805)) { + log_err("uset_cloneAsThawed() does not work\n"); + } + + uset_close(idSet); + uset_close(frozen); + uset_close(thawed); +} + +static void TestSpan() { + static const UChar s16[2]={ 0xe01, 0x3000 }; + static const char* s8="\xE0\xB8\x81\xE3\x80\x80"; + + USet *idSet=openIDSet(); + + if (idSet == NULL) { + log_err("openIDSet() returned NULL"); + return; + } + + if( + 1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) || + 0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) || + 2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) || + 1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) + ) { + log_err("uset_span() or uset_spanBack() does not work\n"); + } + + if( + 3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) || + 0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) || + 6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) || + 3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) + ) { + log_err("uset_spanUTF8() or uset_spanBackUTF8() does not work\n"); + } + + uset_freeze(idSet); + + if( + 1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) || + 0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) || + 2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) || + 1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) + ) { + log_err("uset_span(frozen) or uset_spanBack(frozen) does not work\n"); + } + + if( + 3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) || + 0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) || + 6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) || + 3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) + ) { + log_err("uset_spanUTF8(frozen) or uset_spanBackUTF8(frozen) does not work\n"); + } + + uset_close(idSet); +} + +/*eof*/ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c new file mode 100644 index 00000000000..7f79e770db9 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c @@ -0,0 +1,498 @@ +/******************************************************************** + * Copyright (c) 2001-2007 International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************** + * File USRCHDAT.H + * Modification History: + * Name date Description + * synwee July 31 2001 creation + ********************************************************************/ + + +/* +Note: This file is included by other C and C++ files. This file should not be directly compiled. +*/ +#ifndef USRCHDAT_C +#define USRCHDAT_C + +#include "unicode/ucol.h" + +#if !UCONFIG_NO_COLLATION + +U_CDECL_BEGIN +struct SearchData { + const char *text; + const char *pattern; + const char *collator; + UCollationStrength strength; + const char *breaker; + int8_t offset[32]; + uint8_t size[32]; +}; +U_CDECL_END + +typedef struct SearchData SearchData; + +static const char *TESTCOLLATORRULE = "& o,O ; p,P"; + +static const char *EXTRACOLLATIONRULE = " & ae ; \\u00e4 & AE ; \\u00c4 & oe ; \\u00f6 & OE ; \\u00d6 & ue ; \\u00fc & UE ; \\u00dc"; + +static const SearchData BASIC[] = { + {"xxxxxxxxxxxxxxxxxxxx", "fisher", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"silly spring string", "string", NULL, UCOL_TERTIARY, NULL, {13, -1}, + {6}}, + {"silly spring string string", "string", NULL, UCOL_TERTIARY, NULL, + {13, 20, -1}, {6, 6}}, + {"silly string spring string", "string", NULL, UCOL_TERTIARY, NULL, + {6, 20, -1}, {6, 6}}, + {"string spring string", "string", NULL, UCOL_TERTIARY, NULL, {0, 14, -1}, + {6, 6}}, + {"Scott Ganyo", "c", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"Scott Ganyo", " ", NULL, UCOL_TERTIARY, NULL, {5, -1}, {1}}, + {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + {"a\\u0300b", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"\\u00c9", "e", NULL, UCOL_PRIMARY, NULL, {0, -1}, {1}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData BREAKITERATOREXACT[] = { + {"foxy fox", "fox", NULL, UCOL_TERTIARY, "characterbreaker", {0, 5, -1}, + {3, 3}}, + {"foxy fox", "fox", NULL, UCOL_TERTIARY, "wordbreaker", {5, -1}, {3}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, + "characterbreaker", {10, 14, -1}, {3, 2}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, "wordbreaker", + {10, -1}, {3}}, + {"Channel, another channel, more channels, and one last Channel", + "Channel", "es", UCOL_TERTIARY, "wordbreaker", {0, 54, -1}, {7, 7}}, + /* jitterbug 1745 */ + {"testing that \\u00e9 does not match e", "e", NULL, UCOL_TERTIARY, + "characterbreaker", {1, 17, 30, -1}, {1, 1, 1}}, + {"testing that string ab\\u00e9cd does not match e", "e", NULL, + UCOL_TERTIARY, "characterbreaker", {1, 28, 41, -1}, {1, 1, 1}}, + {"\\u00c9", "e", "fr", UCOL_PRIMARY, "characterbreaker", {0, -1}, {1}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData STRENGTH[] = { + /*012345678901234567890123456789012345678901234567890123456789*/ + {"The quick brown fox jumps over the lazy foxes", "fox", "en", + UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}}, + {"The quick brown fox jumps over the lazy foxes", "fox", "en", + UCOL_PRIMARY, "wordbreaker", {16, -1}, {3}}, + {"blackbirds Pat p\\u00E9ch\\u00E9 p\\u00EAche p\\u00E9cher p\\u00EAcher Tod T\\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe", + "peche", "fr", UCOL_PRIMARY, NULL, {15, 21, 27, 34, -1}, {5, 5, 5, 5}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, NULL, + {10, 14, -1}, {3, 2}}, + {"A channel, another CHANNEL, more Channels, and one last channel...", + "channel", "es", UCOL_PRIMARY, NULL, {2, 19, 33, 56, -1}, + {7, 7, 7, 7}}, + {"\\u00c0 should match but not A", "A\\u0300", "en", UCOL_IDENTICAL, + NULL, {0, -1}, {1, 0}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData VARIABLE[] = { + /*012345678901234567890123456789012345678901234567890123456789*/ + {"blackbirds black blackbirds blackbird black-bird", + "blackbird", NULL, UCOL_TERTIARY, NULL, {0, 17, 28, 38, -1}, + {9, 9, 9, 10}}, + /* to see that it doesn't go into an infinite loop if the start of text + is a ignorable character */ + {" on", "go", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"abcdefghijklmnopqrstuvwxyz", " ", NULL, UCOL_PRIMARY, NULL, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + /* testing tightest match */ + {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_QUATERNARY, + NULL, {1, -1}, {3}}, + /*012345678901234567890123456789012345678901234567890123456789 */ + {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_SECONDARY, + NULL, {1, 6, 13, 21, 31, -1}, {3, 4, 4, 5, 5}}, + /* totally ignorable text */ + {" ---------------", "abc", NULL, UCOL_SECONDARY, + NULL, {-1}, {0}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData NORMEXACT[] = { + {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData NONNORMEXACT[] = { + {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, + {0}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData OVERLAP[] = { + {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 2, 4, -1}, + {4, 4, 4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData NONOVERLAP[] = { + {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 4, -1}, {4, 4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData COLLATOR[] = { + /* english */ + {"fox fpx", "fox", NULL, UCOL_TERTIARY, NULL, {0, -1}, {3}}, + /* tailored */ + {"fox fpx", "fox", NULL, UCOL_PRIMARY, NULL, {0, 4, -1}, {3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData PATTERN[] = { + {"The quick brown fox jumps over the lazy foxes", "the", NULL, + UCOL_PRIMARY, NULL, {0, 31, -1}, {3, 3}}, + {"The quick brown fox jumps over the lazy foxes", "fox", NULL, + UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData TEXT[] = { + {"the foxy brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {4, 15, -1}, + {3, 3}}, + {"the quick brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {16, -1}, + {3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData COMPOSITEBOUNDARIES[] = { + {"\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u00C0C", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}}, + {"\\u00C0A", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}}, + {"B\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"\\u00C0B", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0300\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, + {1, 1}}, + {"\\u00C0\\u0300", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + /* A + 030A + 0301 */ + {"\\u01FA", "\\u01FA", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u01FA", "\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u030AA", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "A\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u030A\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FAA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u0F73", "\\u0F73", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0F73", "\\u0F71", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u0F73", "\\u0F72", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u0F73", "\\u0F71\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u0F73", "A\\u0F71", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u0F73A", "\\u0F72A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData MATCH[] = { + {"a busy bee is a very busy beeee", "bee", NULL, UCOL_TERTIARY, NULL, + {7, 26, -1}, {3, 3}}, + /* 012345678901234567890123456789012345678901234567890 */ + {"a busy bee is a very busy beeee with no bee life", "bee", NULL, + UCOL_TERTIARY, NULL, {7, 26, 40, -1}, {3, 3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData SUPPLEMENTARY[] = { + /* 012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890012345678901234567890123456789 */ + {"abc \\uD800\\uDC00 \\uD800\\uDC01 \\uD801\\uDC00 \\uD800\\uDC00abc abc\\uD800\\uDC00 \\uD800\\uD800\\uDC00 \\uD800\\uDC00\\uDC00", + "\\uD800\\uDC00", NULL, UCOL_TERTIARY, NULL, {4, 13, 22, 26, 29, -1}, + {2, 2, 2, 2, 2}}, + {"and\\uD834\\uDDB9this sentence", "\\uD834\\uDDB9", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {2}}, + {"and \\uD834\\uDDB9 this sentence", " \\uD834\\uDDB9 ", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and-\\uD834\\uDDB9-this sentence", "-\\uD834\\uDDB9-", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and,\\uD834\\uDDB9,this sentence", ",\\uD834\\uDDB9,", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and?\\uD834\\uDDB9?this sentence", "?\\uD834\\uDDB9?", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const char *CONTRACTIONRULE = + "&z = ab/c < AB < X\\u0300 < ABC < X\\u0300\\u0315"; + +static const SearchData CONTRACTION[] = { + /* common discontiguous */ + {"A\\u0300\\u0315", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"A\\u0300\\u0315", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + /* contraction prefix */ + {"AB\\u0315C", "A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"AB\\u0315C", "AB", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"AB\\u0315C", "\\u0315", NULL, UCOL_TERTIARY, NULL, {2, -1}, {1}}, + /* discontiguous problem here for backwards iteration. + accents not found because discontiguous stores all information */ + {"X\\u0300\\u0319\\u0315", "\\u0319", NULL, UCOL_TERTIARY, NULL, {-1}, + {0}}, + /* ends not with a contraction character */ + {"X\\u0315\\u0300D", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {-1}, + {0}}, + {"X\\u0315\\u0300D", "X\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, + {0, -1}, {3}}, + {"X\\u0300\\u031A\\u0315D", "X\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, + {0}}, + /* blocked discontiguous */ + {"X\\u0300\\u031A\\u0315D", "\\u031A\\u0315D", NULL, UCOL_TERTIARY, NULL, + {-1}, {0}}, + {"ab", "z", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const char *IGNORABLERULE = "&a = \\u0300"; + +static const SearchData IGNORABLE[] = { + {"\\u0300\\u0315 \\u0300\\u0315 ", "\\u0300", NULL, UCOL_PRIMARY, NULL, + {0, 3, -1}, {2, 2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData BASICCANONICAL[] = { + {"xxxxxxxxxxxxxxxxxxxx", "fisher", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"silly spring string", "string", NULL, UCOL_TERTIARY, NULL, {13, -1}, + {6}}, + {"silly spring string string", "string", NULL, UCOL_TERTIARY, NULL, + {13, 20, -1}, {6, 6}}, + {"silly string spring string", "string", NULL, UCOL_TERTIARY, NULL, + {6, 20, -1}, {6, 6}}, + {"string spring string", "string", NULL, UCOL_TERTIARY, NULL, {0, 14, -1}, + {6, 6}}, + {"Scott Ganyo", "c", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"Scott Ganyo", " ", NULL, UCOL_TERTIARY, NULL, {5, -1}, {1}}, + {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}}, + {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + {"a\\u0300b", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"a\\u0300\\u0325b", "\\u0300b", NULL, UCOL_TERTIARY, NULL, {1, -1}, {3}}, + {"\\u0325\\u0300A\\u0325\\u0300", "\\u0300A\\u0300", NULL, UCOL_TERTIARY, + NULL, {0, -1}, {5}}, + {"\\u0325\\u0300A\\u0325\\u0300", "\\u0325A\\u0325", NULL, UCOL_TERTIARY, + NULL, {0, -1}, {5}}, + {"a\\u0300\\u0325b\\u0300\\u0325c \\u0325b\\u0300 \\u0300b\\u0325", + "\\u0300b\\u0325", NULL, UCOL_TERTIARY, NULL, {1, 12, -1}, {5, 3}}, + {"\\u00c4\\u0323", "A\\u0323\\u0308", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"\\u0308\\u0323", "\\u0323\\u0308", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData NORMCANONICAL[] = { + {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"\\u0300\\u0325", "\\u0325", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + {"a\\u0300\\u0325", "\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}}, + {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData BREAKITERATORCANONICAL[] = { + {"foxy fox", "fox", NULL, UCOL_TERTIARY, "characterbreaker", {0, 5, -1}, + {3, 3}}, + {"foxy fox", "fox", NULL, UCOL_TERTIARY, "wordbreaker", {5, -1}, {3}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, + "characterbreaker", {10, 14, -1}, {3, 2}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, "wordbreaker", + {10, -1}, {3}}, + {"Channel, another channel, more channels, and one last Channel", + "Channel", "es", UCOL_TERTIARY, "wordbreaker", {0, 54, -1}, {7, 7}}, + /* jitterbug 1745 */ + {"testing that \\u00e9 does not match e", "e", NULL, UCOL_TERTIARY, + "characterbreaker", {1, 17, 30, -1}, {1, 1, 1}}, + {"testing that string ab\\u00e9cd does not match e", "e", NULL, + UCOL_TERTIARY, "characterbreaker", {1, 28, 41, -1}, {1, 1, 1}}, + {"\\u00c9", "e", "fr", UCOL_PRIMARY, "characterbreaker", {0, -1}, {1}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData STRENGTHCANONICAL[] = { + /*012345678901234567890123456789012345678901234567890123456789 */ + {"The quick brown fox jumps over the lazy foxes", "fox", "en", + UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}}, + {"The quick brown fox jumps over the lazy foxes", "fox", "en", + UCOL_PRIMARY, "wordbreaker", {16, -1}, {3}}, + {"blackbirds Pat p\\u00E9ch\\u00E9 p\\u00EAche p\\u00E9cher p\\u00EAcher Tod T\\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe", + "peche", "fr", UCOL_PRIMARY, NULL, {15, 21, 27, 34, -1}, {5, 5, 5, 5}}, + {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, NULL, + {10, 14, -1}, {3, 2}}, + {"A channel, another CHANNEL, more Channels, and one last channel...", + "channel", "es", UCOL_PRIMARY, NULL, {2, 19, 33, 56, -1}, + {7, 7, 7, 7}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData VARIABLECANONICAL[] = { + /*012345678901234567890123456789012345678901234567890123456789 */ + {"blackbirds black blackbirds blackbird black-bird", + "blackbird", NULL, UCOL_TERTIARY, NULL, {0, 17, 28, 38, -1}, + {9, 9, 9, 10}}, + /* to see that it doesn't go into an infinite loop if the start of text + is a ignorable character */ + {" on", "go", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"abcdefghijklmnopqrstuvwxyz", " ", NULL, UCOL_PRIMARY, NULL, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + /* testing tightest match */ + {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_QUATERNARY, + NULL, {1, -1}, {3}}, + /*012345678901234567890123456789012345678901234567890123456789 */ + {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_SECONDARY, + NULL, {1, 6, 13, 21, 31, -1}, {3, 4, 4, 5, 5}}, + /* totally ignorable text */ + {" ---------------", "abc", NULL, UCOL_SECONDARY, + NULL, {-1}, {0}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData OVERLAPCANONICAL[] = { + {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 2, 4, -1}, + {4, 4, 4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData NONOVERLAPCANONICAL[] = { + {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 4, -1}, {4, 4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData COLLATORCANONICAL[] = { + /* english */ + {"fox fpx", "fox", NULL, UCOL_TERTIARY, NULL, {0, -1}, {3}}, + /* tailored */ + {"fox fpx", "fox", NULL, UCOL_PRIMARY, NULL, {0, 4, -1}, {3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData PATTERNCANONICAL[] = { + {"The quick brown fox jumps over the lazy foxes", "the", NULL, + UCOL_PRIMARY, NULL, {0, 31, -1}, {3, 3}}, + {"The quick brown fox jumps over the lazy foxes", "fox", NULL, + UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData TEXTCANONICAL[] = { + {"the foxy brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {4, 15, -1}, + {3, 3}}, + {"the quick brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {16, -1}, + {3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData COMPOSITEBOUNDARIESCANONICAL[] = { + {"\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u00C0C", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}}, + {"\\u00C0A", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}}, + {"B\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"\\u00C0B", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0300\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, + {1, 1}}, + /* \\u0300 blocked by \\u0300 */ + {"\\u00C0\\u0300", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + /* A + 030A + 0301 */ + {"\\u01FA", "\\u01FA", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u01FA", "\\u030A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u01FA", "\\u030AA", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + /* blocked accent */ + {"\\u01FA", "A\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"\\u01FA", "\\u030A\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}}, + {"\\u01FAA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"\\u0F73", "\\u0F73", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0F73", "\\u0F71", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0F73", "\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"\\u0F73", "\\u0F71\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}}, + {"A\\u0F73", "A\\u0F71", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"\\u0F73A", "\\u0F72A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"\\u01FA A\\u0301\\u030A A\\u030A\\u0301 A\\u030A \\u01FA", "A\\u030A", + NULL, UCOL_TERTIARY, NULL, {0, 6, 10, 13, -1}, {1, 3, 2, 1}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData MATCHCANONICAL[] = { + {"a busy bee is a very busy beeee", "bee", NULL, UCOL_TERTIARY, NULL, + {7, 26, -1}, {3, 3}}, + /*012345678901234567890123456789012345678901234567890 */ + {"a busy bee is a very busy beeee with no bee life", "bee", NULL, + UCOL_TERTIARY, NULL, {7, 26, 40, -1}, {3, 3, 3}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData SUPPLEMENTARYCANONICAL[] = { + /*012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890012345678901234567890123456789 */ + {"abc \\uD800\\uDC00 \\uD800\\uDC01 \\uD801\\uDC00 \\uD800\\uDC00abc abc\\uD800\\uDC00 \\uD800\\uD800\\uDC00 \\uD800\\uDC00\\uDC00", + "\\uD800\\uDC00", NULL, UCOL_TERTIARY, NULL, {4, 13, 22, 26, 29, -1}, + {2, 2, 2, 2, 2}}, + {"and\\uD834\\uDDB9this sentence", "\\uD834\\uDDB9", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {2}}, + {"and \\uD834\\uDDB9 this sentence", " \\uD834\\uDDB9 ", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and-\\uD834\\uDDB9-this sentence", "-\\uD834\\uDDB9-", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and,\\uD834\\uDDB9,this sentence", ",\\uD834\\uDDB9,", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {"and?\\uD834\\uDDB9?this sentence", "?\\uD834\\uDDB9?", NULL, + UCOL_TERTIARY, NULL, {3, -1}, {4}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData CONTRACTIONCANONICAL[] = { + /* common discontiguous */ + {"A\\u0300\\u0315", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}}, + {"A\\u0300\\u0315", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {1, -1}, + {2}}, + /* contraction prefix */ + {"AB\\u0315C", "A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}}, + {"AB\\u0315C", "AB", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {"AB\\u0315C", "\\u0315", NULL, UCOL_TERTIARY, NULL, {2, -1}, {1}}, + /* discontiguous problem here for backwards iteration. + forwards gives 0, 4 but backwards give 1, 3 */ + /* {"X\\u0300\\u0319\\u0315", "\\u0319", NULL, UCOL_TERTIARY, NULL, {0, -1}, + {4}}, */ + + /* ends not with a contraction character */ + {"X\\u0315\\u0300D", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {-1}, + {0}}, + {"X\\u0315\\u0300D", "X\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, + {0, -1}, {3}}, + {"X\\u0300\\u031A\\u0315D", "X\\u0300", NULL, UCOL_TERTIARY, NULL, + {0, -1}, {4}}, + /* blocked discontiguous */ + {"X\\u0300\\u031A\\u0315D", "\\u031A\\u0315D", NULL, UCOL_TERTIARY, NULL, + {1, -1}, {4}}, + {"ab", "z", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +static const SearchData DIACTRICMATCH[] = { + {"\\u03BA\\u03B1\\u03B9\\u0300\\u0020\\u03BA\\u03B1\\u1F76", "\\u03BA\\u03B1\\u03B9", NULL, UCOL_PRIMARY, NULL, {0, 5,-1}, {4, 3}}, + {"\\u0061\\u0061\\u00E1", "\\u0061\\u00E1", NULL, UCOL_SECONDARY, NULL, {1, -1}, {2}}, + {"\\u0020\\u00C2\\u0303\\u0020\\u0041\\u0061\\u1EAA\\u0041\\u0302\\u0303\\u00C2\\u0303\\u1EAB\\u0061\\u0302\\u0303\\u00E2\\u0303\\uD806\\uDC01\\u0300\\u0020", + "\\u00C2\\u0303", "LDE_AN_CX_EX_FX_HX_NX_S1", UCOL_PRIMARY, NULL, {1, 4, 5, 6, 7, 10, 12, 13, 16,-1}, {2, 1, 1, 1, 3, 2, 1, 3, 2}}, + {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}} +}; + +#endif /* #if !UCONFIG_NO_COLLATION */ + +#endif diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c new file mode 100644 index 00000000000..80a9f9247da --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c @@ -0,0 +1,2249 @@ +/******************************************************************** + * Copyright (c) 2001-2007 International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************** + * File usrchtst.c + * Modification History: + * Name Date Description + * synwee July 19 2001 creation + ********************************************************************/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/usearch.h" +#include "unicode/ustring.h" +#include "ccolltst.h" +#include "cmemory.h" +#include <stdio.h> +#include "usrchdat.c" +#include "unicode/ubrk.h" + +static UBool TOCLOSE_ = TRUE; +static UCollator *EN_US_; +static UCollator *FR_FR_; +static UCollator *DE_; +static UCollator *ES_; + +/** + * CHECK_BREAK(char *brk) + * Test if a break iterator is passed in AND break iteration is disabled. + * Skip the test if so. + * CHECK_BREAK_BOOL(char *brk) + * Same as above, but returns 'TRUE' as a passing result + */ + +#if !UCONFIG_NO_BREAK_ITERATION +static UBreakIterator *EN_WORDBREAKER_; +static UBreakIterator *EN_CHARACTERBREAKER_; +#define CHECK_BREAK(x) +#define CHECK_BREAK_BOOL(x) +#else +#define CHECK_BREAK(x) if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return; } +#define CHECK_BREAK_BOOL(x) if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return TRUE; } +#endif + +/** +* Opening all static collators and break iterators +*/ +static void open(void) +{ + if (TOCLOSE_) { + UErrorCode status = U_ZERO_ERROR; + UChar rules[1024]; + int32_t rulelength = 0; + + EN_US_ = ucol_open("en_US", &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator\n"); + return; + } + FR_FR_ = ucol_open("fr_FR", &status); + DE_ = ucol_open("de_DE", &status); + ES_ = ucol_open("es_ES", &status); + + u_strcpy(rules, ucol_getRules(DE_, &rulelength)); + u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength); + + ucol_close(DE_); + + DE_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY, + (UParseError *)NULL, &status); + u_strcpy(rules, ucol_getRules(ES_, &rulelength)); + u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength); + + ucol_close(ES_); + ES_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY, + NULL, &status); +#if !UCONFIG_NO_BREAK_ITERATION + EN_WORDBREAKER_ = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status); + EN_CHARACTERBREAKER_ = ubrk_open(UBRK_CHARACTER, "en_US", NULL, 0, + &status); +#endif + TOCLOSE_ = TRUE; + } +} + +/** +* Start opening all static collators and break iterators +*/ +static void TestStart(void) +{ + open(); + TOCLOSE_ = FALSE; +} + +/** +* Closing all static collators and break iterators +*/ +static void close(void) +{ + if (TOCLOSE_) { + ucol_close(EN_US_); + ucol_close(FR_FR_); + ucol_close(DE_); + ucol_close(ES_); +#if !UCONFIG_NO_BREAK_ITERATION + ubrk_close(EN_WORDBREAKER_); + ubrk_close(EN_CHARACTERBREAKER_); +#endif + } + TOCLOSE_ = FALSE; +} + +/** +* End closing all static collators and break iterators +*/ +static void TestEnd(void) +{ + TOCLOSE_ = TRUE; + close(); + TOCLOSE_ = TRUE; +} + +/** +* output UChar strings for printing. +*/ +static char *toCharString(const UChar* unichars) +{ + static char result[1024]; + char *temp = result; + int count = 0; + int length = u_strlen(unichars); + + for (; count < length; count ++) { + UChar ch = unichars[count]; + if (ch >= 0x20 && ch <= 0x7e) { + *temp ++ = (char)ch; + } + else { + sprintf(temp, "\\u%04x", ch); + temp += 6; /* \uxxxx */ + } + } + *temp = 0; + + return result; +} + +/** +* Getting the collator +*/ +static UCollator *getCollator(const char *collator) +{ + if (collator == NULL) { + return EN_US_; + } + if (strcmp(collator, "fr") == 0) { + return FR_FR_; + } + else if (strcmp(collator, "de") == 0) { + return DE_; + } + else if (strcmp(collator, "es") == 0) { + return ES_; + } + else { + return EN_US_; + } +} + +/** +* Getting the breakiterator +*/ +static UBreakIterator *getBreakIterator(const char *breaker) +{ + if (breaker == NULL) { + return NULL; + } +#if !UCONFIG_NO_BREAK_ITERATION + if (strcmp(breaker, "wordbreaker") == 0) { + return EN_WORDBREAKER_; + } + else { + return EN_CHARACTERBREAKER_; + } +#else + return NULL; +#endif +} + +static void TestOpenClose(void) +{ + UErrorCode status = U_ZERO_ERROR; + UStringSearch *result; + const UChar pattern[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; + const UChar text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67}; +#if !UCONFIG_NO_BREAK_ITERATION + UBreakIterator *breakiter = ubrk_open(UBRK_WORD, "en_US", + text, 6, &status); +#endif + /* testing null arguments */ + result = usearch_open(NULL, 0, NULL, 0, NULL, NULL, &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + status = U_ZERO_ERROR; + result = usearch_openFromCollator(NULL, 0, NULL, 0, NULL, NULL, &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + + status = U_ZERO_ERROR; + result = usearch_open(pattern, 3, NULL, 0, NULL, NULL, &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + status = U_ZERO_ERROR; + result = usearch_openFromCollator(pattern, 3, NULL, 0, NULL, NULL, + &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + + status = U_ZERO_ERROR; + result = usearch_open(pattern, 3, text, 6, NULL, NULL, &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + status = U_ZERO_ERROR; + result = usearch_openFromCollator(pattern, 3, text, 6, NULL, NULL, + &status); + if (U_SUCCESS(status) || result != NULL) { + log_err("Error: NULL arguments should produce an error and a NULL result\n"); + } + + status = U_ZERO_ERROR; + result = usearch_open(pattern, 3, text, 6, "en_US", NULL, &status); + if (U_FAILURE(status) || result == NULL) { + log_err("Error: NULL break iterator is valid for opening search\n"); + } + else { + usearch_close(result); + } + open(); + status = U_ZERO_ERROR; + result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, NULL, + &status); + if (U_FAILURE(status) || result == NULL) { + log_err("Error: NULL break iterator is valid for opening search\n"); + } + else { + usearch_close(result); + } + + + status = U_ZERO_ERROR; +#if !UCONFIG_NO_BREAK_ITERATION + + result = usearch_open(pattern, 3, text, 6, "en_US", breakiter, &status); + if (U_FAILURE(status) || result == NULL) { + log_err("Error: Break iterator is valid for opening search\n"); + } + else { + usearch_close(result); + } + status = U_ZERO_ERROR; + result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, breakiter, + &status); + if (U_FAILURE(status) || result == NULL) { + log_err("Error: Break iterator is valid for opening search\n"); + } + else { + usearch_close(result); + } + ubrk_close(breakiter); +#endif + close(); +} + +static void TestInitialization(void) +{ + UErrorCode status = U_ZERO_ERROR; + UChar pattern[512]; + const UChar text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; + int32_t i = 0; + UStringSearch *result; + + /* simple test on the pattern ce construction */ + pattern[0] = 0x41; + pattern[1] = 0x42; + open(); + result = usearch_openFromCollator(pattern, 2, text, 3, EN_US_, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening search %s\n", u_errorName(status)); + } + usearch_close(result); + + /* testing if an extremely large pattern will fail the initialization */ + for(i = 0; i < 512; i++) { + pattern[i] = 0x41; + } + /*uprv_memset(pattern, 0x41, 512);*/ + result = usearch_openFromCollator(pattern, 512, text, 3, EN_US_, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening search %s\n", u_errorName(status)); + } + usearch_close(result); + close(); +} + +static UBool assertEqualWithUStringSearch( UStringSearch *strsrch, + const SearchData search) +{ + int count = 0; + int matchlimit = 0; + UErrorCode status = U_ZERO_ERROR; + int32_t matchindex = search.offset[count]; + int32_t textlength; + UChar matchtext[128]; + + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || + usearch_getMatchedLength(strsrch) != 0) { + log_err("Error with the initialization of match start and length\n"); + } + /* start of following matches */ + while (U_SUCCESS(status) && matchindex >= 0) { + uint32_t matchlength = search.size[count]; + usearch_next(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error following match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return FALSE; + } + count ++; + + if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != + (int32_t) matchlength || U_FAILURE(status) || + memcmp(matchtext, + usearch_getText(strsrch, &textlength) + matchindex, + matchlength * sizeof(UChar)) != 0) { + log_err("Error getting following matched text\n"); + } + + matchindex = search.offset[count]; + } + usearch_next(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || + usearch_getMatchedLength(strsrch) != 0) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error following match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return FALSE; + } + /* start of preceding matches */ + count = count == 0 ? 0 : count - 1; + matchlimit = count; + matchindex = search.offset[count]; + + while (U_SUCCESS(status) && matchindex >= 0) { + uint32_t matchlength = search.size[count]; + usearch_previous(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error preceding match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return FALSE; + } + + if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != + (int32_t) matchlength || U_FAILURE(status) || + memcmp(matchtext, + usearch_getText(strsrch, &textlength) + matchindex, + matchlength * sizeof(UChar)) != 0) { + log_err("Error getting preceding matched text\n"); + } + + matchindex = count > 0 ? search.offset[count - 1] : -1; + count --; + } + usearch_previous(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || + usearch_getMatchedLength(strsrch) != 0) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error preceding match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return FALSE; + } + + return TRUE; +} + +static UBool assertEqual(const SearchData search) +{ + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UCollator *collator = getCollator(search.collator); + UBreakIterator *breaker = getBreakIterator(search.breaker); + UStringSearch *strsrch; + + CHECK_BREAK_BOOL(search.breaker); + + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + ucol_setStrength(collator, search.strength); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + breaker, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + return FALSE; + } + + if (!assertEqualWithUStringSearch(strsrch, search)) { + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return FALSE; + } + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return TRUE; +} + +static UBool assertCanonicalEqual(const SearchData search) +{ + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UCollator *collator = getCollator(search.collator); + UBreakIterator *breaker = getBreakIterator(search.breaker); + UStringSearch *strsrch; + + CHECK_BREAK_BOOL(search.breaker); + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + ucol_setStrength(collator, search.strength); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + breaker, &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + return FALSE; + } + + if (!assertEqualWithUStringSearch(strsrch, search)) { + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return FALSE; + } + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return TRUE; +} + +static UBool assertEqualWithAttribute(const SearchData search, + USearchAttributeValue canonical, + USearchAttributeValue overlap) +{ + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UCollator *collator = getCollator(search.collator); + UBreakIterator *breaker = getBreakIterator(search.breaker); + UStringSearch *strsrch; + + CHECK_BREAK_BOOL(search.breaker); + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + ucol_setStrength(collator, search.strength); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + breaker, &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, canonical, + &status); + usearch_setAttribute(strsrch, USEARCH_OVERLAP, overlap, &status); + + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + return FALSE; + } + + if (!assertEqualWithUStringSearch(strsrch, search)) { + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return FALSE; + } + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + return TRUE; +} + +static void TestBasic(void) +{ + int count = 0; + open(); + while (BASIC[count].text != NULL) { + if (!assertEqual(BASIC[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestNormExact(void) +{ + int count = 0; + UErrorCode status = U_ZERO_ERROR; + open(); + ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + if (U_FAILURE(status)) { + log_err("Error setting collation normalization %s\n", + u_errorName(status)); + } + while (BASIC[count].text != NULL) { + if (!assertEqual(BASIC[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + count = 0; + while (NORMEXACT[count].text != NULL) { + if (!assertEqual(NORMEXACT[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); + count = 0; + while (NONNORMEXACT[count].text != NULL) { + if (!assertEqual(NONNORMEXACT[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestStrength(void) +{ + int count = 0; + open(); + while (STRENGTH[count].text != NULL) { + if (!assertEqual(STRENGTH[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestBreakIterator(void) { + UErrorCode status = U_ZERO_ERROR; + UStringSearch *strsrch; + UChar text[128]; + UChar pattern[32]; + int count = 0; + + CHECK_BREAK("x"); + +#if !UCONFIG_NO_BREAK_ITERATION + open(); + if (usearch_getBreakIterator(NULL) != NULL) { + log_err("Expected NULL breakiterator from NULL string search\n"); + } + u_unescape(BREAKITERATOREXACT[0].text, text, 128); + u_unescape(BREAKITERATOREXACT[0].pattern, pattern, 32); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + goto ENDTESTBREAKITERATOR; + } + + usearch_setBreakIterator(strsrch, NULL, &status); + if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != NULL) { + log_err("Error usearch_getBreakIterator returned wrong object"); + goto ENDTESTBREAKITERATOR; + } + + usearch_setBreakIterator(strsrch, EN_CHARACTERBREAKER_, &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != EN_CHARACTERBREAKER_) { + log_err("Error usearch_getBreakIterator returned wrong object"); + goto ENDTESTBREAKITERATOR; + } + + usearch_setBreakIterator(strsrch, EN_WORDBREAKER_, &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != EN_WORDBREAKER_) { + log_err("Error usearch_getBreakIterator returned wrong object"); + goto ENDTESTBREAKITERATOR; + } + + usearch_close(strsrch); + + count = 0; + while (count < 4) { + /* 0-3 test are fixed */ + const SearchData *search = &(BREAKITERATOREXACT[count]); + UCollator *collator = getCollator(search->collator); + UBreakIterator *breaker = getBreakIterator(search->breaker); + + u_unescape(search->text, text, 128); + u_unescape(search->pattern, pattern, 32); + ucol_setStrength(collator, search->strength); + + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + breaker, &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != breaker) { + log_err("Error setting break iterator\n"); + if (strsrch != NULL) { + usearch_close(strsrch); + } + } + if (!assertEqualWithUStringSearch(strsrch, *search)) { + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + goto ENDTESTBREAKITERATOR; + } + search = &(BREAKITERATOREXACT[count + 1]); + breaker = getBreakIterator(search->breaker); + usearch_setBreakIterator(strsrch, breaker, &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != breaker) { + log_err("Error setting break iterator\n"); + usearch_close(strsrch); + goto ENDTESTBREAKITERATOR; + } + usearch_reset(strsrch); + if (!assertEqualWithUStringSearch(strsrch, *search)) { + log_err("Error at test number %d\n", count); + goto ENDTESTBREAKITERATOR; + } + usearch_close(strsrch); + count += 2; + } + count = 0; + while (BREAKITERATOREXACT[count].text != NULL) { + if (!assertEqual(BREAKITERATOREXACT[count])) { + log_err("Error at test number %d\n", count); + goto ENDTESTBREAKITERATOR; + } + count ++; + } + +ENDTESTBREAKITERATOR: + close(); +#endif +} + +static void TestVariable(void) +{ + int count = 0; + UErrorCode status = U_ZERO_ERROR; + open(); + ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + if (U_FAILURE(status)) { + log_err("Error setting collation alternate attribute %s\n", + u_errorName(status)); + } + while (VARIABLE[count].text != NULL) { + log_verbose("variable %d\n", count); + if (!assertEqual(VARIABLE[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, + UCOL_NON_IGNORABLE, &status); + close(); +} + +static void TestOverlap(void) +{ + int count = 0; + open(); + while (OVERLAP[count].text != NULL) { + if (!assertEqualWithAttribute(OVERLAP[count], USEARCH_OFF, + USEARCH_ON)) { + log_err("Error at overlap test number %d\n", count); + } + count ++; + } + count = 0; + while (NONOVERLAP[count].text != NULL) { + if (!assertEqual(NONOVERLAP[count])) { + log_err("Error at non overlap test number %d\n", count); + } + count ++; + } + + count = 0; + while (count < 1) { + UChar pattern[32]; + UChar text[128]; + const SearchData *search = &(OVERLAP[count]); + UCollator *collator = getCollator(search->collator); + UStringSearch *strsrch; + UErrorCode status = U_ZERO_ERROR; + + u_unescape(search->text, text, 128); + u_unescape(search->pattern, pattern, 32); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) { + log_err("Error setting overlap option\n"); + } + if (!assertEqualWithUStringSearch(strsrch, *search)) { + usearch_close(strsrch); + return; + } + search = &(NONOVERLAP[count]); + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) { + log_err("Error setting overlap option\n"); + } + usearch_reset(strsrch); + if (!assertEqualWithUStringSearch(strsrch, *search)) { + usearch_close(strsrch); + log_err("Error at test number %d\n", count); + } + + count ++; + usearch_close(strsrch); + } + close(); +} + +static void TestCollator(void) +{ + /* test collator that thinks "o" and "p" are the same thing */ + UChar rules[32]; + UCollator *tailored = NULL; + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UStringSearch *strsrch; + + text[0] = 0x41; + text[1] = 0x42; + text[2] = 0x43; + text[3] = 0x44; + text[4] = 0x45; + pattern[0] = 0x62; + pattern[1] = 0x63; + strsrch = usearch_open(pattern, 2, text, 5, "en_US", NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + tailored = usearch_getCollator(strsrch); + if (usearch_next(strsrch, &status) != -1) { + log_err("Error: Found case insensitive match, when we shouldn't\n"); + } + ucol_setStrength(tailored, UCOL_PRIMARY); + usearch_reset(strsrch); + if (usearch_next(strsrch, &status) != 1) { + log_err("Error: Found case insensitive match not found\n"); + } + usearch_close(strsrch); + + open(); + + if (usearch_getCollator(NULL) != NULL) { + log_err("Expected NULL collator from NULL string search\n"); + } + u_unescape(COLLATOR[0].text, text, 128); + u_unescape(COLLATOR[0].pattern, pattern, 32); + + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) { + goto ENDTESTCOLLATOR; + } + + u_unescape(TESTCOLLATORRULE, rules, 32); + tailored = ucol_openRules(rules, -1, UCOL_ON, COLLATOR[1].strength, + NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening rule based collator %s\n", u_errorName(status)); + } + + usearch_setCollator(strsrch, tailored, &status); + if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) { + log_err("Error setting rule based collator\n"); + } + usearch_reset(strsrch); + if (!assertEqualWithUStringSearch(strsrch, COLLATOR[1])) { + goto ENDTESTCOLLATOR; + } + + usearch_setCollator(strsrch, EN_US_, &status); + usearch_reset(strsrch); + if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) { + log_err("Error setting rule based collator\n"); + } + if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) { + goto ENDTESTCOLLATOR; + } + +ENDTESTCOLLATOR: + usearch_close(strsrch); + if (tailored != NULL) { + ucol_close(tailored); + } + close(); +} + +static void TestPattern(void) +{ + UStringSearch *strsrch; + UChar pattern[32]; + UChar bigpattern[512]; + UChar text[128]; + const UChar *temp; + int32_t templength; + UErrorCode status = U_ZERO_ERROR; + + open(); + if (usearch_getPattern(NULL, &templength) != NULL) { + log_err("Error NULL string search expected returning NULL pattern\n"); + } + usearch_setPattern(NULL, pattern, 3, &status); + if (U_SUCCESS(status)) { + log_err("Error expected setting pattern in NULL strings search\n"); + } + status = U_ZERO_ERROR; + u_unescape(PATTERN[0].text, text, 128); + u_unescape(PATTERN[0].pattern, pattern, 32); + + ucol_setStrength(EN_US_, PATTERN[0].strength); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + + status = U_ZERO_ERROR; + usearch_setPattern(strsrch, NULL, 3, &status); + if (U_SUCCESS(status)) { + log_err("Error expected setting NULL pattern in strings search\n"); + } + status = U_ZERO_ERROR; + usearch_setPattern(strsrch, pattern, 0, &status); + if (U_SUCCESS(status)) { + log_err("Error expected setting pattern with length 0 in strings search\n"); + } + status = U_ZERO_ERROR; + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + goto ENDTESTPATTERN; + } + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) { + goto ENDTESTPATTERN; + } + + u_unescape(PATTERN[1].pattern, pattern, 32); + usearch_setPattern(strsrch, pattern, -1, &status); + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + goto ENDTESTPATTERN; + } + usearch_reset(strsrch); + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERN[1])) { + goto ENDTESTPATTERN; + } + + u_unescape(PATTERN[0].pattern, pattern, 32); + usearch_setPattern(strsrch, pattern, -1, &status); + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + goto ENDTESTPATTERN; + } + usearch_reset(strsrch); + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) { + goto ENDTESTPATTERN; + } + /* enormous pattern size to see if this crashes */ + for (templength = 0; templength != 512; templength ++) { + bigpattern[templength] = 0x61; + } + bigpattern[511] = 0; + usearch_setPattern(strsrch, bigpattern, -1, &status); + if (U_FAILURE(status)) { + log_err("Error setting pattern with size 512, %s \n", + u_errorName(status)); + } +ENDTESTPATTERN: + ucol_setStrength(EN_US_, UCOL_TERTIARY); + if (strsrch != NULL) { + usearch_close(strsrch); + } + close(); +} + +static void TestText(void) +{ + UStringSearch *strsrch; + UChar pattern[32]; + UChar text[128]; + const UChar *temp; + int32_t templength; + UErrorCode status = U_ZERO_ERROR; + + u_unescape(TEXT[0].text, text, 128); + u_unescape(TEXT[0].pattern, pattern, 32); + + open(); + + if (usearch_getText(NULL, &templength) != NULL) { + log_err("Error NULL string search should return NULL text\n"); + } + + usearch_setText(NULL, text, 10, &status); + if (U_SUCCESS(status)) { + log_err("Error NULL string search should have an error when setting text\n"); + } + + status = U_ZERO_ERROR; + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + goto ENDTESTPATTERN; + } + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + } + if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) { + goto ENDTESTPATTERN; + } + + u_unescape(TEXT[1].text, text, 32); + usearch_setText(strsrch, text, -1, &status); + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + goto ENDTESTPATTERN; + } + if (U_FAILURE(status)) { + log_err("Error setting text %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, TEXT[1])) { + goto ENDTESTPATTERN; + } + + u_unescape(TEXT[0].text, text, 32); + usearch_setText(strsrch, text, -1, &status); + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + goto ENDTESTPATTERN; + } + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) { + goto ENDTESTPATTERN; + } +ENDTESTPATTERN: + if (strsrch != NULL) { + usearch_close(strsrch); + } + close(); +} + +static void TestCompositeBoundaries(void) +{ + int count = 0; + open(); + while (COMPOSITEBOUNDARIES[count].text != NULL) { + log_verbose("composite %d\n", count); + if (!assertEqual(COMPOSITEBOUNDARIES[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestGetSetOffset(void) +{ + int index = 0; + UChar pattern[32]; + UChar text[128]; + UErrorCode status = U_ZERO_ERROR; + UStringSearch *strsrch; + memset(pattern, 0, 32*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + open(); + if (usearch_getOffset(NULL) != USEARCH_DONE) { + log_err("usearch_getOffset(NULL) expected USEARCH_DONE\n"); + } + strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL, + &status); + /* testing out of bounds error */ + usearch_setOffset(strsrch, -1, &status); + if (U_SUCCESS(status)) { + log_err("Error expecting set offset error\n"); + } + usearch_setOffset(strsrch, 128, &status); + if (U_SUCCESS(status)) { + log_err("Error expecting set offset error\n"); + } + while (BASIC[index].text != NULL) { + int count = 0; + SearchData search = BASIC[index ++]; + int32_t matchindex = search.offset[count]; + int32_t textlength; + + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + status = U_ZERO_ERROR; + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + ucol_setStrength(usearch_getCollator(strsrch), search.strength); + usearch_reset(strsrch); + while (U_SUCCESS(status) && matchindex >= 0) { + uint32_t matchlength = search.size[count]; + usearch_next(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, + &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + usearch_setOffset(strsrch, matchindex + matchlength, &status); + usearch_previous(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, + &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + usearch_setOffset(strsrch, matchindex + matchlength, &status); + matchindex = search.offset[count + 1] == -1 ? -1 : + search.offset[count + 2]; + if (search.offset[count + 1] != -1) { + usearch_setOffset(strsrch, search.offset[count + 1] + 1, + &status); + if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) { + log_err("Error setting offset\n"); + return; + } + } + + count += 2; + } + usearch_next(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + } + ucol_setStrength(usearch_getCollator(strsrch), UCOL_TERTIARY); + usearch_close(strsrch); + close(); +} + +static void TestGetSetAttribute(void) +{ + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UStringSearch *strsrch; + + memset(pattern, 0, 32*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + open(); + if (usearch_getAttribute(NULL, USEARCH_OVERLAP) != USEARCH_DEFAULT || + usearch_getAttribute(NULL, USEARCH_CANONICAL_MATCH) != + USEARCH_DEFAULT) { + log_err( + "Attributes for NULL string search should be USEARCH_DEFAULT\n"); + } + strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening search %s\n", u_errorName(status)); + return; + } + + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_DEFAULT, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) { + log_err("Error setting overlap to the default\n"); + } + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) { + log_err("Error setting overlap true\n"); + } + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) { + log_err("Error setting overlap false\n"); + } + usearch_setAttribute(strsrch, USEARCH_OVERLAP, + USEARCH_ATTRIBUTE_VALUE_COUNT, &status); + if (U_SUCCESS(status)) { + log_err("Error setting overlap to illegal value\n"); + } + status = U_ZERO_ERROR; + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT, + &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) != + USEARCH_OFF) { + log_err("Error setting canonical match to the default\n"); + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) != + USEARCH_ON) { + log_err("Error setting canonical match true\n"); + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_OFF, + &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) != + USEARCH_OFF) { + log_err("Error setting canonical match false\n"); + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, + USEARCH_ATTRIBUTE_VALUE_COUNT, &status); + if (U_SUCCESS(status)) { + log_err("Error setting canonical match to illegal value\n"); + } + status = U_ZERO_ERROR; + usearch_setAttribute(strsrch, USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT, + &status); + if (U_SUCCESS(status)) { + log_err("Error setting illegal attribute success\n"); + } + + usearch_close(strsrch); + close(); +} + +static void TestGetMatch(void) +{ + int count = 0; + UErrorCode status = U_ZERO_ERROR; + UChar text[128]; + UChar pattern[32]; + SearchData search = MATCH[0]; + int32_t matchindex = search.offset[count]; + UStringSearch *strsrch; + int32_t textlength; + UChar matchtext[128]; + + open(); + + if (usearch_getMatchedStart(NULL) != USEARCH_DONE || + usearch_getMatchedLength(NULL) != USEARCH_DONE) { + log_err( + "Expected start and length of NULL string search should be USEARCH_DONE\n"); + } + + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + if (strsrch != NULL) { + usearch_close(strsrch); + } + return; + } + + while (U_SUCCESS(status) && matchindex >= 0) { + int32_t matchlength = search.size[count]; + usearch_next(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + count ++; + + status = U_ZERO_ERROR; + if (usearch_getMatchedText(NULL, matchtext, 128, &status) != + USEARCH_DONE || U_SUCCESS(status)){ + log_err("Error expecting errors with NULL string search\n"); + } + status = U_ZERO_ERROR; + if (usearch_getMatchedText(strsrch, NULL, 0, &status) != + (int32_t)matchlength || U_SUCCESS(status)){ + log_err("Error pre-flighting match length\n"); + } + status = U_ZERO_ERROR; + if (usearch_getMatchedText(strsrch, matchtext, 0, &status) != + (int32_t)matchlength || U_SUCCESS(status)){ + log_err("Error getting match text with buffer size 0\n"); + } + status = U_ZERO_ERROR; + if (usearch_getMatchedText(strsrch, matchtext, matchlength, &status) + != (int32_t)matchlength || matchtext[matchlength - 1] == 0 || + U_FAILURE(status)){ + log_err("Error getting match text with exact size\n"); + } + status = U_ZERO_ERROR; + if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != + (int32_t) matchlength || U_FAILURE(status) || + memcmp(matchtext, + usearch_getText(strsrch, &textlength) + matchindex, + matchlength * sizeof(UChar)) != 0 || + matchtext[matchlength] != 0) { + log_err("Error getting matched text\n"); + } + + matchindex = search.offset[count]; + } + status = U_ZERO_ERROR; + usearch_next(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE || + usearch_getMatchedLength(strsrch) != 0) { + log_err("Error end of match not found\n"); + } + status = U_ZERO_ERROR; + if (usearch_getMatchedText(strsrch, matchtext, 128, &status) != + USEARCH_DONE) { + log_err("Error getting null matches\n"); + } + usearch_close(strsrch); + close(); +} + +static void TestSetMatch(void) +{ + int count = 0; + + open(); + while (MATCH[count].text != NULL) { + SearchData search = MATCH[count]; + int size = 0; + int index = 0; + UChar text[128]; + UChar pattern[32]; + UStringSearch *strsrch; + UErrorCode status = U_ZERO_ERROR; + + if (usearch_first(NULL, &status) != USEARCH_DONE || + usearch_last(NULL, &status) != USEARCH_DONE) { + log_err("Error getting the first and last match of a NULL string search\n"); + } + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + if (strsrch != NULL) { + usearch_close(strsrch); + } + return; + } + + size = 0; + while (search.offset[size] != -1) { + size ++; + } + + if (usearch_first(strsrch, &status) != search.offset[0] || + U_FAILURE(status)) { + log_err("Error getting first match\n"); + } + if (usearch_last(strsrch, &status) != search.offset[size -1] || + U_FAILURE(status)) { + log_err("Error getting last match\n"); + } + + while (index < size) { + if (index + 2 < size) { + if (usearch_following(strsrch, search.offset[index + 2] - 1, + &status) != search.offset[index + 2] || + U_FAILURE(status)) { + log_err("Error getting following match at index %d\n", + search.offset[index + 2] - 1); + } + } + if (index + 1 < size) { + if (usearch_preceding(strsrch, search.offset[index + 1] + + search.size[index + 1] + 1, + &status) != search.offset[index + 1] || + U_FAILURE(status)) { + log_err("Error getting preceeding match at index %d\n", + search.offset[index + 1] + 1); + } + } + index += 2; + } + status = U_ZERO_ERROR; + if (usearch_following(strsrch, u_strlen(text), &status) != + USEARCH_DONE) { + log_err("Error expecting out of bounds match\n"); + } + if (usearch_preceding(strsrch, 0, &status) != USEARCH_DONE) { + log_err("Error expecting out of bounds match\n"); + } + count ++; + usearch_close(strsrch); + } + close(); +} + +static void TestReset(void) +{ + UErrorCode status = U_ZERO_ERROR; + UChar text[] = {0x66, 0x69, 0x73, 0x68, 0x20, + 0x66, 0x69, 0x73, 0x68}; + UChar pattern[] = {0x73}; + UStringSearch *strsrch; + + open(); + strsrch = usearch_openFromCollator(pattern, 1, text, 9, + EN_US_, NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + if (strsrch != NULL) { + usearch_close(strsrch); + } + return; + } + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + usearch_setOffset(strsrch, 9, &status); + if (U_FAILURE(status)) { + log_err("Error setting attributes and offsets\n"); + } + else { + usearch_reset(strsrch); + if (usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF || + usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) != + USEARCH_OFF || + usearch_getOffset(strsrch) != 0 || + usearch_getMatchedLength(strsrch) != 0 || + usearch_getMatchedStart(strsrch) != USEARCH_DONE) { + log_err("Error resetting string search\n"); + } + usearch_previous(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != 7 || + usearch_getMatchedLength(strsrch) != 1) { + log_err("Error resetting string search\n"); + } + } + usearch_close(strsrch); + close(); +} + +static void TestSupplementary(void) +{ + int count = 0; + open(); + while (SUPPLEMENTARY[count].text != NULL) { + if (!assertEqual(SUPPLEMENTARY[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestContraction(void) +{ + UChar rules[128]; + UChar pattern[128]; + UChar text[128]; + UCollator *collator; + UErrorCode status = U_ZERO_ERROR; + int count = 0; + UStringSearch *strsrch; + memset(rules, 0, 128*sizeof(UChar)); + memset(pattern, 0, 128*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + u_unescape(CONTRACTIONRULE, rules, 128); + collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON, + UCOL_TERTIARY, NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator %s\n", u_errorName(status)); + return; + } + strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + } + + while (CONTRACTION[count].text != NULL) { + u_unescape(CONTRACTION[count].text, text, 128); + u_unescape(CONTRACTION[count].pattern, pattern, 128); + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + if (!assertEqualWithUStringSearch(strsrch, CONTRACTION[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + usearch_close(strsrch); + ucol_close(collator); +} + +static void TestIgnorable(void) +{ + UChar rules[128]; + UChar pattern[128]; + UChar text[128]; + UCollator *collator; + UErrorCode status = U_ZERO_ERROR; + UStringSearch *strsrch; + uint32_t count = 0; + + memset(rules, 0, 128*sizeof(UChar)); + memset(pattern, 0, 128*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + u_unescape(IGNORABLERULE, rules, 128); + collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON, + IGNORABLE[count].strength, NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator %s\n", u_errorName(status)); + return; + } + strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + } + + while (IGNORABLE[count].text != NULL) { + u_unescape(IGNORABLE[count].text, text, 128); + u_unescape(IGNORABLE[count].pattern, pattern, 128); + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + if (!assertEqualWithUStringSearch(strsrch, IGNORABLE[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + usearch_close(strsrch); + ucol_close(collator); +} + +static void TestDiactricMatch(void) +{ + UChar pattern[128]; + UChar text[128]; + UErrorCode status = U_ZERO_ERROR; + UStringSearch *strsrch = NULL; + UCollator *coll = NULL; + uint32_t count = 0; + SearchData search; + + memset(pattern, 0, 128*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + strsrch = usearch_open(pattern, 1, text, 1, uloc_getDefault(), NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + return; + } + + search = DIACTRICMATCH[count]; + while (search.text != NULL) { + if (search.collator != NULL) { + coll = ucol_openFromShortString(search.collator, FALSE, NULL, &status); + } else { + coll = ucol_open(uloc_getDefault(), &status); + ucol_setStrength(coll, search.strength); + } + if (U_FAILURE(status)) { + log_err("Error opening string search collator %s\n", u_errorName(status)); + return; + } + + usearch_setCollator(strsrch, coll, &status); + if (U_FAILURE(status)) { + log_err("Error setting string search collator %s\n", u_errorName(status)); + return; + } + + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 128); + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + if (!assertEqualWithUStringSearch(strsrch, search)) { + log_err("Error at test number %d\n", count); + } + ucol_close(coll); + + search = DIACTRICMATCH[++count]; + } + usearch_close(strsrch); +} + +static void TestCanonical(void) +{ + int count = 0; + open(); + while (BASICCANONICAL[count].text != NULL) { + if (!assertCanonicalEqual(BASICCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestNormCanonical(void) +{ + int count = 0; + UErrorCode status = U_ZERO_ERROR; + open(); + ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status); + count = 0; + while (NORMCANONICAL[count].text != NULL) { + if (!assertCanonicalEqual(NORMCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status); + close(); +} + +static void TestStrengthCanonical(void) +{ + int count = 0; + open(); + while (STRENGTHCANONICAL[count].text != NULL) { + if (!assertCanonicalEqual(STRENGTHCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestBreakIteratorCanonical(void) { + UErrorCode status = U_ZERO_ERROR; + int count = 0; + + CHECK_BREAK("x"); + +#if !UCONFIG_NO_BREAK_ITERATION + + open(); + while (count < 4) { + /* 0-3 test are fixed */ + UChar pattern[32]; + UChar text[128]; + const SearchData *search = &(BREAKITERATORCANONICAL[count]); + UCollator *collator = getCollator(search->collator); + UBreakIterator *breaker = getBreakIterator(search->breaker); + UStringSearch *strsrch; + + u_unescape(search->text, text, 128); + u_unescape(search->pattern, pattern, 32); + ucol_setStrength(collator, search->strength); + + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + breaker, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != breaker) { + log_err("Error setting break iterator\n"); + if (strsrch != NULL) { + usearch_close(strsrch); + } + } + if (!assertEqualWithUStringSearch(strsrch, *search)) { + ucol_setStrength(collator, UCOL_TERTIARY); + usearch_close(strsrch); + goto ENDTESTBREAKITERATOR; + } + search = &(BREAKITERATOREXACT[count + 1]); + breaker = getBreakIterator(search->breaker); + usearch_setBreakIterator(strsrch, breaker, &status); + if (U_FAILURE(status) || + usearch_getBreakIterator(strsrch) != breaker) { + log_err("Error setting break iterator\n"); + usearch_close(strsrch); + goto ENDTESTBREAKITERATOR; + } + usearch_reset(strsrch); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (!assertEqualWithUStringSearch(strsrch, *search)) { + log_err("Error at test number %d\n", count); + goto ENDTESTBREAKITERATOR; + } + usearch_close(strsrch); + count += 2; + } + count = 0; + while (BREAKITERATORCANONICAL[count].text != NULL) { + if (!assertEqual(BREAKITERATORCANONICAL[count])) { + log_err("Error at test number %d\n", count); + goto ENDTESTBREAKITERATOR; + } + count ++; + } + +ENDTESTBREAKITERATOR: + close(); +#endif +} + +static void TestVariableCanonical(void) +{ + int count = 0; + UErrorCode status = U_ZERO_ERROR; + open(); + ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status); + if (U_FAILURE(status)) { + log_err("Error setting collation alternate attribute %s\n", + u_errorName(status)); + } + while (VARIABLE[count].text != NULL) { + log_verbose("variable %d\n", count); + if (!assertCanonicalEqual(VARIABLE[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, + UCOL_NON_IGNORABLE, &status); + close(); +} + +static void TestOverlapCanonical(void) +{ + int count = 0; + open(); + while (OVERLAPCANONICAL[count].text != NULL) { + if (!assertEqualWithAttribute(OVERLAPCANONICAL[count], USEARCH_ON, + USEARCH_ON)) { + log_err("Error at overlap test number %d\n", count); + } + count ++; + } + count = 0; + while (NONOVERLAP[count].text != NULL) { + if (!assertCanonicalEqual(NONOVERLAPCANONICAL[count])) { + log_err("Error at non overlap test number %d\n", count); + } + count ++; + } + + count = 0; + while (count < 1) { + UChar pattern[32]; + UChar text[128]; + const SearchData *search = &(OVERLAPCANONICAL[count]); + UCollator *collator = getCollator(search->collator); + UStringSearch *strsrch; + UErrorCode status = U_ZERO_ERROR; + + u_unescape(search->text, text, 128); + u_unescape(search->pattern, pattern, 32); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator, + NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) { + log_err("Error setting overlap option\n"); + } + if (!assertEqualWithUStringSearch(strsrch, *search)) { + usearch_close(strsrch); + return; + } + search = &(NONOVERLAPCANONICAL[count]); + usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status); + if (U_FAILURE(status) || + usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) { + log_err("Error setting overlap option\n"); + } + usearch_reset(strsrch); + if (!assertEqualWithUStringSearch(strsrch, *search)) { + usearch_close(strsrch); + log_err("Error at test number %d\n", count); + } + + count ++; + usearch_close(strsrch); + } + close(); +} + +static void TestCollatorCanonical(void) +{ + /* test collator that thinks "o" and "p" are the same thing */ + UChar rules[32]; + UCollator *tailored = NULL; + UErrorCode status = U_ZERO_ERROR; + UChar pattern[32]; + UChar text[128]; + UStringSearch *strsrch; + + open(); + u_unescape(COLLATORCANONICAL[0].text, text, 128); + u_unescape(COLLATORCANONICAL[0].pattern, pattern, 32); + + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening searcher\n"); + return; + } + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) { + goto ENDTESTCOLLATOR; + } + + u_unescape(TESTCOLLATORRULE, rules, 32); + tailored = ucol_openRules(rules, -1, UCOL_ON, + COLLATORCANONICAL[1].strength, NULL, &status); + if (U_FAILURE(status)) { + log_err("Error opening rule based collator %s\n", u_errorName(status)); + } + + usearch_setCollator(strsrch, tailored, &status); + if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) { + log_err("Error setting rule based collator\n"); + } + usearch_reset(strsrch); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[1])) { + goto ENDTESTCOLLATOR; + } + + usearch_setCollator(strsrch, EN_US_, &status); + usearch_reset(strsrch); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) { + log_err("Error setting rule based collator\n"); + } + if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) { + goto ENDTESTCOLLATOR; + } + +ENDTESTCOLLATOR: + usearch_close(strsrch); + if (tailored != NULL) { + ucol_close(tailored); + } + close(); +} + +static void TestPatternCanonical(void) +{ + UStringSearch *strsrch; + UChar pattern[32]; + UChar text[128]; + const UChar *temp; + int32_t templength; + UErrorCode status = U_ZERO_ERROR; + + open(); + u_unescape(PATTERNCANONICAL[0].text, text, 128); + u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32); + + ucol_setStrength(EN_US_, PATTERNCANONICAL[0].strength); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + goto ENDTESTPATTERN; + } + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) { + goto ENDTESTPATTERN; + } + + u_unescape(PATTERNCANONICAL[1].pattern, pattern, 32); + usearch_setPattern(strsrch, pattern, -1, &status); + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + goto ENDTESTPATTERN; + } + usearch_reset(strsrch); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[1])) { + goto ENDTESTPATTERN; + } + + u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32); + usearch_setPattern(strsrch, pattern, -1, &status); + temp = usearch_getPattern(strsrch, &templength); + if (u_strcmp(pattern, temp) != 0) { + log_err("Error setting pattern\n"); + goto ENDTESTPATTERN; + } + usearch_reset(strsrch); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) { + goto ENDTESTPATTERN; + } +ENDTESTPATTERN: + ucol_setStrength(EN_US_, UCOL_TERTIARY); + if (strsrch != NULL) { + usearch_close(strsrch); + } + close(); +} + +static void TestTextCanonical(void) +{ + UStringSearch *strsrch; + UChar pattern[32]; + UChar text[128]; + const UChar *temp; + int32_t templength; + UErrorCode status = U_ZERO_ERROR; + + u_unescape(TEXTCANONICAL[0].text, text, 128); + u_unescape(TEXTCANONICAL[0].pattern, pattern, 32); + + open(); + strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, + NULL, &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + goto ENDTESTPATTERN; + } + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + } + if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) { + goto ENDTESTPATTERN; + } + + u_unescape(TEXTCANONICAL[1].text, text, 32); + usearch_setText(strsrch, text, -1, &status); + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + goto ENDTESTPATTERN; + } + if (U_FAILURE(status)) { + log_err("Error setting text %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[1])) { + goto ENDTESTPATTERN; + } + + u_unescape(TEXTCANONICAL[0].text, text, 32); + usearch_setText(strsrch, text, -1, &status); + temp = usearch_getText(strsrch, &templength); + if (u_strcmp(text, temp) != 0) { + log_err("Error setting text\n"); + goto ENDTESTPATTERN; + } + if (U_FAILURE(status)) { + log_err("Error setting pattern %s\n", u_errorName(status)); + } + if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) { + goto ENDTESTPATTERN; + } +ENDTESTPATTERN: + if (strsrch != NULL) { + usearch_close(strsrch); + } + close(); +} + +static void TestCompositeBoundariesCanonical(void) +{ + int count = 0; + open(); + while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) { + log_verbose("composite %d\n", count); + if (!assertCanonicalEqual(COMPOSITEBOUNDARIESCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestGetSetOffsetCanonical(void) +{ + int index = 0; + UChar pattern[32]; + UChar text[128]; + UErrorCode status = U_ZERO_ERROR; + UStringSearch *strsrch; + + memset(pattern, 0, 32*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + open(); + strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL, + &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + /* testing out of bounds error */ + usearch_setOffset(strsrch, -1, &status); + if (U_SUCCESS(status)) { + log_err("Error expecting set offset error\n"); + } + usearch_setOffset(strsrch, 128, &status); + if (U_SUCCESS(status)) { + log_err("Error expecting set offset error\n"); + } + while (BASICCANONICAL[index].text != NULL) { + int count = 0; + SearchData search = BASICCANONICAL[index ++]; + int32_t matchindex = search.offset[count]; + int32_t textlength; + + if (BASICCANONICAL[index].text == NULL) { + /* skip the last one */ + break; + } + + u_unescape(search.text, text, 128); + u_unescape(search.pattern, pattern, 32); + status = U_ZERO_ERROR; + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + while (U_SUCCESS(status) && matchindex >= 0) { + uint32_t matchlength = search.size[count]; + usearch_next(strsrch, &status); + if (matchindex != usearch_getMatchedStart(strsrch) || + matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) { + char *str = toCharString(usearch_getText(strsrch, + &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + matchindex = search.offset[count + 1] == -1 ? -1 : + search.offset[count + 2]; + if (search.offset[count + 1] != -1) { + usearch_setOffset(strsrch, search.offset[count + 1] + 1, + &status); + if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) { + log_err("Error setting offset\n"); + return; + } + } + + count += 2; + } + usearch_next(strsrch, &status); + if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) { + char *str = toCharString(usearch_getText(strsrch, &textlength)); + log_err("Text: %s\n", str); + str = toCharString(usearch_getPattern(strsrch, &textlength)); + log_err("Pattern: %s\n", str); + log_err("Error match found at %d %d\n", + usearch_getMatchedStart(strsrch), + usearch_getMatchedLength(strsrch)); + return; + } + } + usearch_close(strsrch); + close(); +} + +static void TestSupplementaryCanonical(void) +{ + int count = 0; + open(); + while (SUPPLEMENTARYCANONICAL[count].text != NULL) { + if (!assertCanonicalEqual(SUPPLEMENTARYCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + close(); +} + +static void TestContractionCanonical(void) +{ + UChar rules[128]; + UChar pattern[128]; + UChar text[128]; + UCollator *collator = NULL; + UErrorCode status = U_ZERO_ERROR; + int count = 0; + UStringSearch *strsrch = NULL; + memset(rules, 0, 128*sizeof(UChar)); + memset(pattern, 0, 128*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + u_unescape(CONTRACTIONRULE, rules, 128); + collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON, + UCOL_TERTIARY, NULL, &status); + if(status == U_FILE_ACCESS_ERROR) { + log_data_err("Is your data around?\n"); + return; + } else if(U_FAILURE(status)) { + log_err("Error opening collator %s\n", u_errorName(status)); + return; + } + strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL, + &status); + usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON, + &status); + if (U_FAILURE(status)) { + log_err("Error opening string search %s\n", u_errorName(status)); + } + + while (CONTRACTIONCANONICAL[count].text != NULL) { + u_unescape(CONTRACTIONCANONICAL[count].text, text, 128); + u_unescape(CONTRACTIONCANONICAL[count].pattern, pattern, 128); + usearch_setText(strsrch, text, -1, &status); + usearch_setPattern(strsrch, pattern, -1, &status); + if (!assertEqualWithUStringSearch(strsrch, + CONTRACTIONCANONICAL[count])) { + log_err("Error at test number %d\n", count); + } + count ++; + } + usearch_close(strsrch); + ucol_close(collator); +} + +static void TestNumeric(void) { + UCollator *coll = NULL; + UStringSearch *strsrch = NULL; + UErrorCode status = U_ZERO_ERROR; + + UChar pattern[128]; + UChar text[128]; + memset(pattern, 0, 128*sizeof(UChar)); + memset(text, 0, 128*sizeof(UChar)); + + coll = ucol_open("", &status); + if(U_FAILURE(status)) { + log_data_err("Could not open UCA. Is your data around?\n"); + return; + } + + ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status); + + strsrch = usearch_openFromCollator(pattern, 1, text, 1, coll, NULL, &status); + + if(status != U_UNSUPPORTED_ERROR || U_SUCCESS(status)) { + log_err("Expected U_UNSUPPORTED_ERROR when trying to instantiate a search object from a CODAN collator, got %s instead\n", u_errorName(status)); + if(strsrch) { + usearch_close(strsrch); + } + } + + ucol_close(coll); + +} + +void addSearchTest(TestNode** root) +{ + addTest(root, &TestStart, "tscoll/usrchtst/TestStart"); + addTest(root, &TestOpenClose, "tscoll/usrchtst/TestOpenClose"); + addTest(root, &TestInitialization, "tscoll/usrchtst/TestInitialization"); + addTest(root, &TestBasic, "tscoll/usrchtst/TestBasic"); + addTest(root, &TestNormExact, "tscoll/usrchtst/TestNormExact"); + addTest(root, &TestStrength, "tscoll/usrchtst/TestStrength"); + addTest(root, &TestBreakIterator, "tscoll/usrchtst/TestBreakIterator"); + addTest(root, &TestVariable, "tscoll/usrchtst/TestVariable"); + addTest(root, &TestOverlap, "tscoll/usrchtst/TestOverlap"); + addTest(root, &TestCollator, "tscoll/usrchtst/TestCollator"); + addTest(root, &TestPattern, "tscoll/usrchtst/TestPattern"); + addTest(root, &TestText, "tscoll/usrchtst/TestText"); + addTest(root, &TestCompositeBoundaries, + "tscoll/usrchtst/TestCompositeBoundaries"); + addTest(root, &TestGetSetOffset, "tscoll/usrchtst/TestGetSetOffset"); + addTest(root, &TestGetSetAttribute, + "tscoll/usrchtst/TestGetSetAttribute"); + addTest(root, &TestGetMatch, "tscoll/usrchtst/TestGetMatch"); + addTest(root, &TestSetMatch, "tscoll/usrchtst/TestSetMatch"); + addTest(root, &TestReset, "tscoll/usrchtst/TestReset"); + addTest(root, &TestSupplementary, "tscoll/usrchtst/TestSupplementary"); + addTest(root, &TestContraction, "tscoll/usrchtst/TestContraction"); + addTest(root, &TestIgnorable, "tscoll/usrchtst/TestIgnorable"); + addTest(root, &TestCanonical, "tscoll/usrchtst/TestCanonical"); + addTest(root, &TestNormCanonical, "tscoll/usrchtst/TestNormCanonical"); + addTest(root, &TestStrengthCanonical, + "tscoll/usrchtst/TestStrengthCanonical"); + addTest(root, &TestBreakIteratorCanonical, + "tscoll/usrchtst/TestBreakIteratorCanonical"); + addTest(root, &TestVariableCanonical, + "tscoll/usrchtst/TestVariableCanonical"); + addTest(root, &TestOverlapCanonical, + "tscoll/usrchtst/TestOverlapCanonical"); + addTest(root, &TestCollatorCanonical, + "tscoll/usrchtst/TestCollatorCanonical"); + addTest(root, &TestPatternCanonical, + "tscoll/usrchtst/TestPatternCanonical"); + addTest(root, &TestTextCanonical, "tscoll/usrchtst/TestTextCanonical"); + addTest(root, &TestCompositeBoundariesCanonical, + "tscoll/usrchtst/TestCompositeBoundariesCanonical"); + addTest(root, &TestGetSetOffsetCanonical, + "tscoll/usrchtst/TestGetSetOffsetCanonical"); + addTest(root, &TestSupplementaryCanonical, + "tscoll/usrchtst/TestSupplementaryCanonical"); + addTest(root, &TestContractionCanonical, + "tscoll/usrchtst/TestContractionCanonical"); + addTest(root, &TestEnd, "tscoll/usrchtst/TestEnd"); + addTest(root, &TestNumeric, "tscoll/usrchtst/TestNumeric"); + addTest(root, &TestDiactricMatch, "tscoll/usrchtst/TestDiactricMatch"); +} + +#endif /* #if !UCONFIG_NO_COLLATION */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c new file mode 100644 index 00000000000..be5941df403 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c @@ -0,0 +1,250 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 2005-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File utexttst.c +* +* Modification History: +* +* Date Name Description +* 06/13/2005 Andy Heninger Creation +******************************************************************************* +*/ + +#include "unicode/utypes.h" +#include "unicode/utext.h" +#include "unicode/ustring.h" +#include "cintltst.h" +#include "memory.h" +#include "string.h" + + +static void TestAPI(void); +void addUTextTest(TestNode** root); + + +void +addUTextTest(TestNode** root) +{ + addTest(root, &TestAPI , "tsutil/UTextTest/TestAPI"); +} + + +#define TEST_ASSERT(x) \ + {if ((x)==FALSE) {log_err("Test failure in file %s at line %d\n", __FILE__, __LINE__);\ + gFailed = TRUE;\ + }} + + +#define TEST_SUCCESS(status) \ + {if (U_FAILURE(status)) {log_err("Test failure in file %s at line %d. Error = \"%s\"\n", \ + __FILE__, __LINE__, u_errorName(status)); \ + gFailed = TRUE;\ + }} + + + +/* + * TestAPI verify that the UText API is accessible from C programs. + * This is not intended to be a complete test of the API functionality. That is + * in the C++ intltest program. + * This test is intended to check that everything can be accessed and built in + * a pure C enviornment. + */ + + +static void TestAPI(void) { + UErrorCode status = U_ZERO_ERROR; + UBool gFailed = FALSE; + + /* Open */ + { + UText utLoc = UTEXT_INITIALIZER; + const char * cString = "\x61\x62\x63\x64"; + UChar uString[] = {0x41, 0x42, 0x43, 0}; + UText *uta; + UText *utb; + UChar c; + + uta = utext_openUChars(NULL, uString, -1, &status); + TEST_SUCCESS(status); + c = utext_next32(uta); + TEST_ASSERT(c == 0x41); + utb = utext_close(uta); + TEST_ASSERT(utb == NULL); + + uta = utext_openUTF8(&utLoc, cString, -1, &status); + TEST_SUCCESS(status); + TEST_ASSERT(uta == &utLoc); + + uta = utext_close(&utLoc); + TEST_ASSERT(uta == &utLoc); + } + + /* utext_clone() */ + { + UChar uString[] = {0x41, 0x42, 0x43, 0}; + int64_t len; + UText *uta; + UText *utb; + + status = U_ZERO_ERROR; + uta = utext_openUChars(NULL, uString, -1, &status); + TEST_SUCCESS(status); + utb = utext_clone(NULL, uta, FALSE, FALSE, &status); + TEST_SUCCESS(status); + TEST_ASSERT(utb != NULL); + TEST_ASSERT(utb != uta); + len = utext_nativeLength(uta); + TEST_ASSERT(len == u_strlen(uString)); + utext_close(uta); + utext_close(utb); + } + + /* basic access functions */ + { + UChar uString[] = {0x41, 0x42, 0x43, 0}; + UText *uta; + UChar32 c; + int64_t len; + UBool b; + int64_t i; + + status = U_ZERO_ERROR; + uta = utext_openUChars(NULL, uString, -1, &status); + TEST_ASSERT(uta!=NULL); + TEST_SUCCESS(status); + b = utext_isLengthExpensive(uta); + TEST_ASSERT(b==TRUE); + len = utext_nativeLength(uta); + TEST_ASSERT(len == u_strlen(uString)); + b = utext_isLengthExpensive(uta); + TEST_ASSERT(b==FALSE); + + c = utext_char32At(uta, 0); + TEST_ASSERT(c==uString[0]); + + c = utext_current32(uta); + TEST_ASSERT(c==uString[0]); + + c = utext_next32(uta); + TEST_ASSERT(c==uString[0]); + c = utext_current32(uta); + TEST_ASSERT(c==uString[1]); + + c = utext_previous32(uta); + TEST_ASSERT(c==uString[0]); + c = utext_current32(uta); + TEST_ASSERT(c==uString[0]); + + c = utext_next32From(uta, 1); + TEST_ASSERT(c==uString[1]); + c = utext_next32From(uta, u_strlen(uString)); + TEST_ASSERT(c==U_SENTINEL); + + c = utext_previous32From(uta, 2); + TEST_ASSERT(c==uString[1]); + i = utext_getNativeIndex(uta); + TEST_ASSERT(i == 1); + + utext_setNativeIndex(uta, 0); + b = utext_moveIndex32(uta, 1); + TEST_ASSERT(b==TRUE); + i = utext_getNativeIndex(uta); + TEST_ASSERT(i==1); + + b = utext_moveIndex32(uta, u_strlen(uString)-1); + TEST_ASSERT(b==TRUE); + i = utext_getNativeIndex(uta); + TEST_ASSERT(i==u_strlen(uString)); + + b = utext_moveIndex32(uta, 1); + TEST_ASSERT(b==FALSE); + i = utext_getNativeIndex(uta); + TEST_ASSERT(i==u_strlen(uString)); + + utext_setNativeIndex(uta, 0); + c = UTEXT_NEXT32(uta); + TEST_ASSERT(c==uString[0]); + c = utext_current32(uta); + TEST_ASSERT(c==uString[1]); + + c = UTEXT_PREVIOUS32(uta); + TEST_ASSERT(c==uString[0]); + c = UTEXT_PREVIOUS32(uta); + TEST_ASSERT(c==U_SENTINEL); + + + utext_close(uta); + } + + { + /* + * extract + */ + UText *uta; + UChar uString[] = {0x41, 0x42, 0x43, 0}; + UChar buf[100]; + int32_t i; + + status = U_ZERO_ERROR; + uta = utext_openUChars(NULL, uString, -1, &status); + TEST_SUCCESS(status); + + status = U_ZERO_ERROR; + i = utext_extract(uta, 0, 100, NULL, 0, &status); + TEST_ASSERT(status==U_BUFFER_OVERFLOW_ERROR); + TEST_ASSERT(i == u_strlen(uString)); + + status = U_ZERO_ERROR; + memset(buf, 0, sizeof(buf)); + i = utext_extract(uta, 0, 100, buf, 100, &status); + TEST_SUCCESS(status); + TEST_ASSERT(i == u_strlen(uString)); + i = u_strcmp(uString, buf); + TEST_ASSERT(i == 0); + utext_close(uta); + } + + { + /* + * Copy, Replace, isWritable + * Can't create an editable UText from plain C, so all we + * can easily do is check that errors returned. + */ + UText *uta; + UChar uString[] = {0x41, 0x42, 0x43, 0}; + UBool b; + + status = U_ZERO_ERROR; + uta = utext_openUChars(NULL, uString, -1, &status); + TEST_SUCCESS(status); + + b = utext_isWritable(uta); + TEST_ASSERT(b == FALSE); + + b = utext_hasMetaData(uta); + TEST_ASSERT(b == FALSE); + + utext_replace(uta, + 0, 1, /* start, limit */ + uString, -1, /* replacement, replacement length */ + &status); + TEST_ASSERT(status == U_NO_WRITE_PERMISSION); + + + utext_copy(uta, + 0, 1, /* start, limit */ + 2, /* destination index */ + FALSE, /* move flag */ + &status); + TEST_ASSERT(status == U_NO_WRITE_PERMISSION); + + utext_close(uta); + } + + +} + diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c new file mode 100644 index 00000000000..38b8fb5fcc2 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c @@ -0,0 +1,734 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1998-2001, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File test.c +* +* Modification History: +* +* Date Name Description +* 05/01/2000 Madhu Creation +******************************************************************************* +*/ + +#include "unicode/utypes.h" +#include "unicode/utf16.h" +#include "unicode/ustring.h" +#include "cmemory.h" +#include "cstring.h" +#include "cintltst.h" +#include <stdio.h> + +#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) + +static void printUChars(const UChar *uchars); + +static void TestCodeUnitValues(void); +static void TestCharLength(void); +static void TestGetChar(void); +static void TestNextPrevChar(void); +static void TestFwdBack(void); +static void TestSetChar(void); +static void TestAppendChar(void); +static void TestAppend(void); +static void TestSurrogate(void); + +void addUTF16Test(TestNode** root); + +void +addUTF16Test(TestNode** root) +{ + addTest(root, &TestCodeUnitValues, "utf16tst/TestCodeUnitValues"); + addTest(root, &TestCharLength, "utf16tst/TestCharLength" ); + addTest(root, &TestGetChar, "utf16tst/TestGetChar" ); + addTest(root, &TestNextPrevChar, "utf16tst/TestNextPrevChar" ); + addTest(root, &TestFwdBack, "utf16tst/TestFwdBack" ); + addTest(root, &TestSetChar, "utf16tst/TestSetChar" ); + addTest(root, &TestAppendChar, "utf16tst/TestAppendChar" ); + addTest(root, &TestAppend, "utf16tst/TestAppend" ); + addTest(root, &TestSurrogate, "utf16tst/TestSurrogate" ); +} + +static void TestCodeUnitValues() +{ + static uint16_t codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0}; + + int16_t i; + for(i=0; i<sizeof(codeunit)/sizeof(codeunit[0]); i++){ + UChar c=codeunit[i]; + log_verbose("Testing code unit value of %x\n", c); + if(i<4){ + if(!UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || UTF16_IS_TRAIL(c) || !U16_IS_SINGLE(c) || U16_IS_LEAD(c) || U16_IS_TRAIL(c)){ + log_err("ERROR: %x is a single character\n", c); + } + } + if(i >= 4 && i< 8){ + if(!UTF16_IS_LEAD(c) || UTF16_IS_SINGLE(c) || UTF16_IS_TRAIL(c) || !U16_IS_LEAD(c) || U16_IS_SINGLE(c) || U16_IS_TRAIL(c)){ + log_err("ERROR: %x is a first surrogate\n", c); + } + } + if(i >= 8 && i< 12){ + if(!UTF16_IS_TRAIL(c) || UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || !U16_IS_TRAIL(c) || U16_IS_SINGLE(c) || U16_IS_LEAD(c)){ + log_err("ERROR: %x is a second surrogate\n", c); + } + } + } +} + +static void TestCharLength() +{ + static uint32_t codepoint[]={ + 1, 0x0061, + 1, 0xe065, + 1, 0x20ac, + 2, 0x20402, + 2, 0x23456, + 2, 0x24506, + 2, 0x20402, + 2, 0x10402, + 1, 0xd7ff, + 1, 0xe000 + }; + + int16_t i; + UBool multiple; + for(i=0; i<sizeof(codepoint)/sizeof(codepoint[0]); i=(int16_t)(i+2)){ + UChar32 c=codepoint[i+1]; + if(UTF16_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U16_LENGTH(c) != (uint16_t)codepoint[i]){ + log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF16_CHAR_LENGTH(c)); + }else{ + log_verbose("The no: of code units for %lx is %d\n",c, UTF16_CHAR_LENGTH(c) ); + } + multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE); + if(UTF16_NEED_MULTIPLE_UCHAR(c) != multiple){ + log_err("ERROR: UTF16_NEED_MULTIPLE_UCHAR failed for %lx\n", c); + } + } +} + +static void TestGetChar() +{ + static UChar input[]={ + /* code unit,*/ + 0xdc00, + 0x20ac, + 0xd841, + 0x61, + 0xd841, + 0xdc02, + 0xd842, + 0xdc06, + 0, + 0xd842, + 0xd7ff, + 0xdc41, + 0xe000, + 0xd800 + }; + static UChar32 result[]={ + /*codepoint-unsafe, codepoint-safe(not strict) codepoint-safe(strict)*/ + (UChar32)0xfca10000, 0xdc00, UTF_ERROR_VALUE, + 0x20ac, 0x20ac, 0x20ac, + 0x12861, 0xd841, UTF_ERROR_VALUE, + 0x61, 0x61, 0x61, + 0x20402, 0x20402, 0x20402, + 0x20402, 0x20402, 0x20402, + 0x20806, 0x20806, 0x20806, + 0x20806, 0x20806, 0x20806, + 0x00, 0x00, 0x00, + 0x203ff, 0xd842, UTF_ERROR_VALUE, + 0xd7ff, 0xd7ff, 0xd7ff, + 0xfc41, 0xdc41, UTF_ERROR_VALUE, + 0xe000, 0xe000, 0xe000, + 0x11734, 0xd800, UTF_ERROR_VALUE + }; + uint16_t i=0; + UChar32 c; + uint16_t offset=0; + for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++) { + if(0<offset && offset<sizeof(input)/U_SIZEOF_UCHAR-1){ + UTF16_GET_CHAR_UNSAFE(input, offset, c); + if(c != result[i]){ + log_err("ERROR: UTF16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + + U16_GET_UNSAFE(input, offset, c); + if(c != result[i]){ + log_err("ERROR: U16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + } + + UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE); + if(c != result[i+1]){ + log_err("ERROR: UTF16_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + U16_GET(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c); + if(c != result[i+1]){ + log_err("ERROR: U16_GET failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE); + if(c != result[i+2]){ + log_err("ERROR: UTF16_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c); + } + i=(uint16_t)(i+3); + } + +} + +static void TestNextPrevChar(){ + + static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000}; + static UChar32 result[]={ + /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/ + 0x0061, 0x0061, 0x0061, 0x0000, 0x0000, 0x0000, + 0x10000, 0x10000, 0x10000, 0x120400, 0xdc00, UTF_ERROR_VALUE, + 0xdc00, 0xdc00, UTF_ERROR_VALUE, 0x20441, 0x20441, 0x20441, + 0x10ffff, 0x10ffff, 0x10ffff, 0xd841, 0xd841, UTF_ERROR_VALUE, + 0xdfff, 0xdfff, UTF_ERROR_VALUE, 0xd7ff, 0xd7ff, 0xd7ff, + 0x0062, 0x0062, 0x0062, 0xd841, 0xd841, UTF_ERROR_VALUE, + 0x1ffff, 0xd841, UTF_ERROR_VALUE, 0x0062, 0x0062, 0x0062, + 0xd7ff, 0xd7ff, 0xd7ff, 0x10ffff, 0x10ffff, 0x10ffff, + 0x20441, 0x20441, 0x20441, 0xdbff, 0xdbff, UTF_ERROR_VALUE, + 0xdc41, 0xdc41, UTF_ERROR_VALUE, 0x10000, 0x10000, 0x10000, + 0xdc00, 0xdc00, UTF_ERROR_VALUE, 0xd800, 0xd800, UTF_ERROR_VALUE, + 0x0000, 0x0000, 0x0000, 0x0061, 0x0061, 0x0061 + }; + static uint16_t movedOffset[]={ + /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/ + 1, 1, 1, 11, 11, 11, + 3, 3, 3, 9, 10 , 10, + 3, 3, 3, 8, 8, 8, + 5, 5, 4, 8, 8, 8, + 5, 5, 5, 7, 7, 7, + 6, 6, 6, 6, 6, 6, + 8, 7, 7, 5, 5, 5, + 8, 8, 8, 3, 3, 3, + 10, 10, 10, 3, 3, 3, + 10, 10, 10, 1, 1, 1, + 11, 11, 11, 1, 1, 1, + 12, 12, 12, 0, 0, 0, + }; + + + UChar32 c=0x0000; + uint16_t i=0; + uint16_t offset=0, setOffset=0; + for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){ + setOffset=offset; + UTF16_NEXT_CHAR_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i]){ + log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i], setOffset); + } + if(c != result[i]){ + log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + + setOffset=offset; + U16_NEXT_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i]){ + log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i], setOffset); + } + if(c != result[i]){ + log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + + setOffset=offset; + UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+1], setOffset); + } + if(c != result[i+1]){ + log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + setOffset=offset; + U16_NEXT(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: U16_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+1], setOffset); + } + if(c != result[i+1]){ + log_err("ERROR: U16_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + setOffset=offset; + UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+2], setOffset); + } + if(c != result[i+2]){ + log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c); + } + + i=(uint16_t)(i+6); + } + i=0; + for(offset=(uint16_t)sizeof(input)/U_SIZEOF_UCHAR; offset > 0; --offset){ + setOffset=offset; + UTF16_PREV_CHAR_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i+3]){ + log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+3], setOffset); + } + if(c != result[i+3]){ + log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c); + } + + setOffset=offset; + U16_PREV_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i+3]){ + log_err("ERROR: U16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+3], setOffset); + } + if(c != result[i+3]){ + log_err("ERROR: U16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c); + } + + setOffset=offset; + UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE); + if(setOffset != movedOffset[i+4]){ + log_err("ERROR: UTF16_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+4], setOffset); + } + if(c != result[i+4]){ + log_err("ERROR: UTF16_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c); + } + + setOffset=offset; + U16_PREV(input, 0, setOffset, c); + if(setOffset != movedOffset[i+4]){ + log_err("ERROR: U16_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+4], setOffset); + } + if(c != result[i+4]){ + log_err("ERROR: U16_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c); + } + + setOffset=offset; + UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, TRUE); + if(setOffset != movedOffset[i+5]){ + log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+5], setOffset); + } + if(c != result[i+5]){ + log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c); + } + + i=(uint16_t)(i+6); + } + +} + +static void TestFwdBack(){ + static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000}; + static uint16_t fwd_unsafe[] ={1, 3, 5, 6, 8, 10, 11, 12}; + static uint16_t fwd_safe[] ={1, 3, 5, 6, 7, 8, 10, 11, 12}; + static uint16_t back_unsafe[]={11, 9, 8, 7, 6, 5, 3, 1, 0}; + static uint16_t back_safe[] ={11, 10, 8, 7, 6, 5, 3, 1, 0}; + + static uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1}; + static uint16_t fwd_N_unsafe[] ={0, 1, 5, 10, 11}; + static uint16_t fwd_N_safe[] ={0, 1, 5, 8, 10, 12, 12}; /*safe macro keeps it at the end of the string */ + static uint16_t back_N_unsafe[]={12, 11, 8, 5, 3}; + static uint16_t back_N_safe[] ={12, 11, 8, 5, 3, 0, 0}; + + uint16_t offunsafe=0, offsafe=0; + uint16_t i=0; + while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){ + UTF16_FWD_1_UNSAFE(input, offunsafe); + if(offunsafe != fwd_unsafe[i]){ + log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe); + } + i++; + } + + offunsafe=0, offsafe=0; + i=0; + while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){ + U16_FWD_1_UNSAFE(input, offunsafe); + if(offunsafe != fwd_unsafe[i]){ + log_err("ERROR: U16_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe); + } + i++; + } + + i=0; + while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){ + UTF16_FWD_1_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR); + if(offsafe != fwd_safe[i]){ + log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe); + } + i++; + } + + i=0; + while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){ + U16_FWD_1(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR); + if(offsafe != fwd_safe[i]){ + log_err("ERROR: U16_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe); + } + i++; + } + + offunsafe=sizeof(input)/U_SIZEOF_UCHAR; + offsafe=sizeof(input)/U_SIZEOF_UCHAR; + i=0; + while(offunsafe > 0){ + UTF16_BACK_1_UNSAFE(input, offunsafe); + if(offunsafe != back_unsafe[i]){ + log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe); + } + i++; + } + + offunsafe=sizeof(input)/U_SIZEOF_UCHAR; + offsafe=sizeof(input)/U_SIZEOF_UCHAR; + i=0; + while(offunsafe > 0){ + U16_BACK_1_UNSAFE(input, offunsafe); + if(offunsafe != back_unsafe[i]){ + log_err("ERROR: U16_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe); + } + i++; + } + + i=0; + while(offsafe > 0){ + UTF16_BACK_1_SAFE(input,0, offsafe); + if(offsafe != back_safe[i]){ + log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe); + } + i++; + } + + i=0; + while(offsafe > 0){ + U16_BACK_1(input,0, offsafe); + if(offsafe != back_safe[i]){ + log_err("ERROR: U16_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe); + } + i++; + } + + offunsafe=0; + offsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ /*didn't want it to fail(we assume 0<i<length)*/ + UTF16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != fwd_N_unsafe[i]){ + log_err("ERROR: Forward_N_unsafe offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe); + } + } + + offunsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ /*didn't want it to fail(we assume 0<i<length)*/ + U16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != fwd_N_unsafe[i]){ + log_err("ERROR: U16_FWD_N_UNSAFE offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe); + } + } + + offsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + UTF16_FWD_N_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]); + if(offsafe != fwd_N_safe[i]){ + log_err("ERROR: Forward_N_safe offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe); + } + + } + + offsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + U16_FWD_N(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]); + if(offsafe != fwd_N_safe[i]){ + log_err("ERROR: U16_FWD_N offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe); + } + + } + + offunsafe=sizeof(input)/U_SIZEOF_UCHAR; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + UTF16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != back_N_unsafe[i]){ + log_err("ERROR: backward_N_unsafe offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe); + } + } + + offunsafe=sizeof(input)/U_SIZEOF_UCHAR; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + U16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != back_N_unsafe[i]){ + log_err("ERROR: U16_BACK_N_UNSAFE offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe); + } + } + + offsafe=sizeof(input)/U_SIZEOF_UCHAR; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + UTF16_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]); + if(offsafe != back_N_safe[i]){ + log_err("ERROR: backward_N_safe offset expected:%d, Got:%d\n", back_N_safe[i], offsafe); + } + } + + offsafe=sizeof(input)/U_SIZEOF_UCHAR; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + U16_BACK_N(input, 0, offsafe, Nvalue[i]); + if(offsafe != back_N_safe[i]){ + log_err("ERROR: U16_BACK_N offset expected:%d, Got:%d\n", back_N_safe[i], offsafe); + } + } +} + +static void TestSetChar(){ + static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000}; + static uint16_t start_unsafe[]={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 9, 11}; + static uint16_t start_safe[] ={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 10, 11}; + static uint16_t limit_unsafe[]={0, 1, 3, 3, 5, 5, 6, 8, 8, 10, 10, 11}; + static uint16_t limit_safe[] ={0, 1, 3, 3, 5, 5, 6, 7, 8, 10, 10, 11}; + + uint16_t i=0; + uint16_t offset=0, setOffset=0; + for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){ + setOffset=offset; + UTF16_SET_CHAR_START_UNSAFE(input, setOffset); + if(setOffset != start_unsafe[i]){ + log_err("ERROR: UTF16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset); + } + + setOffset=offset; + U16_SET_CP_START_UNSAFE(input, setOffset); + if(setOffset != start_unsafe[i]){ + log_err("ERROR: U16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset); + } + + setOffset=offset; + UTF16_SET_CHAR_START_SAFE(input, 0, setOffset); + if(setOffset != start_safe[i]){ + log_err("ERROR: UTF16_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset); + } + + setOffset=offset; + U16_SET_CP_START(input, 0, setOffset); + if(setOffset != start_safe[i]){ + log_err("ERROR: U16_SET_CHAR_START failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset); + } + + if (offset > 0) { + setOffset=offset; + UTF16_SET_CHAR_LIMIT_UNSAFE(input, setOffset); + if(setOffset != limit_unsafe[i]){ + log_err("ERROR: UTF16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset); + } + + setOffset=offset; + U16_SET_CP_LIMIT_UNSAFE(input, setOffset); + if(setOffset != limit_unsafe[i]){ + log_err("ERROR: U16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset); + } + } + + setOffset=offset; + U16_SET_CP_LIMIT(input,0, setOffset, sizeof(input)/U_SIZEOF_UCHAR); + if(setOffset != limit_safe[i]){ + log_err("ERROR: U16_SET_CHAR_LIMIT failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_safe[i], setOffset); + } + + i++; + } +} + +static void TestAppendChar(){ + static UChar s[5]={0x0061, 0x0062, 0x0063, 0x0064, 0x0000}; + static uint32_t test[]={ + /*append-position(unsafe), CHAR to be appended */ + 0, 0x20441, + 2, 0x0028, + 2, 0xdc00, + 3, 0xd800, + 1, 0x20402, + + /*append-position(safe), CHAR to be appended */ + 0, 0x20441, + 2, 0xdc00, + 3, 0xd800, + 1, 0x20402, + 3, 0x20402, + 3, 0x10402, + 2, 0x10402, + + }; + static uint16_t movedOffset[]={ + /*offset-moved-to(unsafe)*/ + 2, /*for append-pos: 0 , CHAR 0x20441*/ + 3, + 3, + 4, + 3, + /*offse-moved-to(safe)*/ + 2, /*for append-pos: 0, CHAR 0x20441*/ + 3, + 4, + 3, + 4, + 4, + 4 + }; + + static UChar result[][5]={ + /*unsafe*/ + {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000}, + {0x0061, 0x0062, 0x0028, 0x0064, 0x0000}, + {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000}, + {0x0061, 0x0062, 0x0063, 0xd800, 0x0000}, + {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000}, + + /*safe*/ + {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000}, + {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000}, + {0x0061, 0x0062, 0x0063, 0xd800, 0x0000}, + {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000}, + {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000}, + {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000}, + {0x0061, 0x0062, 0xd801, 0xdc02, 0x0000}, + + + }; + uint16_t i, count=0; + UChar *str=(UChar*)malloc(sizeof(UChar) * (u_strlen(s)+1)); + uint16_t offset; + for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){ + if(count<5){ + u_strcpy(str, s); + offset=(uint16_t)test[i]; + UTF16_APPEND_CHAR_UNSAFE(str, offset, test[i+1]); + if(offset != movedOffset[count]){ + log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", + count, movedOffset[count], offset); + + } + if(u_strcmp(str, result[count]) !=0){ + log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed for count=%d. Expected:", count); + printUChars(result[count]); + printf("\nGot:"); + printUChars(str); + printf("\n"); + } + }else{ + u_strcpy(str, s); + offset=(uint16_t)test[i]; + UTF16_APPEND_CHAR_SAFE(str, offset, (uint16_t)u_strlen(str), test[i+1]); + if(offset != movedOffset[count]){ + log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", + count, movedOffset[count], offset); + + } + if(u_strcmp(str, result[count]) !=0){ + log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed for count=%d. Expected:", count); + printUChars(result[count]); + printf("\nGot:"); + printUChars(str); + printf("\n"); + } + } + count++; + } + free(str); + +} + +static void TestAppend() { + static const UChar32 codePoints[]={ + 0x61, 0xdf, 0x901, 0x3040, + 0xac00, 0xd800, 0xdbff, 0xdcde, + 0xdffd, 0xe000, 0xffff, 0x10000, + 0x12345, 0xe0021, 0x10ffff, 0x110000, + 0x234567, 0x7fffffff, -1, -1000, + 0, 0x400 + }; + static const UChar expectUnsafe[]={ + 0x61, 0xdf, 0x901, 0x3040, + 0xac00, 0xd800, 0xdbff, 0xdcde, + 0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00, + 0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */ + /* none from this line */ + 0, 0x400 + }, expectSafe[]={ + 0x61, 0xdf, 0x901, 0x3040, + 0xac00, 0xd800, 0xdbff, 0xdcde, + 0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00, + 0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */ + /* none from this line */ + 0, 0x400 + }; + + UChar buffer[100]; + UChar32 c; + int32_t i, length; + UBool isError, expectIsError, wrongIsError; + + length=0; + for(i=0; i<LENGTHOF(codePoints); ++i) { + c=codePoints[i]; + if(c<0 || 0x10ffff<c) { + continue; /* skip non-code points for U16_APPEND_UNSAFE */ + } + + U16_APPEND_UNSAFE(buffer, length, c); + } + if(length!=LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length*U_SIZEOF_UCHAR)) { + log_err("U16_APPEND_UNSAFE did not generate the expected output\n"); + } + + length=0; + wrongIsError=FALSE; + for(i=0; i<LENGTHOF(codePoints); ++i) { + c=codePoints[i]; + expectIsError= c<0 || 0x10ffff<c; /* || U_IS_SURROGATE(c); */ /* surrogates in UTF-32 shouldn't be used, but it's okay to pass them around internally. */ + isError=FALSE; + + U16_APPEND(buffer, length, LENGTHOF(buffer), c, isError); + wrongIsError|= isError!=expectIsError; + } + if(wrongIsError) { + log_err("U16_APPEND did not set isError correctly\n"); + } + if(length!=LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length*U_SIZEOF_UCHAR)) { + log_err("U16_APPEND did not generate the expected output\n"); + } +} + +static void TestSurrogate(){ + static UChar32 s[] = {0x10000, 0x10ffff, 0x50000, 0x100000, 0x1abcd}; + int i = 0; + while (i < 5) { + UChar first = UTF_FIRST_SURROGATE(s[i]); + UChar second = UTF_SECOND_SURROGATE(s[i]); + /* algorithm from the Unicode consortium */ + UChar firstresult = (UChar)(((s[i] - 0x10000) / 0x400) + 0xD800); + UChar secondresult = (UChar)(((s[i] - 0x10000) % 0x400) + 0xDC00); + + if (first != UTF16_LEAD(s[i]) || first != U16_LEAD(s[i]) || first != firstresult) { + log_err("Failure in first surrogate in 0x%x expected to be 0x%x\n", + s[i], firstresult); + } + if (second != UTF16_TRAIL(s[i]) || second != U16_TRAIL(s[i]) || second != secondresult) { + log_err("Failure in second surrogate in 0x%x expected to be 0x%x\n", + s[i], secondresult); + } + i ++; + } +} + +static void printUChars(const UChar *uchars){ + int16_t i=0; + for(i=0; i<u_strlen(uchars); i++){ + printf("%x ", *(uchars+i)); + } +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c new file mode 100644 index 00000000000..eaa8fb28c54 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c @@ -0,0 +1,956 @@ +/******************************************************************** + * COPYRIGHT: + * Copyright (c) 1998-2006, International Business Machines Corporation and + * others. All Rights Reserved. + ********************************************************************/ +/* +* File test.c +* +* Modification History: +* +* Date Name Description +* 07/24/2000 Madhu Creation +******************************************************************************* +*/ + +#include "unicode/utypes.h" +#include "unicode/utf8.h" +#include "cmemory.h" +#include "cintltst.h" + +#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) + +/* lenient UTF-8 ------------------------------------------------------------ */ + +/* + * Lenient UTF-8 differs from conformant UTF-8 in that it allows surrogate + * code points with their "natural" encoding. + * Effectively, this allows a mix of UTF-8 and CESU-8 as well as encodings of + * single surrogates. + * + * This is not conformant with UTF-8. + * + * Supplementary code points may be encoded as pairs of 3-byte sequences, but + * the macros below do not attempt to assemble such pairs. + */ + +#define L8_NEXT(s, i, length, c) { \ + (c)=(uint8_t)(s)[(i)++]; \ + if((c)>=0x80) { \ + if(U8_IS_LEAD(c)) { \ + (c)=utf8_nextCharSafeBody((const uint8_t *)s, &(i), (int32_t)(length), c, -2); \ + } else { \ + (c)=U_SENTINEL; \ + } \ + } \ +} + +#define L8_PREV(s, start, i, c) { \ + (c)=(uint8_t)(s)[--(i)]; \ + if((c)>=0x80) { \ + if((c)<=0xbf) { \ + (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -2); \ + } else { \ + (c)=U_SENTINEL; \ + } \ + } \ +} + +/* -------------------------------------------------------------------------- */ + +static void printUChars(const uint8_t *uchars, int16_t len); + +static void TestCodeUnitValues(void); +static void TestCharLength(void); +static void TestGetChar(void); +static void TestNextPrevChar(void); +static void TestFwdBack(void); +static void TestSetChar(void); +static void TestAppendChar(void); +static void TestAppend(void); +static void TestSurrogates(void); + +void addUTF8Test(TestNode** root); + +void +addUTF8Test(TestNode** root) +{ + addTest(root, &TestCodeUnitValues, "utf8tst/TestCodeUnitValues"); + addTest(root, &TestCharLength, "utf8tst/TestCharLength" ); + addTest(root, &TestGetChar, "utf8tst/TestGetChar" ); + addTest(root, &TestNextPrevChar, "utf8tst/TestNextPrevChar" ); + addTest(root, &TestFwdBack, "utf8tst/TestFwdBack" ); + addTest(root, &TestSetChar, "utf8tst/TestSetChar" ); + addTest(root, &TestAppendChar, "utf8tst/TestAppendChar" ); + addTest(root, &TestAppend, "utf8tst/TestAppend" ); + addTest(root, &TestSurrogates, "utf8tst/TestSurrogates" ); +} + +static void TestCodeUnitValues() +{ + static const uint8_t codeunit[]={0x00, 0x65, 0x7e, 0x7f, 0xc0, 0xc4, 0xf0, 0xfd, 0x80, 0x81, 0xbc, 0xbe,}; + + int16_t i; + for(i=0; i<sizeof(codeunit)/sizeof(codeunit[0]); i++){ + uint8_t c=codeunit[i]; + log_verbose("Testing code unit value of %x\n", c); + if(i<4){ + if(!UTF8_IS_SINGLE(c) || UTF8_IS_LEAD(c) || UTF8_IS_TRAIL(c) || !U8_IS_SINGLE(c) || U8_IS_LEAD(c) || U8_IS_TRAIL(c)){ + log_err("ERROR: 0x%02x is a single byte but results in single: %c lead: %c trail: %c\n", + c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n'); + } + } else if(i< 8){ + if(!UTF8_IS_LEAD(c) || UTF8_IS_SINGLE(c) || UTF8_IS_TRAIL(c) || !U8_IS_LEAD(c) || U8_IS_SINGLE(c) || U8_IS_TRAIL(c)){ + log_err("ERROR: 0x%02x is a lead byte but results in single: %c lead: %c trail: %c\n", + c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n'); + } + } else if(i< 12){ + if(!UTF8_IS_TRAIL(c) || UTF8_IS_SINGLE(c) || UTF8_IS_LEAD(c) || !U8_IS_TRAIL(c) || U8_IS_SINGLE(c) || U8_IS_LEAD(c)){ + log_err("ERROR: 0x%02x is a trail byte but results in single: %c lead: %c trail: %c\n", + c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n'); + } + } + } +} + +static void TestCharLength() +{ + static const uint32_t codepoint[]={ + 1, 0x0061, + 1, 0x007f, + 2, 0x016f, + 2, 0x07ff, + 3, 0x0865, + 3, 0x20ac, + 4, 0x20402, + 4, 0x23456, + 4, 0x24506, + 4, 0x20402, + 4, 0x10402, + 3, 0xd7ff, + 3, 0xe000, + + }; + + int16_t i; + UBool multiple; + for(i=0; i<sizeof(codepoint)/sizeof(codepoint[0]); i=(int16_t)(i+2)){ + UChar32 c=codepoint[i+1]; + if(UTF8_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U8_LENGTH(c) != (uint16_t)codepoint[i]){ + log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF8_CHAR_LENGTH(c)); + }else{ + log_verbose("The no: of code units for %lx is %d\n",c, UTF8_CHAR_LENGTH(c) ); + } + multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE); + if(UTF8_NEED_MULTIPLE_UCHAR(c) != multiple){ + log_err("ERROR: UTF8_NEED_MULTIPLE_UCHAR failed for %lx\n", c); + } + } +} + +static void TestGetChar() +{ + static const uint8_t input[]={ + /* code unit,*/ + 0x61, + 0x7f, + 0xe4, + 0xba, + 0x8c, + 0xF0, + 0x90, + 0x90, + 0x81, + 0xc0, + 0x65, + 0x31, + 0x9a, + 0xc9 + }; + static const UChar32 result[]={ + /*codepoint-unsafe, codepoint-safe(not strict) codepoint-safe(strict)*/ + 0x61, 0x61, 0x61, + 0x7f, 0x7f, 0x7f, + 0x4e8c, 0x4e8c, 0x4e8c, + 0x4e8c, 0x4e8c, 0x4e8c , + 0x4e8c, 0x4e8c, 0x4e8c, + 0x10401, 0x10401, 0x10401 , + 0x10401, 0x10401, 0x10401 , + 0x10401, 0x10401, 0x10401 , + 0x10401, 0x10401, 0x10401, + 0x25, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x65, 0x65, 0x65, + 0x31, 0x31, 0x31, + 0x31, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x240, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1 + }; + uint16_t i=0; + UChar32 c; + uint32_t offset=0; + + for(offset=0; offset<sizeof(input); offset++) { + if (offset < sizeof(input) - 1) { + UTF8_GET_CHAR_UNSAFE(input, offset, c); + if(c != result[i]){ + log_err("ERROR: UTF8_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + + } + + U8_GET_UNSAFE(input, offset, c); + if(c != result[i]){ + log_err("ERROR: U8_GET_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + + } + } + + U8_GET(input, 0, offset, sizeof(input), c); + if(UTF_IS_ERROR(result[i+1]) ? c >= 0 : c != result[i+1]){ + log_err("ERROR: UTF8_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + UTF8_GET_CHAR_SAFE(input, 0, offset, sizeof(input), c, FALSE); + if(c != result[i+1]){ + log_err("ERROR: UTF8_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + UTF8_GET_CHAR_SAFE(input, 0, offset, sizeof(input), c, TRUE); + if(c != result[i+2]){ + log_err("ERROR: UTF8_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c); + } + + i=(uint16_t)(i+3); + } +} + +static void TestNextPrevChar(){ + static const uint8_t input[]={0x61, 0xf0, 0x90, 0x90, 0x81, 0xc0, 0x80, 0xfd, 0xbe, 0xc2, 0x61, 0x81, 0x90, 0x90, 0xf0, 0x00}; + static const UChar32 result[]={ + /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/ + 0x0061, 0x0061, 0x0061, 0x0000, 0x0000, 0x0000, + 0x10401, 0x10401, 0x10401, 0xf0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x2841410, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xa1050, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x81, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x2841, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x00, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, 0x61, 0x61, 0x61, + 0x80, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xc2, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0xfd, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, 0x77e, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, + 0xbe, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xfd, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0xa1, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x00, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, + 0x61, 0x61, 0x61, 0xc0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x81, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x10401, 0x10401, 0x10401, + 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x410, UTF_ERROR_VALUE, UTF_ERROR_VALUE, + 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x410, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, + 0x0840, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xf0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, + 0x0000, 0x0000, 0x0000, 0x0061, 0x0061, 0x0061 + }; + static const int32_t movedOffset[]={ + /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/ + 1, 1, 1, 15, 15, 15, + 5, 5, 5, 14, 14 , 14, + 3, 3, 3, 9, 13, 13, + 4, 4, 4, 9, 12, 12, + 5, 5, 5, 9, 11, 11, + 7, 7, 7, 10, 10, 10, + 7, 7, 7, 9, 9, 9, + 8, 9, 9, 7, 7, 7, + 9, 9, 9, 7, 7, 7, + 11, 10, 10, 5, 5, 5, + 11, 11, 11, 5, 5, 5, + 12, 12, 12, 1, 1, 1, + 13, 13, 13, 1, 1, 1, + 14, 14, 14, 1, 1, 1, + 14, 15, 15, 1, 1, 1, + 14, 16, 16, 0, 0, 0, + + + }; + + + UChar32 c=0x0000; + uint32_t i=0; + uint32_t offset=0; + int32_t setOffset=0; + for(offset=0; offset<sizeof(input); offset++){ + if (offset < sizeof(input) - 2) { /* Can't have it go off the end of the array based on input */ + setOffset=offset; + UTF8_NEXT_CHAR_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i]){ + log_err("ERROR: UTF8_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i], setOffset); + } + if(c != result[i]){ + log_err("ERROR: UTF8_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + + setOffset=offset; + U8_NEXT_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i]){ + log_err("ERROR: U8_NEXT_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i], setOffset); + } + if(c != result[i]){ + log_err("ERROR: U8_NEXT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c); + } + } + + setOffset=offset; + UTF8_NEXT_CHAR_SAFE(input, setOffset, sizeof(input), c, FALSE); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: UTF8_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+1], setOffset); + } + if(c != result[i+1]){ + log_err("ERROR: UTF8_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + setOffset=offset; + U8_NEXT(input, setOffset, sizeof(input), c); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: U8_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+1], setOffset); + } + if(UTF_IS_ERROR(result[i+1]) ? c >= 0 : c != result[i+1]){ + log_err("ERROR: U8_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c); + } + + setOffset=offset; + UTF8_NEXT_CHAR_SAFE(input, setOffset, sizeof(input), c, TRUE); + if(setOffset != movedOffset[i+1]){ + log_err("ERROR: UTF8_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+2], setOffset); + } + if(c != result[i+2]){ + log_err("ERROR: UTF8_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c); + } + + i=i+6; + } + + i=0; + for(offset=sizeof(input); offset > 0; --offset){ + setOffset=offset; + UTF8_PREV_CHAR_UNSAFE(input, setOffset, c); + if(setOffset != movedOffset[i+3]){ + log_err("ERROR: UTF8_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+3], setOffset); + } + if(c != result[i+3]){ + log_err("ERROR: UTF8_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c); + } + + setOffset=offset; + UTF8_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE); + if(setOffset != movedOffset[i+4]){ + log_err("ERROR: UTF8_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+4], setOffset); + } + if(c != result[i+4]){ + log_err("ERROR: UTF8_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c); + } + + setOffset=offset; + U8_PREV(input, 0, setOffset, c); + if(setOffset != movedOffset[i+4]){ + log_err("ERROR: U8_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+4], setOffset); + } + if(UTF_IS_ERROR(result[i+4]) ? c >= 0 : c != result[i+4]){ + log_err("ERROR: U8_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c); + } + + setOffset=offset; + UTF8_PREV_CHAR_SAFE(input, 0, setOffset, c, TRUE); + if(setOffset != movedOffset[i+5]){ + log_err("ERROR: UTF8_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n", + offset, movedOffset[i+5], setOffset); + } + if(c != result[i+5]){ + log_err("ERROR: UTF8_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c); + } + + i=i+6; + } + + { + /* test non-characters */ + static const uint8_t nonChars[]={ + 0xef, 0xb7, 0x90, /* U+fdd0 */ + 0xef, 0xbf, 0xbf, /* U+feff */ + 0xf0, 0x9f, 0xbf, 0xbe, /* U+1fffe */ + 0xf0, 0xbf, 0xbf, 0xbf, /* U+3ffff */ + 0xf4, 0x8f, 0xbf, 0xbe /* U+10fffe */ + }; + + UChar32 ch; + int32_t idx; + + for(idx=0; idx<(int32_t)sizeof(nonChars);) { + U8_NEXT(nonChars, idx, sizeof(nonChars), ch); + if(!U_IS_UNICODE_NONCHAR(ch)) { + log_err("U8_NEXT(before %d) failed to read a non-character\n", idx); + } + } + for(idx=(int32_t)sizeof(nonChars); idx>0;) { + U8_PREV(nonChars, 0, idx, ch); + if(!U_IS_UNICODE_NONCHAR(ch)) { + log_err("U8_PREV(at %d) failed to read a non-character\n", idx); + } + } + } +} + +static void TestFwdBack(){ + static const uint8_t input[]={0x61, 0xF0, 0x90, 0x90, 0x81, 0xff, 0x62, 0xc0, 0x80, 0x7f, 0x8f, 0xc0, 0x63, 0x81, 0x90, 0x90, 0xF0, 0x00}; + static const uint16_t fwd_unsafe[] ={1, 5, 6, 7, 9, 10, 11, 13, 14, 15, 16, 20, }; + static const uint16_t fwd_safe[] ={1, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; + static const uint16_t back_unsafe[]={17, 16, 12, 11, 9, 7, 6, 5, 1, 0}; + static const uint16_t back_safe[] ={17, 16, 15, 14, 13, 12, 11, 10, 9, 7, 6, 5, 1, 0}; + + static const uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1, 5}; + static const uint16_t fwd_N_unsafe[] ={0, 1, 6, 10, 11, 14, 15}; + static const uint16_t fwd_N_safe[] ={0, 1, 6, 10, 11, 13, 14, 18}; /*safe macro keeps it at the end of the string */ + static const uint16_t back_N_unsafe[]={18, 17, 12, 7, 6, 1, 0}; + static const uint16_t back_N_safe[] ={18, 17, 15, 12, 11, 9, 7, 0}; + + + uint32_t offunsafe=0, offsafe=0; + + uint32_t i=0; + while(offunsafe < sizeof(input)){ + UTF8_FWD_1_UNSAFE(input, offunsafe); + if(offunsafe != fwd_unsafe[i]){ + log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe); + } + i++; + } + + i=0; + while(offunsafe < sizeof(input)){ + U8_FWD_1_UNSAFE(input, offunsafe); + if(offunsafe != fwd_unsafe[i]){ + log_err("ERROR: U8_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe); + } + i++; + } + + i=0; + while(offsafe < sizeof(input)){ + UTF8_FWD_1_SAFE(input, offsafe, sizeof(input)); + if(offsafe != fwd_safe[i]){ + log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe); + } + i++; + } + + i=0; + while(offsafe < sizeof(input)){ + U8_FWD_1(input, offsafe, sizeof(input)); + if(offsafe != fwd_safe[i]){ + log_err("ERROR: U8_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe); + } + i++; + } + + offunsafe=sizeof(input); + i=0; + while(offunsafe > 0){ + UTF8_BACK_1_UNSAFE(input, offunsafe); + if(offunsafe != back_unsafe[i]){ + log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe); + } + i++; + } + + offunsafe=sizeof(input); + i=0; + while(offunsafe > 0){ + U8_BACK_1_UNSAFE(input, offunsafe); + if(offunsafe != back_unsafe[i]){ + log_err("ERROR: U8_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe); + } + i++; + } + + i=0; + offsafe=sizeof(input); + while(offsafe > 0){ + UTF8_BACK_1_SAFE(input, 0, offsafe); + if(offsafe != back_safe[i]){ + log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe); + } + i++; + } + + i=0; + offsafe=sizeof(input); + while(offsafe > 0){ + U8_BACK_1(input, 0, offsafe); + if(offsafe != back_safe[i]){ + log_err("ERROR: U8_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe); + } + i++; + } + + offunsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + UTF8_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != fwd_N_unsafe[i]){ + log_err("ERROR: Forward_N_unsafe offset=%d expected:%d, Got:%d\n", i, fwd_N_unsafe[i], offunsafe); + } + } + + offunsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + U8_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != fwd_N_unsafe[i]){ + log_err("ERROR: U8_FWD_N_UNSAFE offset=%d expected:%d, Got:%d\n", i, fwd_N_unsafe[i], offunsafe); + } + } + + offsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + UTF8_FWD_N_SAFE(input, offsafe, sizeof(input), Nvalue[i]); + if(offsafe != fwd_N_safe[i]){ + log_err("ERROR: Forward_N_safe offset=%d expected:%d, Got:%d\n", i, fwd_N_safe[i], offsafe); + } + + } + + offsafe=0; + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + U8_FWD_N(input, offsafe, sizeof(input), Nvalue[i]); + if(offsafe != fwd_N_safe[i]){ + log_err("ERROR: U8_FWD_N offset=%d expected:%d, Got:%d\n", i, fwd_N_safe[i], offsafe); + } + + } + + offunsafe=sizeof(input); + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + UTF8_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != back_N_unsafe[i]){ + log_err("ERROR: backward_N_unsafe offset=%d expected:%d, Got:%d\n", i, back_N_unsafe[i], offunsafe); + } + } + + offunsafe=sizeof(input); + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ + U8_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]); + if(offunsafe != back_N_unsafe[i]){ + log_err("ERROR: U8_BACK_N_UNSAFE offset=%d expected:%d, Got:%d\n", i, back_N_unsafe[i], offunsafe); + } + } + + offsafe=sizeof(input); + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + UTF8_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]); + if(offsafe != back_N_safe[i]){ + log_err("ERROR: backward_N_safe offset=%d expected:%d, Got:%ld\n", i, back_N_safe[i], offsafe); + } + } + + offsafe=sizeof(input); + for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){ + U8_BACK_N(input, 0, offsafe, Nvalue[i]); + if(offsafe != back_N_safe[i]){ + log_err("ERROR: U8_BACK_N offset=%d expected:%d, Got:%ld\n", i, back_N_safe[i], offsafe); + } + } +} + +static void TestSetChar(){ + static const uint8_t input[] + = {0x61, 0xe4, 0xba, 0x8c, 0x7f, 0xfe, 0x62, 0xc5, 0x7f, 0x61, 0x80, 0x80, 0xe0, 0x00 }; + static const int16_t start_unsafe[] + = {0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 12, 13 }; + static const int16_t start_safe[] + = {0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; + static const int16_t limit_unsafe[] + = {0, 1, 4, 4, 4, 5, 6, 7, 9, 9, 10, 10, 10, 15 }; + static const int16_t limit_safe[] + = {0, 1, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; + + uint32_t i=0; + int32_t offset=0, setOffset=0; + for(offset=0; offset<(int32_t)sizeof(input); offset++){ + setOffset=offset; + UTF8_SET_CHAR_START_UNSAFE(input, setOffset); + if(setOffset != start_unsafe[i]){ + log_err("ERROR: UTF8_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_unsafe[i], setOffset); + } + + setOffset=offset; + U8_SET_CP_START_UNSAFE(input, setOffset); + if(setOffset != start_unsafe[i]){ + log_err("ERROR: U8_SET_CP_START_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_unsafe[i], setOffset); + } + + setOffset=offset; + UTF8_SET_CHAR_START_SAFE(input, 0, setOffset); + if(setOffset != start_safe[i]){ + log_err("ERROR: UTF8_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_safe[i], setOffset); + } + + setOffset=offset; + U8_SET_CP_START(input, 0, setOffset); + if(setOffset != start_safe[i]){ + log_err("ERROR: U8_SET_CP_START failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_safe[i], setOffset); + } + + if (offset != 0) { /* Can't have it go off the end of the array */ + setOffset=offset; + UTF8_SET_CHAR_LIMIT_UNSAFE(input, setOffset); + if(setOffset != limit_unsafe[i]){ + log_err("ERROR: UTF8_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_unsafe[i], setOffset); + } + + setOffset=offset; + U8_SET_CP_LIMIT_UNSAFE(input, setOffset); + if(setOffset != limit_unsafe[i]){ + log_err("ERROR: U8_SET_CP_LIMIT_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_unsafe[i], setOffset); + } + } + + setOffset=offset; + UTF8_SET_CHAR_LIMIT_SAFE(input,0, setOffset, sizeof(input)); + if(setOffset != limit_safe[i]){ + log_err("ERROR: UTF8_SET_CHAR_LIMIT_SAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset); + } + + setOffset=offset; + U8_SET_CP_LIMIT(input,0, setOffset, sizeof(input)); + if(setOffset != limit_safe[i]){ + log_err("ERROR: U8_SET_CP_LIMIT failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset); + } + + i++; + } +} + +static void TestAppendChar(){ + static const uint8_t s[11]={0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}; + static const uint32_t test[]={ + /*append-position(unsafe), CHAR to be appended */ + 0, 0x10401, + 2, 0x0028, + 2, 0x007f, + 3, 0xd801, + 1, 0x20402, + 8, 0x10401, + 5, 0xc0, + 5, 0xc1, + 5, 0xfd, + 6, 0x80, + 6, 0x81, + 6, 0xbf, + 7, 0xfe, + + /*append-position(safe), CHAR to be appended */ + 0, 0x10401, + 2, 0x0028, + 3, 0x7f, + 3, 0xd801, /* illegal for UTF-8 starting with Unicode 3.2 */ + 1, 0x20402, + 9, 0x10401, + 5, 0xc0, + 5, 0xc1, + 5, 0xfd, + 6, 0x80, + 6, 0x81, + 6, 0xbf, + 7, 0xfe, + + }; + static const uint16_t movedOffset[]={ + /*offset-moved-to(unsafe)*/ + 4, /*for append-pos: 0 , CHAR 0x10401*/ + 3, + 3, + 6, + 5, + 12, + 7, + 7, + 7, + 8, + 8, + 8, + 9, + + /*offset-moved-to(safe)*/ + 4, /*for append-pos: 0, CHAR 0x10401*/ + 3, + 4, + 6, + 5, + 11, + 7, + 7, + 7, + 8, + 8, + 8, + 9, + + }; + + static const uint8_t result[][11]={ + /*unsafe*/ + {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x7f, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0xed, 0xa0, 0x81, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0xF0, 0x90, 0x90}, + + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00}, + + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00}, + + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00}, + /*safe*/ + {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x7f, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0xef, 0xbf, 0xbf, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc2, 0x9f}, /*gets UTF8_ERROR_VALUE_2 which takes 2 bytes 0xc0, 0x9f*/ + + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00}, + + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00}, + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00}, + + {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00}, + + }; + uint16_t i, count=0; + uint8_t str[12]; + uint32_t offset; +/* UChar32 c=0;*/ + uint16_t size=sizeof(s)/sizeof(s[0]); + for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){ + uprv_memcpy(str, s, size); + offset=test[i]; + if(count<13){ + UTF8_APPEND_CHAR_UNSAFE(str, offset, test[i+1]); + if(offset != movedOffset[count]){ + log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", + count, movedOffset[count], offset); + + } + if(uprv_memcmp(str, result[count], size) !=0){ + log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed for count=%d. \nExpected:", count); + printUChars(result[count], size); + log_err("\nGot: "); + printUChars(str, size); + log_err("\n"); + } + }else{ + UTF8_APPEND_CHAR_SAFE(str, offset, size, test[i+1]); + if(offset != movedOffset[count]){ + log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", + count, movedOffset[count], offset); + + } + if(uprv_memcmp(str, result[count], size) !=0){ + log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed for count=%d. \nExpected:", count); + printUChars(result[count], size); + log_err("\nGot: "); + printUChars(str, size); + log_err("\n"); + } + /*call the API instead of MACRO + uprv_memcpy(str, s, size); + offset=test[i]; + c=test[i+1]; + if((uint32_t)(c)<=0x7f) { + (str)[(offset)++]=(uint8_t)(c); + } else { + (offset)=utf8_appendCharSafeBody(str, (int32_t)(offset), (int32_t)(size), c); + } + if(offset != movedOffset[count]){ + log_err("ERROR: utf8_appendCharSafeBody() failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", + count, movedOffset[count], offset); + + } + if(uprv_memcmp(str, result[count], size) !=0){ + log_err("ERROR: utf8_appendCharSafeBody() failed for count=%d. \nExpected:", count); + printUChars(result[count], size); + printf("\nGot: "); + printUChars(str, size); + printf("\n"); + } + */ + } + count++; + } + + +} + +static void TestAppend() { + static const UChar32 codePoints[]={ + 0x61, 0xdf, 0x901, 0x3040, + 0xac00, 0xd800, 0xdbff, 0xdcde, + 0xdffd, 0xe000, 0xffff, 0x10000, + 0x12345, 0xe0021, 0x10ffff, 0x110000, + 0x234567, 0x7fffffff, -1, -1000, + 0, 0x400 + }; + static const uint8_t expectUnsafe[]={ + 0x61, 0xc3, 0x9f, 0xe0, 0xa4, 0x81, 0xe3, 0x81, 0x80, + 0xea, 0xb0, 0x80, 0xed, 0xa0, 0x80, 0xed, 0xaf, 0xbf, 0xed, 0xb3, 0x9e, + 0xed, 0xbf, 0xbd, 0xee, 0x80, 0x80, 0xef, 0xbf, 0xbf, 0xf0, 0x90, 0x80, 0x80, + 0xf0, 0x92, 0x8d, 0x85, 0xf3, 0xa0, 0x80, 0xa1, 0xf4, 0x8f, 0xbf, 0xbf, /* not 0x110000 */ + /* none from this line */ + 0, 0xd0, 0x80 + }, expectSafe[]={ + 0x61, 0xc3, 0x9f, 0xe0, 0xa4, 0x81, 0xe3, 0x81, 0x80, + 0xea, 0xb0, 0x80, /* no surrogates */ + /* no surrogates */ 0xee, 0x80, 0x80, 0xef, 0xbf, 0xbf, 0xf0, 0x90, 0x80, 0x80, + 0xf0, 0x92, 0x8d, 0x85, 0xf3, 0xa0, 0x80, 0xa1, 0xf4, 0x8f, 0xbf, 0xbf, /* not 0x110000 */ + /* none from this line */ + 0, 0xd0, 0x80 + }; + + uint8_t buffer[100]; + UChar32 c; + int32_t i, length; + UBool isError, expectIsError, wrongIsError; + + length=0; + for(i=0; i<LENGTHOF(codePoints); ++i) { + c=codePoints[i]; + if(c<0 || 0x10ffff<c) { + continue; /* skip non-code points for U8_APPEND_UNSAFE */ + } + + U8_APPEND_UNSAFE(buffer, length, c); + } + if(length!=LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length)) { + log_err("U8_APPEND_UNSAFE did not generate the expected output\n"); + } + + length=0; + wrongIsError=FALSE; + for(i=0; i<LENGTHOF(codePoints); ++i) { + c=codePoints[i]; + expectIsError= c<0 || 0x10ffff<c || U_IS_SURROGATE(c); + isError=FALSE; + + U8_APPEND(buffer, length, LENGTHOF(buffer), c, isError); + wrongIsError|= isError!=expectIsError; + } + if(wrongIsError) { + log_err("U8_APPEND did not set isError correctly\n"); + } + if(length!=LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length)) { + log_err("U8_APPEND did not generate the expected output\n"); + } +} + +static void +TestSurrogates() { + static const uint8_t b[]={ + 0xc3, 0x9f, /* 00DF */ + 0xed, 0x9f, 0xbf, /* D7FF */ + 0xed, 0xa0, 0x81, /* D801 */ + 0xed, 0xbf, 0xbe, /* DFFE */ + 0xee, 0x80, 0x80, /* E000 */ + 0xf0, 0x97, 0xbf, 0xbe /* 17FFE */ + }; + static const UChar32 cp[]={ + 0xdf, 0xd7ff, 0xd801, 0xdffe, 0xe000, 0x17ffe + }; + + UChar32 cu, cs, cl; + int32_t i, j, k, iu, is, il, length; + + k=0; /* index into cp[] */ + length=LENGTHOF(b); + for(i=0; i<length;) { + j=i; + U8_NEXT_UNSAFE(b, j, cu); + iu=j; + + j=i; + U8_NEXT(b, j, length, cs); + is=j; + + j=i; + L8_NEXT(b, j, length, cl); + il=j; + + if(cu!=cp[k]) { + log_err("U8_NEXT_UNSAFE(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cu, (long)cp[k]); + } + + /* U8_NEXT() returns <0 for surrogate code points */ + if(U_IS_SURROGATE(cu) ? cs>=0 : cs!=cu) { + log_err("U8_NEXT(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cs, (long)cu); + } + + /* L8_NEXT() returns surrogate code points like U8_NEXT_UNSAFE() */ + if(cl!=cu) { + log_err("L8_NEXT(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cl, (long)cu); + } + + if(is!=iu || il!=iu) { + log_err("U8_NEXT(b[%ld]) or L8_NEXT(b[%ld]) did not advance the index correctly\n", (long)i, (long)i); + } + + ++k; /* next code point */ + i=iu; /* advance by one UTF-8 sequence */ + } + + while(i>0) { + --k; /* previous code point */ + + j=i; + U8_PREV_UNSAFE(b, j, cu); + iu=j; + + j=i; + U8_PREV(b, 0, j, cs); + is=j; + + j=i; + L8_PREV(b, 0, j, cl); + il=j; + + if(cu!=cp[k]) { + log_err("U8_PREV_UNSAFE(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cu, (long)cp[k]); + } + + /* U8_PREV() returns <0 for surrogate code points */ + if(U_IS_SURROGATE(cu) ? cs>=0 : cs!=cu) { + log_err("U8_PREV(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cs, (long)cu); + } + + /* L8_PREV() returns surrogate code points like U8_PREV_UNSAFE() */ + if(cl!=cu) { + log_err("L8_PREV(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cl, (long)cu); + } + + if(is!=iu || il !=iu) { + log_err("U8_PREV(b[%ld]) or L8_PREV(b[%ld]) did not advance the index correctly\n", (long)i, (long)i); + } + + i=iu; /* go back by one UTF-8 sequence */ + } +} + +static void printUChars(const uint8_t *uchars, int16_t len){ + int16_t i=0; + for(i=0; i<len; i++){ + log_err("0x%02x ", *(uchars+i)); + } +} diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c new file mode 100644 index 00000000000..069a8039479 --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c @@ -0,0 +1,487 @@ +/* + **************************************************************************** + * Copyright (c) 1997-2007, International Business Machines Corporation and * + * others. All Rights Reserved. * + **************************************************************************** + */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/utmscale.h" +#include "unicode/ucal.h" + +#include "cintltst.h" + +#include <stdlib.h> +#include <time.h> + +#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +#define LOOP_COUNT 10000 + +static void TestAPI(void); +static void TestData(void); +static void TestMonkey(void); +static void TestDotNet(void); + +void addUtmsTest(TestNode** root); + +void addUtmsTest(TestNode** root) +{ + addTest(root, &TestAPI, "tsformat/utmstest/TestAPI"); + addTest(root, &TestData, "tsformat/utmstest/TestData"); + addTest(root, &TestMonkey, "tsformat/utmstest/TestMonkey"); + addTest(root, &TestDotNet, "tsformat/utmstest/TestDotNet"); +} + +/** + * Return a random int64_t where U_INT64_MIN <= ran <= U_INT64_MAX. + */ +static uint64_t randomInt64(void) +{ + int64_t ran = 0; + int32_t i; + static UBool initialized = FALSE; + + if (!initialized) { + srand((unsigned)time(NULL)); + initialized = TRUE; + } + + /* Assume rand has at least 12 bits of precision */ + for (i = 0; i < sizeof(ran); i += 1) { + ((char*)&ran)[i] = (char)((rand() & 0x0FF0) >> 4); + } + + return ran; +} + +static int64_t ranInt; +static int64_t ranMin; +static int64_t ranMax; + +static void initRandom(int64_t min, int64_t max) +{ + uint64_t interval = max - min; + + ranMin = min; + ranMax = max; + ranInt = 0; + + /* Verify that we don't have a huge interval. */ + if (interval < (uint64_t)U_INT64_MAX) { + ranInt = interval; + } +} + +static int64_t randomInRange(void) +{ + int64_t value; + + if (ranInt != 0) { + value = randomInt64() % ranInt; + + if (value < 0) { + value = -value; + } + + value += ranMin; + } else { + do { + value = randomInt64(); + } while (value < ranMin || value > ranMax); + } + + return value; +} + +static void roundTripTest(int64_t value, UDateTimeScale scale) +{ + UErrorCode status = U_ZERO_ERROR; + int64_t rt = utmscale_toInt64(utmscale_fromInt64(value, scale, &status), scale, &status); + + if (rt != value) { + log_err("Round-trip error: time scale = %d, value = %lld, round-trip = %lld.\n", scale, value, rt); + } +} + +static void toLimitTest(int64_t toLimit, int64_t fromLimit, UDateTimeScale scale) +{ + UErrorCode status = U_ZERO_ERROR; + int64_t result = utmscale_toInt64(toLimit, scale, &status); + + if (result != fromLimit) { + log_err("toLimit failure: scale = %d, toLimit = %lld , utmscale_toInt64(toLimit, scale, &status) = %lld, fromLimit = %lld.\n", + scale, toLimit, result, fromLimit); + } +} + +static void epochOffsetTest(int64_t epochOffset, int64_t units, UDateTimeScale scale) +{ + UErrorCode status = U_ZERO_ERROR; + int64_t universal = 0; + int64_t universalEpoch = epochOffset * units; + int64_t local = utmscale_toInt64(universalEpoch, scale, &status); + + if (local != 0) { + log_err("utmscale_toInt64(epochOffset, scale, &status): scale = %d epochOffset = %lld, result = %lld.\n", scale, epochOffset, local); + } + + local = utmscale_toInt64(0, scale, &status); + + if (local != -epochOffset) { + log_err("utmscale_toInt64(0, scale): scale = %d, result = %lld.\n", scale, local); + } + + universal = utmscale_fromInt64(-epochOffset, scale, &status); + + if (universal != 0) { + log_err("from(-epochOffest, scale): scale = %d, epochOffset = %lld, result = %lld.\n", scale, epochOffset, universal); + } + + universal = utmscale_fromInt64(0, scale, &status); + + if (universal != universalEpoch) { + log_err("utmscale_fromInt64(0, scale): scale = %d, result = %lld.\n", scale, universal); + } +} + +static void TestEpochOffsets(void) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t scale; + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t units = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_UNITS_VALUE, &status); + int64_t epochOffset = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_EPOCH_OFFSET_VALUE, &status); + + epochOffsetTest(epochOffset, units, (UDateTimeScale)scale); + } +} + +static void TestFromLimits(void) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t scale; + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); + int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); + + roundTripTest(fromMin, (UDateTimeScale)scale); + roundTripTest(fromMax, (UDateTimeScale)scale); + } +} + +static void TestToLimits(void) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t scale; + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); + int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); + int64_t toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status); + int64_t toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status); + + toLimitTest(toMin, fromMin, (UDateTimeScale)scale); + toLimitTest(toMax, fromMax, (UDateTimeScale)scale); + } +} + +static void TestFromInt64(void) +{ + int32_t scale; + int64_t result; + UErrorCode status = U_ZERO_ERROR; + + result = utmscale_fromInt64(0, -1, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(0, -1, status) did not set status to U_ILLEGAL_ARGUMENT_ERROR.\n"); + } + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t fromMin, fromMax; + + status = U_ZERO_ERROR; + fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); + fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); + + status = U_ZERO_ERROR; + result = utmscale_fromInt64(0, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + status = U_ZERO_ERROR; + result = utmscale_fromInt64(fromMin, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(fromMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + if (fromMin > U_INT64_MIN) { + status = U_ZERO_ERROR; + result = utmscale_fromInt64(fromMin - 1, (UDateTimeScale)scale, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(fromMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + } + + status = U_ZERO_ERROR; + result = utmscale_fromInt64(fromMax, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(fromMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + if (fromMax < U_INT64_MAX) { + status = U_ZERO_ERROR; + result = utmscale_fromInt64(fromMax + 1, (UDateTimeScale)scale, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(fromMax + 1, %d, &status) didn't generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + } + } + + status = U_ZERO_ERROR; + result = utmscale_fromInt64(0, UDTS_MAX_SCALE, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_fromInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); + } +} + +static void TestToInt64(void) +{ + int32_t scale; + int64_t result; + UErrorCode status = U_ZERO_ERROR; + + result = utmscale_toInt64(0, -1, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(0, -1, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); + } + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t toMin, toMax; + + status = U_ZERO_ERROR; + toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status); + toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status); + + status = U_ZERO_ERROR; + result = utmscale_toInt64(0, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + status = U_ZERO_ERROR; + result = utmscale_toInt64(toMin, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(toMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + if (toMin > U_INT64_MIN) { + status = U_ZERO_ERROR; + result = utmscale_toInt64(toMin - 1, (UDateTimeScale)scale, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(toMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + } + + + status = U_ZERO_ERROR; + result = utmscale_toInt64(toMax, (UDateTimeScale)scale, &status); + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(toMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + + if (toMax < U_INT64_MAX) { + status = U_ZERO_ERROR; + result = utmscale_toInt64(toMax + 1, (UDateTimeScale)scale, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(toMax + 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); + } + } + } + + status = U_ZERO_ERROR; + result = utmscale_toInt64(0, UDTS_MAX_SCALE, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + log_err("utmscale_toInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); + } +} + +static void TestAPI(void) +{ + TestFromInt64(); + TestToInt64(); +} + +static void TestData(void) +{ + TestEpochOffsets(); + TestFromLimits(); + TestToLimits(); +} + +static void TestMonkey(void) +{ + int32_t scale; + UErrorCode status = U_ZERO_ERROR; + + for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { + int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); + int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); + int32_t i; + + initRandom(fromMin, fromMax); + + for (i = 0; i < LOOP_COUNT; i += 1) { + int64_t value = randomInRange(); + + roundTripTest(value, (UDateTimeScale)scale); + } + } +} + +struct DotNetDateTimeTicks { + int32_t year; + int32_t month; + int32_t day; + int64_t ticks; +}; +typedef struct DotNetDateTimeTicks DotNetDateTimeTicks; + +/* + * This data was generated by C++.Net code like + * Console::WriteLine(L" {{ {0}, 1, 1, INT64_C({1}) }},", year, DateTime(year, 1, 1).Ticks); + * with the DateTime constructor taking int values for year, month, and date. + */ +static const DotNetDateTimeTicks dotNetDateTimeTicks[]={ + /* year, month, day, ticks */ + { 100, 1, 1, INT64_C(31241376000000000) }, + { 100, 3, 1, INT64_C(31292352000000000) }, + { 200, 1, 1, INT64_C(62798112000000000) }, + { 200, 3, 1, INT64_C(62849088000000000) }, + { 300, 1, 1, INT64_C(94354848000000000) }, + { 300, 3, 1, INT64_C(94405824000000000) }, + { 400, 1, 1, INT64_C(125911584000000000) }, + { 400, 3, 1, INT64_C(125963424000000000) }, + { 500, 1, 1, INT64_C(157469184000000000) }, + { 500, 3, 1, INT64_C(157520160000000000) }, + { 600, 1, 1, INT64_C(189025920000000000) }, + { 600, 3, 1, INT64_C(189076896000000000) }, + { 700, 1, 1, INT64_C(220582656000000000) }, + { 700, 3, 1, INT64_C(220633632000000000) }, + { 800, 1, 1, INT64_C(252139392000000000) }, + { 800, 3, 1, INT64_C(252191232000000000) }, + { 900, 1, 1, INT64_C(283696992000000000) }, + { 900, 3, 1, INT64_C(283747968000000000) }, + { 1000, 1, 1, INT64_C(315253728000000000) }, + { 1000, 3, 1, INT64_C(315304704000000000) }, + { 1100, 1, 1, INT64_C(346810464000000000) }, + { 1100, 3, 1, INT64_C(346861440000000000) }, + { 1200, 1, 1, INT64_C(378367200000000000) }, + { 1200, 3, 1, INT64_C(378419040000000000) }, + { 1300, 1, 1, INT64_C(409924800000000000) }, + { 1300, 3, 1, INT64_C(409975776000000000) }, + { 1400, 1, 1, INT64_C(441481536000000000) }, + { 1400, 3, 1, INT64_C(441532512000000000) }, + { 1500, 1, 1, INT64_C(473038272000000000) }, + { 1500, 3, 1, INT64_C(473089248000000000) }, + { 1600, 1, 1, INT64_C(504595008000000000) }, + { 1600, 3, 1, INT64_C(504646848000000000) }, + { 1700, 1, 1, INT64_C(536152608000000000) }, + { 1700, 3, 1, INT64_C(536203584000000000) }, + { 1800, 1, 1, INT64_C(567709344000000000) }, + { 1800, 3, 1, INT64_C(567760320000000000) }, + { 1900, 1, 1, INT64_C(599266080000000000) }, + { 1900, 3, 1, INT64_C(599317056000000000) }, + { 2000, 1, 1, INT64_C(630822816000000000) }, + { 2000, 3, 1, INT64_C(630874656000000000) }, + { 2100, 1, 1, INT64_C(662380416000000000) }, + { 2100, 3, 1, INT64_C(662431392000000000) }, + { 2200, 1, 1, INT64_C(693937152000000000) }, + { 2200, 3, 1, INT64_C(693988128000000000) }, + { 2300, 1, 1, INT64_C(725493888000000000) }, + { 2300, 3, 1, INT64_C(725544864000000000) }, + { 2400, 1, 1, INT64_C(757050624000000000) }, + { 2400, 3, 1, INT64_C(757102464000000000) }, + { 2500, 1, 1, INT64_C(788608224000000000) }, + { 2500, 3, 1, INT64_C(788659200000000000) }, + { 2600, 1, 1, INT64_C(820164960000000000) }, + { 2600, 3, 1, INT64_C(820215936000000000) }, + { 2700, 1, 1, INT64_C(851721696000000000) }, + { 2700, 3, 1, INT64_C(851772672000000000) }, + { 2800, 1, 1, INT64_C(883278432000000000) }, + { 2800, 3, 1, INT64_C(883330272000000000) }, + { 2900, 1, 1, INT64_C(914836032000000000) }, + { 2900, 3, 1, INT64_C(914887008000000000) }, + { 3000, 1, 1, INT64_C(946392768000000000) }, + { 3000, 3, 1, INT64_C(946443744000000000) }, + { 1, 1, 1, INT64_C(0) }, + { 1601, 1, 1, INT64_C(504911232000000000) }, + { 1899, 12, 31, INT64_C(599265216000000000) }, + { 1904, 1, 1, INT64_C(600527520000000000) }, + { 1970, 1, 1, INT64_C(621355968000000000) }, + { 2001, 1, 1, INT64_C(631139040000000000) }, + { 9900, 3, 1, INT64_C(3123873216000000000) }, + { 9999, 12, 31, INT64_C(3155378112000000000) } +}; + +/* + * ICU's Universal Time Scale is designed to be tick-for-tick compatible with + * .Net System.DateTime. Verify that this is so for the + * .Net-supported date range (years 1-9999 AD). + * This requires a proleptic Gregorian calendar because that's what .Net uses. + * Proleptic: No Julian/Gregorian switchover, or a switchover before + * any date that we test, that is, before 0001 AD. + */ +static void +TestDotNet() { + static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */ + const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */ + const int64_t dayTicks = 86400 * INT64_C(10000000); + const DotNetDateTimeTicks *dt; + UCalendar *cal; + UErrorCode errorCode; + UDate icuDate; + int64_t ticks, millis; + int32_t i; + + /* Open a proleptic Gregorian calendar. */ + errorCode = U_ZERO_ERROR; + cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode); + ucal_setGregorianChange(cal, -1000000 * (dayMillis * (UDate)1), &errorCode); + if(U_FAILURE(errorCode)) { + log_err("ucal_open(UTC/proleptic Gregorian) failed: %s\n", u_errorName(errorCode)); + ucal_close(cal); + return; + } + for(i = 0; i < LENGTHOF(dotNetDateTimeTicks); ++i) { + /* Test conversion from .Net/Universal time to ICU time. */ + dt = dotNetDateTimeTicks + i; + millis = utmscale_toInt64(dt->ticks, UDTS_ICU4C_TIME, &errorCode); + ucal_clear(cal); + ucal_setDate(cal, dt->year, dt->month - 1, dt->day, &errorCode); /* Java & ICU use January = month 0. */ + icuDate = ucal_getMillis(cal, &errorCode); + if(millis != icuDate) { + /* Print days not millis to stay within printf() range. */ + log_err("utmscale_toInt64(ticks[%d], ICU4C)=%dd != %dd=ucal_getMillis(%04d-%02d-%02d)\n", + (int)i, (int)(millis/dayMillis), (int)(icuDate/dayMillis), (int)dt->year, (int)dt->month, (int)dt->day); + } + + /* Test conversion from ICU time to .Net/Universal time. */ + ticks = utmscale_fromInt64((int64_t)icuDate, UDTS_ICU4C_TIME, &errorCode); + if(ticks != dt->ticks) { + /* Print days not ticks to stay within printf() range. */ + log_err("utmscale_fromInt64(date[%d], ICU4C)=%dd != %dd=.Net System.DateTime(%04d-%02d-%02d).Ticks\n", + (int)i, (int)(ticks/dayTicks), (int)(dt->ticks/dayTicks), (int)dt->year, (int)dt->month, (int)dt->day); + } + } + + ucal_close(cal); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c new file mode 100644 index 00000000000..ec99292aa9f --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c @@ -0,0 +1,707 @@ +/* + ******************************************************************************* + * Copyright (C) 1997-2006, International Business Machines + * Corporation and others. All Rights Reserved. + ******************************************************************************* + * Date Name Description + * 06/23/00 aliu Creation. + ******************************************************************************* + */ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_TRANSLITERATION + +#include <stdlib.h> +#include <string.h> +#include "unicode/utrans.h" +#include "unicode/ustring.h" +#include "cintltst.h" + +#define TEST(x) addTest(root, &x, "utrans/" # x) + +static void TestAPI(void); +static void TestSimpleRules(void); +static void TestFilter(void); +static void TestOpenInverse(void); +static void TestClone(void); +static void TestRegisterUnregister(void); +static void TestExtractBetween(void); +static void TestUnicodeIDs(void); + +static void _expectRules(const char*, const char*, const char*); +static void _expect(const UTransliterator* trans, const char* cfrom, const char* cto); + +void addUTransTest(TestNode** root); + + +void +addUTransTest(TestNode** root) { + TEST(TestAPI); + TEST(TestSimpleRules); + TEST(TestFilter); + TEST(TestOpenInverse); + TEST(TestClone); + TEST(TestRegisterUnregister); + TEST(TestExtractBetween); + TEST(TestUnicodeIDs); +} + +/*------------------------------------------------------------------ + * Replaceable glue + * + * To test the Replaceable glue we have to dummy up a C-based + * Replaceable callback. This code is for testing purposes only. + *------------------------------------------------------------------*/ + +typedef struct XReplaceable { + UChar* text; /* MUST BE null-terminated */ +} XReplaceable; + +static void InitXReplaceable(XReplaceable* rep, const char* cstring) { + rep->text = malloc(sizeof(UChar) * (strlen(cstring)+1)); + u_uastrcpy(rep->text, cstring); +} + +static void FreeXReplaceable(XReplaceable* rep) { + if (rep->text != NULL) { + free(rep->text); + rep->text = NULL; + } +} + +/* UReplaceableCallbacks callback */ +static int32_t Xlength(const UReplaceable* rep) { + const XReplaceable* x = (const XReplaceable*)rep; + return u_strlen(x->text); +} + +/* UReplaceableCallbacks callback */ +static UChar XcharAt(const UReplaceable* rep, int32_t offset) { + const XReplaceable* x = (const XReplaceable*)rep; + return x->text[offset]; +} + +/* UReplaceableCallbacks callback */ +static UChar32 Xchar32At(const UReplaceable* rep, int32_t offset) { + const XReplaceable* x = (const XReplaceable*)rep; + return x->text[offset]; +} + +/* UReplaceableCallbacks callback */ +static void Xreplace(UReplaceable* rep, int32_t start, int32_t limit, + const UChar* text, int32_t textLength) { + XReplaceable* x = (XReplaceable*)rep; + int32_t newLen = Xlength(rep) + limit - start + textLength; + UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); + u_strncpy(newText, x->text, start); + u_strncpy(newText + start, text, textLength); + u_strcpy(newText + start + textLength, x->text + limit); + free(x->text); + x->text = newText; +} + +/* UReplaceableCallbacks callback */ +static void Xcopy(UReplaceable* rep, int32_t start, int32_t limit, int32_t dest) { + XReplaceable* x = (XReplaceable*)rep; + int32_t newLen = Xlength(rep) + limit - start; + UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); + u_strncpy(newText, x->text, dest); + u_strncpy(newText + dest, x->text + start, limit - start); + u_strcpy(newText + dest + limit - start, x->text + dest); + free(x->text); + x->text = newText; +} + +/* UReplaceableCallbacks callback */ +static void Xextract(UReplaceable* rep, int32_t start, int32_t limit, UChar* dst) { + XReplaceable* x = (XReplaceable*)rep; + int32_t len = limit - start; + u_strncpy(dst, x->text, len); +} + +static void InitXReplaceableCallbacks(UReplaceableCallbacks* callbacks) { + callbacks->length = Xlength; + callbacks->charAt = XcharAt; + callbacks->char32At = Xchar32At; + callbacks->replace = Xreplace; + callbacks->extract = Xextract; + callbacks->copy = Xcopy; +} + +/*------------------------------------------------------------------ + * Tests + *------------------------------------------------------------------*/ + +static void TestAPI() { + enum { BUF_CAP = 128 }; + char buf[BUF_CAP], buf2[BUF_CAP]; + UErrorCode status = U_ZERO_ERROR; + UTransliterator* trans = NULL; + int32_t i, n; + + /* Test getAvailableIDs */ + n = utrans_countAvailableIDs(); + if (n < 1) { + log_err("FAIL: utrans_countAvailableIDs() returned %d\n", n); + } else { + log_verbose("System ID count: %d\n", n); + } + for (i=0; i<n; ++i) { + utrans_getAvailableID(i, buf, BUF_CAP); + if (*buf == 0) { + log_err("FAIL: System transliterator %d: \"\"\n", i); + } else { + log_verbose("System transliterator %d: \"%s\"\n", i, buf); + } + } + + /* Test open */ + utrans_getAvailableID(0, buf, BUF_CAP); + trans = utrans_open(buf, UTRANS_FORWARD,NULL,0,NULL, &status); + if (U_FAILURE(status)) { + log_err("FAIL: utrans_open(%s) failed, error=%s\n", + buf, u_errorName(status)); + } + + else { + /* Test getID */ + utrans_getID(trans, buf2, BUF_CAP); + if (0 != strcmp(buf, buf2)) { + log_err("FAIL: utrans_getID(%s) returned %s\n", + buf, buf2); + } + utrans_close(trans); + } +} + +static void TestUnicodeIDs() { + UEnumeration *uenum; + UTransliterator *utrans; + const UChar *id, *id2; + int32_t idLength, id2Length, count, count2; + + UErrorCode errorCode; + + errorCode=U_ZERO_ERROR; + uenum=utrans_openIDs(&errorCode); + if(U_FAILURE(errorCode)) { + log_err("utrans_openIDs() failed - %s\n", u_errorName(errorCode)); + return; + } + + count=uenum_count(uenum, &errorCode); + if(U_FAILURE(errorCode) || count<1) { + log_err("uenum_count(transliterator IDs)=%d - %s\n", count, u_errorName(errorCode)); + } + + count=0; + for(;;) { + id=uenum_unext(uenum, &idLength, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("uenum_unext(transliterator ID %d) failed - %s\n", count, u_errorName(errorCode)); + break; + } + if(id==NULL) { + break; + } + + if(++count>10) { + /* try to actually open only a few transliterators */ + continue; + } + + utrans=utrans_openU(id, idLength, UTRANS_FORWARD, NULL, 0, NULL, &errorCode); + if(U_FAILURE(errorCode)) { + log_err("utrans_openU(%s) failed - %s\n", aescstrdup(id, idLength), u_errorName(errorCode)); + continue; + } + + id2=utrans_getUnicodeID(utrans, &id2Length); + if(idLength!=id2Length || 0!=u_memcmp(id, id2, idLength)) { + log_err("utrans_getUnicodeID(%s) does not match the original ID\n", aescstrdup(id, idLength)); + } + + utrans_close(utrans); + } + + uenum_reset(uenum, &errorCode); + if(U_FAILURE(errorCode) || count<1) { + log_err("uenum_reset(transliterator IDs) failed - %s\n", u_errorName(errorCode)); + } else { + count2=uenum_count(uenum, &errorCode); + if(U_FAILURE(errorCode) || count<1) { + log_err("2nd uenum_count(transliterator IDs)=%d - %s\n", count2, u_errorName(errorCode)); + } else if(count!=count2) { + log_err("uenum_unext(transliterator IDs) returned %d IDs but uenum_count() after uenum_reset() claims there are %d\n", count, count2); + } + } + + uenum_close(uenum); +} + +static void TestOpenInverse(){ + UErrorCode status=U_ZERO_ERROR; + UTransliterator* t1=NULL; + UTransliterator* inverse1=NULL; + enum { BUF_CAP = 128 }; + char buf1[BUF_CAP]; + int32_t i=0; + + const char TransID[][25]={ + "Halfwidth-Fullwidth", + "Fullwidth-Halfwidth", + "Greek-Latin" , + "Latin-Greek", + /*"Arabic-Latin", // Removed in 2.0*/ + /*"Latin-Arabic", // Removed in 2.0*/ + "Katakana-Latin", + "Latin-Katakana", + /*"Hebrew-Latin", // Removed in 2.0*/ + /*"Latin-Hebrew", // Removed in 2.0*/ + "Cyrillic-Latin", + "Latin-Cyrillic", + "Devanagari-Latin", + "Latin-Devanagari", + "Any-Hex", + "Hex-Any" + }; + + for(i=0; i<sizeof(TransID)/sizeof(TransID[0]); i=i+2){ + status = U_ZERO_ERROR; + t1=utrans_open(TransID[i], UTRANS_FORWARD,NULL,0,NULL, &status); + if(t1 == NULL || U_FAILURE(status)){ + log_err("FAIL: in instantiation for id=%s\n", TransID[i]); + continue; + } + inverse1=utrans_openInverse(t1, &status); + if(U_FAILURE(status)){ + log_err("FAIL: utrans_openInverse() failed for id=%s. Error=%s\n", TransID[i], myErrorName(status)); + continue; + } + utrans_getID(inverse1, buf1, BUF_CAP); + if(strcmp(buf1, TransID[i+1]) != 0){ + log_err("FAIL :openInverse() for %s returned %s instead of %s\n", TransID[i], buf1, TransID[i+1]); + } + utrans_close(t1); + utrans_close(inverse1); + } +} + +static void TestClone(){ + UErrorCode status=U_ZERO_ERROR; + UTransliterator* t1=NULL; + UTransliterator* t2=NULL; + UTransliterator* t3=NULL; + UTransliterator* t4=NULL; + enum { BUF_CAP = 128 }; + char buf1[BUF_CAP], buf2[BUF_CAP], buf3[BUF_CAP]; + + t1=utrans_open("Latin-Devanagari", UTRANS_FORWARD, NULL,0,NULL,&status); + if(U_FAILURE(status)){ + log_err("FAIL: construction\n"); + return; + } + t2=utrans_open("Latin-Greek", UTRANS_FORWARD, NULL,0,NULL,&status); + if(U_FAILURE(status)){ + log_err("FAIL: construction\n"); + utrans_close(t1); + return; + } + + t3=utrans_clone(t1, &status); + t4=utrans_clone(t2, &status); + + utrans_getID(t1, buf1, BUF_CAP); + utrans_getID(t2, buf2, BUF_CAP); + utrans_getID(t3, buf3, BUF_CAP); + + if(strcmp(buf1, buf3) != 0 || + strcmp(buf1, buf2) == 0) { + log_err("FAIL: utrans_clone() failed\n"); + } + + utrans_getID(t4, buf3, BUF_CAP); + + if(strcmp(buf2, buf3) != 0 || + strcmp(buf1, buf3) == 0) { + log_err("FAIL: utrans_clone() failed\n"); + } + + utrans_close(t1); + utrans_close(t2); + utrans_close(t3); + utrans_close(t4); + +} + +static void TestRegisterUnregister(){ + UErrorCode status=U_ZERO_ERROR; + UTransliterator* t1=NULL; + UTransliterator* rules=NULL, *rules2; + UTransliterator* inverse1=NULL; + UChar rule[]={ 0x0061, 0x003c, 0x003e, 0x0063}; /*a<>b*/ + + U_STRING_DECL(ID, "TestA-TestB", 11); + U_STRING_INIT(ID, "TestA-TestB", 11); + + /* Make sure it doesn't exist */ + t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); + if(t1 != NULL || U_SUCCESS(status)) { + log_err("FAIL: TestA-TestB already registered\n"); + return; + } + status=U_ZERO_ERROR; + /* Check inverse too */ + inverse1=utrans_open("TestA-TestB", UTRANS_REVERSE, NULL,0,NULL,&status); + if(inverse1 != NULL || U_SUCCESS(status)) { + log_err("FAIL: TestA-TestB already registered\n"); + return; + } + status=U_ZERO_ERROR; + /* Create it */ + rules=utrans_open("TestA-TestB",UTRANS_FORWARD, rule, 4, NULL, &status); + if(U_FAILURE(status)){ + log_err("FAIL: utrans_openRules(a<>B) failed with error=%s\n", myErrorName(status)); + return; + } + + /* clone it so we can register it a second time */ + rules2=utrans_clone(rules, &status); + if(U_FAILURE(status)) { + log_err("FAIL: utrans_clone(a<>B) failed with error=%s\n", myErrorName(status)); + return; + } + + status=U_ZERO_ERROR; + /* Register it */ + utrans_register(rules, &status); + if(U_FAILURE(status)){ + log_err("FAIL: utrans_register failed with error=%s\n", myErrorName(status)); + return; + } + status=U_ZERO_ERROR; + /* Now check again -- should exist now*/ + t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); + if(U_FAILURE(status) || t1 == NULL){ + log_err("FAIL: TestA-TestB not registered\n"); + return; + } + utrans_close(t1); + + /*unregister the instance*/ + status=U_ZERO_ERROR; + utrans_unregister("TestA-TestB"); + /* now Make sure it doesn't exist */ + t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); + if(U_SUCCESS(status) || t1 != NULL) { + log_err("FAIL: TestA-TestB isn't unregistered\n"); + return; + } + utrans_close(t1); + + /* now with utrans_unregisterID(const UChar *) */ + status=U_ZERO_ERROR; + utrans_register(rules2, &status); + if(U_FAILURE(status)){ + log_err("FAIL: 2nd utrans_register failed with error=%s\n", myErrorName(status)); + return; + } + status=U_ZERO_ERROR; + /* Now check again -- should exist now*/ + t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); + if(U_FAILURE(status) || t1 == NULL){ + log_err("FAIL: 2nd TestA-TestB not registered\n"); + return; + } + utrans_close(t1); + + /*unregister the instance*/ + status=U_ZERO_ERROR; + utrans_unregisterID(ID, -1); + /* now Make sure it doesn't exist */ + t1=utrans_openU(ID, -1, UTRANS_FORWARD,NULL,0,NULL, &status); + if(U_SUCCESS(status) || t1 != NULL) { + log_err("FAIL: 2nd TestA-TestB isn't unregistered\n"); + return; + } + + utrans_close(t1); + utrans_close(inverse1); +} + +static void TestSimpleRules() { + /* Test rules */ + /* Example: rules 1. ab>x|y + * 2. yc>z + * + * []|eabcd start - no match, copy e to tranlated buffer + * [e]|abcd match rule 1 - copy output & adjust cursor + * [ex|y]cd match rule 2 - copy output & adjust cursor + * [exz]|d no match, copy d to transliterated buffer + * [exzd]| done + */ + _expectRules("ab>x|y;" + "yc>z", + "eabcd", "exzd"); + + /* Another set of rules: + * 1. ab>x|yzacw + * 2. za>q + * 3. qc>r + * 4. cw>n + * + * []|ab Rule 1 + * [x|yzacw] No match + * [xy|zacw] Rule 2 + * [xyq|cw] Rule 4 + * [xyqn]| Done + */ + _expectRules("ab>x|yzacw;" + "za>q;" + "qc>r;" + "cw>n", + "ab", "xyqn"); + + /* Test categories + */ + _expectRules("$dummy=" "\\uE100" ";" /* careful here with E100 */ + "$vowel=[aeiouAEIOU];" + "$lu=[:Lu:];" + "$vowel } $lu > '!';" + "$vowel > '&';" + "'!' { $lu > '^';" + "$lu > '*';" + "a > ERROR", + "abcdefgABCDEFGU", "&bcd&fg!^**!^*&"); +} + +static void TestFilter() { + UErrorCode status = U_ZERO_ERROR; + UChar filt[128]; + UChar buf[128]; + UChar exp[128]; + char *cbuf; + int32_t limit; + const char* DATA[] = { + "[^c]", /* Filter out 'c' */ + "abcde", + "\\u0061\\u0062c\\u0064\\u0065", + + "", /* No filter */ + "abcde", + "\\u0061\\u0062\\u0063\\u0064\\u0065" + }; + int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]); + int32_t i; + + UTransliterator* hex = utrans_open("Any-Hex", UTRANS_FORWARD, NULL,0,NULL,&status); + + if (hex == 0 || U_FAILURE(status)) { + log_err("FAIL: utrans_open(Unicode-Hex) failed, error=%s\n", + u_errorName(status)); + goto exit; + } + + for (i=0; i<DATA_length; i+=3) { + /*u_uastrcpy(filt, DATA[i]);*/ + u_charsToUChars(DATA[i], filt, (int32_t)strlen(DATA[i])+1); + utrans_setFilter(hex, filt, -1, &status); + + if (U_FAILURE(status)) { + log_err("FAIL: utrans_setFilter() failed, error=%s\n", + u_errorName(status)); + goto exit; + } + + /*u_uastrcpy(buf, DATA[i+1]);*/ + u_charsToUChars(DATA[i+1], buf, (int32_t)strlen(DATA[i+1])+1); + limit = 5; + utrans_transUChars(hex, buf, NULL, 128, 0, &limit, &status); + + if (U_FAILURE(status)) { + log_err("FAIL: utrans_transUChars() failed, error=%s\n", + u_errorName(status)); + goto exit; + } + + cbuf=aescstrdup(buf, -1); + u_charsToUChars(DATA[i+2], exp, (int32_t)strlen(DATA[i+2])+1); + if (0 == u_strcmp(buf, exp)) { + log_verbose("Ok: %s | %s -> %s\n", DATA[i+1], DATA[i], cbuf); + } else { + log_err("FAIL: %s | %s -> %s, expected %s\n", DATA[i+1], DATA[i], cbuf, DATA[i+2]); + } + } + + exit: + utrans_close(hex); +} + +/** + * Test the UReplaceableCallback extractBetween support. We use a + * transliterator known to rely on this call. + */ +static void TestExtractBetween() { + + UTransliterator *trans; + UErrorCode status = U_ZERO_ERROR; + UParseError parseErr; + + trans = utrans_open("Lower", UTRANS_FORWARD, NULL, -1, + &parseErr, &status); + + if (U_FAILURE(status)) { + log_err("FAIL: utrans_open(Lower) failed, error=%s\n", + u_errorName(status)); + } else { + _expect(trans, "ABC", "abc"); + + utrans_close(trans); + } +} + +static void _expectRules(const char* crules, + const char* cfrom, + const char* cto) { + /* u_uastrcpy has no capacity param for the buffer -- so just + * make all buffers way too big */ + enum { CAP = 256 }; + UChar rules[CAP]; + UTransliterator *trans; + UErrorCode status = U_ZERO_ERROR; + UParseError parseErr; + + u_uastrcpy(rules, crules); + + trans = utrans_open(crules /*use rules as ID*/, UTRANS_FORWARD, rules, -1, + &parseErr, &status); + if (U_FAILURE(status)) { + utrans_close(trans); + log_err("FAIL: utrans_openRules(%s) failed, error=%s\n", + crules, u_errorName(status)); + return; + } + + _expect(trans, cfrom, cto); + + utrans_close(trans); +} + +static void _expect(const UTransliterator* trans, + const char* cfrom, + const char* cto) { + /* u_uastrcpy has no capacity param for the buffer -- so just + * make all buffers way too big */ + enum { CAP = 256 }; + UChar from[CAP]; + UChar to[CAP]; + UChar buf[CAP]; + const UChar *ID; + int32_t IDLength; + const char *id; + + UErrorCode status = U_ZERO_ERROR; + int32_t limit; + UTransPosition pos; + XReplaceable xrep; + XReplaceable *xrepPtr = &xrep; + UReplaceableCallbacks xrepVtable; + + u_uastrcpy(from, cfrom); + u_uastrcpy(to, cto); + + ID = utrans_getUnicodeID(trans, &IDLength); + id = aescstrdup(ID, IDLength); + + /* utrans_transUChars() */ + u_strcpy(buf, from); + limit = u_strlen(buf); + utrans_transUChars(trans, buf, NULL, CAP, 0, &limit, &status); + if (U_FAILURE(status)) { + log_err("FAIL: utrans_transUChars() failed, error=%s\n", + u_errorName(status)); + return; + } + + if (0 == u_strcmp(buf, to)) { + log_verbose("Ok: utrans_transUChars(%s) x %s -> %s\n", + id, cfrom, cto); + } else { + char actual[CAP]; + u_austrcpy(actual, buf); + log_err("FAIL: utrans_transUChars(%s) x %s -> %s, expected %s\n", + id, cfrom, actual, cto); + } + + /* utrans_transIncrementalUChars() */ + u_strcpy(buf, from); + pos.start = pos.contextStart = 0; + pos.limit = pos.contextLimit = u_strlen(buf); + utrans_transIncrementalUChars(trans, buf, NULL, CAP, &pos, &status); + utrans_transUChars(trans, buf, NULL, CAP, pos.start, &pos.limit, &status); + if (U_FAILURE(status)) { + log_err("FAIL: utrans_transIncrementalUChars() failed, error=%s\n", + u_errorName(status)); + return; + } + + if (0 == u_strcmp(buf, to)) { + log_verbose("Ok: utrans_transIncrementalUChars(%s) x %s -> %s\n", + id, cfrom, cto); + } else { + char actual[CAP]; + u_austrcpy(actual, buf); + log_err("FAIL: utrans_transIncrementalUChars(%s) x %s -> %s, expected %s\n", + id, cfrom, actual, cto); + } + + /* utrans_trans() */ + InitXReplaceableCallbacks(&xrepVtable); + InitXReplaceable(&xrep, cfrom); + limit = u_strlen(from); + utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, 0, &limit, &status); + if (U_FAILURE(status)) { + log_err("FAIL: utrans_trans() failed, error=%s\n", + u_errorName(status)); + FreeXReplaceable(&xrep); + return; + } + + if (0 == u_strcmp(xrep.text, to)) { + log_verbose("Ok: utrans_trans(%s) x %s -> %s\n", + id, cfrom, cto); + } else { + char actual[CAP]; + u_austrcpy(actual, xrep.text); + log_err("FAIL: utrans_trans(%s) x %s -> %s, expected %s\n", + id, cfrom, actual, cto); + } + FreeXReplaceable(&xrep); + + /* utrans_transIncremental() */ + InitXReplaceable(&xrep, cfrom); + pos.start = pos.contextStart = 0; + pos.limit = pos.contextLimit = u_strlen(from); + utrans_transIncremental(trans, (UReplaceable*)xrepPtr, &xrepVtable, &pos, &status); + utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, pos.start, &pos.limit, &status); + if (U_FAILURE(status)) { + log_err("FAIL: utrans_transIncremental() failed, error=%s\n", + u_errorName(status)); + FreeXReplaceable(&xrep); + return; + } + + if (0 == u_strcmp(xrep.text, to)) { + log_verbose("Ok: utrans_transIncremental(%s) x %s -> %s\n", + id, cfrom, cto); + } else { + char actual[CAP]; + u_austrcpy(actual, xrep.text); + log_err("FAIL: utrans_transIncremental(%s) x %s -> %s, expected %s\n", + id, cfrom, actual, cto); + } + FreeXReplaceable(&xrep); +} + +#endif /* #if !UCONFIG_NO_TRANSLITERATION */ |