]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/cintltst/idnatest.c
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / idnatest.c
index 49b51675cb683bf152f556752bde8105896cface..e42aedea0c120839878f3091c39c6d04ce13c2ba 100644 (file)
@@ -1,12 +1,14 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
  *******************************************************************************
  *
- *   Copyright (C) 2003-2007, International Business Machines
+ *   Copyright (C) 2003-2016, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *
  *******************************************************************************
  *   file name:  idnatest.c
- *   encoding:   US-ASCII
+ *   encoding:   UTF-8
  *   tab size:   8 (not used)
  *   indentation:4
  *
 #include "unicode/ustring.h"
 #include "unicode/uidna.h"
 #include "cintltst.h"
+#include "cmemory.h"
 
-
-
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
 #define MAX_DEST_SIZE 1000
 
 static void TestToUnicode(void);
@@ -33,10 +33,11 @@ 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 TestLength(void);
+static void TestJB5273(void);
+static void TestUTS46(void);
 
 void addIDNATest(TestNode** root);
 
@@ -61,10 +62,11 @@ addIDNATest(TestNode** root)
    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, &TestJB4490,       "idna/TestJB4490");
    addTest(root, &TestJB4475,       "idna/TestJB4475");
    addTest(root, &TestLength,       "idna/TestLength");
+   addTest(root, &TestJB5273,       "idna/TestJB5273");
+   addTest(root, &TestUTS46,        "idna/TestUTS46");
 }
 
 static void
@@ -106,7 +108,7 @@ testAPI(const UChar* src, const UChar* expected, const char* 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));
+        log_err_status(status,  "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;
     }
@@ -223,7 +225,7 @@ testAPI(const UChar* src, const UChar* expected, const char* testName,
     free(tSrc);
 }
 
-static UChar unicodeIn[][41] ={
+static const UChar unicodeIn[][41] ={
     {
         0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644,
         0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F, 0x0000
@@ -343,7 +345,7 @@ static UChar unicodeIn[][41] ={
     }
 };
 
-static const char *asciiIn[] = {
+static const char * const asciiIn[] = {
     "xn--egbpdaj6bu4bxfgehfvwxn",
     "xn--ihqwcrb4cv8a8dqg056pqjye",
     "xn--Proprostnemluvesky-uyb24dma41a",
@@ -371,7 +373,7 @@ static const char *asciiIn[] = {
 
 };
 
-static const char *domainNames[] = {
+static const char * const domainNames[] = {
     "slip129-37-118-146.nc.us.ibm.net",
     "saratoga.pe.utexas.edu",
     "dial-120-45.ots.utexas.edu",
@@ -430,7 +432,7 @@ TestToASCII(){
     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++){
+    for(i=0;i< UPRV_LENGTHOF(unicodeIn); i++){
         u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1);
         testAPI(unicodeIn[i], buf,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
 
@@ -444,7 +446,7 @@ TestToUnicode(){
     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++){
+    for(i=0;i< UPRV_LENGTHOF(asciiIn); i++){
         u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1);
         testAPI(buf,unicodeIn[i],testName,FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
     }
@@ -461,12 +463,12 @@ TestIDNToUnicode(){
     UParseError parseError;
     const char* testName="uidna_IDNToUnicode";
     TestFunc func = uidna_IDNToUnicode;
-    for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){
+    for(i=0;i< UPRV_LENGTHOF(domainNames); 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));
+            log_err_status(status,  "%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);
@@ -491,12 +493,12 @@ TestIDNToASCII(){
     const char* testName="udina_IDNToASCII";
     TestFunc func=uidna_IDNToASCII;
 
-    for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){
+    for(i=0;i< UPRV_LENGTHOF(domainNames); 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));
+            log_err_status(status,  "%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);
@@ -525,7 +527,7 @@ testCompareWithSrc(const UChar* s1, int32_t s1Len,
         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));
+        log_err_status(status, "%s null terminated source failed. Error: %s\n", testName,u_errorName(status));
     }
 
     status = U_ZERO_ERROR;
@@ -535,7 +537,7 @@ testCompareWithSrc(const UChar* s1, int32_t s1Len,
         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));
+        log_err_status(status, "%s null terminated source and options set failed. Error: %s\n",testName, u_errorName(status));
     }
 
     status = U_ZERO_ERROR;
@@ -545,7 +547,7 @@ testCompareWithSrc(const UChar* s1, int32_t s1Len,
         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));
+        log_err_status(status,  "%s with string length. Error: %s\n",testName, u_errorName(status));
     }
 
     status = U_ZERO_ERROR;
@@ -555,7 +557,7 @@ testCompareWithSrc(const UChar* s1, int32_t s1Len,
         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);
+        log_err_status(status,  "%s with string length and options set. Error: %s\n", u_errorName(status), testName);
     }
 }
 
@@ -597,7 +599,7 @@ TestCompare(){
     /* prepend www. */
     u_strcat(source, www);
 
-    for(i=0;i< (int32_t)(sizeof(unicodeIn)/sizeof(unicodeIn[0])); i++){
+    for(i=0;i< UPRV_LENGTHOF(unicodeIn); i++){
         UChar* src;
         int32_t srcLen;
 
@@ -638,31 +640,6 @@ TestCompare(){
     }
 }
 
-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(errorCode!=U_IDNA_VERIFICATION_ERROR) {
-            log_err("string %d yields %s instead of U_IDNA_VERIFICATION_ERROR\n",
-                i, u_errorName(errorCode));
-        }
-    }
-}
-
 static void TestJB4490(){
     static const UChar data[][50]= {
         {0x00F5,0x00dE,0x00dF,0x00dD, 0x0000},
@@ -671,7 +648,7 @@ static void TestJB4490(){
     UChar output1[40] = {0};
     UChar output2[40] = {0};
     int32_t i;
-    for(i=0; i< sizeof(data)/sizeof(data[0]); i++){
+    for(i=0; i< UPRV_LENGTHOF(data); i++){
         const UChar* src1 = data[i];
         int32_t src1Len = u_strlen(src1);
         UChar* dest1 = output1;
@@ -684,13 +661,13 @@ static void TestJB4490(){
         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));
+            log_err_status(status, "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));
+            log_err_status(status, "uidna_toUnicode failed with error %s.\n", u_errorName(status));
         }
     }
 }
@@ -703,7 +680,7 @@ static void TestJB4475(){
     };
     int i;
     UChar output[40] = {0};
-    for(i=0; i< sizeof(input)/sizeof(input[0]); i++){
+    for(i=0; i< UPRV_LENGTHOF(input); i++){
         const UChar* src = input[i];
         int32_t srcLen = u_strlen(src);
         UChar* dest = output;
@@ -713,52 +690,338 @@ static void TestJB4475(){
 
         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));
+            log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status));
+            continue;
         } 
         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_long_and_incredibly_uncreative_domain_label"; 
-          UChar ul[128] = {'\0'}; 
-          UChar dest[256] = {'\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_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 = -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); 
-          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)); 
-          } 
-    } 
-} 
+
+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 = UPRV_LENGTHOF(ul1)-1/*remove the null termination*/;
+        int32_t destLen = UPRV_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_status(status, "uidna_toUnicode failed with error %s.\n", u_errorName(status));
+        }
+
+        status = U_ZERO_ERROR;
+        destLen = UPRV_LENGTHOF(dest);
+        len = -1;
+        destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+        if(status != U_ZERO_ERROR){
+            log_err_status(status, "uidna_toUnicode failed with error %s.\n", u_errorName(status));
+        }
+        status = U_ZERO_ERROR;
+        destLen = UPRV_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_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status));
+        }
+        
+        status = U_ZERO_ERROR;
+        destLen = UPRV_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_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status));
+        }
+
+        status = U_ZERO_ERROR;
+        destLen = UPRV_LENGTHOF(dest);
+        destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+        if(status != U_ZERO_ERROR){
+            log_err_status(status, "uidna_toASCII failed with error %s.\n", u_errorName(status));
+        }
+        
+        status = U_ZERO_ERROR;
+        destLen = UPRV_LENGTHOF(dest);
+        len1 = -1;
+        destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+        if(status != U_ZERO_ERROR){
+            log_err_status(status, "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 = UPRV_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_status(status, "uidna_IDNToUnicode failed with error %s.\n", u_errorName(status));
+        }
+        
+        status = U_ZERO_ERROR;
+        destLen = UPRV_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_status(status, "uidna_IDNToUnicode failed with error %s.\n", u_errorName(status));
+        }
+        
+        status = U_ZERO_ERROR;
+        destLen = UPRV_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_status(status, "uidna_IDNToASCII failed with error %s.\n", u_errorName(status));
+        }
+        
+        status = U_ZERO_ERROR;
+        destLen = UPRV_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_status(status, "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_status(status, "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_status(status, "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, (int32_t)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);
+    (void)outLen;    /* Suppress set but not used warning. */
+    if(U_FAILURE(status)){
+        log_err_status(status, "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_status(status, "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_status(status, "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_status(status, "uidna_toUnicode failed with error: %s\n", u_errorName(status));
+    }
+}
+
+/*
+ * Test the new (ICU 4.6/2010) C API that was added for UTS #46.
+ * Just an API test: Functionality is tested via C++ intltest.
+ */
+static void TestUTS46() {
+    static const UChar fA_sharps16[] = { 0x66, 0x41, 0xdf, 0 };
+    static const char fA_sharps8[] = { 0x66, 0x41, (char)0xc3, (char)0x9f, 0 };
+    static const UChar fa_sharps16[] = { 0x66, 0x61, 0xdf, 0 };
+    static const char fa_sharps8[] = { 0x66, 0x61, (char)0xc3, (char)0x9f, 0 };
+    static const UChar fass16[] = { 0x66, 0x61, 0x73, 0x73, 0 };
+    static const char fass8[] = { 0x66, 0x61, 0x73, 0x73, 0 };
+    static const UChar fA_BEL[] = { 0x66, 0x41, 7, 0 };
+    static const UChar fa_FFFD[] = { 0x66, 0x61, 0xfffd, 0 };
+
+    UChar dest16[10];
+    char dest8[10];
+    int32_t length;
+
+    UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+    UErrorCode errorCode = U_ZERO_ERROR;
+    UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE,
+                                   &errorCode);
+    if(U_FAILURE(errorCode)) {
+        log_err_status(errorCode, "uidna_openUTS46() failed: %s\n", u_errorName(errorCode));
+        return;
+    }
+
+    /* These calls should succeed. */
+    length = uidna_labelToASCII(uts46, fA_sharps16, -1,
+                                dest16, UPRV_LENGTHOF(dest16), &info, &errorCode);
+    if( U_FAILURE(errorCode) || length != 4 || 0 != u_memcmp(dest16, fass16, 5) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_labelToASCII() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToUnicode(uts46, fA_sharps16, u_strlen(fA_sharps16),
+                                  dest16, UPRV_LENGTHOF(dest16), &info, &errorCode);
+    if( U_FAILURE(errorCode) || length != 3 || 0 != u_memcmp(dest16, fa_sharps16, 4) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_labelToUnicode() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToASCII(uts46, fA_sharps16, u_strlen(fA_sharps16),
+                               dest16, 4, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 4 || 0 != u_memcmp(dest16, fass16, 4) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_nameToASCII() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToUnicode(uts46, fA_sharps16, -1,
+                                 dest16, 3, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 3 || 0 != u_memcmp(dest16, fa_sharps16, 3) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_nameToUnicode() failed: %s\n", u_errorName(errorCode));
+    }
+
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToASCII_UTF8(uts46, fA_sharps8, -1,
+                                     dest8, UPRV_LENGTHOF(dest8), &info, &errorCode);
+    if( U_FAILURE(errorCode) || length != 4 || 0 != memcmp(dest8, fass8, 5) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_labelToASCII_UTF8() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToUnicodeUTF8(uts46, fA_sharps8, (int32_t)strlen(fA_sharps8),
+                                      dest8, UPRV_LENGTHOF(dest8), &info, &errorCode);
+    if( U_FAILURE(errorCode) || length != 4 || 0 != memcmp(dest8, fa_sharps8, 5) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_labelToUnicodeUTF8() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToASCII_UTF8(uts46, fA_sharps8, (int32_t)strlen(fA_sharps8),
+                                    dest8, 4, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 4 || 0 != memcmp(dest8, fass8, 4) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_nameToASCII_UTF8() failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToUnicodeUTF8(uts46, fA_sharps8, -1,
+                                     dest8, 4, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 4 || 0 != memcmp(dest8, fa_sharps8, 4) ||
+        !info.isTransitionalDifferent || info.errors != 0
+    ) {
+        log_err("uidna_nameToUnicodeUTF8() failed: %s\n", u_errorName(errorCode));
+    }
+
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToASCII(uts46, NULL, 0,
+                               dest16, 0, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 0 ||
+        info.isTransitionalDifferent || info.errors != UIDNA_ERROR_EMPTY_LABEL
+    ) {
+        log_err("uidna_nameToASCII(empty) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToUnicode(uts46, fA_BEL, -1,
+                                 dest16, 3, &info, &errorCode);
+    if( errorCode != U_STRING_NOT_TERMINATED_WARNING ||
+        length != 3 || 0 != u_memcmp(dest16, fa_FFFD, 3) ||
+        info.isTransitionalDifferent || info.errors == 0
+    ) {
+        log_err("uidna_nameToUnicode(fa<BEL>) failed: %s\n", u_errorName(errorCode));
+    }
+
+    /* These calls should fail. */
+    errorCode = U_USELESS_COLLATOR_ERROR;
+    length = uidna_labelToASCII(uts46, fA_sharps16, -1,
+                                dest16, UPRV_LENGTHOF(dest16), &info, &errorCode);
+    if(errorCode != U_USELESS_COLLATOR_ERROR) {
+        log_err("uidna_labelToASCII(failure) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToUnicode(uts46, fA_sharps16, u_strlen(fA_sharps16),
+                                  dest16, UPRV_LENGTHOF(dest16), NULL, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_labelToUnicode(UIDNAInfo=NULL) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToASCII(uts46, NULL, u_strlen(fA_sharps16),
+                               dest16, 4, &info, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_nameToASCII(src=NULL) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToUnicode(uts46, fA_sharps16, -2,
+                                 dest16, 3, &info, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_nameToUnicode(length<-1) failed: %s\n", u_errorName(errorCode));
+    }
+
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToASCII_UTF8(uts46, fA_sharps8, -1,
+                                     NULL, UPRV_LENGTHOF(dest8), &info, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_labelToASCII_UTF8(dest=NULL) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_labelToUnicodeUTF8(uts46, fA_sharps8, (int32_t)strlen(fA_sharps8),
+                                      dest8, -1, &info, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_labelToUnicodeUTF8(capacity<0) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToASCII_UTF8(uts46, dest8, (int32_t)strlen(fA_sharps8),
+                                    dest8, 4, &info, &errorCode);
+    if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+        log_err("uidna_nameToASCII_UTF8(src==dest!=NULL) failed: %s\n", u_errorName(errorCode));
+    }
+    errorCode = U_ZERO_ERROR;
+    length = uidna_nameToUnicodeUTF8(uts46, fA_sharps8, -1,
+                                     dest8, 3, &info, &errorCode);
+    if(errorCode != U_BUFFER_OVERFLOW_ERROR || length != 4) {
+        log_err("uidna_nameToUnicodeUTF8() overflow failed: %s\n", u_errorName(errorCode));
+    }
+
+    uidna_close(uts46);
+}
+
 #endif
 
 /*
@@ -769,4 +1032,3 @@ static void TestLength(){
  * End:
  *
  */
-