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 TestConstruct01 and TestConstruct02 11 * test applications. 12 */ 13 14package com.sleepycat.db.test; 15 16import org.junit.Before; 17import org.junit.After; 18import org.junit.AfterClass; 19import org.junit.BeforeClass; 20import org.junit.Test; 21import static org.junit.Assert.assertEquals; 22import static org.junit.Assert.fail; 23 24import com.sleepycat.db.Cursor; 25import com.sleepycat.db.CursorConfig; 26import com.sleepycat.db.Database; 27import com.sleepycat.db.DatabaseConfig; 28import com.sleepycat.db.DatabaseEntry; 29import com.sleepycat.db.DatabaseException; 30import com.sleepycat.db.DatabaseType; 31import com.sleepycat.db.Environment; 32import com.sleepycat.db.EnvironmentConfig; 33import com.sleepycat.db.LockMode; 34import com.sleepycat.db.OperationStatus; 35 36import java.io.File; 37import java.io.IOException; 38import java.io.FileNotFoundException; 39import com.sleepycat.db.test.TestUtils; 40 41public class DatabaseTest { 42 43 public static final String DATABASETEST_DBNAME = "databasetest.db"; 44 45 private static int itemcount; // count the number of items in the database 46 47 @BeforeClass public static void ClassInit() { 48 TestUtils.loadConfig(null); 49 TestUtils.check_file_removed(TestUtils.getDBFileName(DATABASETEST_DBNAME), true, true); 50 TestUtils.removeall(true, true, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(DATABASETEST_DBNAME)); 51 itemcount = 0; 52 } 53 54 @AfterClass public static void ClassShutdown() { 55 TestUtils.check_file_removed(TestUtils.getDBFileName(DATABASETEST_DBNAME), true, true); 56 TestUtils.removeall(true, true, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(DATABASETEST_DBNAME)); 57 } 58 59 @Before public void PerTestInit() 60 throws Exception { 61 } 62 63 @After public void PerTestShutdown() 64 throws Exception { 65 } 66 67 /* 68 * Test creating a new database. 69 */ 70 @Test public void test1() 71 throws DatabaseException, FileNotFoundException 72 { 73 TestOptions options = new TestOptions(); 74 options.db_config.setErrorPrefix("DatabaseTest::test1 "); 75 76 rundb(itemcount++, options); 77 } 78 79 /* 80 * Test opening and adding to an existing database. 81 */ 82 @Test public void test2() 83 throws DatabaseException, FileNotFoundException 84 { 85 TestOptions options = new TestOptions(); 86 options.db_config.setErrorPrefix("DatabaseTest::test2 "); 87 88 rundb(itemcount++, options); 89 } 90 91 /* 92 * Test modifying the error prefix multiple times ? 93 */ 94 @Test public void test3() 95 throws DatabaseException, FileNotFoundException 96 { 97 TestOptions options = new TestOptions(); 98 options.db_config.setErrorPrefix("DatabaseTest::test3 "); 99 100 for (int i=0; i<100; i++) 101 options.db_config.setErrorPrefix("str" + i); 102 103 rundb(itemcount++, options); 104 } 105 106 /* 107 * Test opening a database with an env. 108 */ 109 @Test public void test4() 110 throws DatabaseException, FileNotFoundException 111 { 112 TestOptions options = new TestOptions(); 113 options.db_config.setErrorPrefix("DatabaseTest::test4 "); 114 115 EnvironmentConfig envc = new EnvironmentConfig(); 116 envc.setAllowCreate(true); 117 envc.setInitializeCache(true); 118 options.db_env = new Environment(TestUtils.BASETEST_DBFILE, envc); 119 120 rundb(itemcount++, options); 121 options.db_env.close(); 122 } 123 124 /* 125 * Test opening multiple databases using the same env. 126 */ 127 @Test public void test5() 128 throws DatabaseException, FileNotFoundException 129 { 130 TestOptions options = new TestOptions(); 131 options.db_config.setErrorPrefix("DatabaseTest::test5 "); 132 133 EnvironmentConfig envc = new EnvironmentConfig(); 134 envc.setAllowCreate(true); 135 envc.setInitializeCache(true); 136 options.db_env = new Environment(TestUtils.BASETEST_DBFILE, envc); 137 138 rundb(itemcount++, options); 139 140 rundb(itemcount++, options); 141 142 options.db_env.close(); 143 } 144 145 /* 146 * Test just opening and closing a DB and an Env without doing any operations. 147 */ 148 @Test public void test6() 149 throws DatabaseException, FileNotFoundException 150 { 151 TestOptions options = new TestOptions(); 152 options.db_config.setErrorPrefix("DatabaseTest::test6 "); 153 154 Database db = new Database(TestUtils.getDBFileName(DATABASETEST_DBNAME), null, options.db_config); 155 156 EnvironmentConfig envc = new EnvironmentConfig(); 157 envc.setAllowCreate(true); 158 envc.setInitializeCache(true); 159 Environment db_env = new Environment(TestUtils.BASETEST_DBFILE, envc); 160 161 db.close(); 162 db_env.close(); 163 164 System.gc(); 165 System.runFinalization(); 166 } 167 168 /* 169 * test7 leaves a db and dbenv open; it should be detected. 170 */ 171 /* Not sure if relevant with current API. 172 @Test public void test7() 173 throws DatabaseException, FileNotFoundException 174 { 175 TestOptions options = new TestOptions(); 176 options.db_config.setErrorPrefix("DatabaseTest::test7 "); 177 178 Database db = new Database(TestUtils.getDBFileName(DATABASETEST_DBNAME), null, options.db_config); 179 180 EnvironmentConfig envc = new EnvironmentConfig(); 181 envc.setAllowCreate(true); 182 envc.setInitializeCache(true); 183 Environment db_env = new Environment(TestUtils.BASETEST_DBFILE, envc); 184 185 System.gc(); 186 System.runFinalization(); 187 } 188 */ 189 190 /* 191 * Test creating a new database. 192 */ 193 @Test public void test8() 194 throws DatabaseException, FileNotFoundException 195 { 196 TestUtils.removeall(true, false, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(DATABASETEST_DBNAME)); 197 itemcount = 0; 198 TestOptions options = new TestOptions(); 199 options.save_db = true; 200 options.db_config.setErrorPrefix("DatabaseTest::test8 "); 201 202 EnvironmentConfig envc = new EnvironmentConfig(); 203 envc.setAllowCreate(true); 204 envc.setInitializeCache(true); 205 options.db_env = new Environment(TestUtils.BASETEST_DBFILE, envc); 206 207 // stop rundb from closing the database, and pass in one created. 208 rundb(itemcount++, options); 209 rundb(itemcount++, options); 210 rundb(itemcount++, options); 211 rundb(itemcount++, options); 212 rundb(itemcount++, options); 213 rundb(itemcount++, options); 214 215 options.database.close(); 216 options.database = null; 217 218 // reopen the same database. 219 rundb(itemcount++, options); 220 rundb(itemcount++, options); 221 rundb(itemcount++, options); 222 rundb(itemcount++, options); 223 rundb(itemcount++, options); 224 rundb(itemcount++, options); 225 226 options.database.close(); 227 options.database = null; 228 229 } 230 231 // Check that key/data for 0 - count-1 are already present, 232 // and write a key/data for count. The key and data are 233 // both "0123...N" where N == count-1. 234 // 235 // For some reason on Windows, we need to open using the full pathname 236 // of the file when there is no environment, thus the 'has_env' 237 // variable. 238 // 239 void rundb(int count, TestOptions options) 240 throws DatabaseException, FileNotFoundException 241 { 242 String name; 243 244 Database db; 245 if(options.database == null) 246 { 247 if (options.db_env != null) 248 name = DATABASETEST_DBNAME; 249 else 250 name = TestUtils.getDBFileName(DATABASETEST_DBNAME); 251 252 if(count == 0) 253 options.db_config.setAllowCreate(true); 254 255 if(options.db_env == null) 256 db = new Database(name, null, options.db_config); 257 else 258 db = options.db_env.openDatabase(null, name, null, options.db_config); 259 } else { 260 db = options.database; 261 } 262 263 // The bit map of keys we've seen 264 long bitmap = 0; 265 266 // The bit map of keys we expect to see 267 long expected = (1 << (count+1)) - 1; 268 269 byte outbuf[] = new byte[count+1]; 270 int i; 271 for (i=0; i<count; i++) { 272 outbuf[i] = (byte)('0' + i); 273 } 274 outbuf[i++] = (byte)'x'; 275 276 DatabaseEntry key = new DatabaseEntry(outbuf, 0, i); 277 DatabaseEntry data = new DatabaseEntry(outbuf, 0, i); 278 279 TestUtils.DEBUGOUT("Put: " + (char)outbuf[0] + ": " + new String(outbuf, 0, i)); 280 db.putNoOverwrite(null, key, data); 281 282 // Acquire a cursor for the table. 283 Cursor dbcp = db.openCursor(null, CursorConfig.DEFAULT); 284 285 // Walk through the table, checking 286 DatabaseEntry readkey = new DatabaseEntry(); 287 DatabaseEntry readdata = new DatabaseEntry(); 288 DatabaseEntry whoknows = new DatabaseEntry(); 289 290 /* 291 * NOTE: Maybe want to change from user-buffer to DB buffer 292 * depending on the flag options.user_buffer (setReuseBuffer) 293 * The old version set MALLOC/REALLOC here - not sure if it is the same. 294 */ 295 296 TestUtils.DEBUGOUT("Dbc.get"); 297 while (dbcp.getNext(readkey, readdata, LockMode.DEFAULT) == OperationStatus.SUCCESS) { 298 String key_string = 299 new String(readkey.getData(), 0, readkey.getSize()); 300 String data_string = 301 new String(readdata.getData(), 0, readkey.getSize()); 302 TestUtils.DEBUGOUT("Got: " + key_string + ": " + data_string); 303 int len = key_string.length(); 304 if (len <= 0 || key_string.charAt(len-1) != 'x') { 305 TestUtils.ERR("reread terminator is bad"); 306 } 307 len--; 308 long bit = (1 << len); 309 if (len > count) { 310 TestUtils.ERR("reread length is bad: expect " + count + " got "+ len + " (" + key_string + ")" ); 311 } 312 else if (!data_string.equals(key_string)) { 313 TestUtils.ERR("key/data don't match"); 314 } 315 else if ((bitmap & bit) != 0) { 316 TestUtils.ERR("key already seen"); 317 } 318 else if ((expected & bit) == 0) { 319 TestUtils.ERR("key was not expected"); 320 } 321 else { 322 bitmap |= bit; 323 expected &= ~(bit); 324 for (i=0; i<len; i++) { 325 if (key_string.charAt(i) != ('0' + i)) { 326 System.out.print(" got " + key_string 327 + " (" + (int)key_string.charAt(i) 328 + "), wanted " + i 329 + " (" + (int)('0' + i) 330 + ") at position " + i + "\n"); 331 TestUtils.ERR("key is corrupt"); 332 } 333 } 334 } 335 } 336 if (expected != 0) { 337 System.out.print(" expected more keys, bitmap is: " + expected + "\n"); 338 TestUtils.ERR("missing keys in database"); 339 } 340 341 dbcp.close(); 342 TestUtils.DEBUGOUT("options.save_db " + options.save_db + " options.database " + options.database); 343 if(options.save_db == false) 344 db.close(false); 345 else if (options.database == null) 346 options.database = db; 347 } 348} 349 350 351class TestOptions 352{ 353 int testmask = 0; // which tests to run 354 int user_buffer = 0; // use DB_DBT_USERMEM or DB_DBT_MALLOC 355 int successcounter =0; 356 boolean save_db = false; 357 Environment db_env = null; 358 DatabaseConfig db_config; 359 Database database = null; // db is saved here by rundb if save_db is true. 360 361 public TestOptions() 362 { 363 this.testmask = 0; 364 this.user_buffer = 0; 365 this.successcounter = 0; 366 this.db_env = null; 367 368 db_config = new DatabaseConfig(); 369 db_config.setErrorStream(TestUtils.getErrorStream()); 370 db_config.setErrorPrefix("DatabaseTest"); 371 db_config.setType(DatabaseType.BTREE); 372 // We don't really care about the pagesize 373 db_config.setPageSize(1024); 374 375 } 376 377} 378