/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved.
*
*/
/*
* Alexg 23-4-06
* Based on scr016 TestAppendRecno test application.
*/
package com.sleepycat.db.test;
import org.junit.Before;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileNotFoundException;
import com.sleepycat.db.*;
import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.test.TestUtils;
public class AppendRecnoTest implements RecordNumberAppender {
public static final String RECNOTEST_DBNAME = "appendrecnotest.db";
public static final String[] EXPECTED_ENTRIES = { "data0_xyz", "data1_xy", "ata4_xyz", "ata5_xy",
"abc", "", "data9_xyz" };
int callback_count = 0;
boolean callback_throws = false;
@BeforeClass public static void ClassInit() {
TestUtils.loadConfig(null);
TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true);
}
@AfterClass public static void ClassShutdown() {
TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true);
}
@Before public void PerTestInit()
throws Exception {
TestUtils.removeall(true, false, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(RECNOTEST_DBNAME));
}
@After public void PerTestShutdown()
throws Exception {
}
/*
* Test creating a new database.
*/
@Test public void test1()
throws DatabaseException, FileNotFoundException
{
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setErrorStream(TestUtils.getErrorStream());
dbConfig.setErrorPrefix("AppendRecnoTest");
dbConfig.setType(DatabaseType.RECNO);
dbConfig.setPageSize(1024);
dbConfig.setAllowCreate(true);
dbConfig.setRecordNumberAppender(this);
Database db = new Database(TestUtils.getDBFileName(RECNOTEST_DBNAME), null, dbConfig);
for (int i=0; i<10; i++) {
TestUtils.DEBUGOUT("\n*** Iteration " + i );
boolean gotExcept = false;
try {
RecnoEntry key = new RecnoEntry(77+i);
DatabaseEntry data = new DatabaseEntry((new String("data" + i + "_xyz")).getBytes());
db.append(null, key, data);
}
catch (DatabaseException dbe) {
gotExcept = true;
// Can be expected since testing throwing from the appendRecordNumber callback.
TestUtils.DEBUGOUT("dbe: " + dbe);
} catch (ArrayIndexOutOfBoundsException e) {
gotExcept = true;
TestUtils.DEBUGOUT("ArrayIndex: " + e);
}
if((gotExcept && callback_throws == false ) || (!gotExcept && callback_throws == true))
TestUtils.DEBUGOUT(3, "appendRecordNumber callback exception or non-exception condition dealt with incorrectly. Case " + callback_count);
}
Cursor dbcp = db.openCursor(null, CursorConfig.DEFAULT);
// Walk through the table, validating the key/data pairs.
RecnoEntry readkey = new RecnoEntry();
DatabaseEntry readdata = new DatabaseEntry();
TestUtils.DEBUGOUT("Dbc.get");
int itemcount = 0;
while (dbcp.getNext(readkey, readdata, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
String gotString = new String(readdata.getData(), readdata.getOffset(), readdata.getSize());
TestUtils.DEBUGOUT(1, readkey.getRecno() + " : " + gotString);
if(readkey.getRecno() != ++itemcount)
TestUtils.DEBUGOUT(3, "Recno iteration out of order. key: " + readkey.getRecno() + " item: " + itemcount);
if(itemcount > EXPECTED_ENTRIES.length)
TestUtils.ERR("More entries in recno DB than expected.");
if(gotString.compareTo(EXPECTED_ENTRIES[itemcount-1]) != 0)
TestUtils.DEBUGOUT(3, "Recno - stored data mismatch. Expected: " + EXPECTED_ENTRIES[itemcount-1] + " received: " + gotString);
}
dbcp.close();
db.close(false);
}
public void appendRecordNumber(Database db, DatabaseEntry data, int recno)
throws DatabaseException
{
callback_throws = false;
TestUtils.DEBUGOUT("AppendRecnoTest::appendRecordNumber. data " + new String(data.getData()) + " recno: " + recno);
switch (callback_count++) {
case 0:
// nothing
break;
case 1:
data.setSize(data.getSize() - 1);
break;
case 2:
// Should result in an error.
callback_throws = true;
TestUtils.DEBUGOUT("throwing...");
throw new DatabaseException("appendRecordNumber thrown");
//not reached
case 3:
// Should result in an error (size unchanged).
callback_throws = true;
data.setOffset(1);
break;
case 4:
data.setOffset(1);
data.setSize(data.getSize() - 1);
break;
case 5:
data.setOffset(1);
data.setSize(data.getSize() - 2);
break;
case 6:
data.setData(new String("abc").getBytes());
data.setSize(3);
break;
case 7:
// Should result in an error.
callback_throws = true;
data.setData(new String("abc").getBytes());
data.setSize(4);
break;
// TODO: Broken - does not throw an exception.
case 8:
// TODO: Should this result in an error?
data.setData(null);
break;
default:
break;
}
}
static class RecnoEntry extends DatabaseEntry
{
public RecnoEntry() {
super();
}
public RecnoEntry(int value)
{
setReuseBuffer(false);
arr = new byte[4];
setData(arr); // use our local array for data
setRecno(value);
}
public void setRecno(int value)
{
setRecordNumber(value);
}
public int getRecno()
{
return getRecordNumber();
}
byte arr[];
} // end of RecnoEntry sub-class.
}