1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 */ 7 8/* 9 * Alexg 23-4-06 10 * Based on scr016 TestAppendRecno test application. 11 */ 12 13package com.sleepycat.db.test; 14 15import org.junit.Before; 16import org.junit.After; 17import org.junit.AfterClass; 18import org.junit.BeforeClass; 19import org.junit.Test; 20import static org.junit.Assert.assertEquals; 21import static org.junit.Assert.fail; 22 23import java.io.File; 24import java.io.FileNotFoundException; 25import com.sleepycat.db.*; 26 27import com.sleepycat.db.DatabaseException; 28 29import com.sleepycat.db.test.TestUtils; 30 31public class AppendRecnoTest implements RecordNumberAppender { 32 33 public static final String RECNOTEST_DBNAME = "appendrecnotest.db"; 34 35 public static final String[] EXPECTED_ENTRIES = { "data0_xyz", "data1_xy", "ata4_xyz", "ata5_xy", 36 "abc", "", "data9_xyz" }; 37 38 int callback_count = 0; 39 boolean callback_throws = false; 40 41 @BeforeClass public static void ClassInit() { 42 TestUtils.loadConfig(null); 43 TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true); 44 } 45 46 @AfterClass public static void ClassShutdown() { 47 TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true); 48 } 49 50 @Before public void PerTestInit() 51 throws Exception { 52 TestUtils.removeall(true, false, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(RECNOTEST_DBNAME)); 53 } 54 55 @After public void PerTestShutdown() 56 throws Exception { 57 } 58 59 /* 60 * Test creating a new database. 61 */ 62 @Test public void test1() 63 throws DatabaseException, FileNotFoundException 64 { 65 DatabaseConfig dbConfig = new DatabaseConfig(); 66 dbConfig.setErrorStream(TestUtils.getErrorStream()); 67 dbConfig.setErrorPrefix("AppendRecnoTest"); 68 dbConfig.setType(DatabaseType.RECNO); 69 dbConfig.setPageSize(1024); 70 dbConfig.setAllowCreate(true); 71 dbConfig.setRecordNumberAppender(this); 72 73 Database db = new Database(TestUtils.getDBFileName(RECNOTEST_DBNAME), null, dbConfig); 74 75 for (int i=0; i<10; i++) { 76 TestUtils.DEBUGOUT("\n*** Iteration " + i ); 77 boolean gotExcept = false; 78 try { 79 RecnoEntry key = new RecnoEntry(77+i); 80 DatabaseEntry data = new DatabaseEntry((new String("data" + i + "_xyz")).getBytes()); 81 db.append(null, key, data); 82 } 83 catch (DatabaseException dbe) { 84 gotExcept = true; 85 // Can be expected since testing throwing from the appendRecordNumber callback. 86 TestUtils.DEBUGOUT("dbe: " + dbe); 87 } catch (ArrayIndexOutOfBoundsException e) { 88 gotExcept = true; 89 TestUtils.DEBUGOUT("ArrayIndex: " + e); 90 } 91 if((gotExcept && callback_throws == false ) || (!gotExcept && callback_throws == true)) 92 TestUtils.DEBUGOUT(3, "appendRecordNumber callback exception or non-exception condition dealt with incorrectly. Case " + callback_count); 93 } 94 95 Cursor dbcp = db.openCursor(null, CursorConfig.DEFAULT); 96 97 // Walk through the table, validating the key/data pairs. 98 RecnoEntry readkey = new RecnoEntry(); 99 DatabaseEntry readdata = new DatabaseEntry(); 100 TestUtils.DEBUGOUT("Dbc.get"); 101 102 int itemcount = 0; 103 while (dbcp.getNext(readkey, readdata, LockMode.DEFAULT) == OperationStatus.SUCCESS) { 104 String gotString = new String(readdata.getData(), readdata.getOffset(), readdata.getSize()); 105 TestUtils.DEBUGOUT(1, readkey.getRecno() + " : " + gotString); 106 107 if(readkey.getRecno() != ++itemcount) 108 TestUtils.DEBUGOUT(3, "Recno iteration out of order. key: " + readkey.getRecno() + " item: " + itemcount); 109 110 if(itemcount > EXPECTED_ENTRIES.length) 111 TestUtils.ERR("More entries in recno DB than expected."); 112 113 114 if(gotString.compareTo(EXPECTED_ENTRIES[itemcount-1]) != 0) 115 TestUtils.DEBUGOUT(3, "Recno - stored data mismatch. Expected: " + EXPECTED_ENTRIES[itemcount-1] + " received: " + gotString); 116 } 117 118 dbcp.close(); 119 db.close(false); 120 121 } 122 123 public void appendRecordNumber(Database db, DatabaseEntry data, int recno) 124 throws DatabaseException 125 { 126 callback_throws = false; 127 TestUtils.DEBUGOUT("AppendRecnoTest::appendRecordNumber. data " + new String(data.getData()) + " recno: " + recno); 128 129 switch (callback_count++) { 130 case 0: 131 // nothing 132 break; 133 134 case 1: 135 data.setSize(data.getSize() - 1); 136 break; 137 138 case 2: 139 // Should result in an error. 140 callback_throws = true; 141 TestUtils.DEBUGOUT("throwing..."); 142 throw new DatabaseException("appendRecordNumber thrown"); 143 //not reached 144 145 case 3: 146 // Should result in an error (size unchanged). 147 callback_throws = true; 148 data.setOffset(1); 149 break; 150 151 case 4: 152 data.setOffset(1); 153 data.setSize(data.getSize() - 1); 154 break; 155 156 case 5: 157 data.setOffset(1); 158 data.setSize(data.getSize() - 2); 159 break; 160 161 case 6: 162 data.setData(new String("abc").getBytes()); 163 data.setSize(3); 164 break; 165 166 case 7: 167 // Should result in an error. 168 callback_throws = true; 169 data.setData(new String("abc").getBytes()); 170 data.setSize(4); 171 break; 172// TODO: Broken - does not throw an exception. 173 case 8: 174 // TODO: Should this result in an error? 175 data.setData(null); 176 break; 177 178 default: 179 break; 180 } 181 } 182 183 static class RecnoEntry extends DatabaseEntry 184 { 185 public RecnoEntry() { 186 super(); 187 } 188 189 public RecnoEntry(int value) 190 { 191 setReuseBuffer(false); 192 arr = new byte[4]; 193 setData(arr); // use our local array for data 194 setRecno(value); 195 } 196 197 public void setRecno(int value) 198 { 199 setRecordNumber(value); 200 } 201 202 public int getRecno() 203 { 204 return getRecordNumber(); 205 } 206 byte arr[]; 207 } // end of RecnoEntry sub-class. 208 209} 210