/* HeliDB -- A simple database for Java, http://www.helidb.org
* Copyright (C) 2008, 2009 Karl Gustafsson
*
* This file is a part of HeliDB.
*
* HeliDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeliDB 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.helidb.backend;
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.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.entityfs.RandomAccess;
import org.entityfs.support.io.RandomAccessMode;
import org.entityfs.util.io.ReadWritableFileAdapter;
import org.helidb.lang.KeyExistsException;
import org.helidb.lang.Record;
import org.helidb.search.SearchMode;
import org.helidb.test.support.FileSupport;
import org.helidb.util.ComparableComparator;
import org.junit.Test;
public abstract class AbstractVariableRecordSizeBackendTest<P> extends AbstractDatabaseBackendTest<String, String, P>
{
@Override
protected String createKey()
{
return "a key";
}
@Override
protected String createValue()
{
return "a value";
}
@Override
protected void populateBackend(DatabaseBackend<String, String, P> b)
{
b.insert("key1", "value1");
b.insert("key10", "value10");
}
@Test
public void testInsertAndRead()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertEquals(0, b.getKeys().size());
assertEquals(0, b.getValues().size());
assertNull(b.find("key1"));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key1", "value1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertEquals(1, b.getValues().size());
P pos = b.find("key1");
assertNotNull(pos);
assertRecordEquals(new Record<String, String>("key1", "value1"), b, pos);
assertNull(b.find("key2"));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 2", "value 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertEquals(2, b.getValues().size());
pos = b.find("key 2");
assertNotNull(pos);
assertEquals("key 2", b.readKeyAt(pos));
assertEquals("value 2", b.readValueAt(pos));
assertRecordEquals(new Record<String, String>("key 2", "value 2"), b, pos);
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.insert("key1", "value1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.find("key1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testGetKeysValuesAndRecords()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertEquals(0, b.getKeys().size());
assertEquals(0, b.getValues().size());
assertEquals(0, b.getRecords().size());
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 1", "value 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains("key 1"));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains("value 1"));
assertEquals(1, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 1", "value 1")));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 2", "value 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains("key 1"));
assertTrue(b.getKeys().contains("key 2"));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains("value 1"));
assertTrue(b.getValues().contains("value 2"));
assertEquals(2, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 1", "value 1")));
assertTrue(b.getRecords().contains(new Record<String, String>("key 2", "value 2")));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 1"), "key 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains("key 2"));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains("value 2"));
assertEquals(1, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 2", "value 2")));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 2"), "key 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(0, b.getKeys().size());
assertEquals(0, b.getValues().size());
assertEquals(0, b.getRecords().size());
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.getKeys();
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.getValues();
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.getRecords();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testFind()
{
Comparator<String> cmp = new ComparableComparator<String>();
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertNull(b.find("key 1"));
b.insert("key 1", "value 1");
int contentsVersion = b.getContentsVersion();
assertNotNull(b.find("key 1"));
assertNotNull(b.find("key 1", SearchMode.EXACT_MATCH, cmp));
assertNull(b.find("key 2"));
assertNull(b.find("key 2", SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 2", "value 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNotNull(b.find("key 1"));
assertNotNull(b.find("key 1", SearchMode.EXACT_MATCH, cmp));
assertNotNull(b.find("key 2"));
assertNotNull(b.find("key 2", SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 1"), "key 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.find("key 1"));
assertNull(b.find("key 1", SearchMode.EXACT_MATCH, cmp));
assertNotNull(b.find("key 2"));
assertNotNull(b.find("key 2", SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 2"), "key 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.find("key 1"));
assertNull(b.find("key 1", SearchMode.EXACT_MATCH, cmp));
assertNull(b.find("key 2"));
assertNull(b.find("key 2", SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.find("key 2");
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.find("key 2", SearchMode.EXACT_MATCH, cmp);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testDelete()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
b.insert("key 2", "value 2");
b.insert("key 3", "value 3");
int contentsVersion = b.getContentsVersion();
assertTrue(b.delete("key 2"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 1", "value 1")));
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertEquals(contentsVersion, b.getContentsVersion());
assertFalse(b.delete("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals(2, b.getKeys().size());
assertTrue(b.delete("key 1"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertTrue(b.delete("key 3"));
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.delete("key 3");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testGetValueFor()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor("key 1"));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 1", "value 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals("value 1", b.getValueFor("key 1"));
assertNull(b.getValueFor("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert("key 2", "value 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals("value 1", b.getValueFor("key 1"));
assertEquals("value 2", b.getValueFor("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
assertTrue(b.delete("key 1"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor("key 1"));
assertEquals("value 2", b.getValueFor("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
assertTrue(b.delete("key 2"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor("key 1"));
assertNull(b.getValueFor("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.getValueFor("key 1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testInsertCheckKeyUnique()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
b.insertCheckKeyUnique("key 1", "value 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
try
{
b.insertCheckKeyUnique("key 1", "value 1p");
fail();
}
catch (KeyExistsException e)
{
// ok
}
assertEquals(contentsVersion, b.getContentsVersion());
b.insertCheckKeyUnique("key 2", "value 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
try
{
b.insertCheckKeyUnique("key 1", "value 1p");
fail();
}
catch (KeyExistsException e)
{
// ok
}
try
{
b.insertCheckKeyUnique("key 2", "value 2");
fail();
}
catch (KeyExistsException e)
{
// ok
}
assertEquals("value 1", b.getValueFor("key 1"));
assertEquals("value 2", b.getValueFor("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.insertCheckKeyUnique("key 1", "value 1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testInsertOrUpdate()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertFalse(b.insertOrUpdate("key 1", "value 1"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertTrue(b.insertOrUpdate("key 1", "value 1p"));
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals("value 1p", b.getValueFor("key 1"));
b.close();
try
{
b.insertOrUpdate("key 1", "value 1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testRemove()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
b.insert("key 2", "value 2");
b.insert("key 3", "value 3");
int contentsVersion = b.getContentsVersion();
assertEquals("value 2", b.remove("key 2"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 1", "value 1")));
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertEquals(contentsVersion, b.getContentsVersion());
assertNull(b.remove("key 2"));
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals(2, b.getKeys().size());
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals("value 1", b.remove("key 1"));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals("value 3", b.remove("key 3"));
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.remove("key 2");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testUpdate()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
int contentsVersion = b.getContentsVersion();
b.update("key 1", "value 1p");
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains("key 1"));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains("value 1p"));
b.insert("key 2", "value 2");
contentsVersion = b.getContentsVersion();
b.update("key 1", "value 1pp");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains("key 2"));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains("value 1pp"));
b.close();
try
{
b.update("key 1", "value 1pp");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testUpdateAt()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
int contentsVersion = b.getContentsVersion();
b.updateAt(b.find("key 1"), "key 1", "value 1p");
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains("key 1"));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains("value 1p"));
b.insert("key 2", "value 2");
contentsVersion = b.getContentsVersion();
b.updateAt(b.find("key 1"), "key 1", "value 1pp");
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains("key 2"));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains("value 1pp"));
b.close();
try
{
b.updateAt(null, "key1", "value1");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testRemoveAt()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
b.insert("key 2", "value 2");
b.insert("key 3", "value 3");
int contentsVersion = b.getContentsVersion();
b.removeAt(b.find("key 2"), "key 2");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 1", "value 1")));
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 1"), "key 1");
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<String, String>("key 3", "value 3")));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find("key 3"), "key 3");
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.removeAt(null, "key 3");
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testClear()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key 1", "value 1");
b.insert("key 2", "value 2");
b.insert("key 3", "value 3");
int contentsVersion = b.getContentsVersion();
b.clear();
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.clear();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testIterator()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertFalse(b.iterator().hasNext());
try
{
b.iterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<String, String> kv1 = new Record<String, String>("key 1", "value 1");
b.insert(kv1.getKey(), kv1.getValue());
Record<String, String> kv2 = new Record<String, String>("key 2", "value 2");
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<Record<String, String>> itr = b.iterator();
assertTrue(itr.hasNext());
Record<String, String> kv = itr.next();
assertTrue(kv.equals(kv1) || kv.equals(kv2));
assertTrue(itr.hasNext());
kv = itr.next();
assertTrue(kv.equals(kv1) || kv.equals(kv2));
assertFalse(itr.hasNext());
try
{
itr.next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.iterator();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testKeyIterator()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertFalse(b.keyIterator().hasNext());
try
{
b.keyIterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<String, String> kv1 = new Record<String, String>("key 1", "value 1");
b.insert(kv1.getKey(), kv1.getValue());
Record<String, String> kv2 = new Record<String, String>("key 2", "value 2");
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<String> itr = b.keyIterator();
assertTrue(itr.hasNext());
String k = itr.next();
assertTrue(k.equals(kv1.getKey()) || k.equals(kv2.getKey()));
assertTrue(itr.hasNext());
k = itr.next();
assertTrue(k.equals(kv1.getKey()) || k.equals(kv2.getKey()));
assertFalse(itr.hasNext());
try
{
itr.next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.keyIterator();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testValueIterator()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertFalse(b.valueIterator().hasNext());
try
{
b.valueIterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<String, String> kv1 = new Record<String, String>("key 1", "value 1");
b.insert(kv1.getKey(), kv1.getValue());
Record<String, String> kv2 = new Record<String, String>("key 2", "value 2");
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<String> itr = b.valueIterator();
assertTrue(itr.hasNext());
String v = itr.next();
assertTrue(v.equals(kv1.getValue()) || v.equals(kv2.getValue()));
assertTrue(itr.hasNext());
v = itr.next();
assertTrue(v.equals(kv1.getValue()) || v.equals(kv2.getValue()));
assertFalse(itr.hasNext());
try
{
itr.next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.valueIterator();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testSameValueForTwoDifferentKeys()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
String s = "One value to rule them all";
b.insert("key1", s);
b.insert("key10", s);
assertEquals(2, b.getValues().size());
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testCompact()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
b.insert("key1", "value1");
b.insert("key10", "value10");
b.insert("key11", "value11");
b.insert("key100", "value100");
b.insert("key101", "value101");
int contentsVersion = b.getContentsVersion();
if (b.compact())
{
assertFalse(contentsVersion == b.getContentsVersion());
}
else
{
assertEquals(contentsVersion, b.getContentsVersion());
}
assertRecordEquals(new Record<String, String>("key1", "value1"), b, b.find("key1"));
assertRecordEquals(new Record<String, String>("key10", "value10"), b, b.find("key10"));
assertRecordEquals(new Record<String, String>("key11", "value11"), b, b.find("key11"));
assertRecordEquals(new Record<String, String>("key100", "value100"), b, b.find("key100"));
assertRecordEquals(new Record<String, String>("key101", "value101"), b, b.find("key101"));
b.removeAt(b.find("key10"), "key10");
b.removeAt(b.find("key100"), "key100");
assertRecordEquals(new Record<String, String>("key1", "value1"), b, b.find("key1"));
assertNull(b.find("key10"));
assertRecordEquals(new Record<String, String>("key11", "value11"), b, b.find("key11"));
assertNull(b.find("key100"));
assertRecordEquals(new Record<String, String>("key101", "value101"), b, b.find("key101"));
contentsVersion = b.getContentsVersion();
if (b.compact())
{
assertFalse(contentsVersion == b.getContentsVersion());
}
else
{
assertEquals(contentsVersion, b.getContentsVersion());
}
assertRecordEquals(new Record<String, String>("key1", "value1"), b, b.find("key1"));
assertNull(b.find("key10"));
assertRecordEquals(new Record<String, String>("key11", "value11"), b, b.find("key11"));
assertNull(b.find("key100"));
assertRecordEquals(new Record<String, String>("key101", "value101"), b, b.find("key101"));
b.removeAt(b.find("key1"), "key1");
assertNull(b.find("key1"));
assertNull(b.find("key10"));
assertRecordEquals(new Record<String, String>("key11", "value11"), b, b.find("key11"));
assertNull(b.find("key100"));
assertRecordEquals(new Record<String, String>("key101", "value101"), b, b.find("key101"));
contentsVersion = b.getContentsVersion();
if (b.compact())
{
assertFalse(contentsVersion == b.getContentsVersion());
}
else
{
assertEquals(contentsVersion, b.getContentsVersion());
}
assertNull(b.find("key1"));
assertNull(b.find("key10"));
assertRecordEquals(new Record<String, String>("key11", "value11"), b, b.find("key11"));
assertNull(b.find("key100"));
assertRecordEquals(new Record<String, String>("key101", "value101"), b, b.find("key101"));
assertEquals(2, b.getKeys().size());
b.removeAt(b.find("key11"), "key11");
b.removeAt(b.find("key101"), "key101");
assertNull(b.find("key1"));
assertNull(b.find("key10"));
assertNull(b.find("key11"));
assertNull(b.find("key100"));
assertNull(b.find("key101"));
contentsVersion = b.getContentsVersion();
if (b.compact())
{
assertFalse(contentsVersion == b.getContentsVersion());
}
else
{
assertEquals(contentsVersion, b.getContentsVersion());
}
assertNull(b.find("key1"));
assertNull(b.find("key10"));
assertNull(b.find("key11"));
assertNull(b.find("key100"));
assertNull(b.find("key101"));
b.insert("key1", "value1p");
b.insert("key10", "value10p");
assertRecordEquals(new Record<String, String>("key1", "value1p"), b, b.find("key1"));
assertRecordEquals(new Record<String, String>("key10", "value10p"), b, b.find("key10"));
contentsVersion = b.getContentsVersion();
if (b.compact())
{
assertFalse(contentsVersion == b.getContentsVersion());
}
else
{
assertEquals(contentsVersion, b.getContentsVersion());
}
assertRecordEquals(new Record<String, String>("key1", "value1p"), b, b.find("key1"));
assertRecordEquals(new Record<String, String>("key10", "value10p"), b, b.find("key10"));
b.close();
try
{
b.compact();
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testForEachKey()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
Collection<Record<String, P>> c = new ArrayList<Record<String, P>>(5);
c.add(new Record<String, P>("key1", b.insert("key1", "value1")));
c.add(new Record<String, P>("key10", b.insert("key10", "value10")));
c.add(new Record<String, P>("key11", b.insert("key11", "value11")));
c.add(new Record<String, P>("key100", b.insert("key100", "value100")));
c.add(new Record<String, P>("key101", b.insert("key101", "value101")));
TestForEachKeyCallback<String, P> cbk = new TestForEachKeyCallback<String, P>(new ArrayList<Record<String, P>>(c));
b.forEachKey(cbk);
assertTrue(cbk.getRemainingKeys().isEmpty());
P k11pos = b.find("key11");
b.removeAt(k11pos, "key11");
c = new ArrayList<Record<String, P>>(4);
c.add(new Record<String, P>("key1", b.find("key1")));
c.add(new Record<String, P>("key10", b.find("key10")));
c.add(new Record<String, P>("key100", b.find("key100")));
c.add(new Record<String, P>("key101", b.find("key101")));
cbk = new TestForEachKeyCallback<String, P>(new ArrayList<Record<String, P>>(c));
b.forEachKey(cbk);
assertTrue(cbk.getRemainingKeys().isEmpty());
b.close();
try
{
b.forEachKey(cbk);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testReplaceContentsWith()
{
DatabaseBackend<String, String, P> b1 = createBackend();
try
{
b1.insert("b1 key 1", "b1 value 1");
b1.insert("b1 key 2", "b1 value 2");
b1.insert("b1 åäö key 3", "b1 value 3 åäö");
DatabaseBackend<String, String, P> b2 = createBackend();
try
{
b2.insert("b2 key 1", "b2 value 1");
b2.insert("b2 key 2", "b2 value 2");
File f = FileSupport.createTempFile();
try
{
RandomAccess ra = new ReadWritableFileAdapter(f).openForRandomAccess(RandomAccessMode.READ_WRITE);
try
{
long dataSize = b1.writeContentsTo(ra);
ra.seek(0);
int contentsVersion = b2.getContentsVersion();
b2.replaceContentsWith(ra, dataSize);
assertFalse(contentsVersion == b2.getContentsVersion());
assertEquals(3, b2.getKeys().size());
assertRecordEquals(new Record<String, String>("b1 key 1", "b1 value 1"), b2, b2.find("b1 key 1"));
assertRecordEquals(new Record<String, String>("b1 key 2", "b1 value 2"), b2, b2.find("b1 key 2"));
assertRecordEquals(new Record<String, String>("b1 åäö key 3", "b1 value 3 åäö"), b2, b2.find("b1 åäö key 3"));
}
finally
{
ra.close();
}
}
finally
{
assertTrue(f.delete());
}
}
finally
{
tearDownBackend(b2);
}
}
finally
{
tearDownBackend(b1);
}
}
@Test
public void testFindClosestNaturalOrdering()
{
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertNull(b.find("a", SearchMode.CLOSEST_BELOW));
assertNull(b.find("a", SearchMode.CLOSEST_ABOVE));
assertNull(b.find("a", SearchMode.CLOSEST_MATCH));
b.insert("b", "b");
b.insert("g", "g");
b.insert("k", "k");
int contentsVersion = b.getContentsVersion();
assertNull(b.find("a", SearchMode.CLOSEST_BELOW));
assertEquals("b", b.readKeyAt(b.find("a", SearchMode.CLOSEST_ABOVE)));
assertEquals("b", b.readKeyAt(b.find("a", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_BELOW)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_ABOVE)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("c", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("c", SearchMode.CLOSEST_ABOVE)));
assertEquals("b", b.readKeyAt(b.find("c", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_ABOVE)));
assertEquals("b", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("d", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("d", SearchMode.CLOSEST_ABOVE)));
assertEquals("b", b.readKeyAt(b.find("d", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("e", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("e", SearchMode.CLOSEST_ABOVE)));
assertEquals("g", b.readKeyAt(b.find("e", SearchMode.CLOSEST_MATCH)));
assertEquals("b", b.readKeyAt(b.find("f", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("f", SearchMode.CLOSEST_ABOVE)));
assertEquals("g", b.readKeyAt(b.find("f", SearchMode.CLOSEST_MATCH)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_BELOW)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_ABOVE)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_MATCH)));
assertEquals("g", b.readKeyAt(b.find("h", SearchMode.CLOSEST_BELOW)));
assertEquals("k", b.readKeyAt(b.find("h", SearchMode.CLOSEST_ABOVE)));
assertEquals("g", b.readKeyAt(b.find("h", SearchMode.CLOSEST_MATCH)));
assertEquals("g", b.readKeyAt(b.find("i", SearchMode.CLOSEST_BELOW)));
assertEquals("k", b.readKeyAt(b.find("i", SearchMode.CLOSEST_ABOVE)));
String closestMatch = b.readKeyAt(b.find("i", SearchMode.CLOSEST_MATCH));
assertTrue("g".equals(closestMatch) || "k".equals(closestMatch));
assertEquals("g", b.readKeyAt(b.find("j", SearchMode.CLOSEST_BELOW)));
assertEquals("k", b.readKeyAt(b.find("j", SearchMode.CLOSEST_ABOVE)));
assertEquals("k", b.readKeyAt(b.find("j", SearchMode.CLOSEST_MATCH)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_BELOW)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_ABOVE)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_MATCH)));
assertEquals("k", b.readKeyAt(b.find("l", SearchMode.CLOSEST_BELOW)));
assertNull(b.find("l", SearchMode.CLOSEST_ABOVE));
assertEquals("k", b.readKeyAt(b.find("l", SearchMode.CLOSEST_MATCH)));
assertEquals(contentsVersion, b.getContentsVersion());
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testFindClosestCustomComparator()
{
Comparator<String> cmp = new ComparableComparator<String>();
DatabaseBackend<String, String, P> b = createBackend();
try
{
assertNull(b.find("a", SearchMode.CLOSEST_BELOW, cmp));
assertNull(b.find("a", SearchMode.CLOSEST_ABOVE, cmp));
assertNull(b.find("a", SearchMode.CLOSEST_MATCH, cmp));
b.insert("b", "b");
b.insert("g", "g");
b.insert("k", "k");
int contentsVersion = b.getContentsVersion();
assertNull(b.find("a", SearchMode.CLOSEST_BELOW, cmp));
assertEquals("b", b.readKeyAt(b.find("a", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("b", b.readKeyAt(b.find("a", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("b", b.readKeyAt(b.find("b", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("c", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("c", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("b", b.readKeyAt(b.find("c", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("b", b.readKeyAt(b.find("cc", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("d", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("d", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("b", b.readKeyAt(b.find("d", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("e", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("e", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("g", b.readKeyAt(b.find("e", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("b", b.readKeyAt(b.find("f", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("f", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("g", b.readKeyAt(b.find("f", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("g", b.readKeyAt(b.find("g", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("g", b.readKeyAt(b.find("h", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("k", b.readKeyAt(b.find("h", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("g", b.readKeyAt(b.find("h", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("g", b.readKeyAt(b.find("i", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("k", b.readKeyAt(b.find("i", SearchMode.CLOSEST_ABOVE, cmp)));
String closestMatch = b.readKeyAt(b.find("i", SearchMode.CLOSEST_MATCH, cmp));
assertTrue("g".equals(closestMatch) || "k".equals(closestMatch));
assertEquals("g", b.readKeyAt(b.find("j", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("k", b.readKeyAt(b.find("j", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("k", b.readKeyAt(b.find("j", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_BELOW, cmp)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_ABOVE, cmp)));
assertEquals("k", b.readKeyAt(b.find("k", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals("k", b.readKeyAt(b.find("l", SearchMode.CLOSEST_BELOW, cmp)));
assertNull(b.find("l", SearchMode.CLOSEST_ABOVE, cmp));
assertEquals("k", b.readKeyAt(b.find("l", SearchMode.CLOSEST_MATCH, cmp)));
assertEquals(contentsVersion, b.getContentsVersion());
}
finally
{
tearDownBackend(b);
}
}
}