/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.test.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.jdo.PersistenceManager;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.zoodb.api.DBArrayList;
import org.zoodb.api.DBHashMap;
import org.zoodb.test.testutil.TestTools;
/**
* Test harness for DBHashtable.
*
* @author Tilmann Zaeschke
*/
public final class DBHashMapTest {
private static final String KEY1 = "1";
private static final String KEY2 = "2";
private static final String KEY3 = "3";
private static final String KEY4 = "4";
private static final String KEY5 = "5";
private static final String KEY6 = "6";
private static final String ELEMENT1 = "first one";
private static final String ELEMENT2 = "second element";
private static final String ELEMENT3 = "third element";
private static final String ELEMENT4 = "fourth element";
private static final String ELEMENT5 = "fifth element";
private static final String ELEMENT6 = "sixth element";
private DBHashMap<String, String> dbHashtable;
/**
* Run before each test.
* The setUp method tests the put method of DBHashtable.
*/
@Before
public void before() {
//create a DBHashtable
dbHashtable = new DBHashMap<String, String>();
dbHashtable.put(KEY1, ELEMENT1);
dbHashtable.put(KEY2, ELEMENT2);
dbHashtable.put(KEY3, ELEMENT3);
}
/**
* Run after each test.
*/
@After
public void after() {
dbHashtable.clear();
TestTools.closePM();
}
@BeforeClass
public static void beforeClass() {
TestTools.createDb();
TestTools.defineSchema(PersistentDummyImpl.class);
}
@AfterClass
public static void afterClass() {
TestTools.removeDb();
}
/**
* Test the clear() and size() methods.
*/
@Test
public void testClearAndSize() {
assertEquals("Check size 1", 3, dbHashtable.size());
dbHashtable.clear();
assertEquals("Check size 2", 0, dbHashtable.size());
}
/**
* Test the values method returns the correct collection.
*/
@Test
public void testIterator() {
HashSet<String> temp = new HashSet<String>();
temp.add(ELEMENT1);
temp.add(ELEMENT2);
temp.add(ELEMENT3);
Iterator<String> i = dbHashtable.values().iterator();
while (i.hasNext()) {
assertTrue(temp.remove(i.next()));
}
assertTrue(temp.isEmpty());
assertFalse("Check the number of remaining elements", i.hasNext());
}
/**
* Test the remove method removes the correct values.
*/
@Test
public void testRemove() {
dbHashtable.remove(KEY2);
assertEquals("Check element 1", ELEMENT1, dbHashtable.get(KEY1));
assertEquals("Check element 2", null, dbHashtable.get(KEY2));
assertEquals("Check element 3", ELEMENT3, dbHashtable.get(KEY3));
assertTrue("Check the number of values", dbHashtable.size()==2);
}
/**
* Test the contains method returns the correct results.
*/
@Test
public void testContains() {
dbHashtable.remove(ELEMENT2);
assertEquals("Check element 1", true, dbHashtable.containsValue(ELEMENT1));
assertEquals("Check element 2", true, dbHashtable.containsValue(ELEMENT2));
assertEquals("Check element 3", true, dbHashtable.containsValue(ELEMENT3));
assertEquals("Check no element", false, dbHashtable.containsValue(KEY1));
assertEquals("Check no element", false, dbHashtable.containsValue(ELEMENT4));
}
/**
* Test the addAll methods add the correct values.
*/
@Test
public void testPutAll() {
HashMap<String, String> h= new HashMap<String, String>();
h.put(KEY3, ELEMENT3);
h.put(KEY4, ELEMENT4);
h.put(KEY5, ELEMENT5);
h.put(KEY6, ELEMENT6);
dbHashtable.putAll(h);
assertTrue("Check the number of values", dbHashtable.size()==6);
assertEquals("Check element 1", ELEMENT1, dbHashtable.get(KEY1));
assertEquals("Check element 2", ELEMENT2, dbHashtable.get(KEY2));
assertEquals("Check element 3", ELEMENT3, dbHashtable.get(KEY3));
assertEquals("Check element 4", ELEMENT4, dbHashtable.get(KEY4));
assertEquals("Check element 5", ELEMENT5, dbHashtable.get(KEY5));
assertEquals("Check element 6", ELEMENT6, dbHashtable.get(KEY6));
}
/**
* Test the keySet method returns the correct set.
*/
@Test
public void testKeySet() {
SortedSet<String> keys = new TreeSet<String>(dbHashtable.keySet());
assertTrue("Check the number of keys", keys.size()==3);
String[] keyArray = keys.toArray(new String[0]);
assertEquals("Check key 1", KEY1, keyArray[0]);
assertEquals("Check key 2", KEY2, keyArray[1]);
assertEquals("Check key 3", KEY3, keyArray[2]);
}
/**
* Test the entrySet method returns the correct set.
*/
@Test
public void testEntrySet() {
Set<Entry<String, String>> entries = dbHashtable.entrySet();
assertTrue("Check the number of entries", entries.size()==3);
boolean b1 = false;
boolean b2 = false;
boolean b3 = false;
for (Iterator<Entry<String, String>> i =
entries.iterator(); i.hasNext(); ) {
Map.Entry<String, String> me = i.next();
if (me.getKey().equals(KEY1)) {
assertEquals("Check entry 1", ELEMENT1, me.getValue());
b1 = true;
} else if (me.getKey().equals(KEY2)) {
assertEquals("Check entry 2", ELEMENT2, me.getValue());
b2 = true;
} else if (me.getKey().equals(KEY3)) {
assertEquals("Check entry 3", ELEMENT3, me.getValue());
b3 = true;
} else {
fail ("Unexpected key found.");
}
}
assertEquals("Check occurences of entries", b1 && b2 && b3, true);
}
/**
* Test the values method returns the correct collection.
*/
@Test
public void testValues() {
Collection<String> values = dbHashtable.values();
assertTrue("Check the number of values", values.size()==3);
HashSet<String> temp = new HashSet<String>();
temp.add(ELEMENT1);
temp.add(ELEMENT2);
temp.add(ELEMENT3);
Iterator<String> i = values.iterator();
while (i.hasNext()) {
assertTrue(temp.remove(i.next()));
}
assertTrue(temp.isEmpty());
}
/**
* test batch loading.
*/
@SuppressWarnings("unchecked")
@Test
public void testBatchLoading() {
System.out.println("Batch-test");
PersistenceManager pm = null;
Object oid = null;
pm = TestTools.openPM();
pm.currentTransaction().begin();
DBHashMap<Object, Object> dbh =
new DBHashMap<Object, Object>();
dbh.put("TestString", "TestString");
for (int i = 0 ; i < 100; i++) {
dbh.put("TS" + i, new PersistentDummyImpl());
}
dbh.put("TestString2", "TestString2");
pm.makePersistent(dbh);
oid = pm.getObjectId(dbh);
pm.currentTransaction().commit();
pm.close();
pm = null;
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
long t1 = System.currentTimeMillis();
for (Object o: dbh.values()) {
o.hashCode();
}
long t2 = System.currentTimeMillis();
System.out.println("NORMAL: " + (t2 - t1));
pm.currentTransaction().commit();
pm.close();
pm = null;
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
t1 = System.currentTimeMillis();
dbh.setBatchSize(1000);
for (Object o: dbh.values()) {
o.hashCode();
}
t2 = System.currentTimeMillis();
System.out.println("BATCHED: " + (t2 - t1));
pm.currentTransaction().commit();
pm.close();
pm = null;
//Close the store and load the stuff
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
t1 = System.currentTimeMillis();
dbh.setBatchSize(1);
for (Object o: dbh.values()) {
o.hashCode();
}
t2 = System.currentTimeMillis();
System.out.println("NORMAL: " + (t2 - t1));
pm.currentTransaction().commit();
pm.close();
pm = null;
//Close the store and load the stuff
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
t1 = System.currentTimeMillis();
dbh.setBatchSize(0);
for (Object o: dbh.values()) {
o.hashCode();
}
t2 = System.currentTimeMillis();
System.out.println("BATCHED: " + (t2 - t1));
pm.currentTransaction().commit();
pm.close();
pm = null;
//Close the store, load the stuff and test with transient object
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
PersistentDummyImpl dummyTrans = new PersistentDummyImpl();
dbh.put("13", dummyTrans);
t1 = System.currentTimeMillis();
dbh.setBatchSize(0);
for (Object o: dbh.values()) {
o.hashCode();
}
t2 = System.currentTimeMillis();
assertEquals(dummyTrans, dbh.get("13"));
System.out.println("BATCHED: " + (t2 - t1));
pm.currentTransaction().commit();
pm.close();
pm = null;
//Close the store, load the stuff and test with modified object
pm = TestTools.openPM();
pm.currentTransaction().begin();
dbh = (DBHashMap<Object, Object>) pm.getObjectById(oid);
((PersistentDummyImpl)dbh.get("TS18")).setData(new byte[]{15});
t1 = System.currentTimeMillis();
dbh.setBatchSize(0);
for (Object o: dbh.values()) {
o.hashCode();
}
t2 = System.currentTimeMillis();
assertEquals(15, ((PersistentDummyImpl)dbh.get("TS18")).getData()[0]);
System.out.println("BATCHED but dirty: " + (t2 - t1));
pm.currentTransaction().rollback();
TestTools.closePM();
//TODO use setBatch() also for all other tests to verify batch loading!
//Or call these tests here again, outside the store.!
}
@SuppressWarnings("unchecked")
@Test
public void testPersistent() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
DBHashMap<DBArrayList<String>, DBArrayList<String>> map =
new DBHashMap<DBArrayList<String>, DBArrayList<String>>();
DBArrayList<String> a1 = new DBArrayList<String>();
a1.add("a1");
DBArrayList<String> a2 = new DBArrayList<String>();
a2.add("a2");
map.put(a1, a2);
pm.makePersistent(map);
Object oid = pm.getObjectId(map);
pm.currentTransaction().commit();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
map = (DBHashMap<DBArrayList<String>, DBArrayList<String>>) pm.getObjectById(oid);
Set<DBArrayList<String>> ks = map.keySet();
Iterator<DBArrayList<String>> iter = ks.iterator();
assertTrue(iter.hasNext());
a1 = iter.next();
assertEquals(a1.get(0), "a1");
assertFalse(iter.hasNext());
a2 = map.get(a1);
assertEquals(a2.get(0), "a2");
pm.currentTransaction().commit();
TestTools.closePM();
}
@SuppressWarnings("unchecked")
@Test
public void testPersistentNull() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
DBHashMap<DBArrayList<String>, DBArrayList<String>> map =
new DBHashMap<DBArrayList<String>, DBArrayList<String>>();
DBArrayList<String> a1 = new DBArrayList<String>();
a1.add("a1");
DBArrayList<String> a2 = new DBArrayList<String>();
a2.add("a2");
map.put(a1, null);
map.put(null, a2);
pm.makePersistent(map);
Object oid = pm.getObjectId(map);
pm.currentTransaction().commit();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
map = (DBHashMap<DBArrayList<String>, DBArrayList<String>>) pm.getObjectById(oid);
Set<DBArrayList<String>> ks = map.keySet();
Iterator<DBArrayList<String>> iter = ks.iterator();
assertTrue(iter.hasNext());
a1 = iter.next();
if (a1 != null) {
assertEquals(a1.get(0), "a1");
assertNull(iter.next());
} else {
a1 = iter.next();
assertEquals(a1.get(0), "a1");
}
assertFalse(iter.hasNext());
assertNull(map.get(a1));
a2 = map.get(null);
assertEquals(a2.get(0), "a2");
pm.currentTransaction().commit();
TestTools.closePM();
}
@SuppressWarnings("unchecked")
@Test
public void testPersistentSelf() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map0 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map1 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map2 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
map0.put(map0, map1);
map0.put(map2, map0);
pm.makePersistent(map0);
Object oid0 = pm.getObjectId(map0);
pm.makePersistent(map1);
Object oid1 = pm.getObjectId(map1);
pm.makePersistent(map2);
Object oid2 = pm.getObjectId(map2);
pm.currentTransaction().commit();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
map0 = (DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>) pm.getObjectById(oid0);
map2 = (DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>) pm.getObjectById(oid2);
assertEquals(2, map0.size());
map1 = (DBHashMap<DBHashMap<?, ?>, DBHashMap<?, ?>>) map0.get(map0);
assertNotNull(map1);
assertEquals(oid1, pm.getObjectId(map1));
assertEquals(map0, map0.get(map2));
pm.currentTransaction().commit();
TestTools.closePM();
}
@SuppressWarnings("unchecked")
@Test
public void testPersistentSelfWithLoop() {
PersistenceManager pm = TestTools.openPM();
pm.currentTransaction().begin();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map0 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map1 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>> map2 =
new DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>();
map0.put(map0, null);
map0.put(map1, null);
map1.put(map0, map2);
map1.put(map1, map2);
map2.put(map2, map2);
pm.makePersistent(map0);
pm.makePersistent(map1);
pm.makePersistent(map2);
Object oid0 = pm.getObjectId(map0);
Object oid1 = pm.getObjectId(map1);
Object oid2 = pm.getObjectId(map2);
pm.currentTransaction().commit();
TestTools.closePM();
pm = TestTools.openPM();
pm.currentTransaction().begin();
map0 = (DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>) pm.getObjectById(oid0);
map1 = (DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>) pm.getObjectById(oid1);
map2 = (DBHashMap<DBHashMap<?,?>, DBHashMap<?,?>>) pm.getObjectById(oid2);
assertEquals(2, map0.size());
assertEquals(2, map1.size());
assertEquals(null, map0.get(map0));
assertEquals(null, map0.get(map1));
assertEquals(map2, map1.get(map0));
assertEquals(map2, map1.get(map1));
assertEquals(map2, map2.get(map2));
pm.currentTransaction().commit();
TestTools.closePM();
}
}