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