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