1/* 2******************************************************************************* 3* Copyright (C) 2014, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6* 7* File UNIFIEDCACHETEST.CPP 8* 9******************************************************************************** 10*/ 11#include "cstring.h" 12#include "intltest.h" 13#include "unifiedcache.h" 14 15class UCTItem : public SharedObject { 16 public: 17 char *value; 18 UCTItem(const char *x) : value(NULL) { 19 value = uprv_strdup(x); 20 } 21 virtual ~UCTItem() { 22 uprv_free(value); 23 } 24}; 25 26class UCTItem2 : public SharedObject { 27}; 28 29U_NAMESPACE_BEGIN 30 31template<> U_EXPORT 32const UCTItem *LocaleCacheKey<UCTItem>::createObject( 33 const void * /*unused*/, UErrorCode &status) const { 34 if (uprv_strcmp(fLoc.getName(), "zh") == 0) { 35 status = U_MISSING_RESOURCE_ERROR; 36 return NULL; 37 } 38 if (uprv_strcmp(fLoc.getLanguage(), fLoc.getName()) != 0) { 39 const UCTItem *item = NULL; 40 UnifiedCache::getByLocale(fLoc.getLanguage(), item, status); 41 if (U_FAILURE(status)) { 42 return NULL; 43 } 44 return item; 45 } 46 UCTItem *result = new UCTItem(fLoc.getName()); 47 result->addRef(); 48 return result; 49} 50 51template<> U_EXPORT 52const UCTItem2 *LocaleCacheKey<UCTItem2>::createObject( 53 const void * /*unused*/, UErrorCode & /*status*/) const { 54 return NULL; 55} 56 57U_NAMESPACE_END 58 59 60class UnifiedCacheTest : public IntlTest { 61public: 62 UnifiedCacheTest() { 63 } 64 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); 65private: 66 void TestBasic(); 67 void TestError(); 68 void TestHashEquals(); 69}; 70 71void UnifiedCacheTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) { 72 TESTCASE_AUTO_BEGIN; 73 TESTCASE_AUTO(TestBasic); 74 TESTCASE_AUTO(TestError); 75 TESTCASE_AUTO(TestHashEquals); 76 TESTCASE_AUTO_END; 77} 78 79void UnifiedCacheTest::TestBasic() { 80 UErrorCode status = U_ZERO_ERROR; 81 const UnifiedCache *cache = UnifiedCache::getInstance(status); 82 assertSuccess("", status); 83 cache->flush(); 84 int32_t baseCount = cache->keyCount(); 85 const UCTItem *en = NULL; 86 const UCTItem *enGb = NULL; 87 const UCTItem *enGb2 = NULL; 88 const UCTItem *enUs = NULL; 89 const UCTItem *fr = NULL; 90 const UCTItem *frFr = NULL; 91 cache->get(LocaleCacheKey<UCTItem>("en"), en, status); 92 cache->get(LocaleCacheKey<UCTItem>("en_US"), enUs, status); 93 cache->get(LocaleCacheKey<UCTItem>("en_GB"), enGb, status); 94 cache->get(LocaleCacheKey<UCTItem>("fr_FR"), frFr, status); 95 cache->get(LocaleCacheKey<UCTItem>("fr"), fr, status); 96 cache->get(LocaleCacheKey<UCTItem>("en_GB"), enGb2, status); 97 SharedObject::clearPtr(enGb2); 98 if (enGb != enUs) { 99 errln("Expected en_GB and en_US to resolve to same object."); 100 } 101 if (fr != frFr) { 102 errln("Expected fr and fr_FR to resolve to same object."); 103 } 104 if (enGb == fr) { 105 errln("Expected en_GB and fr to return different objects."); 106 } 107 assertSuccess("", status); 108 // en_US, en_GB, en share one object; fr_FR and fr don't share. 109 // 5 keys in all. 110 assertEquals("", baseCount + 5, cache->keyCount()); 111 SharedObject::clearPtr(enGb); 112 cache->flush(); 113 assertEquals("", baseCount + 5, cache->keyCount()); 114 SharedObject::clearPtr(enUs); 115 SharedObject::clearPtr(en); 116 cache->flush(); 117 // With en_GB and en_US and en cleared there are no more hard references to 118 // the "en" object, so it gets flushed and the keys that refer to it 119 // get removed from the cache. 120 assertEquals("", baseCount + 2, cache->keyCount()); 121 SharedObject::clearPtr(fr); 122 cache->flush(); 123 assertEquals("", baseCount + 2, cache->keyCount()); 124 SharedObject::clearPtr(frFr); 125 cache->flush(); 126 assertEquals("", baseCount + 0, cache->keyCount()); 127} 128 129void UnifiedCacheTest::TestError() { 130 UErrorCode status = U_ZERO_ERROR; 131 const UnifiedCache *cache = UnifiedCache::getInstance(status); 132 assertSuccess("", status); 133 cache->flush(); 134 int32_t baseCount = cache->keyCount(); 135 const UCTItem *zh = NULL; 136 const UCTItem *zhTw = NULL; 137 const UCTItem *zhHk = NULL; 138 139 status = U_ZERO_ERROR; 140 cache->get(LocaleCacheKey<UCTItem>("zh"), zh, status); 141 if (status != U_MISSING_RESOURCE_ERROR) { 142 errln("Expected U_MISSING_RESOURCE_ERROR"); 143 } 144 status = U_ZERO_ERROR; 145 cache->get(LocaleCacheKey<UCTItem>("zh_TW"), zhTw, status); 146 if (status != U_MISSING_RESOURCE_ERROR) { 147 errln("Expected U_MISSING_RESOURCE_ERROR"); 148 } 149 status = U_ZERO_ERROR; 150 cache->get(LocaleCacheKey<UCTItem>("zh_HK"), zhHk, status); 151 if (status != U_MISSING_RESOURCE_ERROR) { 152 errln("Expected U_MISSING_RESOURCE_ERROR"); 153 } 154 // 3 keys in cache zh, zhTW, zhHk all pointing to error placeholders 155 assertEquals("", baseCount + 3, cache->keyCount()); 156 cache->flush(); 157 // error placeholders have no hard references so they always get flushed. 158 assertEquals("", baseCount + 0, cache->keyCount()); 159} 160 161void UnifiedCacheTest::TestHashEquals() { 162 LocaleCacheKey<UCTItem> key1("en_US"); 163 LocaleCacheKey<UCTItem> key2("en_US"); 164 LocaleCacheKey<UCTItem> diffKey1("en_UT"); 165 LocaleCacheKey<UCTItem2> diffKey2("en_US"); 166 assertTrue("", key1.hashCode() == key2.hashCode()); 167 assertTrue("", key1.hashCode() != diffKey1.hashCode()); 168 assertTrue("", key1.hashCode() != diffKey2.hashCode()); 169 assertTrue("", diffKey1.hashCode() != diffKey2.hashCode()); 170 assertTrue("", key1 == key2); 171 assertTrue("", key1 != diffKey1); 172 assertTrue("", key1 != diffKey2); 173 assertTrue("", diffKey1 != diffKey2); 174} 175 176extern IntlTest *createUnifiedCacheTest() { 177 return new UnifiedCacheTest(); 178} 179