Author: mthl
Date: Sat May 25 21:19:54 2019 New Revision: 1860017 URL: http://svn.apache.org/viewvc?rev=1860017&view=rev Log: Improved: Turn ‘UtilCacheTests’ into a unit test class (OFBIZ-11067) Added: ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/ ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java (with props) Removed: ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/util/cache/test/ Modified: ofbiz/ofbiz-framework/trunk/framework/base/testdef/basetests.xml Added: ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java?rev=1860017&view=auto ============================================================================== --- ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java (added) +++ ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java Sat May 25 21:19:54 2019 @@ -0,0 +1,451 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ofbiz.base.util.cache; + +import static org.apache.ofbiz.base.test.GenericTestCaseBase.useAllMemory; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.ofbiz.base.util.UtilMisc; +import org.apache.ofbiz.base.util.UtilObject; +import org.junit.Test; + +@SuppressWarnings("serial") +public class UtilCacheTests implements Serializable { + public static final String module = UtilCacheTests.class.getName(); + + protected static abstract class Change { + protected int count = 1; + } + + protected static final class Removal<V> extends Change { + private final V oldValue; + + protected Removal(V oldValue) { + this.oldValue = oldValue; + } + + @Override + public int hashCode() { + return UtilObject.doHashCode(oldValue); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Removal<?>) { + Removal<?> other = (Removal<?>) o; + return UtilObject.equalsHelper(oldValue, other.oldValue); + } + return false; + } + } + + protected static final class Addition<V> extends Change { + private final V newValue; + + protected Addition(V newValue) { + this.newValue = newValue; + } + + @Override + public int hashCode() { + return UtilObject.doHashCode(newValue); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Addition<?>) { + Addition<?> other = (Addition<?>) o; + return UtilObject.equalsHelper(newValue, other.newValue); + } + return false; + } + } + + protected static final class Update<V> extends Change { + private final V newValue; + private final V oldValue; + + protected Update(V newValue, V oldValue) { + this.newValue = newValue; + this.oldValue = oldValue; + } + + @Override + public int hashCode() { + return UtilObject.doHashCode(newValue) ^ UtilObject.doHashCode(oldValue); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Update<?>) { + Update<?> other = (Update<?>) o; + if (!UtilObject.equalsHelper(newValue, other.newValue)) { + return false; + } + return UtilObject.equalsHelper(oldValue, other.oldValue); + } + return false; + } + } + + protected static class Listener<K, V> implements CacheListener<K, V> { + protected Map<K, Set<Change>> changeMap = new HashMap<>(); + + private void add(K key, Change change) { + Set<Change> changeSet = changeMap.get(key); + if (changeSet == null) { + changeSet = new HashSet<>(); + changeMap.put(key, changeSet); + } + for (Change checkChange: changeSet) { + if (checkChange.equals(change)) { + checkChange.count++; + return; + } + } + changeSet.add(change); + } + + @Override + public synchronized void noteKeyRemoval(UtilCache<K, V> cache, K key, V oldValue) { + add(key, new Removal<>(oldValue)); + } + + @Override + public synchronized void noteKeyAddition(UtilCache<K, V> cache, K key, V newValue) { + add(key, new Addition<>(newValue)); + } + + @Override + public synchronized void noteKeyUpdate(UtilCache<K, V> cache, K key, V newValue, V oldValue) { + add(key, new Update<>(newValue, oldValue)); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Listener)) { + return false; + } + Listener<?, ?> other = (Listener<?, ?>) o; + return changeMap.equals(other.changeMap); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + } + + private static <K, V> Listener<K, V> createListener(UtilCache<K, V> cache) { + Listener<K, V> listener = new Listener<>(); + cache.addListener(listener); + return listener; + } + + private <K, V> UtilCache<K, V> createUtilCache(int sizeLimit, int maxInMemory, long ttl, boolean useSoftReference) { + return UtilCache.createUtilCache(getClass().getName(), sizeLimit, maxInMemory, ttl, useSoftReference); + } + + private static <K, V> void assertUtilCacheSettings(UtilCache<K, V> cache, Integer sizeLimit, Integer maxInMemory, + Long expireTime, Boolean useSoftReference) { + if (sizeLimit != null) { + assertEquals(cache.getName() + ":sizeLimit", sizeLimit.intValue(), cache.getSizeLimit()); + } + if (maxInMemory != null) { + assertEquals(cache.getName() + ":maxInMemory", maxInMemory.intValue(), cache.getMaxInMemory()); + } + if (expireTime != null) { + assertEquals(cache.getName() + ":expireTime", expireTime.longValue(), cache.getExpireTime()); + } + if (useSoftReference != null) { + assertEquals(cache.getName() + ":useSoftReference", useSoftReference.booleanValue(), + cache.getUseSoftReference()); + } + assertEquals("initial empty", true, cache.isEmpty()); + assertEquals("empty keys", Collections.emptySet(), cache.getCacheLineKeys()); + assertEquals("empty values", Collections.emptyList(), cache.values()); + assertSame("find cache", cache, UtilCache.findCache(cache.getName())); + assertNotSame("new cache", cache, UtilCache.createUtilCache()); + } + + @Test + public void testCreateUtilCache() { + String name = getClass().getName(); + assertUtilCacheSettings(UtilCache.createUtilCache(), null, null, null, null); + assertUtilCacheSettings(UtilCache.createUtilCache(name), null, null, null, null); + assertUtilCacheSettings(UtilCache.createUtilCache(name, false), null, null, null, Boolean.FALSE); + assertUtilCacheSettings(UtilCache.createUtilCache(name, true), null, null, null, Boolean.TRUE); + assertUtilCacheSettings(UtilCache.createUtilCache(5, 15000), 5, null, 15000L, null); + assertUtilCacheSettings(UtilCache.createUtilCache(name, 6, 16000), 6, null, 16000L, null); + assertUtilCacheSettings(UtilCache.createUtilCache(name, 7, 17000, false), 7, null, 17000L, Boolean.FALSE); + assertUtilCacheSettings(UtilCache.createUtilCache(name, 8, 18000, true), 8, null, 18000L, Boolean.TRUE); + assertUtilCacheSettings(UtilCache.createUtilCache(name, 9, 5, 19000, false), 9, 5, 19000L, Boolean.FALSE); + assertUtilCacheSettings(UtilCache.createUtilCache(name, 10, 6, 20000, false), 10, 6, 20000L, Boolean.FALSE); + assertUtilCacheSettings( + UtilCache.createUtilCache(name, 11, 7, 21000, false, "a", "b"), 11, 7, 21000L, Boolean.FALSE); + assertUtilCacheSettings( + UtilCache.createUtilCache(name, 12, 8, 22000, false, "c", "d"), 12, 8, 22000L, Boolean.FALSE); + } + + public static <K, V> void assertKey(String label, UtilCache<K, V> cache, K key, V value, V other, int size, + Map<K, V> map) { + assertNull(label + ":get-empty", cache.get(key)); + assertFalse(label + ":containsKey-empty", cache.containsKey(key)); + V oldValue = cache.put(key, other); + assertTrue(label + ":containsKey-class", cache.containsKey(key)); + assertEquals(label + ":get-class", other, cache.get(key)); + assertNull(label + ":oldValue-class", oldValue); + assertEquals(label + ":size-class", size, cache.size()); + oldValue = cache.put(key, value); + assertTrue(label + ":containsKey-value", cache.containsKey(key)); + assertEquals(label + ":get-value", value, cache.get(key)); + assertEquals(label + ":oldValue-value", other, oldValue); + assertEquals(label + ":size-value", size, cache.size()); + map.put(key, value); + assertEquals(label + ":map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat(label + ":map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + } + + private static <K, V> void assertHasSingleKey(UtilCache<K, V> cache, K key, V value) { + assertFalse("is-empty", cache.isEmpty()); + assertEquals("size", 1, cache.size()); + assertTrue("found", cache.containsKey(key)); + assertTrue("validKey", UtilCache.validKey(cache.getName(), key)); + assertFalse("validKey", UtilCache.validKey(":::" + cache.getName(), key)); + assertEquals("get", value, cache.get(key)); + assertEquals("keys", new HashSet<>(UtilMisc.toList(key)), cache.getCacheLineKeys()); + assertEquals("values", UtilMisc.toList(value), cache.values()); + } + + private static <K, V> void assertNoSingleKey(UtilCache<K, V> cache, K key) { + assertFalse("not-found", cache.containsKey(key)); + assertFalse("validKey", UtilCache.validKey(cache.getName(), key)); + assertNull("no-get", cache.get(key)); + assertNull("remove", cache.remove(key)); + assertTrue("is-empty", cache.isEmpty()); + assertEquals("size", 0, cache.size()); + assertEquals("keys", Collections.emptySet(), cache.getCacheLineKeys()); + assertEquals("values", Collections.emptyList(), cache.values()); + } + + private static void basicTest(UtilCache<String, String> cache) throws Exception { + Listener<String, String> gotListener = createListener(cache); + Listener<String, String> wantedListener = new Listener<>(); + for (int i = 0; i < 2; i++) { + assertTrue("UtilCacheTable.keySet", UtilCache.getUtilCacheTableKeySet().contains(cache.getName())); + assertSame("UtilCache.findCache", cache, UtilCache.findCache(cache.getName())); + assertSame("UtilCache.getOrCreateUtilCache", cache, UtilCache.getOrCreateUtilCache(cache.getName(), + cache.getSizeLimit(), cache.getMaxInMemory(), cache.getExpireTime(), cache.getUseSoftReference())); + + assertNoSingleKey(cache, "one"); + long origByteSize = cache.getSizeInBytes(); + + wantedListener.noteKeyAddition(cache, null, "null"); + assertNull("put", cache.put(null, "null")); + assertHasSingleKey(cache, null, "null"); + long nullByteSize = cache.getSizeInBytes(); + assertThat(nullByteSize, greaterThan(origByteSize)); + + wantedListener.noteKeyRemoval(cache, null, "null"); + assertEquals("remove", "null", cache.remove(null)); + assertNoSingleKey(cache, null); + + wantedListener.noteKeyAddition(cache, "one", "uno"); + assertNull("put", cache.put("one", "uno")); + assertHasSingleKey(cache, "one", "uno"); + long unoByteSize = cache.getSizeInBytes(); + assertThat(unoByteSize, greaterThan(origByteSize)); + + wantedListener.noteKeyUpdate(cache, "one", "single", "uno"); + assertEquals("replace", "uno", cache.put("one", "single")); + assertHasSingleKey(cache, "one", "single"); + long singleByteSize = cache.getSizeInBytes(); + assertThat(singleByteSize, greaterThan(origByteSize)); + assertThat(singleByteSize, greaterThan(unoByteSize)); + + wantedListener.noteKeyRemoval(cache, "one", "single"); + assertEquals("remove", "single", cache.remove("one")); + assertNoSingleKey(cache, "one"); + assertEquals("byteSize", origByteSize, cache.getSizeInBytes()); + + wantedListener.noteKeyAddition(cache, "one", "uno"); + assertNull("put", cache.put("one", "uno")); + assertHasSingleKey(cache, "one", "uno"); + + wantedListener.noteKeyUpdate(cache, "one", "only", "uno"); + assertEquals("replace", "uno", cache.put("one", "only")); + assertHasSingleKey(cache, "one", "only"); + + wantedListener.noteKeyRemoval(cache, "one", "only"); + cache.erase(); + assertNoSingleKey(cache, "one"); + assertEquals("byteSize", origByteSize, cache.getSizeInBytes()); + + cache.setExpireTime(100); + wantedListener.noteKeyAddition(cache, "one", "uno"); + assertNull("put", cache.put("one", "uno")); + assertHasSingleKey(cache, "one", "uno"); + + wantedListener.noteKeyRemoval(cache, "one", "uno"); + Thread.sleep(200); + assertNoSingleKey(cache, "one"); + } + + assertEquals("get-miss", 10, cache.getMissCountNotFound()); + assertEquals("get-miss-total", 10, cache.getMissCountTotal()); + assertEquals("get-hit", 12, cache.getHitCount()); + assertEquals("remove-hit", 6, cache.getRemoveHitCount()); + assertEquals("remove-miss", 10, cache.getRemoveMissCount()); + cache.removeListener(gotListener); + assertEquals("listener", wantedListener, gotListener); + UtilCache.clearCache(cache.getName()); + UtilCache.clearCache(":::" + cache.getName()); + } + + @Test + public void testSimple() throws Exception { + UtilCache<String, String> cache = createUtilCache(5, 0, 0, false); + basicTest(cache); + } + + @Test + public void testPutIfAbsent() throws Exception { + UtilCache<String, String> cache = createUtilCache(5, 5, 2000, false); + Listener<String, String> gotListener = createListener(cache); + Listener<String, String> wantedListener = new Listener<>(); + wantedListener.noteKeyAddition(cache, "two", "dos"); + assertNull("putIfAbsent", cache.putIfAbsent("two", "dos")); + assertHasSingleKey(cache, "two", "dos"); + assertEquals("putIfAbsent", "dos", cache.putIfAbsent("two", "double")); + assertHasSingleKey(cache, "two", "dos"); + cache.removeListener(gotListener); + assertEquals("listener", wantedListener, gotListener); + } + + @Test + public void testPutIfAbsentAndGet() throws Exception { + UtilCache<String, String> cache = createUtilCache(5, 5, 2000, false); + Listener<String, String> gotListener = createListener(cache); + Listener<String, String> wantedListener = new Listener<>(); + wantedListener.noteKeyAddition(cache, "key", "value"); + wantedListener.noteKeyAddition(cache, "anotherKey", "anotherValue"); + assertNull("no-get", cache.get("key")); + assertEquals("putIfAbsentAndGet", "value", cache.putIfAbsentAndGet("key", "value")); + assertHasSingleKey(cache, "key", "value"); + assertEquals("putIfAbsentAndGet", "value", cache.putIfAbsentAndGet("key", "newValue")); + assertHasSingleKey(cache, "key", "value"); + String anotherValueAddedToCache = new String("anotherValue"); + String anotherValueNotAddedToCache = new String("anotherValue"); + assertEquals(anotherValueAddedToCache, anotherValueNotAddedToCache); + assertNotSame(anotherValueAddedToCache, anotherValueNotAddedToCache); + String cachedValue = cache.putIfAbsentAndGet("anotherKey", anotherValueAddedToCache); + assertSame(cachedValue, anotherValueAddedToCache); + cachedValue = cache.putIfAbsentAndGet("anotherKey", anotherValueNotAddedToCache); + assertNotSame(cachedValue, anotherValueNotAddedToCache); + assertSame(cachedValue, anotherValueAddedToCache); + cache.removeListener(gotListener); + assertEquals("listener", wantedListener, gotListener); + } + + @Test + public void testChangeMemSize() throws Exception { + int size = 5; + long ttl = 2000; + UtilCache<String, Serializable> cache = createUtilCache(size, size, ttl, false); + Map<String, Serializable> map = new HashMap<>(); + assertKeyLoop(size, cache, map); + cache.setMaxInMemory(2); + assertEquals("cache.size", 2, cache.size()); + map.keySet().retainAll(cache.getCacheLineKeys()); + assertEquals("map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat("map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + cache.setMaxInMemory(0); + assertEquals("map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat("map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + for (int i = size * 2; i < size * 3; i++) { + String s = Integer.toString(i); + assertKey(s, cache, s, new String(s), new String(":" + s), i - size * 2 + 3, map); + } + cache.setMaxInMemory(0); + assertEquals("map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat("map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + cache.setMaxInMemory(size); + for (int i = 0; i < size * 2; i++) { + map.remove(Integer.toString(i)); + } + // Can't compare the contents of these collections, as setting LRU after not + // having one, means the items that get evicted are essentially random. + assertEquals("map-keys", map.keySet().size(), cache.getCacheLineKeys().size()); + assertEquals("map-values", map.values().size(), cache.values().size()); + } + + private static void expireTest(UtilCache<String, Serializable> cache, int size, long ttl) throws Exception { + Map<String, Serializable> map = new HashMap<>(); + assertKeyLoop(size, cache, map); + Thread.sleep(ttl + 500); + map.clear(); + for (int i = 0; i < size; i++) { + String s = Integer.toString(i); + assertNull("no-key(" + s + ")", cache.get(s)); + } + assertEquals("map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat("map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + assertKeyLoop(size, cache, map); + assertEquals("map-keys", map.keySet(), cache.getCacheLineKeys()); + assertThat("map-values", cache.values(), containsInAnyOrder(map.values().toArray())); + } + + private static void assertKeyLoop(int size, UtilCache<String, Serializable> cache, Map<String, Serializable> map) { + for (int i = 0; i < size; i++) { + String s = Integer.toString(i); + assertKey(s, cache, s, new String(s), new String(":" + s), i + 1, map); + } + } + + @Test + public void testExpire() throws Exception { + UtilCache<String, Serializable> cache = createUtilCache(5, 5, 2000, false); + expireTest(cache, 5, 2000); + long start = System.currentTimeMillis(); + useAllMemory(); + long end = System.currentTimeMillis(); + long ttl = end - start + 1000; + cache = createUtilCache(1, 1, ttl, true); + expireTest(cache, 1, ttl); + assertFalse("not empty", cache.isEmpty()); + useAllMemory(); + assertNull("not-key(0)", cache.get("0")); + assertTrue("empty", cache.isEmpty()); + } +} Propchange: ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/ofbiz-framework/trunk/framework/base/src/test/java/org/apache/ofbiz/base/util/cache/UtilCacheTests.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ofbiz/ofbiz-framework/trunk/framework/base/testdef/basetests.xml URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/base/testdef/basetests.xml?rev=1860017&r1=1860016&r2=1860017&view=diff ============================================================================== --- ofbiz/ofbiz-framework/trunk/framework/base/testdef/basetests.xml (original) +++ ofbiz/ofbiz-framework/trunk/framework/base/testdef/basetests.xml Sat May 25 21:19:54 2019 @@ -28,7 +28,6 @@ <junit-test-suite class-name="org.apache.ofbiz.base.util.test.UtilHttpTests"/> <junit-test-suite class-name="org.apache.ofbiz.base.util.string.test.FlexibleStringExpanderTests"/> <junit-test-suite class-name="org.apache.ofbiz.base.util.collections.test.FlexibleMapAccessorTests"/> - <junit-test-suite class-name="org.apache.ofbiz.base.util.cache.test.UtilCacheTests"/> <junit-test-suite class-name="org.apache.ofbiz.base.conversion.test.TestBooleanConverters"/> <junit-test-suite class-name="org.apache.ofbiz.base.conversion.test.TestJSONConverters"/> <!--junit-test-suite class-name="org.apache.ofbiz.base.util.test.UtilIOTests"/--> |
Free forum by Nabble | Edit this page |