/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ package org.voltcore.zk; import java.util.Map; import org.json_voltpatches.JSONObject; import static org.junit.Assert.assertEquals; import org.apache.zookeeper_voltpatches.ZooDefs.Ids; import org.apache.zookeeper_voltpatches.CreateMode; import org.apache.zookeeper_voltpatches.ZooKeeper; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.google_voltpatches.common.collect.ImmutableMap; public class TestMapCache extends ZKTestBase { private final int NUM_AGREEMENT_SITES = 8; public static class TestCallback extends MapCache.Callback { ImmutableMap<String, JSONObject> m_cache = null; public void run(ImmutableMap<String, JSONObject> cache) { m_cache = cache; } } @Before public void setUp() throws Exception { setUpZK(NUM_AGREEMENT_SITES); } @After public void tearDown() throws Exception { tearDownZK(); } void configure(String root, ZooKeeper zk) throws Exception { JSONObject aa = new JSONObject("{key:aaval}"); JSONObject bb = new JSONObject("{key:bbval}"); JSONObject cc = new JSONObject("{key:ccval}"); zk.create(root, new byte[]{}, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.create(root + "/aa", aa.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.create(root + "/bb", bb.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.create(root + "/cc", cc.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } @Test public void testInitialCache() throws Exception { ZooKeeper zk = getClient(0); configure("/cache01", zk); MapCache dut = new MapCache(zk, "/cache01"); dut.start(true); Map<String, JSONObject> cache = dut.pointInTimeCache(); assertEquals("3 items cached.", 3, cache.size()); assertEquals("aaval", cache.get("/cache01/aa").get("key")); assertEquals("bbval", cache.get("/cache01/bb").get("key")); assertEquals("ccval", cache.get("/cache01/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testInitialCacheWithCallback() throws Exception { ZooKeeper zk = getClient(0); configure("/cache01", zk); TestCallback cb = new TestCallback(); MapCache dut = new MapCache(zk, "/cache01", cb); dut.start(true); assertEquals("3 items cached.", 3, cb.m_cache.size()); assertEquals("aaval", cb.m_cache.get("/cache01/aa").get("key")); assertEquals("bbval", cb.m_cache.get("/cache01/bb").get("key")); assertEquals("ccval", cb.m_cache.get("/cache01/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testModifyChild() throws Exception { ZooKeeper zk = getClient(0); configure("/cache03", zk); MapCache dut = new MapCache(zk, "/cache03"); dut.start(true); Map<String, JSONObject> cache = dut.pointInTimeCache(); assertEquals("3 items cached.", 3, cache.size()); assertEquals("aaval", cache.get("/cache03/aa").get("key")); JSONObject aa = new JSONObject("{key:aaval2}"); zk.setData("/cache03/aa", aa.toString().getBytes(), -1); while(true) { cache = dut.pointInTimeCache(); if (cache.get("/cache03/aa").get("key").equals("aaval2")) { break; } } assertEquals("3 items cached.", 3, cache.size()); assertEquals("aaval2", cache.get("/cache03/aa").get("key")); assertEquals("bbval", cache.get("/cache03/bb").get("key")); assertEquals("ccval", cache.get("/cache03/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testModifyChildWithCallback() throws Exception { ZooKeeper zk = getClient(0); configure("/cache03", zk); TestCallback cb = new TestCallback(); MapCache dut = new MapCache(zk, "/cache03", cb); dut.start(true); Map<String, JSONObject> cache = cb.m_cache; assertEquals("3 items cached.", 3, cache.size()); assertEquals("aaval", cache.get("/cache03/aa").get("key")); JSONObject aa = new JSONObject("{key:aaval2}"); zk.setData("/cache03/aa", aa.toString().getBytes(), -1); while(true) { cache = cb.m_cache; if (cache.get("/cache03/aa").get("key").equals("aaval2")) { break; } } assertEquals("3 items cached.", 3, cache.size()); assertEquals("aaval2", cache.get("/cache03/aa").get("key")); assertEquals("bbval", cache.get("/cache03/bb").get("key")); assertEquals("ccval", cache.get("/cache03/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testDeleteChild() throws Exception { ZooKeeper zk = getClient(0); configure("/cache02", zk); MapCache dut = new MapCache(zk, "/cache02"); dut.start(true); Map<String, JSONObject> cache = dut.pointInTimeCache(); assertEquals("3 items cached.", 3, cache.size()); zk.delete("/cache02/bb", -1); while(true) { cache = dut.pointInTimeCache(); if (cache.size() == 3) { Thread.sleep(1); } else { break; } } assertEquals("Item removed", 2, cache.size()); assertEquals(null, cache.get("/cache02/bb")); assertEquals("aaval", cache.get("/cache02/aa").get("key")); assertEquals("ccval", cache.get("/cache02/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testDeleteChildWithCallback() throws Exception { ZooKeeper zk = getClient(0); configure("/cache02", zk); TestCallback cb = new TestCallback(); MapCache dut = new MapCache(zk, "/cache02", cb); dut.start(true); Map<String, JSONObject> cache = cb.m_cache; assertEquals("3 items cached.", 3, cache.size()); zk.delete("/cache02/bb", -1); while(true) { cache = cb.m_cache; if (cache.size() == 3) { Thread.sleep(1); } else { break; } } assertEquals("Item removed", 2, cache.size()); assertEquals(null, cache.get("/cache02/bb")); assertEquals("aaval", cache.get("/cache02/aa").get("key")); assertEquals("ccval", cache.get("/cache02/cc").get("key")); dut.shutdown(); zk.close(); } @Test public void testAddChildWithPut() throws Exception { ZooKeeper zk = getClient(0); configure("/cache04", zk); MapCache dut = new MapCache(zk, "/cache04"); dut.start(true); Map<String, JSONObject> cache = dut.pointInTimeCache(); JSONObject dd = new JSONObject("{key:ddval}"); dut.put("dd", dd); while(true) { cache = dut.pointInTimeCache(); if (cache.size() == 3) { Thread.sleep(1); } else { break; } } assertEquals("Item added", 4, cache.size()); assertEquals("aaval", cache.get("/cache04/aa").get("key")); assertEquals("bbval", cache.get("/cache04/bb").get("key")); assertEquals("ccval", cache.get("/cache04/cc").get("key")); assertEquals("ddval", cache.get("/cache04/dd").get("key")); // modify the new child and make sure it has a watch set. JSONObject dd2 = new JSONObject("{key:ddval2}"); dut.put("dd", dd2); while(true) { cache = dut.pointInTimeCache(); if (cache.get("/cache04/dd").get("key").equals("ddval2")) { break; } } assertEquals("Items accounted for.", 4, cache.size()); assertEquals("ddval2", cache.get("/cache04/dd").get("key")); dut.shutdown(); zk.close(); } @Test public void testAddChildWithPutWithCallback() throws Exception { ZooKeeper zk = getClient(0); configure("/cache04", zk); TestCallback cb = new TestCallback(); MapCache dut = new MapCache(zk, "/cache04", cb); dut.start(true); Map<String, JSONObject> cache = cb.m_cache; JSONObject dd = new JSONObject("{key:ddval}"); dut.put("dd", dd); while(true) { cache = cb.m_cache; if (cache.size() == 3) { Thread.sleep(1); } else { break; } } assertEquals("Item added", 4, cache.size()); assertEquals("aaval", cache.get("/cache04/aa").get("key")); assertEquals("bbval", cache.get("/cache04/bb").get("key")); assertEquals("ccval", cache.get("/cache04/cc").get("key")); assertEquals("ddval", cache.get("/cache04/dd").get("key")); // modify the new child and make sure it has a watch set. JSONObject dd2 = new JSONObject("{key:ddval2}"); dut.put("dd", dd2); while(true) { cache = cb.m_cache; if (cache.get("/cache04/dd").get("key").equals("ddval2")) { break; } } assertEquals("Items accounted for.", 4, cache.size()); assertEquals("ddval2", cache.get("/cache04/dd").get("key")); dut.shutdown(); zk.close(); } }