/* 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 AbstractConstantRecordSizeBackendTest<P, Q> extends AbstractDatabaseBackendTest<Integer, Long, P>
{
protected abstract DatabaseBackend<Character, Character, Q> createCharacterBackend();
@Override
protected Integer createKey()
{
return 17;
}
@Override
protected Long createValue()
{
return 23832L;
}
@Override
protected void populateBackend(DatabaseBackend<Integer, Long, P> b)
{
b.insert(1, 2L);
b.insert(2, 4L);
}
@Test
public void testInsertAndRead()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertEquals(0, b.getKeys().size());
assertEquals(0, b.getValues().size());
assertNull(b.find(2));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(2, 5L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertEquals(1, b.getValues().size());
P pos = b.find(2);
assertNotNull(pos);
assertRecordEquals(new Record<Integer, Long>(2, 5L), b, pos);
assertNull(b.find(3));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(2832, 932932932L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertEquals(2, b.getValues().size());
pos = b.find(2832);
assertNotNull(pos);
assertRecordEquals(new Record<Integer, Long>(2832, 932932932L), b, pos);
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.insert(2, 4L);
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.find(2);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testGetKeysValuesAndRecords()
{
DatabaseBackend<Integer, Long, 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(2, 4L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains(4L));
assertEquals(1, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(2, 4L)));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(6, 12L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertTrue(b.getKeys().contains(6));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains(4L));
assertTrue(b.getValues().contains(12L));
assertEquals(2, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(2, 4L)));
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 12L)));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(2), 2);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains(6));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains(12L));
assertEquals(1, b.getRecords().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 12L)));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(6), 6);
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<Integer> cmp = new ComparableComparator<Integer>();
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertNull(b.find(2));
assertNull(b.find(2, SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(2, 5L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNotNull(b.find(2));
assertNotNull(b.find(2, SearchMode.EXACT_MATCH, cmp));
assertNull(b.find(4));
assertNull(b.find(4, SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(4, 9L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNotNull(b.find(2));
assertNotNull(b.find(2, SearchMode.EXACT_MATCH, cmp));
assertNotNull(b.find(4));
assertNotNull(b.find(4, SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(2), 2);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.find(2));
assertNull(b.find(2, SearchMode.EXACT_MATCH, cmp));
assertNotNull(b.find(4));
assertNotNull(b.find(4, SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(4), 4);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.find(2));
assertNull(b.find(2, SearchMode.EXACT_MATCH, cmp));
assertNull(b.find(4));
assertNull(b.find(4, SearchMode.EXACT_MATCH, cmp));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.find(4);
fail();
}
catch (IllegalStateException e)
{
// ok
}
try
{
b.find(4, SearchMode.EXACT_MATCH, cmp);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testDelete()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 5L);
b.insert(4, 10L);
b.insert(6, 15L);
int contentsVersion = b.getContentsVersion();
assertTrue(b.delete(4));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(2, 5L)));
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertFalse(b.delete(4));
assertEquals(contentsVersion, b.getContentsVersion());
assertTrue(b.delete(2));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertEquals(contentsVersion, b.getContentsVersion());
assertTrue(b.delete(6));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(0, b.getKeys().size());
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.delete(2);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testGetValueFor()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor(2));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(2, 5L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(5L, b.getValueFor(2).longValue());
assertNull(b.getValueFor(4));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(4, 9L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(5L, b.getValueFor(2).longValue());
assertEquals(9L, b.getValueFor(4).longValue());
assertEquals(contentsVersion, b.getContentsVersion());
b.remove(2);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor(2));
assertEquals(9L, b.getValueFor(4).longValue());
assertEquals(contentsVersion, b.getContentsVersion());
b.remove(4);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertNull(b.getValueFor(2));
assertNull(b.getValueFor(4));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.getValueFor(2);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testInsertCheckKeyUnique()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
b.insertCheckKeyUnique(2, 4L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
try
{
b.insertCheckKeyUnique(2, 4L);
fail();
}
catch (KeyExistsException e)
{
// ok
}
assertEquals(contentsVersion, b.getContentsVersion());
b.insertCheckKeyUnique(4, 8L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
try
{
b.insertCheckKeyUnique(2, 4L);
fail();
}
catch (KeyExistsException e)
{
// ok
}
try
{
b.insertCheckKeyUnique(4, 8L);
fail();
}
catch (KeyExistsException e)
{
// ok
}
assertEquals(4L, b.getValueFor(2).longValue());
assertEquals(8L, b.getValueFor(4).longValue());
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.insertCheckKeyUnique(2, 5L);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testInsertOrUpdate()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
int contentsVersion = b.getContentsVersion();
assertFalse(b.insertOrUpdate(2, 4L));
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertTrue(b.insertOrUpdate(2, 5L));
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(5L, b.getValueFor(2).longValue());
b.close();
try
{
b.insertOrUpdate(2, 4L);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testRemove()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 5L);
b.insert(4, 10L);
b.insert(6, 15L);
int contentsVersion = b.getContentsVersion();
assertEquals(10L, b.remove(4).longValue());
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(2, 5L)));
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertEquals(contentsVersion, b.getContentsVersion());
assertNull(b.remove(4));
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals(5L, b.remove(2).longValue());
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertEquals(contentsVersion, b.getContentsVersion());
assertEquals(15L, b.remove(6).longValue());
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.remove(2);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testUpdate()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 6L);
int contentsVersion = b.getContentsVersion();
b.update(2, 9L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains(9L));
b.insert(4, 12L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
b.update(2, 14L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertTrue(b.getKeys().contains(4));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains(14L));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.update(2, 4L);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testUpdateAt()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 6L);
int contentsVersion = b.getContentsVersion();
b.updateAt(b.find(2), 2, 9L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertEquals(1, b.getValues().size());
assertTrue(b.getValues().contains(9L));
assertEquals(contentsVersion, b.getContentsVersion());
b.insert(4, 12L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
b.updateAt(b.find(2), 2, 14L);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getKeys().contains(2));
assertTrue(b.getKeys().contains(4));
assertEquals(2, b.getValues().size());
assertTrue(b.getValues().contains(14L));
assertEquals(contentsVersion, b.getContentsVersion());
b.close();
try
{
b.updateAt(null, 4, 44L);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testRemoveAt()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 5L);
b.insert(4, 10L);
b.insert(6, 15L);
int contentsVersion = b.getContentsVersion();
b.removeAt(b.find(4), 4);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(2, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(2, 5L)));
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(2), 2);
assertFalse(contentsVersion == b.getContentsVersion());
contentsVersion = b.getContentsVersion();
assertEquals(1, b.getKeys().size());
assertTrue(b.getRecords().contains(new Record<Integer, Long>(6, 15L)));
assertEquals(contentsVersion, b.getContentsVersion());
b.removeAt(b.find(6), 6);
assertFalse(contentsVersion == b.getContentsVersion());
assertEquals(0, b.getKeys().size());
b.close();
try
{
b.removeAt(null, 3);
fail();
}
catch (IllegalStateException e)
{
// ok
}
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testClear()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
b.insert(2, 5L);
b.insert(4, 10L);
b.insert(6, 15L);
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<Integer, Long, P> b = createBackend();
try
{
assertFalse(b.iterator().hasNext());
try
{
b.iterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<Integer, Long> kv1 = new Record<Integer, Long>(2, 5L);
b.insert(kv1.getKey(), kv1.getValue());
Record<Integer, Long> kv2 = new Record<Integer, Long>(4, 10L);
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<Record<Integer, Long>> itr = b.iterator();
assertTrue(itr.hasNext());
Record<Integer, Long> 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<Integer, Long, P> b = createBackend();
try
{
assertFalse(b.keyIterator().hasNext());
try
{
b.keyIterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<Integer, Long> kv1 = new Record<Integer, Long>(2, 5L);
b.insert(kv1.getKey(), kv1.getValue());
Record<Integer, Long> kv2 = new Record<Integer, Long>(4, 10L);
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<Integer> itr = b.keyIterator();
assertTrue(itr.hasNext());
Integer 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<Integer, Long, P> b = createBackend();
try
{
assertFalse(b.valueIterator().hasNext());
try
{
b.valueIterator().next();
fail();
}
catch (NoSuchElementException e)
{
// ok
}
Record<Integer, Long> kv1 = new Record<Integer, Long>(2, 5L);
b.insert(kv1.getKey(), kv1.getValue());
Record<Integer, Long> kv2 = new Record<Integer, Long>(4, 10L);
b.insert(kv2.getKey(), kv2.getValue());
int contentsVersion = b.getContentsVersion();
Iterator<Long> itr = b.valueIterator();
assertTrue(itr.hasNext());
Long 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<Integer, Long, P> b = createBackend();
try
{
Long l = 17L;
b.insert(1, l);
b.insert(2, l);
assertEquals(2, b.getValues().size());
}
finally
{
tearDownBackend(b);
}
}
@Test
public void testForEachKey()
{
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
Collection<Record<Integer, P>> c = new ArrayList<Record<Integer, P>>(5);
c.add(new Record<Integer, P>(1, b.insert(1, 1L)));
c.add(new Record<Integer, P>(2, b.insert(2, 2L)));
c.add(new Record<Integer, P>(3, b.insert(3, 2L)));
c.add(new Record<Integer, P>(4, b.insert(4, 3L)));
c.add(new Record<Integer, P>(5, b.insert(5, 3L)));
TestForEachKeyCallback<Integer, P> cbk = new TestForEachKeyCallback<Integer, P>(new ArrayList<Record<Integer, P>>(c));
b.forEachKey(cbk);
assertTrue(cbk.getRemainingKeys().isEmpty());
P k11pos = b.find(4);
b.removeAt(k11pos, 4);
c = new ArrayList<Record<Integer, P>>(4);
c.add(new Record<Integer, P>(1, b.find(1)));
c.add(new Record<Integer, P>(2, b.find(2)));
c.add(new Record<Integer, P>(3, b.find(3)));
c.add(new Record<Integer, P>(5, b.find(5)));
cbk = new TestForEachKeyCallback<Integer, P>(new ArrayList<Record<Integer, 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<Integer, Long, P> b1 = createBackend();
try
{
b1.insert(23, 234923L);
b1.insert(23823, 348723823L);
b1.insert(-27237, -23823832L);
DatabaseBackend<Integer, Long, P> b2 = createBackend();
try
{
b2.insert(-1223, 348324823L);
b2.insert(34823, 348234823L);
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<Integer, Long>(23, 234923L), b2, b2.find(23));
assertRecordEquals(new Record<Integer, Long>(23823, 348723823L), b2, b2.find(23823));
assertRecordEquals(new Record<Integer, Long>(-27237, -23823832L), b2, b2.find(-27237));
// Try to feed it invalid data
ra.seek(1);
try
{
b2.replaceContentsWith(ra, dataSize - 1);
fail();
}
catch (RuntimeException e)
{
// ok
}
}
finally
{
ra.close();
}
}
finally
{
assertTrue(f.delete());
}
}
finally
{
tearDownBackend(b2);
}
}
finally
{
tearDownBackend(b1);
}
}
@Test
public void testFindClosest()
{
// Have to use Character keys since the compareTo method of Number
// classes does not give the distance between the compared values.
DatabaseBackend<Character, Character, Q> b = createCharacterBackend();
try
{
assertNull(b.find('a', SearchMode.CLOSEST_ABOVE));
assertNull(b.find('a', SearchMode.CLOSEST_BELOW));
assertNull(b.find('a', SearchMode.CLOSEST_MATCH));
b.insert('b', 'b');
b.insert('g', 'g');
b.insert('k', 'k');
int contentsVersion = b.getContentsVersion();
assertEquals('b', b.readKeyAt(b.find('a', SearchMode.CLOSEST_ABOVE)).charValue());
assertNull(b.find('a', SearchMode.CLOSEST_BELOW));
assertEquals('b', b.readKeyAt(b.find('a', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('b', b.readKeyAt(b.find('b', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('b', b.readKeyAt(b.find('b', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('b', b.readKeyAt(b.find('b', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('g', b.readKeyAt(b.find('c', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('b', b.readKeyAt(b.find('c', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('b', b.readKeyAt(b.find('c', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('g', b.readKeyAt(b.find('d', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('b', b.readKeyAt(b.find('d', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('b', b.readKeyAt(b.find('d', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('g', b.readKeyAt(b.find('e', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('b', b.readKeyAt(b.find('e', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('g', b.readKeyAt(b.find('e', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('g', b.readKeyAt(b.find('f', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('b', b.readKeyAt(b.find('f', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('g', b.readKeyAt(b.find('f', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('g', b.readKeyAt(b.find('g', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('g', b.readKeyAt(b.find('g', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('g', b.readKeyAt(b.find('g', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('k', b.readKeyAt(b.find('h', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('g', b.readKeyAt(b.find('h', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('g', b.readKeyAt(b.find('h', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('k', b.readKeyAt(b.find('i', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('g', b.readKeyAt(b.find('i', SearchMode.CLOSEST_BELOW)).charValue());
char closest = b.readKeyAt(b.find('i', SearchMode.CLOSEST_MATCH)).charValue();
assertTrue(closest == 'g' || closest == 'k');
assertEquals('k', b.readKeyAt(b.find('j', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('g', b.readKeyAt(b.find('j', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('k', b.readKeyAt(b.find('j', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals('k', b.readKeyAt(b.find('k', SearchMode.CLOSEST_ABOVE)).charValue());
assertEquals('k', b.readKeyAt(b.find('k', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('k', b.readKeyAt(b.find('k', SearchMode.CLOSEST_MATCH)).charValue());
assertNull(b.find('l', SearchMode.CLOSEST_ABOVE));
assertEquals('k', b.readKeyAt(b.find('l', SearchMode.CLOSEST_BELOW)).charValue());
assertEquals('k', b.readKeyAt(b.find('l', SearchMode.CLOSEST_MATCH)).charValue());
assertEquals(contentsVersion, b.getContentsVersion());
}
finally
{
tearDownBackend(b);
}
}
private static class IntegerComparator implements Comparator<Integer>
{
public int compare(Integer o1, Integer o2)
{
return o1 - o2;
}
}
@Test
public void testFindClosestCustomComparator()
{
IntegerComparator cmp = new IntegerComparator();
DatabaseBackend<Integer, Long, P> b = createBackend();
try
{
assertNull(b.find(1, SearchMode.CLOSEST_ABOVE, cmp));
assertNull(b.find(1, SearchMode.CLOSEST_BELOW, cmp));
assertNull(b.find(1, SearchMode.CLOSEST_MATCH, cmp));
b.insert(1, 1L);
b.insert(6, 6L);
b.insert(10, 10L);
int contentsVersion = b.getContentsVersion();
assertEquals(1, b.readKeyAt(b.find(0, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertNull(b.find(0, SearchMode.CLOSEST_BELOW, cmp));
assertEquals(1, b.readKeyAt(b.find(0, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(1, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(1, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(1, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(2, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(2, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(2, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(3, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(3, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(3, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(4, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(4, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(4, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(5, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(1, b.readKeyAt(b.find(5, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(5, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(6, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(6, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(6, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(7, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(7, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(7, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(8, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(8, SearchMode.CLOSEST_BELOW, cmp)).intValue());
int closest = b.readKeyAt(b.find(8, SearchMode.CLOSEST_MATCH, cmp)).intValue();
assertTrue(closest == 6 || closest == 10);
assertEquals(10, b.readKeyAt(b.find(9, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(6, b.readKeyAt(b.find(9, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(9, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(10, SearchMode.CLOSEST_ABOVE, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(10, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(10, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertNull(b.find(11, SearchMode.CLOSEST_ABOVE, cmp));
assertEquals(10, b.readKeyAt(b.find(11, SearchMode.CLOSEST_BELOW, cmp)).intValue());
assertEquals(10, b.readKeyAt(b.find(11, SearchMode.CLOSEST_MATCH, cmp)).intValue());
assertEquals(contentsVersion, b.getContentsVersion());
}
finally
{
tearDownBackend(b);
}
}
}