| Index: icu46/source/test/intltest/idnaconf.cpp
|
| ===================================================================
|
| --- icu46/source/test/intltest/idnaconf.cpp (revision 0)
|
| +++ icu46/source/test/intltest/idnaconf.cpp (revision 0)
|
| @@ -0,0 +1,353 @@
|
| +/*
|
| + *******************************************************************************
|
| + *
|
| + * Copyright (C) 2005-2009, International Business Machines
|
| + * Corporation and others. All Rights Reserved.
|
| + *
|
| + *******************************************************************************
|
| + *
|
| + * created on: 2005jun15
|
| + * created by: Raymond Yang
|
| + */
|
| +
|
| +#if !UCONFIG_NO_IDNA
|
| +
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +#include <string.h>
|
| +#include "unicode/utypes.h"
|
| +#include "unicode/ucnv.h"
|
| +#include "unicode/ustring.h"
|
| +#include "unicode/uidna.h"
|
| +
|
| +#include "idnaconf.h"
|
| +
|
| +static const UChar C_TAG[] = {0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0}; // =====
|
| +static const UChar C_NAMEZONE[] = {0x6E, 0x61, 0x6D, 0x65, 0x7A, 0x6F, 0x6E, 0x65, 0}; // namezone
|
| +static const UChar C_NAMEBASE[] = {0x6E, 0x61, 0x6D, 0x65, 0x62, 0x61, 0x73, 0x65, 0}; // namebase
|
| +static const UChar C_NAMEUTF8[] = {0x6E, 0x61, 0x6D, 0x65, 0x75, 0x74, 0x66, 0x38, 0}; // nameutf8
|
| +
|
| +static const UChar C_TYPE[] = {0x74, 0x79, 0x70, 0x65, 0}; // type
|
| +static const UChar C_TOASCII[] = {0x74, 0x6F, 0x61, 0x73, 0x63, 0x69, 0x69, 0}; // toascii
|
| +static const UChar C_TOUNICODE[] = {0x74, 0x6F, 0x75, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0}; // tounicode
|
| +
|
| +static const UChar C_PASSFAIL[] = {0x70, 0x61, 0x73, 0x73, 0x66, 0x61, 0x69, 0x6C, 0}; // passfail
|
| +static const UChar C_PASS[] = {0x70, 0x61, 0x73, 0x73, 0}; // pass
|
| +static const UChar C_FAIL[] = {0x66, 0x61, 0x69, 0x6C, 0}; // fail
|
| +
|
| +static const UChar C_DESC[] = {0x64, 0x65, 0x73, 0x63, 0}; // desc
|
| +static const UChar C_USESTD3ASCIIRULES[] = {0x55, 0x73, 0x65, 0x53, 0x54, 0x44,
|
| + 0x33, 0x41, 0x53, 0x43, 0x49, 0x49, 0x52, 0x75, 0x6C, 0x65, 0x73, 0}; // UseSTD3ASCIIRules
|
| +
|
| +IdnaConfTest::IdnaConfTest(){
|
| + base = NULL;
|
| + len = 0;
|
| + curOffset = 0;
|
| +
|
| + type = option = passfail = -1;
|
| + namebase.setToBogus();
|
| + namezone.setToBogus();
|
| +}
|
| +IdnaConfTest::~IdnaConfTest(){
|
| + delete [] base;
|
| +}
|
| +
|
| +#if !UCONFIG_NO_IDNA
|
| +/* this function is modified from RBBITest::ReadAndConvertFile()
|
| + *
|
| + */
|
| +UBool IdnaConfTest::ReadAndConvertFile(){
|
| +
|
| + char * source = NULL;
|
| + size_t source_len;
|
| +
|
| + // read the test data file to memory
|
| + FILE* f = NULL;
|
| + UErrorCode status = U_ZERO_ERROR;
|
| +
|
| + const char *path = IntlTest::getSourceTestData(status);
|
| + if (U_FAILURE(status)) {
|
| + errln("%s", u_errorName(status));
|
| + return FALSE;
|
| + }
|
| +
|
| + const char* name = "idna_conf.txt"; // test data file
|
| + int t = strlen(path) + strlen(name) + 1;
|
| + char* absolute_name = new char[t];
|
| + strcpy(absolute_name, path);
|
| + strcat(absolute_name, name);
|
| + f = fopen(absolute_name, "rb");
|
| + delete [] absolute_name;
|
| +
|
| + if (f == NULL){
|
| + dataerrln("fopen error on %s", name);
|
| + return FALSE;
|
| + }
|
| +
|
| + fseek( f, 0, SEEK_END);
|
| + if ((source_len = ftell(f)) <= 0){
|
| + errln("Error reading test data file.");
|
| + fclose(f);
|
| + return FALSE;
|
| + }
|
| +
|
| + source = new char[source_len];
|
| + fseek(f, 0, SEEK_SET);
|
| + if (fread(source, 1, source_len, f) != source_len) {
|
| + errln("Error reading test data file.");
|
| + delete [] source;
|
| + fclose(f);
|
| + return FALSE;
|
| + }
|
| + fclose(f);
|
| +
|
| + // convert the UTF-8 encoded stream to UTF-16 stream
|
| + UConverter* conv = ucnv_open("utf-8", &status);
|
| + int dest_len = ucnv_toUChars(conv,
|
| + NULL, // dest,
|
| + 0, // destCapacity,
|
| + source,
|
| + source_len,
|
| + &status);
|
| + if (status == U_BUFFER_OVERFLOW_ERROR) {
|
| + // Buffer Overflow is expected from the preflight operation.
|
| + status = U_ZERO_ERROR;
|
| + UChar * dest = NULL;
|
| + dest = new UChar[ dest_len + 1];
|
| + ucnv_toUChars(conv, dest, dest_len + 1, source, source_len, &status);
|
| + // Do not know the "if possible" behavior of ucnv_toUChars()
|
| + // Do it by ourself.
|
| + dest[dest_len] = 0;
|
| + len = dest_len;
|
| + base = dest;
|
| + delete [] source;
|
| + ucnv_close(conv);
|
| + return TRUE; // The buffer will owned by caller.
|
| + }
|
| + errln("UConverter error: %s", u_errorName(status));
|
| + delete [] source;
|
| + ucnv_close(conv);
|
| + return FALSE;
|
| +}
|
| +
|
| +int IdnaConfTest::isNewlineMark(){
|
| + static const UChar LF = 0x0a;
|
| + static const UChar CR = 0x0d;
|
| + UChar c = base[curOffset];
|
| + // CR LF
|
| + if ( c == CR && curOffset + 1 < len && base[curOffset + 1] == LF){
|
| + return 2;
|
| + }
|
| +
|
| + // CR or LF
|
| + if ( c == CR || c == LF) {
|
| + return 1;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +/* Read a logical line.
|
| + *
|
| + * All lines ending in a backslash (\) and immediately followed by a newline
|
| + * character are joined with the next line in the source file forming logical
|
| + * lines from the physical lines.
|
| + *
|
| + */
|
| +UBool IdnaConfTest::ReadOneLine(UnicodeString& buf){
|
| + if ( !(curOffset < len) ) return FALSE; // stream end
|
| +
|
| + static const UChar BACKSLASH = 0x5c;
|
| + buf.remove();
|
| + int t = 0;
|
| + while (curOffset < len){
|
| + if ((t = isNewlineMark())) { // end of line
|
| + curOffset += t;
|
| + break;
|
| + }
|
| + UChar c = base[curOffset];
|
| + if (c == BACKSLASH && curOffset < len -1){ // escaped new line mark
|
| + if ((t = isNewlineMark())){
|
| + curOffset += 1 + t; // BACKSLAH and NewlineMark
|
| + continue;
|
| + }
|
| + };
|
| + buf.append(c);
|
| + curOffset++;
|
| + }
|
| + return TRUE;
|
| +}
|
| +
|
| +//
|
| +//===============================================================
|
| +//
|
| +
|
| +/* Explain <xxxxx> tag to a native value
|
| + *
|
| + * Since <xxxxx> is always larger than the native value,
|
| + * the operation will replace the tag directly in the buffer,
|
| + * and, of course, will shift tail elements.
|
| + */
|
| +void IdnaConfTest::ExplainCodePointTag(UnicodeString& buf){
|
| + buf.append((UChar)0); // add a terminal NULL
|
| + UChar* bufBase = buf.getBuffer(buf.length());
|
| + UChar* p = bufBase;
|
| + while (*p != 0){
|
| + if ( *p != 0x3C){ // <
|
| + *bufBase++ = *p++;
|
| + } else {
|
| + p++; // skip <
|
| + UChar32 cp = 0;
|
| + for ( ;*p != 0x3E; p++){ // >
|
| + if (0x30 <= *p && *p <= 0x39){ // 0-9
|
| + cp = (cp * 16) + (*p - 0x30);
|
| + } else if (0x61 <= *p && *p <= 0x66){ // a-f
|
| + cp = (cp * 16) + (*p - 0x61) + 10;
|
| + } else if (0x41 <= *p && *p <= 0x46) {// A-F
|
| + cp = (cp * 16) + (*p - 0x41) + 10;
|
| + }
|
| + // no else. hope everything is good.
|
| + }
|
| + p++; // skip >
|
| + if (U_IS_BMP(cp)){
|
| + *bufBase++ = cp;
|
| + } else {
|
| + *bufBase++ = U16_LEAD(cp);
|
| + *bufBase++ = U16_TRAIL(cp);
|
| + }
|
| + }
|
| + }
|
| + *bufBase = 0; // close our buffer
|
| + buf.releaseBuffer();
|
| +}
|
| +
|
| +void IdnaConfTest::Call(){
|
| + if (type == -1 || option == -1 || passfail == -1 || namebase.isBogus() || namezone.isBogus()){
|
| + errln("Incomplete record");
|
| + } else {
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + UChar result[200] = {0,}; // simple life
|
| + const UChar *p = namebase.getTerminatedBuffer();
|
| + const int p_len = namebase.length();
|
| +
|
| + if (type == 0 && option == 0){
|
| + uidna_IDNToASCII(p, p_len, result, 200, UIDNA_USE_STD3_RULES, NULL, &status);
|
| + } else if (type == 0 && option == 1){
|
| + uidna_IDNToASCII(p, p_len, result, 200, UIDNA_ALLOW_UNASSIGNED, NULL, &status);
|
| + } else if (type == 1 && option == 0){
|
| + uidna_IDNToUnicode(p, p_len, result, 200, UIDNA_USE_STD3_RULES, NULL, &status);
|
| + } else if (type == 1 && option == 1){
|
| + uidna_IDNToUnicode(p, p_len, result, 200, UIDNA_ALLOW_UNASSIGNED, NULL, &status);
|
| + }
|
| + if (passfail == 0){
|
| + if (U_FAILURE(status)){
|
| + id.append(" should pass, but failed. - ");
|
| + id.append(u_errorName(status));
|
| + errcheckln(status, id);
|
| + } else{
|
| + if (namezone.compare(result, -1) == 0){
|
| + // expected
|
| + logln(UnicodeString("namebase: ") + prettify(namebase) + UnicodeString(" result: ") + prettify(result));
|
| + } else {
|
| + id.append(" no error, but result is not as expected.");
|
| + errln(id);
|
| + }
|
| + }
|
| + } else if (passfail == 1){
|
| + if (U_FAILURE(status)){
|
| + // expected
|
| + // TODO: Uncomment this when U_IDNA_ZERO_LENGTH_LABEL_ERROR is added to u_errorName
|
| + //logln("Got the expected error: " + UnicodeString(u_errorName(status)));
|
| + } else{
|
| + if (namebase.compare(result, -1) == 0){
|
| + // garbage in -> garbage out
|
| + logln(UnicodeString("ICU will not recognize malformed ACE-Prefixes or incorrect ACE-Prefixes. ") + UnicodeString("namebase: ") + prettify(namebase) + UnicodeString(" result: ") + prettify(result));
|
| + } else {
|
| + id.append(" should fail, but not failed. ");
|
| + id.append(u_errorName(status));
|
| + errln(id);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + type = option = passfail = -1;
|
| + namebase.setToBogus();
|
| + namezone.setToBogus();
|
| + id.remove();
|
| + return;
|
| +}
|
| +
|
| +void IdnaConfTest::Test(void){
|
| + if (!ReadAndConvertFile())return;
|
| +
|
| + UnicodeString s;
|
| + UnicodeString key;
|
| + UnicodeString value;
|
| +
|
| + // skip everything before the first "=====" and "=====" itself
|
| + do {
|
| + if (!ReadOneLine(s)) {
|
| + errln("End of file prematurely found");
|
| + break;
|
| + }
|
| + }
|
| + while (s.compare(C_TAG, -1) != 0); //"====="
|
| +
|
| + while(ReadOneLine(s)){
|
| + s.trim();
|
| + key.remove();
|
| + value.remove();
|
| + if (s.compare(C_TAG, -1) == 0){ //"====="
|
| + Call();
|
| + } else {
|
| + // explain key:value
|
| + int p = s.indexOf((UChar)0x3A); // :
|
| + key.setTo(s,0,p).trim();
|
| + value.setTo(s,p+1).trim();
|
| + if (key.compare(C_TYPE, -1) == 0){
|
| + if (value.compare(C_TOASCII, -1) == 0) {
|
| + type = 0;
|
| + } else if (value.compare(C_TOUNICODE, -1) == 0){
|
| + type = 1;
|
| + }
|
| + } else if (key.compare(C_PASSFAIL, -1) == 0){
|
| + if (value.compare(C_PASS, -1) == 0){
|
| + passfail = 0;
|
| + } else if (value.compare(C_FAIL, -1) == 0){
|
| + passfail = 1;
|
| + }
|
| + } else if (key.compare(C_DESC, -1) == 0){
|
| + if (value.indexOf(C_USESTD3ASCIIRULES, u_strlen(C_USESTD3ASCIIRULES), 0) == -1){
|
| + option = 1; // not found
|
| + } else {
|
| + option = 0;
|
| + }
|
| + id.setTo(value, 0, value.indexOf((UChar)0x20)); // space
|
| + } else if (key.compare(C_NAMEZONE, -1) == 0){
|
| + ExplainCodePointTag(value);
|
| + namezone.setTo(value);
|
| + } else if (key.compare(C_NAMEBASE, -1) == 0){
|
| + ExplainCodePointTag(value);
|
| + namebase.setTo(value);
|
| + }
|
| + // just skip other lines
|
| + }
|
| + }
|
| +
|
| + Call(); // for last record
|
| +}
|
| +#else
|
| +void IdnaConfTest::Test(void)
|
| +{
|
| + // test nothing...
|
| +}
|
| +#endif
|
| +
|
| +void IdnaConfTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/){
|
| + switch (index) {
|
| + TESTCASE(0,Test);
|
| + default: name = ""; break;
|
| + }
|
| +}
|
| +
|
| +#endif
|
|
|
| Property changes on: icu46/source/test/intltest/idnaconf.cpp
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|