LoganBerryTest.mesa (Cedar10 version)
Copyright Ó 1986, 1992 by Xerox Corporation. All rights reserved.
Doug Terry, June 17, 1992 1:00 pm PDT
Brian Oki, February 13, 1990 11:14:53 am PST
A test program for LoganBerry. Simply type "TestLoganBerry" to a command tool.
Willie-s, April 23, 1992 3:21 pm PDT
DIRECTORY
BasicTime USING [GetClockPulses, GMT, Pulses, PulsesToMicroseconds],
Commander USING [Register, CommandProc],
CommanderOps USING [ParseToList],
Convert USING [AppendChar, RopeFromInt, IntFromRope, Error],
IO,
LoganBerry,
PFS USING [Delete, PATH, PathFromRope, StreamOpen],
PrintEnglish USING [IntToEnglish],
Random USING [RandomStream, Create, ChooseInt],
Rope USING [ROPE, Equal];
LoganBerryTest: CEDAR PROGRAM
IMPORTS BasicTime, Commander, CommanderOps, Convert, IO, LoganBerry, PFS, PrintEnglish, Random, Rope
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
defaultDbFileName: ROPE ¬ "LoganBerry.df";
dbFileName: ROPE ¬ defaultDbFileName;
database: LoganBerry.OpenDB ¬ LoganBerry.nullDB;
rs: Random.RandomStream¬ Random.Create[range: 10000, seed: -1];
The set of tests must be updated whenever a new test is added
TestCase: TYPE = {create, enumerate, generate, deleteA, deleteB, rewriteA, rewriteB, replace, readRandom, checkData, closeAndOpen, bidirectionalGenerate, binaryData, invalidOps, buildIndices, compactA, compactB, generateSecondary};
The following numbers pertain to specific tests
dbSize: CARDINAL ¬ 1000; -- size of test database, should be less than 10000
numReads: CARDINAL ¬ 100;
numDeletes: CARDINAL ¬ 10;
numReplaces: CARDINAL ¬ 10;
savedEntries: LIST OF LoganBerry.Entry;
RunTest: PROC [n: TestCase, out: IO.STREAM ¬ NIL] RETURNS [failed: BOOLEAN ¬ FALSE] ~ {
Runs and times the given test.
ENABLE LoganBerry.Error => {
IF out # NIL THEN out.PutF["Error from LoganBerry: %g - %g\n", IO.atom[ec], IO.rope[explanation]];
failed ¬ TRUE;
CONTINUE;
};
start, stop: BasicTime.Pulses;
attr: LoganBerry.Attribute;
atype: LoganBerry.AttributeType;
avalue: LoganBerry.AttributeValue;
entry: LoganBerry.Entry;
cursor: LoganBerry.Cursor;
schema: LoganBerry.SchemaInfo;
i: INT;
count: CARDINAL;
start ¬ BasicTime.GetClockPulses[];
SELECT n FROM
$create => { -- build a LoganBerry test database in random order
newStream: IO.STREAM;
filename: PFS.PATH;
IF out # NIL THEN out.PutF1["Creating new test database with %g entries.\n", IO.int[dbSize]];
somehow need to delete old database entries first
schema ¬ LoganBerry.Describe[db: database];
LoganBerry.Close[db: database];
Create a file given name by opening a stream, then closing it
filename ¬ PFS.PathFromRope[schema.logs.first.file];
newStream ¬ PFS.StreamOpen[fileName: filename, accessOptions: $create];
IO.PutChar[newStream, 377C];
IO.Close[newStream];
<<FS.Close[FS.Create[name: schema.logs.first.file]];>>
FOR i: LIST OF LoganBerry.IndexInfo ¬ schema.indices, i.rest WHILE i#NIL DO
PFS.Delete[name: PFS.PathFromRope[i.first.file]];
ENDLOOP;
<<database ¬ LoganBerry.Open[dbName: dbFileName ! LoganBerry.Error => {
IO.PutF[out, "Error from LoganBerry: %g - %g\n", IO.atom[ec], IO.rope[explanation]];
RETRY -- this statement added to original code; bombed out otherwise
}
];>>
database ¬ LoganBerry.Open[dbName: dbFileName ! LoganBerry.Error => IF ec=$BadIndex THEN RETRY];
log and indices should be empty at this point, but rebuild just to be sure
LoganBerry.BuildIndices[db: database];
MarkKeysUnused[1, dbSize];
now generate new entries
THROUGH [1..dbSize] DO
i ¬ GenerateUnusedKey[1, dbSize];
entry ¬ LIST[[$Integer, Convert.RopeFromInt[i]], [$Rope, PrintEnglish.IntToEnglish[i]]];
LoganBerry.WriteEntry[db: database, entry: entry];
ENDLOOP;
};
$enumerate => { -- enumerate the database to get the number of entries
AddOne: LoganBerry.EntryProc = {
[entry: LoganBerry.Entry] RETURNS [continue: BOOL]
count ¬ count + 1;
RETURN[TRUE];
};
IF out # NIL THEN out.PutRope["Enumerating entries.\n"];
count ¬ 0;
LoganBerry.EnumerateEntries[db: database, key: $Integer, proc: AddOne];
IF count # dbSize AND out # NIL THEN out.PutRope["Warning: count # standard database size.\n"];
dbSize ¬ count;
IF out # NIL THEN out.PutF1["Test database contains %g entries.\n", IO.card[dbSize]];
};
$generate => { -- generate the complete database and see if the number is correct
IF out # NIL THEN out.PutRope["Generating entries.\n"];
count ¬ 0;
cursor ¬ LoganBerry.GenerateEntries[db: database, key: $Integer];
entry ¬ LoganBerry.NextEntry[cursor: cursor];
UNTIL entry = NIL DO
count ¬ count + 1;
entry ¬ LoganBerry.NextEntry[cursor: cursor];
ENDLOOP;
LoganBerry.EndGenerate[cursor: cursor];
IF count # dbSize THEN {
IF out # NIL THEN out.PutRope["Error: count # database size.\n"];
failed ¬ TRUE;
};
};
$generateSecondary => { -- generate the complete database using secondary index
IF out # NIL THEN out.PutRope["Generating entries using secondary index.\n"];
count ¬ 0;
cursor ¬ LoganBerry.GenerateEntries[db: database, key: $Rope];
entry ¬ LoganBerry.NextEntry[cursor: cursor];
UNTIL entry = NIL DO
count ¬ count + 1;
entry ¬ LoganBerry.NextEntry[cursor: cursor];
ENDLOOP;
LoganBerry.EndGenerate[cursor: cursor];
IF count # dbSize THEN {
IF out # NIL THEN out.PutRope["Error: count # database size.\n"];
failed ¬ TRUE;
};
};
$deleteA => { -- delete some entries
IF out # NIL THEN out.PutF1["Reading and deleting %g entries.\n", IO.card[numDeletes]];
MarkKeysUnused[1, dbSize];
savedEntries ¬ NIL;
THROUGH [1..numDeletes] DO
i ¬ GenerateUnusedKey[1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry;
savedEntries ¬ CONS[entry, savedEntries];
LoganBerry.DeleteEntry[db: database, key: $Integer, value: avalue];
ENDLOOP;
};
$deleteB => { -- verify that the deleted entries can not be read
IF out # NIL THEN out.PutRope["Verifying deletes.\n"];
THROUGH [1..3] DO
i ¬ GenerateUsedKey[1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
IF LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry # NIL THEN {
IF out # NIL THEN out.PutRope["Error: sucessfully read deleted entry.\n"];
failed ¬ TRUE;
};
ENDLOOP;
};
$rewriteA => { -- rewrite the deleted entries
IF out # NIL THEN out.PutRope["Rewriting deleted entries.\n"];
WHILE savedEntries # NIL DO
LoganBerry.WriteEntry[db: database, entry: savedEntries.first];
savedEntries ¬ savedEntries.rest;
ENDLOOP;
};
$rewriteB => { -- verify that the rewritten entries can be read
IF out # NIL THEN out.PutRope["Verifying rewrites.\n"];
THROUGH [1..3] DO
i ¬ GenerateUsedKey[1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
IF LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry = NIL THEN {
IF out # NIL THEN out.PutRope["Error: unable to read replaced entry.\n"];
failed ¬ TRUE;
};
ENDLOOP;
};
$readRandom => { -- read some random entries
IF out # NIL THEN out.PutF1["Reading %g entries.\n", IO.card[numReads]];
THROUGH [1..numReads] DO
i ¬ Random.ChooseInt[rs, 1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
IF LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry = NIL THEN {
IF out # NIL THEN out.PutF1["Error: unable to read entry #%g.\n", IO.rope[avalue]];
failed ¬ TRUE;
};
ENDLOOP;
};
$checkData => { -- check the consistency of the data
IF out # NIL THEN out.PutRope["Checking data.\n"];
THROUGH [1..10] DO
i ¬ Random.ChooseInt[rs, 1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry;
avalue ¬ GetAttributeValue[entry, $Rope];
IF NOT Rope.Equal[avalue, PrintEnglish.IntToEnglish[i]] THEN {
IF out # NIL THEN out.PutRope["Error: $Rope value # expected value.\n"];
failed ¬ TRUE;
};
ENDLOOP;
};
$replace => { -- replace some random entries (then restore to original values)
replacement: LoganBerry.Entry;
IF out # NIL THEN out.PutF1["Replacing (then restoring) %g entries.\n", IO.card[numReplaces]];
THROUGH [1..numReplaces] DO
i ¬ Random.ChooseInt[rs, 1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry;
replacement ¬ LIST[[$Integer, avalue], [$Rope, "replacement value"]];
LoganBerry.WriteEntry[db: database, entry: replacement, replace: TRUE];
replacement ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry;
IF NOT Rope.Equal[GetAttributeValue[replacement, $Rope], "replacement value"] THEN {
IF out # NIL THEN out.PutRope["Error: replacement $Rope value # expected value.\n"];
failed ¬ TRUE;
};
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
ENDLOOP;
};
$closeAndOpen => { -- close and reopen the database
caughtError: BOOLEAN ¬ FALSE;
IF out # NIL THEN out.PutRope["Closing and reopening the database.\n"];
i ¬ Random.ChooseInt[rs, 1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
LoganBerry.Close[db: database];
[] ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue !
LoganBerry.Error => {
caughtError ¬ TRUE;
IF ec = $DBClosed THEN CONTINUE ELSE REJECT};
];
IF caughtError THEN {
IF out # NIL THEN out.PutRope["Error: database not reopened after close.\n"];
failed ¬ TRUE;
};
database ¬ LoganBerry.Open[dbName: dbFileName];
IF LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry = NIL THEN {
IF out # NIL THEN out.PutF1["Error: unable to read entry #%g.\n", IO.rope[avalue]];
failed ¬ TRUE;
};
};
$bidirectionalGenerate => { -- generate a subrange of entries in both directions
IF out # NIL THEN out.PutRope["Advanced test of generate.\n"];
i ¬ Random.ChooseInt[rs, 1, dbSize-10];
avalue ¬ Convert.RopeFromInt[i];
cursor ¬ LoganBerry.GenerateEntries[db: database, key: $Integer, start: avalue, end: Convert.RopeFromInt[i+9]];
Retrieve [start..end]
count ¬ 0;
entry ¬ LoganBerry.NextEntry[cursor: cursor];
UNTIL entry = NIL DO
count ¬ count + 1;
entry ¬ LoganBerry.NextEntry[cursor: cursor];
ENDLOOP;
Note: at this point it is hard to predict count since ordering is non-numerical
Retrieve (end..start]
entry ¬ LoganBerry.NextEntry[cursor: cursor, dir: decreasing];
UNTIL entry = NIL DO
count ¬ count - 1;
entry ¬ LoganBerry.NextEntry[cursor: cursor, dir: decreasing];
ENDLOOP;
IF count # 1 THEN {
IF out # NIL THEN out.PutRope["Error: generated increasing/decreasing subrange of wrong size.\n"];
failed ¬ TRUE;
};
LoganBerry.EndGenerate[cursor: cursor];
};
$compactA => { -- compact the database
IF out # NIL THEN out.PutRope["Compacting log.\n"];
LoganBerry.CompactLogs[db: database];
};
$compactB => { -- verify that the compacted database has the correct number of entries
IF out # NIL THEN out.PutRope["Counting number of entries.\n"];
count ¬ 0;
cursor ¬ LoganBerry.GenerateEntries[db: database, key: $Integer];
entry ¬ LoganBerry.NextEntry[cursor: cursor];
UNTIL entry = NIL DO
count ¬ count + 1;
entry ¬ LoganBerry.NextEntry[cursor: cursor];
ENDLOOP;
LoganBerry.EndGenerate[cursor: cursor];
IF count # dbSize THEN {
IF out # NIL THEN out.PutF1["Error: count # database size. count = %g\n", IO.card[count]];
failed ¬ TRUE;
};
};
$buildIndices => { -- rebuild the database indices
IF out # NIL THEN out.PutRope["Rebuilding indices.\n"];
LoganBerry.BuildIndices[db: database];
};
$binaryData => { -- write and read strange values (then delete them)
IF out # NIL THEN out.PutRope["Writing strange values and verifying them.\n"];
avalue ¬ "CR\r in value";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back value with CR.\n"];
failed ¬ TRUE;
};
avalue ¬ "LF\l in value";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back value with LF.\n"];
failed ¬ TRUE;
};
avalue ¬ "\"quoted\"";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back quoted value.\n"];
failed ¬ TRUE;
};
avalue ¬ "backslash-quote\\\" in value";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back value with backslash-quote.\n"];
failed ¬ TRUE;
};
avalue ¬ "\"";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back value = quote.\n"];
failed ¬ TRUE;
};
avalue ¬ "\\";
entry ¬ LIST[[$Integer, "0"], [$Rope, avalue]];
LoganBerry.WriteEntry[db: database, entry: entry, replace: TRUE];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: "0"].entry;
IF NOT Rope.Equal[avalue, GetAttributeValue[entry, $Rope]] THEN {
IF out # NIL THEN out.PutRope["Error: incorrectly read back value = backslash.\n"];
failed ¬ TRUE;
};
LoganBerry.DeleteEntry[db: database, key: $Integer, value: "0"];
};
$invalidOps => { -- try to raise errors
caughtError: BOOLEAN ¬ FALSE;
IF out # NIL THEN out.PutRope["Checking generated errors.\n"];
[] ¬ LoganBerry.Open[dbName: "Nonexistent.badname" !
LoganBerry.Error => {caughtError ¬ TRUE; IF ec = $CantOpenSchema THEN CONTINUE ELSE REJECT};];
IF NOT caughtError THEN {
IF out # NIL THEN out.PutRope["Error: able to open nonexistent database.\n"];
failed ¬ TRUE;
};
caughtError ¬ FALSE;
[] ¬ LoganBerry.Describe[db: 1010101 !
LoganBerry.Error => {caughtError ¬ TRUE; IF ec = $BadDBHandle THEN CONTINUE ELSE REJECT};];
IF NOT caughtError THEN {
IF out # NIL THEN out.PutRope["Error: able to operate on bad database.\n"];
failed ¬ TRUE;
};
caughtError ¬ FALSE;
[] ¬ LoganBerry.ReadEntry[db: database, key: $NonIndex, value: avalue !
LoganBerry.Error => {caughtError ¬ TRUE; IF ec = $NoIndex THEN CONTINUE ELSE REJECT};];
IF NOT caughtError THEN {
IF out # NIL THEN out.PutRope["Error: able to read using nonexistent index.\n"];
failed ¬ TRUE;
};
i ¬ Random.ChooseInt[rs, 1, dbSize];
avalue ¬ Convert.RopeFromInt[i];
entry ¬ LoganBerry.ReadEntry[db: database, key: $Integer, value: avalue].entry;
caughtError ¬ FALSE;
[] ¬ LoganBerry.WriteEntry[db: database, entry: entry !
LoganBerry.Error => {caughtError ¬ TRUE; IF ec = $ValueNotUnique THEN CONTINUE ELSE REJECT};];
IF NOT caughtError THEN {
IF out # NIL THEN out.PutRope["Error: able to write duplicate entry.\n"];
failed ¬ TRUE;
};
caughtError ¬ FALSE;
[] ¬ LoganBerry.WriteEntry[db: database, entry: entry.rest !
LoganBerry.Error => {caughtError ¬ TRUE; IF ec = $NoPrimaryKey THEN CONTINUE ELSE REJECT};];
IF NOT caughtError THEN {
IF out # NIL THEN out.PutRope["Error: able to write without primary key.\n"];
failed ¬ TRUE;
};
};
ENDCASE => {
IF out # NIL THEN out.PutRope["Error: No such test.\n"];
failed ¬ TRUE;
};
stop ¬ BasicTime.GetClockPulses[];
IF out # NIL THEN out.PutF1["Running time: %g\n", IO.rope[ElapsedTime[start, stop]]];
};
ElapsedTime: PROC [start, stop: BasicTime.Pulses] RETURNS [ROPE] ~ {
Taken from InitialCommandsImpl.Time.
microseconds, seconds: LONG CARDINAL;
digit: CARDINAL;
any: BOOL ¬ FALSE;
text: REF TEXT ¬ NEW[TEXT[8]];
microseconds ¬ BasicTime.PulsesToMicroseconds[stop - start];
seconds ¬ microseconds / 1000000;
microseconds ¬ microseconds MOD 1000000;
THROUGH [0..6) DO
microseconds ¬ microseconds * 10;
digit ¬ microseconds / 1000000;
microseconds ¬ microseconds MOD 1000000;
IF NOT any THEN {
text ¬ Convert.AppendChar[to: text, from: '., quote: FALSE];
any ¬ TRUE;
};
text ¬ Convert.AppendChar[to: text, from: digit + '0, quote: FALSE];
IF microseconds = 0 THEN EXIT;
ENDLOOP;
RETURN [IO.PutFR["%r%g\n", IO.card[seconds], IO.text[text]]];
};
usedKeys: PACKED ARRAY [1..10000] OF BOOLEAN;
MarkKeysUnused: PROC [min, max: INT] RETURNS [] ~ {
FOR i: INT IN [min..max] DO
usedKeys[i] ¬ FALSE;
ENDLOOP;
};
GenerateUnusedKey: PROC [min, max: INT] RETURNS [INT] ~ {
i: INT;
i ¬ Random.ChooseInt[rs, min, max];
WHILE usedKeys[i] DO
IF i < max THEN i ¬ i + 1
ELSE i ¬ min;
ENDLOOP;
usedKeys[i] ¬ TRUE;
RETURN[i];
};
GenerateUsedKey: PROC [min, max: INT] RETURNS [INT] ~ {
i: INT;
i ¬ Random.ChooseInt[rs, min, max];
WHILE NOT usedKeys[i] DO
IF i < max THEN i ¬ i + 1
ELSE i ¬ min;
ENDLOOP;
RETURN[i];
};
GetAttributeValue: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType] RETURNS [LoganBerry.AttributeValue] ~ {
FOR e: LoganBerry.Entry ¬ entry, e.rest WHILE e # NIL DO
IF e.first.type = type THEN
RETURN[e.first.value];
ENDLOOP;
RETURN[NIL];
};
TestLoganBerry: Commander.CommandProc = {
[cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL]
needToBuildIndices: BOOLEAN ¬ FALSE;
numErrors: INT ¬ 0;
firstTest: TestCase ¬ enumerate;
lastTest: TestCase ¬ invalidOps;
start, stop: BasicTime.Pulses;
args: LIST OF ROPE ¬ CommanderOps.ParseToList[cmd].list;
dbFileName ¬ defaultDbFileName;
WHILE args#NIL DO
SELECT TRUE FROM
Rope.Equal[args.first, "-s"] => { -- standard test case
run all test cases except for create and compact (which take too long)
firstTest ¬ enumerate;
lastTest ¬ invalidOps;
};
Rope.Equal[args.first, "-f"] => { -- full testcase
IO.PutRope[cmd.out, "Running ALL tests... \n\n"];
firstTest ¬ FIRST[TestCase];
lastTest ¬ LAST[TestCase];
};
Rope.Equal[args.first, "-r"] => { -- specified range of tests
ENABLE Convert.Error => GOTO Usage;
f, l: CARDINAL; -- ordinal value of desired tests
IF args.rest = NIL OR args.rest.rest = NIL THEN GOTO Usage;
f ¬ Convert.IntFromRope[args.rest.first];
l ¬ Convert.IntFromRope[args.rest.rest.first];
firstTest ¬ VAL[f];
lastTest ¬ VAL[l];
args ¬ args.rest.rest;
};
Rope.Equal[args.first, "-t"] => { -- specific test
ENABLE Convert.Error => GOTO Usage;
t: CARDINAL; -- ordinal value of desired test
IF args.rest = NIL THEN GOTO Usage;
t ¬ Convert.IntFromRope[args.rest.first];
firstTest ¬ lastTest ¬ VAL[t];
args ¬ args.rest;
};
Rope.Equal[args.first, "-d"] => { -- use named database
IF args.rest = NIL THEN GOTO Usage;
dbFileName ¬ args.rest.first;
args ¬ args.rest;
};
ENDCASE => {
GOTO Usage;
};
args ¬ args.rest;
ENDLOOP;
database ¬ LoganBerry.Open[dbName: dbFileName ! LoganBerry.Error => {
IF ec=$BadIndex THEN {needToBuildIndices ¬ TRUE; RETRY}
ELSE {IO.PutF[cmd.out, "Error from LoganBerry: %g - %g\n", IO.atom[ec], IO.rope[explanation]]; GOTO CantOpen}} ];
IF needToBuildIndices THEN {
IO.PutRope[cmd.out, "Building indices..."];
LoganBerry.BuildIndices[db: database];
IO.PutRope[cmd.out, " done\n"];
};
start ¬ BasicTime.GetClockPulses[];
FOR t: TestCase IN [firstTest..lastTest] DO
IF RunTest[t, cmd.out] THEN numErrors ¬ numErrors + 1;
ENDLOOP;
stop ¬ BasicTime.GetClockPulses[];
IO.PutF[cmd.out, "%g Errors; elapsed time = %g\n", IO.int[numErrors], IO.rope[ElapsedTime[start, stop]]];
LoganBerry.Close[db: database];
EXITS
CantOpen =>
IO.PutRope[cmd.out, "Test case not run.\n"];
Usage =>
IO.PutRope[cmd.out, "Usage: TestLoganBerry {-s} {-f} {-r first last} {-t testcase} {-d database}
Arguments:
-s => standard test case [1..13] (default)
-f => full test case [0..17]
-r => range of test cases [first..last]
-t => specific test case [testcase]
-d => use named database (default=LoganBerry-Source.df)
Valid testcases:
0 = $create => build a LoganBerry test database in random order
1 = $enumerate => enumerate the database to get the number of entries
2 = $generate => generate the complete database and see if the number is correct
3 = $deleteA => delete some entries
4 = $deleteB => verify that the deleted entries can not be read
5 = $rewriteA => rewrite the deleted entries
6 = $rewriteB => verify that the rewritten entries can be read
7 = $replace => replace some random entries (then restore to original values)
8 = $readRandom => read some random entries
9 = $checkData => check the consistency of the data
10 = $closeAndOpen => close and reopen the database
11 = $bidirectionalGenerate => generate a subrange of entries in both directions
12 = $binaryData => write and read strange values (then delete them)
13 = $invalidOps => try to raise errors
14 = $buildIndices => rebuild the database indices
15 = $compactA => compact the database
16 = $compactB => verify that the compacted database has the correct number of entries
17 = $generateSecondary => generate the complete database using secondary index
"];
};
Commander.Register[key: "TestLoganBerry", proc: TestLoganBerry,
doc: "Test the LoganBerry package." ];
END.
Doug Terry, February 27, 1986 10:43:30 am PST
changes to: DIRECTORY, LoganBerryTest, IMPORTS, ~, RunTest, Proc, Proc, Proc, TestLoganBerry, TestLoganQuery
Doug Terry, February 27, 1986 7:21:25 pm PST
changes to: DIRECTORY, LoganBerryTest, IMPORTS, ~, RunTest, ElapsedTime, Proc, Proc, TestLoganBerry, TestLoganQuery, END, RunTest, MarkKeysUnused, GenerateUnusedKey, GenerateUsedKey, TestCase, AddOne (local of RunTest)
Doug Terry, February 27, 1986 8:45:56 pm PST
changes to: TestCase, ~, RunTest, GetAttributeValue, Proc, DIRECTORY, IMPORTS, TestLoganQuery, ElapsedTime, MarkKeysUnused, TestLoganBerry
Doug Terry, February 27, 1986 9:35:37 pm PST
changes to: TestLoganBerry
Brian Oki, June 12, 1989 (PCedar version) 8:49:06 am PDT
changes for PCedar version: replaced FS with UFS, used streams instead of files.
changed create seletion in RunTest; added RETRY statement to LoganBerry.Open signal
Brian Oki, February 13, 1990 10:47:18 am PST (PCedar version)
changes for PCedar version: replaced UFS with PFS