/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1998-2003, International Business Machines Corporation and
+ * Copyright (c) 1998-2004, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*
*/
#include "unicode/utypes.h"
+#include "unicode/putil.h"
#include "unicode/udata.h"
#include "unicode/uchar.h"
#include "unicode/ucnv.h"
#include "cmemory.h"
#include "cstring.h"
#include "filestrm.h"
+#include "udatamem.h"
#include "cintltst.h"
#include <sys/types.h>
#include <unistd.h>
#endif
+/* includes for TestSwapData() */
+#include "udataswp.h"
+
+/* swapping implementations in common */
+#include "uresdata.h"
+#include "ucnv_io.h"
+#include "uprops.h"
+#include "ucase.h"
+#include "ucol_swp.h"
+#include "ucnv_bld.h"
+#include "unormimp.h"
+#include "sprpimpl.h"
+#include "propname.h"
+#include "rbbidata.h"
+
+/* other definitions and prototypes */
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
static void TestUDataOpen(void);
static void TestUDataOpenChoiceDemo1(void);
static void TestUDataOpenChoiceDemo2(void);
static void TestErrorConditions(void);
static void TestAppData(void);
static void TestICUDataName(void);
+static void TestSwapData(void);
void addUDataTest(TestNode** root);
addTest(root, &TestErrorConditions, "udatatst/TestErrorConditions");
addTest(root, &TestAppData, "udatatst/TestAppData" );
addTest(root, &TestICUDataName, "udatatst/TestICUDataName" );
-
+ addTest(root, &TestSwapData, "udatatst/TestSwapData" );
}
#if 0
UDataMemory *result;
UErrorCode status=U_ZERO_ERROR;
const char* memMap[][2]={
- {"tz", "icu"},
+ {"root", "res"},
+ {"unorm", "icu"},
{"cnvalias", "icu"},
{"unames", "icu"},
{"ibm-37_P100-1995", "cnv"}
};
- const char* name = "test";
- const char* type = "icu";
- const char dirSepString[] = {U_FILE_SEP_CHAR, 0};
+ const char* name = "test";
+ const char* type = "icu";
+ const char dirSepString[] = {U_FILE_SEP_CHAR, 0};
+ const char pathSepString[] = {U_PATH_SEP_CHAR, 0};
+
char* path=(char*)malloc(sizeof(char) * (strlen(ctest_dataOutDir())
+ strlen(U_ICUDATA_NAME)
int i;
log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
for(i=0; i<sizeof(memMap)/sizeof(memMap[0]); i++){
- /* lots_of_mallocs(); */
+ /* lots_of_mallocs(); */
status=U_ZERO_ERROR;
result=udata_open(path, memMap[i][1], memMap[i][0], &status);
if(U_FAILURE(status)) {
- log_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status));
+ log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status));
} else {
log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", path, memMap[i][0], memMap[i][1]);
udata_close(result);
strcat(icuDataFilePath, dirSepString);
strcat(icuDataFilePath, U_ICUDATA_NAME);
strcat(icuDataFilePath, "_");
- strcat(icuDataFilePath, "tz.icu");
+ strcat(icuDataFilePath, "unorm.icu");
/* lots_of_mallocs(); */
- if (stat(icuDataFilePath, &stat_buf) == 0)
+/* if (stat(icuDataFilePath, &stat_buf) == 0)*/
{
int i;
log_verbose("%s exists, so..\n", icuDataFilePath);
status=U_ZERO_ERROR;
result=udata_open(icuDataFilePath, memMap[i][1], memMap[i][0], &status);
if(U_FAILURE(status)) {
- log_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1], myErrorName(status));
+ log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1], myErrorName(status));
} else {
log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1]);
udata_close(result);
}
}
}
- else
+/* else
{
log_verbose("Skipping tests of udata_open() on %s. File not present in this configuration.\n",
icuDataFilePath);
- }
+ }*/
free(icuDataFilePath);
icuDataFilePath = NULL;
log_verbose("calling udat_open with non-existing file returned null as expected\n");
}
+ /*
+ * Try opening data with absurdly long path and name, to trigger buffer size
+ * overflow handling code.
+ */
+ {
+ char longTestPath[1024]; /* Implementation goes to heap at length of 128. */
+ char longName[1024];
+
+ /* Try a very long nonexistent directory path.
+ * udata_open should still succeed. Opening with the path will fail,
+ * then fall back to skipping the directory portion of the path.
+ */
+ log_verbose("Testing udata_open() with really long names\n");
+ longTestPath[0] = 0;
+ strcat(longTestPath, "bogus_directory_name");
+ while (strlen(longTestPath) < 500) {
+ strcat(longTestPath, dirSepString);
+ strcat(longTestPath, "bogus_directory_name");
+ }
+ strcat(longTestPath, pathSepString);
+ strcat(longTestPath, testPath);
+ result=udata_open(longTestPath, type, name, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
+ longTestPath, name, type, myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_open worked\n");
+ udata_close(result);
+ }
+
+ /* Try a very long name. Won't open, but shouldn't blow up.
+ */
+ longName[0] = 0;
+ while (strlen(longName) < 500) {
+ strcat(longName, name);
+ strcat(longName, "_");
+ }
+ strcat(longName, dirSepString);
+ strcat(longName, name);
+
+ result=udata_open(longTestPath, type, longName, &status);
+ if (status != U_FILE_ACCESS_ERROR) {
+ log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
+ longTestPath, longName, type, myErrorName(status));
+ }
+ udata_close(result);
+ }
+
free(path);
}
log_verbose("Testing udata_setAppData() with %s\n", filePath);
-#ifdef WIN32
+#if defined(WIN32) || defined(U_CYGWIN)
fileHandle = open( filePath, O_RDONLY | O_BINARY );
#else
fileHandle = open( filePath, O_RDONLY);
i = read(fileHandle, fileBuf, fileSize);
if (i != fileSize) {
- log_err("FAIL: TestUDataSetAppData() error reading file \"%s\".\n", filePath);
+ log_err("FAIL: TestUDataSetAppData() error reading file \"%s\" size=%d read=%d.\n", filePath, fileSize, i);
goto cleanupAndReturn;
}
static void TestUDataOpenChoiceDemo1() {
UDataMemory *result;
UErrorCode status=U_ZERO_ERROR;
-
+
const char* name[]={
"cnvalias",
"unames",
#endif
}
+
+/* test data swapping ------------------------------------------------------- */
+
+/* test cases for maximum data swapping code coverage */
+static const struct {
+ const char *name, *type;
+ UDataSwapFn *swapFn;
+} swapCases[]={
+ /* resource bundles */
+
+ /* resource bundle with many data types */
+ {"*testtypes", "res", ures_swap},
+ /* resource bundle with collation data */
+ {"ja", "res", ures_swap},
+ /* resource bundle with options-only collation data */
+ {"ru", "res", ures_swap},
+ {"el", "res", ures_swap},
+ /* ICU's root */
+ {"root", "res", ures_swap},
+
+ /* ICU 2.6 resource bundle - data format 1.0, without indexes[] (little-endian ASCII) */
+ {"*icu26_testtypes", "res", ures_swap},
+ /* same for big-endian EBCDIC */
+ {"*icu26e_testtypes", "res", ures_swap},
+
+#if !UCONFIG_NO_COLLATION
+ /* standalone collation data files */
+ {"ucadata", "icu", ucol_swap},
+ {"invuca", "icu", ucol_swapInverseUCA},
+#endif
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* conversion table files */
+
+ /* SBCS conversion table file without extension */
+ {"ibm-913_P100-2000", "cnv", ucnv_swap},
+ /* EBCDIC_STATEFUL conversion table file with extension */
+ {"ibm-1390_P110-2003", "cnv", ucnv_swap},
+ /* DBCS extension-only conversion table file */
+ {"ibm-16684_P110-2003", "cnv", ucnv_swap},
+ /* EUC-TW (3-byte) conversion table file without extension */
+ {"ibm-964_P110-1999", "cnv", ucnv_swap},
+ /* GB 18030 (4-byte) conversion table file without extension */
+ {"gb18030", "cnv", ucnv_swap},
+ /* MBCS conversion table file with extension */
+ {"*test4x", "cnv", ucnv_swap},
+
+ /* alias table */
+ {"cnvalias", "icu", ucnv_swapAliases},
+#endif
+
+#if !UCONFIG_NO_IDNA
+ {"uidna", "spp", usprep_swap},
+#endif
+
+#if !UCONFIG_NO_BREAK_ITERATION
+ {"char", "brk", ubrk_swap},
+#endif
+
+ /* the last item should not be #if'ed so that it can reliably omit the last comma */
+
+ /* Unicode properties */
+ {"unames", "icu", uchar_swapNames},
+ {"pnames", "icu", upname_swap},
+#if !UCONFIG_NO_NORMALIZATION
+ {"unorm", "icu", unorm_swap},
+#endif
+ {"uprops", "icu", uprops_swap},
+ {"ucase", "icu", ucase_swap}
+};
+
+#define SWAP_BUFFER_SIZE 1000000
+
+static void U_CALLCONV
+printError(void *context, const char *fmt, va_list args) {
+ vlog_info("[swap] ", fmt, args);
+}
+
+static void
+TestSwapCase(UDataMemory *pData, const char *name,
+ UDataSwapFn *swapFn,
+ uint8_t *buffer, uint8_t *buffer2) {
+ UDataSwapper *ds;
+ const void *inData, *inHeader;
+ int32_t length, dataLength, length2, headerLength;
+
+ UErrorCode errorCode;
+
+ UBool inEndian, oppositeEndian;
+ uint8_t inCharset, oppositeCharset;
+
+ inData=udata_getMemory(pData);
+
+ /*
+ * get the data length if possible, to verify that swapping and preflighting
+ * handles the entire data
+ */
+ dataLength=udata_getLength(pData);
+
+ /*
+ * get the header and its length
+ * all of the swap implementation functions require the header to be included
+ */
+ inHeader=udata_getRawMemory(pData);
+ headerLength=(int32_t)((const char *)inData-(const char *)inHeader);
+
+ /* first swap to opposite endianness but same charset family */
+ errorCode=U_ZERO_ERROR;
+ ds=udata_openSwapperForInputData(inHeader, headerLength,
+ !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapperForInputData(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ inEndian=ds->inIsBigEndian;
+ inCharset=ds->inCharset;
+
+ oppositeEndian=!inEndian;
+ oppositeCharset= inCharset==U_ASCII_FAMILY ? U_EBCDIC_FAMILY : U_ASCII_FAMILY;
+
+ /* make this test work with data files that are built for a different platform */
+ if(inEndian!=U_IS_BIG_ENDIAN || inCharset!=U_CHARSET_FAMILY) {
+ udata_closeSwapper(ds);
+ ds=udata_openSwapper(inEndian, inCharset, oppositeEndian, inCharset, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ }
+
+ ds->printError=printError;
+
+ /* preflight the length */
+ length=swapFn(ds, inHeader, -1, NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(preflight %s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ udata_closeSwapper(ds);
+ return;
+ }
+
+ /* compare the preflighted length against the data length */
+ if(dataLength>=0 && (length+15)<(headerLength+dataLength)) {
+ log_err("swapFn(preflight %s->!isBig+same charset) length too small: %d < data length %d\n",
+ name, length, (headerLength+dataLength));
+ udata_closeSwapper(ds);
+ return;
+ }
+
+ /* swap, not in-place */
+ length2=swapFn(ds, inHeader, length, buffer, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the preflighted length */
+ if(length2!=length) {
+ log_err("swapFn(%s->!isBig+same charset) length differs from preflighting: %d != preflighted %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* next swap to opposite charset family */
+ ds=udata_openSwapper(oppositeEndian, inCharset,
+ oppositeEndian, oppositeCharset,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->!isBig+other charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ ds->printError=printError;
+
+ /* swap in-place */
+ length2=swapFn(ds, buffer, length, buffer, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->!isBig+other charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the original length */
+ if(length2!=length) {
+ log_err("swapFn(%s->!isBig+other charset) length differs from original: %d != original %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* finally swap to original platform values */
+ ds=udata_openSwapper(oppositeEndian, oppositeCharset,
+ inEndian, inCharset,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->back to original) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ ds->printError=printError;
+
+ /* swap, not in-place */
+ length2=swapFn(ds, buffer, length, buffer2, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->back to original) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the original length */
+ if(length2!=length) {
+ log_err("swapFn(%s->back to original) length differs from original: %d != original %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* compare the final contents with the original */
+ if(0!=uprv_memcmp(inHeader, buffer2, length)) {
+ const uint8_t *original;
+ uint8_t diff[8];
+ int32_t i, j;
+
+ log_err("swapFn(%s->back to original) contents differs from original\n",
+ name);
+
+ /* find the first difference */
+ original=(const uint8_t *)inHeader;
+ for(i=0; i<length && original[i]==buffer2[i]; ++i) {}
+
+ /* find the next byte that is the same */
+ for(j=i+1; j<length && original[j]!=buffer2[j]; ++j) {}
+ log_info(" difference at index %d=0x%x, until index %d=0x%x\n", i, i, j, j);
+
+ /* round down to the last 4-boundary for better result output */
+ i&=~3;
+ log_info("showing bytes from index %d=0x%x (length %d=0x%x):\n", i, i, length, length);
+
+ /* print 8 bytes but limit to the buffer contents */
+ length2=i+sizeof(diff);
+ if(length2>length) {
+ length2=length;
+ }
+
+ /* print the original bytes */
+ uprv_memset(diff, 0, sizeof(diff));
+ for(j=i; j<length2; ++j) {
+ diff[j-i]=original[j];
+ }
+ log_info(" original: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
+
+ /* print the swapped bytes */
+ uprv_memset(diff, 0, sizeof(diff));
+ for(j=i; j<length2; ++j) {
+ diff[j-i]=buffer2[j];
+ }
+ log_info(" swapped: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
+ }
+}
+
+static void
+TestSwapData() {
+ char name[100];
+ UDataMemory *pData;
+ uint8_t *buffer;
+ const char *pkg, *nm;
+
+ UErrorCode errorCode;
+ int32_t i;
+
+ buffer=(uint8_t *)uprv_malloc(2*SWAP_BUFFER_SIZE);
+ if(buffer==NULL) {
+ log_err("unable to allocate %d bytes\n", 2*SWAP_BUFFER_SIZE);
+ return;
+ }
+
+ for(i=0; i<LENGTHOF(swapCases); ++i) {
+ /* build the name for logging */
+ errorCode=U_ZERO_ERROR;
+ if(swapCases[i].name[0]=='*') {
+ pkg=loadTestData(&errorCode);
+ nm=swapCases[i].name+1;
+ uprv_strcpy(name, "testdata");
+ } else {
+ pkg=NULL;
+ nm=swapCases[i].name;
+ uprv_strcpy(name, "NULL");
+ }
+ uprv_strcat(name, "/");
+ uprv_strcat(name, nm);
+ uprv_strcat(name, ".");
+ uprv_strcat(name, swapCases[i].type);
+
+ pData=udata_open(pkg, swapCases[i].type, nm, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ TestSwapCase(pData, name, swapCases[i].swapFn, buffer, buffer+SWAP_BUFFER_SIZE);
+ udata_close(pData);
+ } else {
+ log_data_err("udata_open(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ }
+ }
+
+ uprv_free(buffer);
+}