+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 2003-2006, International Business Machines Corporation and
+ * Copyright (c) 2003-2015, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*
#include "unicode/uchar.h"
#include "unicode/ures.h"
#include "cintltst.h"
-#include "umutex.h"
#include "unicode/utrace.h"
#include <stdlib.h>
#include <string.h>
} ctest_AlignedMemory;
static void TestHeapFunctions(void);
-static void TestMutexFunctions(void);
-static void TestIncDecFunctions(void);
void addHeapMutexTest(TestNode **root);
addHeapMutexTest(TestNode** root)
{
addTest(root, &TestHeapFunctions, "hpmufn/TestHeapFunctions" );
- addTest(root, &TestMutexFunctions, "hpmufn/TestMutexFunctions" );
- addTest(root, &TestIncDecFunctions, "hpmufn/TestIncDecFunctions");
}
static int32_t gMutexFailures = 0;
#define TEST_STATUS(status, expected) \
if (status != expected) { \
-log_err("FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \
+log_err_status(status, "FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \
__FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailures++; }
* probably because some earlier test accidently left something open. */
ctest_resetICU();
- /* Can not set memory functions if ICU is already initialized */
- u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
-
/* Un-initialize ICU */
u_cleanup();
TEST_STATUS(status, U_ZERO_ERROR);
- /* After reinitializing ICU, we should not be able to set the memory funcs again. */
+ /* After reinitializing ICU, we can not set the memory funcs again. */
status = U_ZERO_ERROR;
u_setDataDirectory(icuDataDir);
u_init(&status);
TEST_STATUS(status, U_ZERO_ERROR);
- u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
/* Doing ICU operations should cause allocations to come through our test heap */
gBlockCount = 0;
}
-/*
- * Test u_setMutexFunctions()
- */
-
-int gTotalMutexesInitialized = 0; /* Total number of mutexes created */
-int gTotalMutexesActive = 0; /* Total mutexes created, but not destroyed */
-int gAccumulatedLocks = 0;
-const void *gMutexContext;
-
-typedef struct DummyMutex {
- int fLockCount;
- int fMagic;
-} DummyMutex;
-
-
-static void U_CALLCONV myMutexInit(const void *context, UMTX *mutex, UErrorCode *status) {
- DummyMutex *theMutex;
-
- TEST_STATUS(*status, U_ZERO_ERROR);
- theMutex = (DummyMutex *)malloc(sizeof(DummyMutex));
- theMutex->fLockCount = 0;
- theMutex->fMagic = 123456;
- gTotalMutexesInitialized++;
- gTotalMutexesActive++;
- gMutexContext = context;
- *mutex = theMutex;
-}
-
-
-static void U_CALLCONV myMutexDestroy(const void *context, UMTX *mutex) {
- DummyMutex *This = *(DummyMutex **)mutex;
-
- gTotalMutexesActive--;
- TEST_ASSERT(This->fLockCount == 0);
- TEST_ASSERT(This->fMagic == 123456);
- This->fMagic = 0;
- This->fLockCount = 0;
- free(This);
-}
-
-static void U_CALLCONV myMutexLock(const void *context, UMTX *mutex) {
- DummyMutex *This = *(DummyMutex **)mutex;
-
- TEST_ASSERT(This->fMagic == 123456);
- This->fLockCount++;
- gAccumulatedLocks++;
-}
-
-static void U_CALLCONV myMutexUnlock(const void *context, UMTX *mutex) {
- DummyMutex *This = *(DummyMutex **)mutex;
-
- TEST_ASSERT(This->fMagic == 123456);
- This->fLockCount--;
- TEST_ASSERT(This->fLockCount >= 0);
-}
-
-
-
-static void TestMutexFunctions() {
- UErrorCode status = U_ZERO_ERROR;
- UResourceBundle *rb = NULL;
- char *icuDataDir;
-
- gMutexFailures = 0;
-
- /* Save initial ICU state so that it can be restored later.
- * u_cleanup(), which is called in this test, resets ICU's state.
- */
- icuDataDir = safeGetICUDataDirectory();
-
- /* Verify that ICU can be cleaned up and reinitialized successfully.
- * Failure here usually means that some ICU service didn't clean up successfully,
- * probably because some earlier test accidently left something open. */
- ctest_resetICU();
-
- /* Can not set mutex functions if ICU is already initialized */
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
-
- /* Un-initialize ICU */
- u_cleanup();
-
- /* Can not set Mutex functions with NULL values */
- status = U_ZERO_ERROR;
- u_setMutexFunctions(&gContext, NULL, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
- status = U_ZERO_ERROR;
- u_setMutexFunctions(&gContext, myMutexInit, NULL, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
- status = U_ZERO_ERROR;
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, NULL, myMutexUnlock, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
- status = U_ZERO_ERROR;
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, NULL, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
-
- /* u_setMutexFunctions() should work with null or non-null context pointer */
- status = U_ZERO_ERROR;
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_ZERO_ERROR);
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_ZERO_ERROR);
-
-
- /* After reinitializing ICU, we should not be able to set the mutex funcs again. */
- status = U_ZERO_ERROR;
- u_setDataDirectory(icuDataDir);
- u_init(&status);
- TEST_STATUS(status, U_ZERO_ERROR);
- u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
-
- /* Doing ICU operations should cause allocations to come through our test mutexes */
- gBlockCount = 0;
- status = U_ZERO_ERROR;
- rb = ures_open(NULL, "es", &status);
- TEST_STATUS(status, U_ZERO_ERROR);
- TEST_ASSERT(gTotalMutexesInitialized > 0);
- TEST_ASSERT(gTotalMutexesActive > 0);
-
- ures_close(rb);
-
- /* Cleanup should destroy all of the mutexes. */
- ctest_resetICU();
- status = U_ZERO_ERROR;
- TEST_ASSERT(gTotalMutexesInitialized > 0);
- TEST_ASSERT(gTotalMutexesActive == 0);
-
-
- /* Additional ICU operations should no longer use our dummy test mutexes */
- gTotalMutexesInitialized = 0;
- gTotalMutexesActive = 0;
- u_init(&status);
- TEST_STATUS(status, U_ZERO_ERROR);
-
- status = U_ZERO_ERROR;
- rb = ures_open(NULL, "fr", &status);
- TEST_STATUS(status, U_ZERO_ERROR);
- TEST_ASSERT(gTotalMutexesInitialized == 0);
- TEST_ASSERT(gTotalMutexesActive == 0);
-
- ures_close(rb);
- free(icuDataDir);
-
- if(gMutexFailures) {
- log_info("Note: these failures may be caused by ICU failing to initialize/uninitialize properly.\n");
- log_verbose("Check for prior tests which may not have closed all open resources. See the internal function ures_flushCache()\n");
- }
-}
-
-
-
-
-/*
- * Test Atomic Increment & Decrement Functions
- */
-
-int gIncCount = 0;
-int gDecCount = 0;
-const void *gIncDecContext;
-const void *gExpectedContext = &gIncDecContext;
-
-
-static int32_t U_CALLCONV myIncFunc(const void *context, int32_t *p) {
- int32_t retVal;
- TEST_ASSERT(context == gExpectedContext);
- gIncCount++;
- retVal = ++(*p);
- return retVal;
-}
-
-static int32_t U_CALLCONV myDecFunc(const void *context, int32_t *p) {
- int32_t retVal;
- TEST_ASSERT(context == gExpectedContext);
- gDecCount++;
- retVal = --(*p);
- return retVal;
-}
-
-
-
-
-static void TestIncDecFunctions() {
- UErrorCode status = U_ZERO_ERROR;
- int32_t t = 1; /* random value to make sure that Inc/dec works */
- char *dataDir;
-
- /* Save ICU's data dir and tracing functions so that they can be resored
- after cleanup and reinit. */
- dataDir = safeGetICUDataDirectory();
-
- /* Verify that ICU can be cleaned up and reinitialized successfully.
- * Failure here usually means that some ICU service didn't clean up successfully,
- * probably because some earlier test accidently left something open. */
- ctest_resetICU();
-
- /* Can not set mutex functions if ICU is already initialized */
- u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
-
- /* Clean up ICU */
- u_cleanup();
-
- /* Can not set functions with NULL values */
- status = U_ZERO_ERROR;
- u_setAtomicIncDecFunctions(&gIncDecContext, NULL, myDecFunc, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
- status = U_ZERO_ERROR;
- u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, NULL, &status);
- TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
-
- /* u_setIncDecFunctions() should work with null or non-null context pointer */
- status = U_ZERO_ERROR;
- gExpectedContext = NULL;
- u_setAtomicIncDecFunctions(NULL, myIncFunc, myDecFunc, &status);
- TEST_STATUS(status, U_ZERO_ERROR);
- gExpectedContext = &gIncDecContext;
- u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
- TEST_STATUS(status, U_ZERO_ERROR);
-
-
- /* After reinitializing ICU, we should not be able to set the inc/dec funcs again. */
- status = U_ZERO_ERROR;
- u_setDataDirectory(dataDir);
- u_init(&status);
- TEST_STATUS(status, U_ZERO_ERROR);
- gExpectedContext = &gIncDecContext;
- u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
- TEST_STATUS(status, U_INVALID_STATE_ERROR);
-
- /* Doing ICU operations should cause our functions to be called */
- gIncCount = 0;
- gDecCount = 0;
- umtx_atomic_inc(&t);
- TEST_ASSERT(t == 2);
- umtx_atomic_dec(&t);
- TEST_ASSERT(t == 1);
- TEST_ASSERT(gIncCount > 0);
- TEST_ASSERT(gDecCount > 0);
-
-
- /* Cleanup should cancel use of our inc/dec functions. */
- /* Additional ICU operations should not use them */
- ctest_resetICU();
- gIncCount = 0;
- gDecCount = 0;
- status = U_ZERO_ERROR;
- u_setDataDirectory(dataDir);
- u_init(&status);
- TEST_ASSERT(gIncCount == 0);
- TEST_ASSERT(gDecCount == 0);
-
- status = U_ZERO_ERROR;
- umtx_atomic_inc(&t);
- umtx_atomic_dec(&t);
- TEST_STATUS(status, U_ZERO_ERROR);
- TEST_ASSERT(gIncCount == 0);
- TEST_ASSERT(gDecCount == 0);
-
- free(dataDir);
-}
-