libdb/test/csharp/RecnoDatabaseTest.cs
2012-11-14 16:35:20 -05:00

466 lines
12 KiB
C#

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved.
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using NUnit.Framework;
using BerkeleyDB;
namespace CsharpAPITest
{
[TestFixture]
public class RecnoDatabaseTest : DatabaseTest
{
[TestFixtureSetUp]
public void SetUpTestFixture()
{
testFixtureName = "RecnoDatabaseTest";
base.SetUpTestfixture();
}
[Test]
public void TestOpenExistingRecnoDB()
{
testName = "TestOpenExistingRecnoDB";
SetUpTest(true);
string recnoDBFileName = testHome + "/" +
testName + ".db";
RecnoDatabaseConfig recConfig =
new RecnoDatabaseConfig();
recConfig.Creation = CreatePolicy.ALWAYS;
RecnoDatabase recDB = RecnoDatabase.Open(
recnoDBFileName, recConfig);
recDB.Close();
RecnoDatabaseConfig dbConfig = new RecnoDatabaseConfig();
string backingFile = testHome + "/backingFile";
File.Copy(recnoDBFileName, backingFile);
dbConfig.BackingFile = backingFile;
RecnoDatabase db = RecnoDatabase.Open(recnoDBFileName, dbConfig);
Assert.AreEqual(db.Type, DatabaseType.RECNO);
db.Close();
}
[Test]
public void TestOpenNewRecnoDB()
{
RecnoDatabase recnoDB;
RecnoDatabaseConfig recnoConfig;
testName = "TestOpenNewRecnoDB";
SetUpTest(true);
string recnoDBFileName = testHome + "/" +
testName + ".db";
XmlElement xmlElem = Configuration.TestSetUp(
testFixtureName, testName);
recnoConfig = new RecnoDatabaseConfig();
RecnoDatabaseConfigTest.Config(xmlElem,
ref recnoConfig, true);
recnoDB = RecnoDatabase.Open(recnoDBFileName,
recnoConfig);
Confirm(xmlElem, recnoDB, true);
recnoDB.Close();
}
[Test]
public void TestAppendWithoutTxn()
{
testName = "TestAppendWithoutTxn";
SetUpTest(true);
string recnoDBFileName = testHome + "/" +
testName + ".db";
RecnoDatabaseConfig recnoConfig =
new RecnoDatabaseConfig();
recnoConfig.Creation = CreatePolicy.ALWAYS;
RecnoDatabase recnoDB = RecnoDatabase.Open(
recnoDBFileName, recnoConfig);
DatabaseEntry data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes("data"));
uint num = recnoDB.Append(data);
DatabaseEntry key = new DatabaseEntry(
BitConverter.GetBytes(num));
Assert.IsTrue(recnoDB.Exists(key));
KeyValuePair<DatabaseEntry, DatabaseEntry> record =
recnoDB.Get(key);
Assert.IsTrue(data.Data.Length ==
record.Value.Data.Length);
for (int i = 0; i < data.Data.Length; i++)
Assert.IsTrue(data.Data[i] ==
record.Value.Data[i]);
recnoDB.Close();
}
[Test]
public void TestCompact()
{
testName = "TestCompact";
SetUpTest(true);
string recnoDBFileName = testHome + "/" +
testName + ".db";
RecnoDatabaseConfig recnoConfig =
new RecnoDatabaseConfig();
recnoConfig.Creation = CreatePolicy.ALWAYS;
recnoConfig.Length = 512;
DatabaseEntry key, data;
RecnoDatabase recnoDB;
using (recnoDB = RecnoDatabase.Open(
recnoDBFileName, recnoConfig))
{
for (int i = 1; i <= 5000; i++)
{
data = new DatabaseEntry(
BitConverter.GetBytes(i));
recnoDB.Append(data);
}
for (int i = 1; i <= 5000; i++)
{
if (i > 500 && (i % 5 != 0))
{
key = new DatabaseEntry(
BitConverter.GetBytes(i));
recnoDB.Delete(key);
}
}
int startInt = 1;
int stopInt = 2500;
DatabaseEntry start, stop;
start = new DatabaseEntry(
BitConverter.GetBytes(startInt));
stop = new DatabaseEntry(
BitConverter.GetBytes(stopInt));
Assert.IsTrue(recnoDB.Exists(start));
Assert.IsTrue(recnoDB.Exists(stop));
CompactConfig cCfg = new CompactConfig();
cCfg.start = start;
cCfg.stop = stop;
cCfg.FillPercentage = 30;
cCfg.Pages = 1;
cCfg.returnEnd = true;
cCfg.Timeout = 5000;
cCfg.TruncatePages = true;
CompactData compactData = recnoDB.Compact(cCfg);
Assert.IsNotNull(compactData.End);
Assert.AreNotEqual(0, compactData.PagesExamined);
}
}
[Test]
public void TestStats()
{
testName = "TestStats";
SetUpTest(true);
string dbFileName = testHome + "/" +
testName + ".db";
RecnoDatabaseConfig dbConfig =
new RecnoDatabaseConfig();
ConfigCase1(dbConfig);
RecnoDatabase db = RecnoDatabase.Open(dbFileName,
dbConfig);
RecnoStats stats = db.Stats();
ConfirmStatsPart1Case1(stats);
// Put 1000 records into the database.
PutRecordCase1(db, null);
stats = db.Stats();
ConfirmStatsPart2Case1(stats);
// Delete 500 records.
for (int i = 250; i <= 750; i++)
db.Delete(new DatabaseEntry(BitConverter.GetBytes(i)));
stats = db.Stats();
ConfirmStatsPart3Case1(stats);
db.Close();
}
[Test]
public void TestStatsInTxn()
{
testName = "TestStatsInTxn";
SetUpTest(true);
StatsInTxn(testHome, testName, false);
}
[Test]
public void TestStatsWithIsolation()
{
testName = "TestStatsWithIsolation";
SetUpTest(true);
StatsInTxn(testHome, testName, true);
}
public void StatsInTxn(string home, string name, bool ifIsolation)
{
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
EnvConfigCase1(envConfig);
DatabaseEnvironment env = DatabaseEnvironment.Open(
home, envConfig);
Transaction openTxn = env.BeginTransaction();
RecnoDatabaseConfig dbConfig =
new RecnoDatabaseConfig();
ConfigCase1(dbConfig);
dbConfig.Env = env;
RecnoDatabase db = RecnoDatabase.Open(name + ".db",
dbConfig, openTxn);
openTxn.Commit();
Transaction statsTxn = env.BeginTransaction();
RecnoStats stats;
RecnoStats fastStats;
if (ifIsolation == false)
{
stats = db.Stats(statsTxn);
fastStats = db.FastStats(statsTxn);
}
else
{
stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
fastStats = db.FastStats(statsTxn,
Isolation.DEGREE_ONE);
}
ConfirmStatsPart1Case1(stats);
// Put 1000 records into the database.
PutRecordCase1(db, statsTxn);
if (ifIsolation == false)
{
stats = db.Stats(statsTxn);
fastStats = db.FastStats(statsTxn);
}
else
{
stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
fastStats = db.FastStats(statsTxn,
Isolation.DEGREE_TWO);
}
ConfirmStatsPart2Case1(stats);
// Delete 500 records.
for (int i = 250; i <= 750; i++)
db.Delete(new DatabaseEntry(BitConverter.GetBytes(i)),
statsTxn);
if (ifIsolation == false)
{
stats = db.Stats(statsTxn);
fastStats = db.FastStats(statsTxn);
}
else
{
stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
fastStats = db.FastStats(statsTxn,
Isolation.DEGREE_THREE);
}
ConfirmStatsPart3Case1(stats);
statsTxn.Commit();
db.Close();
env.Close();
}
public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
{
cfg.Create = true;
cfg.UseTxns = true;
cfg.UseMPool = true;
cfg.UseLogging = true;
}
public void ConfigCase1(RecnoDatabaseConfig dbConfig)
{
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.PageSize = 4096;
dbConfig.Length = 4000;
dbConfig.PadByte = 256;
}
public void PutRecordCase1(RecnoDatabase db, Transaction txn)
{
for (int i = 1; i <= 1000; i++)
{
if (txn == null)
db.Put(new DatabaseEntry(
BitConverter.GetBytes(i)),
new DatabaseEntry(BitConverter.GetBytes(i)));
else
db.Put(new DatabaseEntry(
BitConverter.GetBytes(i)),
new DatabaseEntry(
BitConverter.GetBytes(i)), txn);
}
}
public void ConfirmStatsPart1Case1(RecnoStats stats)
{
Assert.AreEqual(1, stats.EmptyPages);
Assert.AreEqual(1, stats.Levels);
Assert.AreNotEqual(0, stats.MagicNumber);
Assert.AreEqual(10, stats.MetadataFlags);
Assert.AreEqual(2, stats.MinKey);
Assert.AreEqual(2, stats.nPages);
Assert.AreEqual(4096, stats.PageSize);
Assert.AreEqual(4000, stats.RecordLength);
Assert.AreEqual(256, stats.RecordPadByte);
Assert.AreEqual(9, stats.Version);
}
public void ConfirmStatsPart2Case1(RecnoStats stats)
{
Assert.AreEqual(0, stats.DuplicatePages);
Assert.AreEqual(0, stats.DuplicatePagesFreeBytes);
Assert.AreNotEqual(0, stats.InternalPages);
Assert.AreNotEqual(0, stats.InternalPagesFreeBytes);
Assert.AreNotEqual(0, stats.LeafPages);
Assert.AreNotEqual(0, stats.LeafPagesFreeBytes);
Assert.AreEqual(1000, stats.nData);
Assert.AreEqual(1000, stats.nKeys);
Assert.AreNotEqual(0, stats.OverflowPages);
Assert.AreNotEqual(0, stats.OverflowPagesFreeBytes);
}
public void ConfirmStatsPart3Case1(RecnoStats stats)
{
Assert.AreNotEqual(0, stats.FreePages);
}
[Test]
public void TestTruncateUnusedPages()
{
testName = "TestTruncateUnusedPages";
SetUpTest(true);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseCDB = true;
envConfig.UseMPool = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
RecnoDatabaseConfig dbConfig =
new RecnoDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
dbConfig.PageSize = 512;
RecnoDatabase db = RecnoDatabase.Open(
testName + ".db", dbConfig);
ModifyRecordsInDB(db, null);
Assert.Less(0, db.TruncateUnusedPages());
db.Close();
env.Close();
}
[Test]
public void TestTruncateUnusedPagesInTxn()
{
testName = "TestTruncateUnusedPagesInTxn";
SetUpTest(true);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseLogging = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
Transaction openTxn = env.BeginTransaction();
RecnoDatabaseConfig dbConfig =
new RecnoDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
dbConfig.PageSize = 512;
RecnoDatabase db = RecnoDatabase.Open(
testName + ".db", dbConfig, openTxn);
openTxn.Commit();
Transaction modifyTxn = env.BeginTransaction();
ModifyRecordsInDB(db, modifyTxn);
Assert.Less(0, db.TruncateUnusedPages(modifyTxn));
modifyTxn.Commit();
db.Close();
env.Close();
}
public void ModifyRecordsInDB(RecnoDatabase db,
Transaction txn)
{
uint[] recnos = new uint[100];
if (txn == null)
{
// Add a lot of records into database.
for (int i = 0; i < 100; i++)
recnos[i] = db.Append(new DatabaseEntry(
new byte[10240]));
// Remove some records from database.
for (int i = 30; i < 100; i++)
db.Delete(new DatabaseEntry(
BitConverter.GetBytes(recnos[i])));
}
else
{
// Add a lot of records into database in txn.
for (int i = 0; i < 100; i++)
recnos[i] = db.Append(new DatabaseEntry(
new byte[10240]), txn);
// Remove some records from database in txn.
for (int i = 30; i < 100; i++)
db.Delete(new DatabaseEntry(
BitConverter.GetBytes(recnos[i])), txn);
}
}
public static void Confirm(XmlElement xmlElem,
RecnoDatabase recnoDB, bool compulsory)
{
DatabaseTest.Confirm(xmlElem, recnoDB, compulsory);
// Confirm recno database specific field/property
Configuration.ConfirmInt(xmlElem, "Delimiter",
recnoDB.RecordDelimiter, compulsory);
Configuration.ConfirmUint(xmlElem, "Length",
recnoDB.RecordLength, compulsory);
Configuration.ConfirmInt(xmlElem, "PadByte",
recnoDB.RecordPad, compulsory);
Configuration.ConfirmBool(xmlElem, "Renumber",
recnoDB.Renumber, compulsory);
Configuration.ConfirmBool(xmlElem, "Snapshot",
recnoDB.Snapshot, compulsory);
Assert.AreEqual(DatabaseType.RECNO, recnoDB.Type);
string type = recnoDB.Type.ToString();
Assert.IsNotNull(type);
}
}
}