Home | History | Annotate | Download | only in letest
      1 /*
      2  *******************************************************************************
      3  *
      4  *   Copyright (C) 1999-2007, International Business Machines
      5  *   Corporation and others.  All Rights Reserved.
      6  *
      7  *******************************************************************************
      8  */
      9 
     10 #include "unicode/utypes.h"
     11 #include "unicode/uclean.h"
     12 #include "unicode/uchar.h"
     13 #include "unicode/unistr.h"
     14 #include "unicode/uscript.h"
     15 #include "unicode/putil.h"
     16 #include "unicode/ctest.h"
     17 
     18 #include "layout/LETypes.h"
     19 #include "layout/LEScripts.h"
     20 
     21 #include "letsutil.h"
     22 #include "letest.h"
     23 
     24 #include "xmlreader.h"
     25 
     26 #include "xmlparser.h"
     27 
     28 #include <stdlib.h>
     29 #include <stdio.h>
     30 #include <string.h>
     31 
     32 //U_NAMESPACE_USE
     33 
     34 #define CH_COMMA 0x002C
     35 
     36 static le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize)
     37 {
     38     int32_t offset = -1;
     39 
     40     arraySize = 1;
     41     while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
     42         arraySize += 1;
     43     }
     44 
     45     le_uint32 *array = NEW_ARRAY(le_uint32, arraySize);
     46     char number[16];
     47     le_int32 count = 0;
     48     le_int32 start = 0, end = 0;
     49     le_int32 len = 0;
     50 
     51     // trim leading whitespace
     52     while(u_isUWhiteSpace(numbers[start])) {
     53         start += 1;
     54     }
     55 
     56     while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
     57         len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
     58         number[len] = '\0';
     59         start = end + 1;
     60 
     61         sscanf(number, "%x", &array[count++]);
     62 
     63         // trim whitespace following the comma
     64         while(u_isUWhiteSpace(numbers[start])) {
     65             start += 1;
     66         }
     67     }
     68 
     69     // trim trailing whitespace
     70     end = numbers.length();
     71     while(u_isUWhiteSpace(numbers[end - 1])) {
     72         end -= 1;
     73     }
     74 
     75     len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
     76     number[len] = '\0';
     77     sscanf(number, "%x", &array[count]);
     78 
     79     return array;
     80 }
     81 
     82 static float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize)
     83 {
     84     int32_t offset = -1;
     85 
     86     arraySize = 1;
     87     while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
     88         arraySize += 1;
     89     }
     90 
     91     float *array = NEW_ARRAY(float, arraySize);
     92     char number[32];
     93     le_int32 count = 0;
     94     le_int32 start = 0, end = 0;
     95     le_int32 len = 0;
     96 
     97     // trim leading whitespace
     98     while(u_isUWhiteSpace(numbers[start])) {
     99         start += 1;
    100     }
    101 
    102     while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
    103         len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
    104         number[len] = '\0';
    105         start = end + 1;
    106 
    107         sscanf(number, "%f", &array[count++]);
    108 
    109         // trim whiteapce following the comma
    110         while(u_isUWhiteSpace(numbers[start])) {
    111             start += 1;
    112         }
    113     }
    114 
    115     while(u_isUWhiteSpace(numbers[start])) {
    116         start += 1;
    117     }
    118 
    119     // trim trailing whitespace
    120     end = numbers.length();
    121     while(u_isUWhiteSpace(numbers[end - 1])) {
    122         end -= 1;
    123     }
    124 
    125     len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
    126     number[len] = '\0';
    127     sscanf(number, "%f", &array[count]);
    128 
    129     return array;
    130 }
    131 
    132 U_CDECL_BEGIN
    133 void readTestFile(const char *testFilePath, TestCaseCallback callback)
    134 {
    135 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
    136     UErrorCode status = U_ZERO_ERROR;
    137     UXMLParser  *parser = UXMLParser::createParser(status);
    138     UXMLElement *root   = parser->parseFile(testFilePath, status);
    139 
    140     if (root == NULL) {
    141         log_err("Could not open the test data file: %s\n", testFilePath);
    142         delete parser;
    143         return;
    144     }
    145 
    146     UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
    147     UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
    148     UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
    149     UnicodeString result_glyphs    = UNICODE_STRING_SIMPLE("result-glyphs");
    150     UnicodeString result_indices   = UNICODE_STRING_SIMPLE("result-indices");
    151     UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions");
    152 
    153     // test-case attributes
    154     UnicodeString id_attr     = UNICODE_STRING_SIMPLE("id");
    155     UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
    156     UnicodeString lang_attr   = UNICODE_STRING_SIMPLE("lang");
    157 
    158     // test-font attributes
    159     UnicodeString name_attr   = UNICODE_STRING_SIMPLE("name");
    160     UnicodeString ver_attr    = UNICODE_STRING_SIMPLE("version");
    161     UnicodeString cksum_attr  = UNICODE_STRING_SIMPLE("checksum");
    162 
    163     const UXMLElement *testCase;
    164     int32_t tc = 0;
    165 
    166     while((testCase = root->nextChildElement(tc)) != NULL) {
    167         if (testCase->getTagName().compare(test_case) == 0) {
    168             char *id = getCString(testCase->getAttribute(id_attr));
    169             char *script    = getCString(testCase->getAttribute(script_attr));
    170             char *lang      = getCString(testCase->getAttribute(lang_attr));
    171             char *fontName  = NULL;
    172 			char *fontVer   = NULL;
    173 			char *fontCksum = NULL;
    174             const UXMLElement *element;
    175             int32_t ec = 0;
    176             int32_t charCount = 0;
    177             int32_t typoFlags = 3; // kerning + ligatures...
    178             UScriptCode scriptCode;
    179             le_int32 languageCode = -1;
    180             UnicodeString text, glyphs, indices, positions;
    181             int32_t glyphCount = 0, indexCount = 0, positionCount = 0;
    182             TestResult expected = {0, NULL, NULL, NULL};
    183 
    184             uscript_getCode(script, &scriptCode, 1, &status);
    185             if (LE_FAILURE(status)) {
    186                 log_err("invalid script name: %s.\n", script);
    187                 goto free_c_strings;
    188             }
    189 
    190             if (lang != NULL) {
    191                 languageCode = getLanguageCode(lang);
    192 
    193                 if (languageCode < 0) {
    194                     log_err("invalid language name: %s.\n", lang);
    195                     goto free_c_strings;
    196                 }
    197             }
    198 
    199             while((element = testCase->nextChildElement(ec)) != NULL) {
    200                 UnicodeString tag = element->getTagName();
    201 
    202                 // TODO: make sure that each element is only used once.
    203                 if (tag.compare(test_font) == 0) {
    204                     fontName  = getCString(element->getAttribute(name_attr));
    205                     fontVer   = getCString(element->getAttribute(ver_attr));
    206                     fontCksum = getCString(element->getAttribute(cksum_attr));
    207 
    208                 } else if (tag.compare(test_text) == 0) {
    209                     text = element->getText(TRUE);
    210                     charCount = text.length();
    211                 } else if (tag.compare(result_glyphs) == 0) {
    212                     glyphs = element->getText(TRUE);
    213                 } else if (tag.compare(result_indices) == 0) {
    214                     indices = element->getText(TRUE);
    215                 } else if (tag.compare(result_positions) == 0) {
    216                     positions = element->getText(TRUE);
    217                 } else {
    218                     // an unknown tag...
    219                     char *cTag = getCString(&tag);
    220 
    221                     log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag);
    222                     freeCString(cTag);
    223                 }
    224             }
    225 
    226             expected.glyphs    = (LEGlyphID *) getHexArray(glyphs, glyphCount);
    227             expected.indices   = (le_int32 *)  getHexArray(indices, indexCount);
    228             expected.positions = getFloatArray(positions, positionCount);
    229 
    230             expected.glyphCount = glyphCount;
    231 
    232             if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
    233                 log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
    234                     id, charCount, glyphCount, indexCount, positionCount);
    235                 goto free_expected;
    236             };
    237 
    238 			(*callback)(id, fontName, fontVer, fontCksum, scriptCode, languageCode, text.getBuffer(), charCount, &expected);
    239 
    240 free_expected:
    241             DELETE_ARRAY(expected.positions);
    242             DELETE_ARRAY(expected.indices);
    243             DELETE_ARRAY(expected.glyphs);
    244 
    245 free_c_strings:
    246 			freeCString(fontCksum);
    247 			freeCString(fontVer);
    248 			freeCString(fontName);
    249             freeCString(lang);
    250             freeCString(script);
    251             freeCString(id);
    252         }
    253     }
    254 
    255     delete root;
    256     delete parser;
    257 #endif
    258 }
    259 U_CDECL_END
    260