From 688b99d198c57b2f9295374b21a88b7f30567960 Mon Sep 17 00:00:00 2001 From: LamGC Date: Fri, 4 Sep 2020 19:58:45 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=20=E6=B7=BB=E5=8A=A0=20MapCacheStore=20?= =?UTF-8?q?=E7=9A=84=E6=9C=AC=E5=9C=B0=E5=AE=9E=E7=8E=B0;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Add] HashMapCacheStore 添加基于 Hashtable 的 MapCacheStore 实现; [Add] HashMapCacheStoreTest 添加针对 HashMapCacheStore 的完整单元测试; --- .../bot/cache/local/HashMapCacheStore.java | 117 ++++++++++++++++ .../cache/local/HashMapCacheStoreTest.java | 130 ++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-local/src/test/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStoreTest.java diff --git a/ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStore.java b/ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStore.java new file mode 100644 index 0000000..8de517b --- /dev/null +++ b/ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStore.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache.local; + +import net.lamgc.cgj.bot.cache.MapCacheStore; + +import java.util.*; +import java.util.function.Function; + +/** + * + * @param + * @see net.lamgc.cgj.bot.cache.CacheStore + * @see net.lamgc.cgj.bot.cache.MapCacheStore + * @author LamGC + */ +public class HashMapCacheStore extends HashCacheStore> implements MapCacheStore { + + @Override + public int mapSize(String key) { + return getMap(key, false, Map::size, -1); + } + + @Override + public Set mapFieldSet(String key) { + return getMap(key, false, Map::keySet, null); + } + + @Override + public Set mapValueSet(String key) { + return getMap(key, false, map -> new HashSet<>(map.values()), null); + } + + @Override + public boolean put(String key, String field, V value) { + return getMap(key, true, map -> { + map.put(Objects.requireNonNull(field), Objects.requireNonNull(value)); + return true; + }, false); + } + + @Override + public boolean putAll(String key, Map map) { + return getMap(key, true, keyMap -> { + keyMap.putAll(Objects.requireNonNull(map)); + return true; + }, false); + } + + @Override + public boolean putIfNotExist(String key, String field, V value) { + return getMap(key, true, map -> { + if (map.containsKey(Objects.requireNonNull(field))) { + return false; + } + map.put(Objects.requireNonNull(field), Objects.requireNonNull(value)); + return true; + }, false); + } + + @Override + public V get(String key, String field) { + return getMap(key, false, map -> map.get(Objects.requireNonNull(field)), null); + } + + @Override + public boolean removeField(String key, String field) { + return getMap(key, false, map -> map.remove(Objects.requireNonNull(field)) != null, false); + } + + @Override + public boolean containsField(String key, String field) { + return getMap(key, false, map -> map.containsKey(Objects.requireNonNull(field)), false); + } + + @Override + public boolean mapIsEmpty(String key) { + return getMap(key, false, Map::isEmpty, false); + } + + @Override + public boolean clearMap(String key) { + return getMap(key, false, map -> { + map.clear(); + return true; + }, false); + } + + private R getMap(String key, boolean create, Function, R> notNull, R isNull) { + Objects.requireNonNull(key); + Map>> cacheMap = getCacheMap(); + if (!cacheMap.containsKey(key)) { + if (create) { + cacheMap.put(key, new CacheItem<>(new Hashtable<>())); + } else { + return isNull; + } + } + return notNull.apply(cacheMap.get(key).getValue()); + } + +} diff --git a/ContentGrabbingJi-CacheStore-local/src/test/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStoreTest.java b/ContentGrabbingJi-CacheStore-local/src/test/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStoreTest.java new file mode 100644 index 0000000..906a279 --- /dev/null +++ b/ContentGrabbingJi-CacheStore-local/src/test/java/net/lamgc/cgj/bot/cache/local/HashMapCacheStoreTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache.local; + + +import net.lamgc.cgj.bot.cache.MapCacheStore; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @see HashMapCacheStore + */ +public class HashMapCacheStoreTest { + + @Test + public void nullThrowTest() { + final MapCacheStore cacheStore = new HashMapCacheStore<>(); + + Assert.assertThrows(NullPointerException.class, () -> cacheStore.mapSize(null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.mapFieldSet(null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.mapValueSet(null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.put(null, "field", "value")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.put("testKey", null, "value")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.put("testKey", "field", null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.putAll(null, new HashMap<>())); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.putAll("testKey", null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.putIfNotExist(null, "field", "value")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.putIfNotExist("testKey", null, "value")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.putIfNotExist("testKey", "field", null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.get("testKey", null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.get(null, "field")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.removeField("testKey", null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.removeField(null, "field")); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.mapIsEmpty(null)); + Assert.assertThrows(NullPointerException.class, () -> cacheStore.clearMap(null)); + } + + @Test + public void keyNotExistTest() { + final MapCacheStore cacheStore = new HashMapCacheStore<>(); + final String key = "testKey"; + + Assert.assertEquals(-1, cacheStore.mapSize(key)); + Assert.assertFalse(cacheStore.mapIsEmpty(key)); + Assert.assertFalse(cacheStore.clearMap(key)); + Assert.assertFalse(cacheStore.containsField(key, "Field")); + Assert.assertFalse(cacheStore.removeField(key, "Field")); + Assert.assertNull(cacheStore.get(key, "Field")); + Assert.assertTrue(cacheStore.put(key, "Field", "value")); + Assert.assertTrue("clearMap operation failed!", cacheStore.remove(key)); + Assert.assertTrue(cacheStore.putAll(key, new HashMap<>())); + Assert.assertTrue("clearMap operation failed!", cacheStore.remove(key)); + Assert.assertTrue(cacheStore.putIfNotExist(key, "Field", "value")); + } + + @Test + public void putAndGetTest() { + final MapCacheStore cacheStore = new HashMapCacheStore<>(); + final String key = "testKey"; + final Map expectedMap = new HashMap<>(); + expectedMap.put("test01", "testValue01"); + expectedMap.put("test02", "testValue02"); + expectedMap.put("test03", "testValue03"); + expectedMap.put("test04", "testValue04"); + expectedMap.put("test05", "testValue05"); + expectedMap.put("test06", "testValue06"); + + // put/get, mapIsEmpty, containsField + Assert.assertTrue("put operation failed!", cacheStore.put(key, "test00", "testValue00")); + Assert.assertTrue(cacheStore.containsField(key, "test00")); + Assert.assertEquals("testValue00", cacheStore.get(key, "test00")); + Assert.assertTrue("removeField operation failed!", cacheStore.removeField(key, "test00")); + + // putIfNotExist + Assert.assertTrue(cacheStore.putIfNotExist(key, "test00", "testValue00")); + Assert.assertFalse(cacheStore.putIfNotExist(key, "test00", "testValue00")); + Assert.assertTrue("clearMap operation failed!", cacheStore.clearMap(key)); + + // putAll + Assert.assertTrue(cacheStore.putAll(key, expectedMap)); + Assert.assertTrue(expectedMap.keySet().containsAll(cacheStore.mapFieldSet(key))); + Assert.assertTrue(expectedMap.values().containsAll(cacheStore.mapValueSet(key))); + } + + @Test + public void fieldChangeTest() { + final MapCacheStore cacheStore = new HashMapCacheStore<>(); + final String key = "testKey"; + final Map expectedMap = new HashMap<>(); + expectedMap.put("test01", "testValue01"); + expectedMap.put("test02", "testValue02"); + expectedMap.put("test03", "testValue03"); + expectedMap.put("test04", "testValue04"); + expectedMap.put("test05", "testValue05"); + expectedMap.put("test06", "testValue06"); + + // mapSize, clearMap, mapIsEmpty 测试 + Assert.assertTrue("putAll operation failed!", cacheStore.putAll(key, expectedMap)); + Assert.assertEquals(expectedMap.size(), cacheStore.mapSize(key)); + Assert.assertTrue(cacheStore.clearMap(key)); + Assert.assertTrue(cacheStore.mapIsEmpty(key)); + + // removeField 多分支测试 + Assert.assertTrue("put operation failed!", cacheStore.put(key, "test00", "testValue00")); + Assert.assertTrue(cacheStore.containsField(key, "test00")); + Assert.assertEquals("testValue00", cacheStore.get(key, "test00")); + Assert.assertTrue("removeField operation failed!", cacheStore.removeField(key, "test00")); + Assert.assertFalse(cacheStore.removeField(key, "test00")); + } + + +} \ No newline at end of file