| OLD | NEW |
| (Empty) |
| 1 /******************************************************************** | |
| 2 * COPYRIGHT: | |
| 3 * Copyright (c) 2003-2015, International Business Machines Corporation and | |
| 4 * others. All Rights Reserved. | |
| 5 ********************************************************************/ | |
| 6 /* | |
| 7 * File hpmufn.c | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "unicode/utypes.h" | |
| 12 #include "unicode/putil.h" | |
| 13 #include "unicode/uclean.h" | |
| 14 #include "unicode/uchar.h" | |
| 15 #include "unicode/ures.h" | |
| 16 #include "cintltst.h" | |
| 17 #include "unicode/utrace.h" | |
| 18 #include <stdlib.h> | |
| 19 #include <string.h> | |
| 20 | |
| 21 /** | |
| 22 * This should align the memory properly on any machine. | |
| 23 */ | |
| 24 typedef union { | |
| 25 long t1; | |
| 26 double t2; | |
| 27 void *t3; | |
| 28 } ctest_AlignedMemory; | |
| 29 | |
| 30 static void TestHeapFunctions(void); | |
| 31 | |
| 32 void addHeapMutexTest(TestNode **root); | |
| 33 | |
| 34 | |
| 35 void | |
| 36 addHeapMutexTest(TestNode** root) | |
| 37 { | |
| 38 addTest(root, &TestHeapFunctions, "hpmufn/TestHeapFunctions" ); | |
| 39 } | |
| 40 | |
| 41 static int32_t gMutexFailures = 0; | |
| 42 | |
| 43 #define TEST_STATUS(status, expected) \ | |
| 44 if (status != expected) { \ | |
| 45 log_err_status(status, "FAIL at %s:%d. Actual status = \"%s\"; Expected status
= \"%s\"\n", \ | |
| 46 __FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailure
s++; } | |
| 47 | |
| 48 | |
| 49 #define TEST_ASSERT(expr) \ | |
| 50 if (!(expr)) { \ | |
| 51 log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__);
\ | |
| 52 gMutexFailures++; \ | |
| 53 } | |
| 54 | |
| 55 | |
| 56 /* These tests do cleanup and reinitialize ICU in the course of their operation
. | |
| 57 * The ICU data directory must be preserved across these operations. | |
| 58 * Here is a helper function to assist with that. | |
| 59 */ | |
| 60 static char *safeGetICUDataDirectory() { | |
| 61 const char *dataDir = u_getDataDirectory(); /* Returned string vanashes wit
h u_cleanup */ | |
| 62 char *retStr = NULL; | |
| 63 if (dataDir != NULL) { | |
| 64 retStr = (char *)malloc(strlen(dataDir)+1); | |
| 65 strcpy(retStr, dataDir); | |
| 66 } | |
| 67 return retStr; | |
| 68 } | |
| 69 | |
| 70 | |
| 71 | |
| 72 /* | |
| 73 * Test Heap Functions. | |
| 74 * Implemented on top of the standard malloc heap. | |
| 75 * All blocks increased in size by 8 to 16 bytes, and the poiner returned to
ICU is | |
| 76 * offset up by 8 to 16, which should cause a good heap corruption if one
of our "blocks" | |
| 77 * ends up being freed directly, without coming through us. | |
| 78 * Allocations are counted, to check that ICU actually does call back to us. | |
| 79 */ | |
| 80 int gBlockCount = 0; | |
| 81 const void *gContext; | |
| 82 | |
| 83 static void * U_CALLCONV myMemAlloc(const void *context, size_t size) { | |
| 84 char *retPtr = (char *)malloc(size+sizeof(ctest_AlignedMemory)); | |
| 85 if (retPtr != NULL) { | |
| 86 retPtr += sizeof(ctest_AlignedMemory); | |
| 87 } | |
| 88 gBlockCount ++; | |
| 89 return retPtr; | |
| 90 } | |
| 91 | |
| 92 static void U_CALLCONV myMemFree(const void *context, void *mem) { | |
| 93 char *freePtr = (char *)mem; | |
| 94 if (freePtr != NULL) { | |
| 95 freePtr -= sizeof(ctest_AlignedMemory); | |
| 96 } | |
| 97 free(freePtr); | |
| 98 } | |
| 99 | |
| 100 | |
| 101 | |
| 102 static void * U_CALLCONV myMemRealloc(const void *context, void *mem, size_t siz
e) { | |
| 103 char *p = (char *)mem; | |
| 104 char *retPtr; | |
| 105 | |
| 106 if (p!=NULL) { | |
| 107 p -= sizeof(ctest_AlignedMemory); | |
| 108 } | |
| 109 retPtr = realloc(p, size+sizeof(ctest_AlignedMemory)); | |
| 110 if (retPtr != NULL) { | |
| 111 p += sizeof(ctest_AlignedMemory); | |
| 112 } | |
| 113 return retPtr; | |
| 114 } | |
| 115 | |
| 116 | |
| 117 static void TestHeapFunctions() { | |
| 118 UErrorCode status = U_ZERO_ERROR; | |
| 119 UResourceBundle *rb = NULL; | |
| 120 char *icuDataDir; | |
| 121 UVersionInfo unicodeVersion = {0,0,0,0}; | |
| 122 | |
| 123 icuDataDir = safeGetICUDataDirectory(); /* save icu data dir, so we can pu
t it back | |
| 124 * after doing u_cleanup().
*/ | |
| 125 | |
| 126 | |
| 127 /* Verify that ICU can be cleaned up and reinitialized successfully. | |
| 128 * Failure here usually means that some ICU service didn't clean up success
fully, | |
| 129 * probably because some earlier test accidently left something open. */ | |
| 130 ctest_resetICU(); | |
| 131 | |
| 132 /* Un-initialize ICU */ | |
| 133 u_cleanup(); | |
| 134 | |
| 135 /* Can not set memory functions with NULL values */ | |
| 136 status = U_ZERO_ERROR; | |
| 137 u_setMemoryFunctions(&gContext, NULL, myMemRealloc, myMemFree, &status); | |
| 138 TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); | |
| 139 status = U_ZERO_ERROR; | |
| 140 u_setMemoryFunctions(&gContext, myMemAlloc, NULL, myMemFree, &status); | |
| 141 TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); | |
| 142 status = U_ZERO_ERROR; | |
| 143 u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, NULL, &status); | |
| 144 TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR); | |
| 145 | |
| 146 /* u_setMemoryFunctions() should work with null or non-null context pointer
*/ | |
| 147 status = U_ZERO_ERROR; | |
| 148 u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status); | |
| 149 TEST_STATUS(status, U_ZERO_ERROR); | |
| 150 u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status
); | |
| 151 TEST_STATUS(status, U_ZERO_ERROR); | |
| 152 | |
| 153 | |
| 154 /* After reinitializing ICU, we can not set the memory funcs again. */ | |
| 155 status = U_ZERO_ERROR; | |
| 156 u_setDataDirectory(icuDataDir); | |
| 157 u_init(&status); | |
| 158 TEST_STATUS(status, U_ZERO_ERROR); | |
| 159 | |
| 160 /* Doing ICU operations should cause allocations to come through our test he
ap */ | |
| 161 gBlockCount = 0; | |
| 162 status = U_ZERO_ERROR; | |
| 163 rb = ures_open(NULL, "es", &status); | |
| 164 TEST_STATUS(status, U_ZERO_ERROR); | |
| 165 if (gBlockCount == 0) { | |
| 166 log_err("Heap functions are not being called from ICU.\n"); | |
| 167 } | |
| 168 ures_close(rb); | |
| 169 | |
| 170 /* Cleanup should put the heap back to its default implementation. */ | |
| 171 ctest_resetICU(); | |
| 172 u_getUnicodeVersion(unicodeVersion); | |
| 173 if (unicodeVersion[0] <= 0) { | |
| 174 log_err("Properties doesn't reinitialize without u_init.\n"); | |
| 175 } | |
| 176 status = U_ZERO_ERROR; | |
| 177 u_init(&status); | |
| 178 TEST_STATUS(status, U_ZERO_ERROR); | |
| 179 | |
| 180 /* ICU operations should no longer cause allocations to come through our tes
t heap */ | |
| 181 gBlockCount = 0; | |
| 182 status = U_ZERO_ERROR; | |
| 183 rb = ures_open(NULL, "fr", &status); | |
| 184 TEST_STATUS(status, U_ZERO_ERROR); | |
| 185 if (gBlockCount != 0) { | |
| 186 log_err("Heap functions did not reset after u_cleanup.\n"); | |
| 187 } | |
| 188 ures_close(rb); | |
| 189 free(icuDataDir); | |
| 190 | |
| 191 ctest_resetICU(); | |
| 192 } | |
| 193 | |
| 194 | |
| OLD | NEW |