+#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.
+ */
+}