Package org.helidb.backend

Source Code of org.helidb.backend.AbstractConstantRecordSizeBackendTest

/* 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);
    }
  }
}
TOP

Related Classes of org.helidb.backend.AbstractConstantRecordSizeBackendTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.