NavTestImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann October 31, 1988 10:30:31 pm PST
DIRECTORY
BasicTime,
Camelot,
Commander,
CommandTool,
Convert,
File,
FS,
IO,
Mach,
PBasics,
Process,
Random,
Rope,
YggDID,
YggDIDPrivate,
YggDIDMap,
YggDIDMapPrivate,
YggLock,
YggFixedNames,
YggEnvironment,
YggFile,
YggFileStream,
YggIndexMaint,
YggInternal,
YggMonitoringLog,
YggRep,
YggTransaction,
YggVolatileObjectCache;
NavTestImpl: CEDAR PROGRAM
IMPORTS BasicTime, Commander, CommandTool, Convert, IO, Process, Random, Rope, YggDID, YggRep, YggVolatileObjectCache
EXPORTS YggDID, YggTransaction, YggInternal
= BEGIN
ROPE: TYPE = Rope.ROPE;
Exported junk
BigRope: ROPE ← "Four score and seven years ago, our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great blah blah blah";
LittleRopes: ARRAY [0..3) OF ROPE ← ["foo", "bar", "bleah"];
attrNameArray: ARRAY [0..8] OF ROPE ← ["attr0", "thisisattribute1", "two", "attribute three is fairly long", "but then again, attribute four is longer than three", "and attribute five is longer than three and four together", "6", "sept", "eight"];
fieldNameArray: ARRAY [1..5] OF ROPE ← [NIL, "field2", "field3", "the name for field 4 is quite long", "field5"];
DID: PUBLIC TYPE ~ REF DIDRep;
DIDRep: PUBLIC TYPE ~ YggDIDPrivate.DIDRep;
Document: TYPE = REF DocumentRep;
DocumentRep: PUBLIC TYPE = YggDIDMapPrivate.DocumentRep;
Global data
NextDID: DIDRep ← [33, 400];
KnownDIDs: LIST OF DIDStuff ← NIL;
NumberOfKnownDIDs: INT ← 0;
DIDStuff: TYPE = RECORD [
did: DID,
doc: Document,
contents: YggRep.TypedPrimitiveElement,
attributes: LIST OF YggRep.Attribute ← NIL
];
NextTransCount: CARD ← 10001;
Local procs
GetNextTrans: PROC RETURNS [transID: YggTransaction.TransID] ~ {
NextTransCount ← NextTransCount + 1;
transID ← [top: [lowTicker: NextTransCount], bottom: []];
};
GetNextDID: PROC RETURNS [did: YggDID.DID] ~ {
did ← NEW[YggDIDPrivate.DIDRep ← [NextDID.didHigh, NextDID.didLow]];
NextDID.didLow ← NextDID.didLow + 1;
};
GetNextDIDWithEmptyDoc: PROC RETURNS [did: YggDID.DID, doc: Document, didStuff: LIST OF DIDStuff] ~ {
did ← GetNextDID[];
doc ← NEW[DocumentRep ← [did: did, name: NIL, componentFiles: NIL]];
didStuff ← KnownDIDs ← CONS[[did: did, doc: doc], KnownDIDs];
NumberOfKnownDIDs ← NumberOfKnownDIDs + 1;
};
DoCommit: PROC [transID: YggTransaction.TransID] ~ {
ERROR;
};
VolatilizeTest Command
NavTestProc: Commander.CommandProc = {
[cmd: Handle] RETURNS [result: REFNIL, msg: ROPENIL]
CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...]
MakeUpTPE: PROC RETURNS [tpe: YggRep.TypedPrimitiveElement] ~ {
tpe.docType ← Random.ChooseInt[randomStream, 1, 8];
SELECT tpe.docType FROM
YggRep.int => {
tpe.bits ← NEW[INT ← Random.ChooseInt[randomStream, 1, 1066]];
};
YggRep.rope => {
tpe.bits ← BigRope;
};
YggRep.shortRope => {
randr: INT = Random.ChooseInt[randomStream, 0, 2];
tpe.bits ← LittleRopes[randr];
};
YggRep.float => {
rr: REAL32;
ii: INT ;
ii ← Random.ChooseInt[randomStream, 1, 1492];
rr ← ii;
tpe.bits ← NEW[REAL32 ← rr];
};
YggRep.date => {
newData: YggRep.AccurateGMT;
newData ← NEW[YggRep.AccurateGMTRep ← [BasicTime.Now[], Random.ChooseInt[randomStream, 1, 1789]]];
tpe.bits ← newData;
};
YggRep.did => {
newDID: DID;
newDID ← GetNextDID[];
tpe.bits ← newDID;
};
YggRep.uninterpretedBytes => {
noBytes: INT ← Random.ChooseInt[randomStream, 1, 1920];
theBytes: REF YggRep.BitsRep;
theBytes ← NEW[YggRep.BitsRep[noBytes]];
theBytes.validBytes ← Random.ChooseInt[randomStream, 1, noBytes];
FOR byteNo: CARD IN [0..theBytes.validBytes) DO
theBytes.b[byteNo] ← Random.ChooseInt[randomStream, 1, 255];
ENDLOOP;
tpe.bits ← theBytes;
};
8 => {
noBytes: INT ← Random.ChooseInt[randomStream, 1, 1920];
theBytes: REF YggRep.BitsRep;
tpe.docType ← Random.ChooseInt[randomStream, YggRep.lastReservedDocType+1, YggRep.lastReservedDocType+1334];
theBytes ← NEW[YggRep.BitsRep[noBytes]];
theBytes.validBytes ← Random.ChooseInt[randomStream, 1, noBytes];
FOR byteNo: CARD IN [0..theBytes.validBytes) DO
theBytes.b[byteNo] ← Random.ChooseInt[randomStream, 1, 255];
ENDLOOP;
tpe.bits ← theBytes;
};
ENDCASE => ERROR;
};
CompareTPE: PROC [tpe1: YggRep.TypedPrimitiveElement, tpe2: YggRep.TypedPrimitiveElement] ~ {
IF tpe1.docType # tpe2.docType THEN ERROR;
SELECT tpe1.docType FROM
YggRep.int => {
vInt: REF INT;
mInt: REF INT;
vInt ← NARROW[tpe1.bits];
mInt ← NARROW[tpe2.bits];
IF vInt^ # mInt^ THEN ERROR;
};
YggRep.rope => {
biggaRope: ROPE;
biggaRope ← NARROW[tpe1.bits];
IF ~Rope.Equal[biggaRope, BigRope] THEN ERROR;
};
YggRep.shortRope => {
smallaRope: ROPE;
listRope: ROPE;
smallaRope ← NARROW[tpe1.bits];
listRope ← NARROW[tpe2.bits];
IF ~Rope.Equal[smallaRope, listRope] THEN ERROR;
};
YggRep.float => {
vReal: REF REAL32;
mReal: REF REAL32;
vReal ← NARROW[tpe1.bits];
mReal ← NARROW[tpe2.bits];
IF vReal^ # mReal^ THEN ERROR;
};
YggRep.date => {
vDate: YggRep.AccurateGMT;
mDate: YggRep.AccurateGMT;
vDate ← NARROW[tpe1.bits];
mDate ← NARROW[tpe2.bits];
IF BasicTime.Period[vDate.gmt, mDate.gmt] # 0 THEN ERROR;
IF vDate.usecs # mDate.usecs THEN ERROR;
};
YggRep.did => {
vDID: DID;
mDID: DID;
vDID ← NARROW[tpe1.bits];
mDID ← NARROW[tpe2.bits];
IF ~YggDID.EqualDIDs[vDID, mDID] THEN ERROR;
};
YggRep.uninterpretedBytes => {
vUnintBytes: REF YggRep.BitsRep;
mUnintBytes: REF YggRep.BitsRep;
vUnintBytes ← NARROW[tpe1.bits];
mUnintBytes ← NARROW[tpe2.bits];
IF vUnintBytes.validBytes # mUnintBytes.validBytes THEN ERROR;
FOR byteNo: CARD IN [0..vUnintBytes.validBytes) DO
IF vUnintBytes.b[byteNo] # mUnintBytes.b[byteNo] THEN ERROR;
ENDLOOP;
};
IN [YggRep.lastReservedDocType+1 .. YggRep.lastReservedDocType+1334] => {
vUnintBytes: REF YggRep.BitsRep;
mUnintBytes: REF YggRep.BitsRep;
vUnintBytes ← NARROW[tpe1.bits];
mUnintBytes ← NARROW[tpe2.bits];
IF vUnintBytes.validBytes # mUnintBytes.validBytes THEN ERROR;
FOR byteNo: CARD IN [0..vUnintBytes.validBytes) DO
IF vUnintBytes.b[byteNo] # mUnintBytes.b[byteNo] THEN ERROR;
ENDLOOP;
};
ENDCASE => ERROR;
};
CheckADID: PROC [lokd: LIST OF DIDStuff] ~ {
vDoc: YggRep.VDoc ← NIL;
trans: YggTransaction.TransID;
vDocAttCount: INT ← 0;
savedAttCount: INT ← 0;
YggVolatileObjectCache.InvalidateDID[did: lokd.first.did, transID: YggEnvironment.nullTransID];
IF YggVolatileObjectCache.LookupDIDInCache[did: lokd.first.did, transID: YggEnvironment.nullTransID, mode: read] # NIL THEN ERROR;
trans ← GetNextTrans[] ;
vDoc ← YggRep.VolatizeFromDID[transID: trans, did: lokd.first.did,
access: readOnly, lock: [read, wait], metaAttributesOnly: FALSE];
IF ~YggDID.EqualDIDs[vDoc.did, lokd.first.did] THEN ERROR;
CompareTPE[vDoc.contents, lokd.first.contents];
FOR aL: LIST OF YggRep.Attribute ← lokd.first.attributes, aL.rest UNTIL aL = NIL DO
FOR aLVDoc: LIST OF YggRep.Attribute ← vDoc.attributes, aLVDoc.rest UNTIL aLVDoc = NIL DO
IF Rope.Equal[aL.first.attributeName, aLVDoc.first.attributeName] THEN {
savedValue: LIST OF YggRep.AttributeValue ← aL.first.value;
vDocValue: LIST OF YggRep.AttributeValue ← aLVDoc.first.value;
FOR loav: LIST OF YggRep.AttributeValue ← vDocValue, loav.rest UNTIL loav = NIL DO
savedValueSet: LIST OF YggRep.TypedPrimitiveElement;
IF savedValue = NIL THEN ERROR;
savedValueSet ← savedValue.first.valueSet;
IF ~Rope.Equal[savedValue.first.fieldName, loav.first.fieldName] THEN ERROR;
FOR vtpeList: LIST OF YggRep.TypedPrimitiveElement ← loav.first.valueSet, vtpeList.rest UNTIL vtpeList = NIL DO
IF savedValueSet = NIL THEN ERROR;
CompareTPE[vtpeList.first, savedValueSet.first];
savedValueSet ← savedValueSet.rest;
ENDLOOP;
IF savedValueSet # NIL THEN ERROR;
savedValue ← savedValue.rest;
ENDLOOP;
IF savedValue # NIL THEN ERROR;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
savedAttCount ← savedAttCount + 1;
ENDLOOP;
FOR aL: LIST OF YggRep.Attribute ← vDoc.attributes, aL.rest UNTIL aL = NIL DO
vDocAttCount ← vDocAttCount + 1;
ENDLOOP;
IF vDocAttCount # savedAttCount THEN ERROR;
DoCommit[trans];
};
argv: CommandTool.ArgumentVector;
out: IO.STREAM;
randomStream: Random.RandomStream;
noisy: BOOLFALSE;
offset: INT ← 0;
noTests: INT;
out ← cmd.out;
argv ← CommandTool.Parse[cmd: cmd ! CommandTool.Failed => {msg ← errorMsg; GO TO failed}];
IF argv.argc < 2 THEN GOTO failed;
IF Rope.InlineFetch[argv[1], 0] = '- THEN {
c: CHAR;
IF argv[1].Length[] # 2 THEN GOTO failed;
c ← argv[1].InlineFetch[1] ;
SELECT c FROM
'n => noisy ← TRUE;
ENDCASE;
offset ← 1;
};
noTests ← Convert.IntFromRope[argv[1+offset] ! Convert.Error => GOTO failed];
KnownDIDs ← NIL;
NumberOfKnownDIDs ← 0;
NextDID.didHigh ← LOOPHOLE[BasicTime.Now[], PBasics.LongNumber].lo;
[] ← GetNextDID[];
IF noTests <= 0 THEN RETURN;
randomStream ← Random.Create[range: 16384, seed: -1] ;
FOR loopCount: INT IN (0..noTests] DO
rand: INT ← Random.ChooseInt[randomStream, 0, 24];
Process.CheckForAbort[];
IF loopCount = noTests THEN rand ← 0;
SELECT rand FROM
IN [0..3) => { -- volatalize and look up old did
lokd: LIST OF DIDStuff;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
FOR lokd ← KnownDIDs, lokd.rest UNTIL lokd = NIL DO
CheckADID[lokd];
ENDLOOP;
IF noisy THEN out.PutF["\nLook Up All Old Dids\n\n"];
};
IN [3..13) => { -- make new doc with a contents
newDID: DID;
doc: Document;
didStuff: LIST OF DIDStuff;
contents: YggRep.TypedPrimitiveElement;
vDoc: YggRep.VDoc;
trans: YggTransaction.TransID;
trans ← GetNextTrans[] ;
[newDID, doc, didStuff] ← GetNextDIDWithEmptyDoc[];
vDoc ← YggRep.VolatizeFromDID[trans, newDID, readWrite, [write, wait]];
contents ← MakeUpTPE[];
didStuff.first.contents ← contents;
vDoc.contents ← contents;
vDoc.contentsChanged ← TRUE;
DoCommit[trans];
IF noisy THEN out.PutF["Make new doc: did= %g\n", IO.card[newDID.didLow] ];
};
IN [8..16) => { -- volatalize and look up old did
rand: INT;
lokd: LIST OF DIDStuff;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
rand ← Random.ChooseInt[randomStream, 0, MIN[16384, NumberOfKnownDIDs]];
FOR lokd ← KnownDIDs, lokd.rest UNTIL lokd = NIL DO
rand ← rand - 1;
IF rand <= 0 THEN EXIT;
ENDLOOP;
IF lokd = NIL THEN LOOP;
CheckADID[lokd];
IF noisy THEN out.PutF["look up old did: did= %g\n", IO.card[lokd.first.did.didLow] ];
};
IN [16..24) => { -- add attribute to did
rand: INT;
trans: YggTransaction.TransID;
lokd: LIST OF DIDStuff;
attrName: ROPE;
noAttrVals: INT ;
property: YggRep.Attribute;
fieldTaken: ARRAY [1..5] OF BOOL ← ALL[FALSE];
vDoc: YggRep.VDoc ← NIL;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
rand ← Random.ChooseInt[randomStream, 0, MIN[16384, NumberOfKnownDIDs]];
FOR lokd ← KnownDIDs, lokd.rest UNTIL lokd = NIL DO
rand ← rand - 1;
IF rand <= 0 THEN EXIT;
ENDLOOP;
IF lokd = NIL THEN LOOP;
trans ← GetNextTrans[] ;
vDoc ← YggRep.VolatizeFromDID[transID: trans, did: lokd.first.did,
access: readWrite, lock: [write, wait], metaAttributesOnly: FALSE];
IF ~YggDID.EqualDIDs[vDoc.did, lokd.first.did] THEN ERROR;
IF vDoc.contents.docType # lokd.first.contents.docType THEN ERROR;
FOR tryNo: INT IN [0..7] DO
propExists: BOOL ← FALSE;
rand ← Random.ChooseInt[randomStream, 0, 8];
attrName ← attrNameArray[rand];
FOR aL: LIST OF YggRep.Attribute ← vDoc.attributes, aL.rest UNTIL aL = NIL DO
IF Rope.Equal[aL.first.attributeName, attrName] THEN {
propExists ← TRUE;
EXIT;
};
ENDLOOP;
IF ~propExists THEN EXIT;
attrName ← NIL;
ENDLOOP;
IF attrName = NIL THEN {DoCommit[trans]; LOOP;};
noAttrVals ← Random.ChooseInt[randomStream, 1, 5];
property.value ← NIL;
FOR attrValNo: INT IN [0..noAttrVals) DO
attrVal: YggRep.AttributeValue;
fni: INT;
fni ← noAttrVals ← Random.ChooseInt[randomStream, 1, 5];
IF fieldTaken[fni] THEN LOOP;
fieldTaken[fni] ← TRUE;
attrVal.fieldName ← fieldNameArray[fni];
attrVal.valueSet ← NIL;
FOR tpeNo: INT IN [1..fni] DO
attrVal.valueSet ← CONS[MakeUpTPE[], attrVal.valueSet];
ENDLOOP;
property.value ← CONS[attrVal, property.value];
ENDLOOP;
property.attributeName ← attrName;
vDoc.attributes ← CONS[property, vDoc.attributes];
lokd.first.attributes ← CONS[property, lokd.first.attributes];
vDoc.namesOfAttributesChanged ← LIST[attrName];
DoCommit[trans];
IF noisy THEN out.PutF["add attribute to old did: did= %g\n", IO.card[lokd.first.did.didLow]];
};
ENDCASE;
ENDLOOP;
EXITS
failed => {result ← $Failure};
};
Initialization
Init: PROC = {
Commander.Register["NavTest", NavTestProc, "NavTest noTests"];
};
Init[];
END.