NavTestImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann May 10, 1989 10:09:49 am PDT
DIRECTORY
BasicTime,
Camelot,
Commander,
CommandTool,
Convert,
File,
FS,
IO,
Mach,
PBasics,
Process,
Random,
Rope,
YggDID,
YggDIDPrivate,
YggDIDMap,
YggDIDMapPrivate,
YggdrasilInit,
YggLock,
YggFixedNames,
YggEnvironment,
YggFile,
YggFileStream,
YggIndexMaint,
YggInternal,
YggMonitoringLog,
YggNav,
YggRep,
YggTransaction,
YggVolatileObjectCache;
NavTestImpl: CEDAR PROGRAM
IMPORTS BasicTime, Commander, CommandTool, Convert, IO, Process, Random, Rope, YggDID, YggDIDMap, YggdrasilInit, YggNav, YggRep, YggVolatileObjectCache
EXPORTS YggDID, 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"];
linkTypes: ARRAY [0..8] OF ROPE ← [NIL, "refersTo", "author", "the name for link number three is quite long", "foo", "zorch", "grumble", "hype", "rtext"];
DID: PUBLIC TYPE ~ REF DIDRep;
DIDRep: PUBLIC TYPE ~ YggDIDPrivate.DIDRep;
Document: TYPE = REF DocumentRep;
DocumentRep: PUBLIC TYPE = YggDIDMapPrivate.DocumentRep;
Global data
RandomSequenceSize: INT = 20;
1) make a new object with int contents of 77
1a) bug: now it looks it up
2) add one attribute to it: "two" with two values: (NIL with a "foo", and field2 with a did of 1234 and a string of bar)
RandomSequence: ARRAY [0..RandomSequenceSize) OF INT ← [3, 1, 77, 16, 0, 2, 2, 1, 3, 0, 2, 6, 1234, 3, 1, 13, 0, 52, 4, 77];
KnownDIDs: LIST OF DIDStuff ← NIL;
linkStuff: TYPE = RECORD [
linkType: ROPE,
linkDID: YggDID.DID,
otherDID: YggDID.DID
];
NumberOfKnownDIDs: INT ← 0;
DIDStuff: TYPE = RECORD [
did: DID,
contents: YggRep.TypedPrimitiveElement,
attributes: LIST OF YggRep.Attribute ← NIL,
outlinks: LIST OF linkStuff,
inlinks: LIST OF linkStuff,
containers: LIST OF DID
];
VolatilizeTest Command
NavTestProc: Commander.CommandProc = {
[cmd: Handle] RETURNS [result: REFNIL, msg: ROPENIL]
CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...]
randomIndex: INT ← 0;
RandomChooseInt: PROC [rs: Random.RandomStream ← NIL, min: INT ← 0, max: INT] RETURNS [int: INT] ~ {
IF fixedRandom THEN {
v: INT;
v ← RandomSequence[randomIndex];
IF v >= min AND v <= max THEN int ← v
ELSE {
v ← v MOD (max-min);
v ← v + min;
};
IF v < min OR v > max THEN ERROR;
int ← v;
randomIndex ← (randomIndex + 1) MOD RandomSequenceSize;
}
ELSE RETURN[Random.ChooseInt[rs, min, max]];
};
MakeUpTPE: PROC RETURNS [tpe: YggRep.TypedPrimitiveElement] ~ {
tpe.docType ← RandomChooseInt[randomStream, 1, 8];
SELECT tpe.docType FROM
YggRep.int => {
tpe ← YggNav.ConstructIntTPE[RandomChooseInt[randomStream, 1, 1066]];
tpe.bits ← NEW[INT ← RandomChooseInt[randomStream, 1, 1066]];
};
YggRep.rope => {
tpe ← YggNav.ConstructRopeTPE[BigRope];
tpe.bits ← BigRope;
};
YggRep.shortRope => {
randr: INT = RandomChooseInt[randomStream, 0, 2];
tpe ← YggNav.ConstructShortRopeTPE[LittleRopes[randr]];
tpe.bits ← LittleRopes[randr];
};
YggRep.float => {
rr: REAL32;
ii: INT ;
ii ← RandomChooseInt[randomStream, 1, 1492];
rr ← ii;
tpe.bits ← NEW[REAL32 ← rr];
tpe ← YggNav.ConstructFloatTPE[rr];
};
YggRep.date => {
newData: YggRep.AccurateGMT;
newData ← NEW[YggRep.AccurateGMTRep ← [BasicTime.Now[], RandomChooseInt[randomStream, 1, 1789]]];
tpe.bits ← newData;
tpe ← YggNav.ConstructDateTPE[newData^];
};
YggRep.did => {
newDID: DID;
newDID ← NEW[YggDIDPrivate.DIDRep ← [412, RandomChooseInt[randomStream, 1, 1970]]];
tpe.bits ← newDID;
};
YggRep.uninterpretedBytes => {
noBytes: INT ← RandomChooseInt[randomStream, 1, 1920];
theBytes: REF YggRep.BitsRep;
theBytes ← NEW[YggRep.BitsRep[noBytes]];
theBytes.validBytes ← RandomChooseInt[randomStream, 1, noBytes];
FOR byteNo: CARD IN [0..theBytes.validBytes) DO
theBytes.b[byteNo] ← RandomChooseInt[randomStream, 1, 255];
ENDLOOP;
tpe.bits ← theBytes;
TRUSTED {tpe ← YggNav.ConstructUninterpretedBytesTPE[YggRep.uninterpretedBytes, LOOPHOLE[theBytes, LONG POINTER] + UNITS[YggRep.BitsRep[0]], noBytes];};
};
8 => {
noBytes: INT ← RandomChooseInt[randomStream, 1, 1920];
theBytes: REF YggRep.BitsRep;
tpe.docType ← RandomChooseInt[randomStream, YggRep.lastReservedDocType+1, YggRep.lastReservedDocType+1334];
theBytes ← NEW[YggRep.BitsRep[noBytes]];
theBytes.validBytes ← RandomChooseInt[randomStream, 1, noBytes];
FOR byteNo: CARD IN [0..theBytes.validBytes) DO
theBytes.b[byteNo] ← RandomChooseInt[randomStream, 1, 255];
ENDLOOP;
tpe.bits ← theBytes;
TRUSTED {tpe ← YggNav.ConstructUninterpretedBytesTPE[tpe.docType, LOOPHOLE[theBytes, LONG POINTER] + UNITS[YggRep.BitsRep[0]], noBytes];};
};
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;
contents: YggRep.TypedPrimitiveElement;
vDocAttCount: INT ← 0;
savedAttCount: INT ← 0;
success: BOOL;
parentDIDs: LIST OF YggDID.DID;
YggVolatileObjectCache.InvalidateDID[did: lokd.first.did, transID: YggEnvironment.nullTransID];
IF YggVolatileObjectCache.LookupDIDInCache[did: lokd.first.did, transID: YggEnvironment.nullTransID, mode: read] # NIL THEN ERROR;
YggDIDMap.FlushDocument[lokd.first.did, YggEnvironment.nullTransID];
trans ← YggNav.StartTransaction[YggEnvironment.nullTransID] ;
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];
IF lokd.first.contents.docType # YggNav.GetTypeOfContents[trans: YggEnvironment.nullTransID, did: lokd.first.did] THEN ERROR;
[dids: parentDIDs, success: success] ← YggNav.GetParents[trans: trans, did: lokd.first.did, dontWait: TRUE];
FOR lop: LIST OF DID ← parentDIDs, lop.rest UNTIL lop = NIL DO
FOR lodid: LIST OF DID ← lokd.first.containers, lodid.rest UNTIL lodid = NIL DO
IF YggDID.EqualDIDs[lodid.first, lop.first] THEN EXIT;
REPEAT FINISHED => ERROR;
ENDLOOP;
ENDLOOP;
FOR lodid: LIST OF DID ← lokd.first.containers, lodid.rest UNTIL lodid = NIL DO
IF lodid.first = NIL THEN {
roots: LIST OF YggDID.DID;
roots ← YggNav.GetRoots[];
FOR loroots: LIST OF DID ← roots, loroots.rest UNTIL loroots = NIL DO
IF YggDID.EqualDIDs[loroots.first, lokd.first.did] THEN EXIT;
REPEAT FINISHED => ERROR;
ENDLOOP;
};
ENDLOOP;
SELECT lokd.first.contents.docType FROM
YggRep.int, YggRep.rope, YggRep.shortRope, YggRep.float, YggRep.date, YggRep.did => {
contents ← YggNav.GetContents[ trans: YggEnvironment.nullTransID, did: lokd.first.did];
CompareTPE[contents, lokd.first.contents];
};
YggRep.uninterpretedBytes => {
bytesMoved: CARD ← 0;
firstByte: CARD ← 0;
lastByte: CARD ← 0;
uBytes: REF YggRep.BitsRep;
gBytes: REF YggRep.BitsRep;
uBytes ← NARROW[lokd.first.contents.bits];
gBytes ← NEW[YggRep.BitsRep[uBytes.validBytes]];
IF uBytes.validBytes > 3 THEN {
lastByte ← RandomChooseInt[randomStream, 1, MIN[16384, uBytes.validBytes - 1]];
firstByte ← RandomChooseInt[randomStream, 0, lastByte-1];
}
ELSE {firstByte ← 0; lastByte ← uBytes.validBytes - 1;};
TRUSTED {bytesMoved ← YggNav.GetUninterpretedContents[ trans: YggEnvironment.nullTransID, did: lokd.first.did, firstByte: firstByte, byteCount: lastByte-firstByte+1, to: LOOPHOLE[gBytes, LONG POINTER] + UNITS[YggRep.BitsRep[0]]]; };
IF bytesMoved # (lastByte-firstByte+1) THEN ERROR;
FOR index: CARD IN [0..bytesMoved) DO
IF gBytes[index] # uBytes[index+firstByte] THEN ERROR;
ENDLOOP;
};
ENDCASE;
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
IF aL.first.attributeName # NIL THEN {
IF Rope.Fetch[aL.first.attributeName, 0] = '$ THEN LOOP;
};
vDocAttCount ← vDocAttCount + 1;
ENDLOOP;
IF vDocAttCount # savedAttCount THEN ERROR;
{
contents: YggRep.TypedPrimitiveElement;
properties: LIST OF YggRep.Attribute;
savedAttCount ← 0;
contents ← YggNav.GetContents[trans: trans, did: lokd.first.did];
CompareTPE[contents, lokd.first.contents];
properties ← YggNav.GetAllProperties[trans: trans, did: lokd.first.did];
FOR aL: LIST OF YggRep.Attribute ← lokd.first.attributes, aL.rest UNTIL aL = NIL DO
FOR aLVDoc: LIST OF YggRep.Attribute ← properties, 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;
vDocAttCount ← 0;
FOR aL: LIST OF YggRep.Attribute ← properties, aL.rest UNTIL aL = NIL DO
IF aL.first.attributeName # NIL THEN {
IF Rope.Fetch[aL.first.attributeName, 0] = '$ THEN LOOP;
};
vDocAttCount ← vDocAttCount + 1;
ENDLOOP;
IF vDocAttCount # savedAttCount THEN ERROR;
};
{
linkList: LIST OF YggNav.LinkList;
linkList ← YggNav.GetAllInlinks[trans: trans, did: lokd.first.did];
FOR ll: LIST OF YggNav.LinkList ← linkList, ll.rest UNTIL ll = NIL DO
FOR didList: LIST OF YggDID.DID ← ll.first.dids, didList.rest UNTIL didList = NIL DO
FOR inl: LIST OF linkStuff ← lokd.first.inlinks, inl.rest UNTIL inl = NIL DO
IF Rope.Equal[ll.first.linkName, inl.first.linkType] AND YggDID.EqualDIDs[didList.first, inl.first.linkDID] THEN EXIT;
REPEAT FINISHED => ERROR;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR;
};
argv: CommandTool.ArgumentVector;
out: IO.STREAM;
randomStream: Random.RandomStream;
noisy: BOOLFALSE;
fixedRandom: 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;
DO
IF Rope.InlineFetch[argv[offset+1], 0] = '- THEN {
c: CHAR;
IF argv[offset+1].Length[] # 2 THEN GOTO failed;
c ← argv[offset+1].InlineFetch[1] ;
SELECT c FROM
'n => noisy ← TRUE;
'f => fixedRandom ← TRUE;
ENDCASE;
offset ← offset + 1;
}
ELSE EXIT;
ENDLOOP;
noTests ← Convert.IntFromRope[argv[1+offset] ! Convert.Error => GOTO failed];
KnownDIDs ← NIL;
NumberOfKnownDIDs ← 0;
IF noTests <= 0 THEN RETURN;
YggdrasilInit.InitializePart1[];
YggdrasilInit.InitializePart2["bogus", "pooz"];
randomStream ← Random.Create[range: 16384, seed: -1] ;
FOR loopCount: INT IN (0..noTests] DO
rand: INT ← RandomChooseInt[randomStream, 0, 40];
Process.CheckForAbort[];
IF noisy AND (loopCount MOD 100) = 0 THEN out.PutF["...(loopCount %g, number of DIDs %g at %g)...\n", IO.int[loopCount], IO.int[NumberOfKnownDIDs], IO.time[]];
IF loopCount = noTests THEN rand ← 0;
SELECT rand FROM
IN [0..1) => { -- volatalize and look up all old dids
lokd: LIST OF DIDStuff;
skipMax: INT ← 1;
skipCnt: INT ← 0;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
SELECT loopCount FROM
IN [250..500) => skipMax ← RandomChooseInt[randomStream, 1, 3];
IN [500..1000) => skipMax ← RandomChooseInt[randomStream, 1, 7];
IN [1000..2000) => skipMax ← RandomChooseInt[randomStream, 1, 15];
IN [2000..4000) => skipMax ← RandomChooseInt[randomStream, 1, 33];
IN [4000..8000) => skipMax ← RandomChooseInt[randomStream, 1, 67];
IN [8000..16000) => skipMax ← RandomChooseInt[randomStream, 1, 155];
ENDCASE;
IF loopCount = noTests THEN skipMax ← 1;
IF noisy THEN out.PutF["\nStart Look Up All Old Dids, loopCount= %g, skipMax= %g\n", IO.int[loopCount], IO.int[skipMax]];
FOR lokd ← KnownDIDs, lokd.rest UNTIL lokd = NIL DO
skipCnt ← skipCnt + 1;
IF skipCnt >= skipMax THEN skipCnt ← 0 ELSE LOOP;
CheckADID[lokd];
ENDLOOP;
IF noisy THEN out.PutF["Look Up All Old Dids Done\n\n"];
};
IN [1..13) => { -- make new doc with a contents
rand: INT;
lokd: LIST OF DIDStuff;
newDID: DID;
containerDID: DID ← NIL;
contents: YggRep.TypedPrimitiveElement;
trans: YggTransaction.TransID;
rand ← RandomChooseInt[randomStream, 0, MIN[16384, MAX[0, NumberOfKnownDIDs-2]]];
FOR lokd ← KnownDIDs, lokd.rest UNTIL lokd = NIL DO
rand ← rand - 1;
IF rand <= 0 THEN EXIT;
ENDLOOP;
IF lokd # NIL THEN containerDID ← lokd.first.did;
trans ← YggNav.StartTransaction[YggEnvironment.nullTransID] ;
newDID ← YggNav.CreateObject [trans: trans, containerDID: containerDID, makeRoot: IF lokd = NIL THEN TRUE ELSE FALSE] ;
contents ← MakeUpTPE[];
KnownDIDs ← CONS[[did: newDID, contents: contents, containers: LIST[containerDID]], KnownDIDs];
NumberOfKnownDIDs ← NumberOfKnownDIDs + 1;
YggNav.SetContents[trans: trans, did: newDID, contents: contents];
IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR;
IF noisy THEN out.PutF["Make new doc: did= %g contents type= %g\n", IO.card[newDID.didLow], IO.card[contents.docType] ];
};
IN [13..19) => { -- volatalize and look up old did
rand: INT;
lokd: LIST OF DIDStuff;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
rand ← RandomChooseInt[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 [19..28) => { -- 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];
IF NumberOfKnownDIDs <= 0 THEN LOOP;
rand ← RandomChooseInt[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 ← YggNav.StartTransaction[YggEnvironment.nullTransID] ;
FOR tryNo: INT IN [0..7] DO
propertyNames: LIST OF ROPE;
propExists: BOOL ← FALSE;
rand ← RandomChooseInt[randomStream, 0, 8];
attrName ← attrNameArray[rand];
propertyNames ← YggNav.ListAllProperties[trans: trans, did: lokd.first.did];
FOR lor: LIST OF ROPE ← propertyNames, lor.rest UNTIL lor = NIL DO
IF Rope.Equal[lor.first, attrName] THEN {
propExists ← TRUE;
EXIT;
};
ENDLOOP;
IF ~propExists THEN EXIT;
attrName ← NIL;
ENDLOOP;
IF attrName = NIL THEN {IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR; LOOP;};
noAttrVals ← RandomChooseInt[randomStream, 1, 5];
property.value ← NIL;
FOR attrValNo: INT IN [0..noAttrVals) DO
attrVal: YggRep.AttributeValue;
fni: INT;
fni ← RandomChooseInt[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;
YggNav.SetProperty[trans: trans, did: lokd.first.did, propertyName: attrName, property: property, appendProperty: TRUE];
lokd.first.attributes ← CONS[property, lokd.first.attributes];
IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR;
IF noisy THEN out.PutF["add attribute to old did: did= %g\n", IO.card[lokd.first.did.didLow]];
};
IN [28..32) => { -- change contents
rand: INT;
contents: YggRep.TypedPrimitiveElement;
trans: YggTransaction.TransID;
lokd: LIST OF DIDStuff;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
rand ← RandomChooseInt[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 ← YggNav.StartTransaction[YggEnvironment.nullTransID] ;
SELECT lokd.first.contents.docType FROM
YggRep.uninterpretedBytes => {
newSize: CARD ← 0;
bytesMoved: CARD ← 0;
firstByte: CARD ← 0;
lastByte: CARD ← 0;
uBytes: REF YggRep.BitsRep;
gBytes: REF YggRep.BitsRep;
uBytes ← NARROW[lokd.first.contents.bits];
newSize ← RandomChooseInt[randomStream, 8+uBytes.validBytes/2, 8+3*uBytes.validBytes/2];
gBytes ← NEW[YggRep.BitsRep[newSize]];
gBytes.validBytes ← newSize;
FOR byteNo: CARD IN [0..MIN[uBytes.validBytes, gBytes.validBytes]) DO
gBytes.b[byteNo] ← uBytes.b[byteNo];
ENDLOOP;
FOR byteNo: CARD IN [MIN[uBytes.validBytes, gBytes.validBytes]..newSize) DO
gBytes.b[byteNo] ← RandomChooseInt[randomStream, 1, 255];
ENDLOOP;
IF newSize <= uBytes.validBytes THEN YggNav.SetSize[trans: trans, did: lokd.first.did, size: newSize]
ELSE {
bytesMoved: CARD ← 0;
roundDownFirstByte: CARD ← 0;
roundDownFirstByte ← (uBytes.validBytes/2) * 2;
TRUSTED {bytesMoved ← YggNav.SetUninterpretedContents[trans: trans, did: lokd.first.did, setDocType: FALSE, docType: YggRep.noValue, firstByte: roundDownFirstByte, byteCount: newSize-roundDownFirstByte, from: LOOPHOLE[gBytes, LONG POINTER] + UNITS[YggRep.BitsRep[roundDownFirstByte]]]; };
IF bytesMoved # (newSize - roundDownFirstByte) THEN ERROR;
};
lokd.first.contents.bits ← gBytes;
};
ENDCASE => {
contents ← MakeUpTPE[];
lokd.first.contents ← contents;
YggNav.SetContents[trans: trans, did: lokd.first.did, contents: contents];
};
IF lokd.first.contents.docType # YggNav.GetTypeOfContents[trans: trans, did: lokd.first.did] THEN ERROR;
IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR;
IF noisy THEN out.PutF["change contents of old did: did= %g, contents type= %g\n", IO.card[lokd.first.did.didLow], IO.card[lokd.first.contents.docType]];
};
IN [32..40) => { -- add a link
inrand: INT;
outrand: INT;
ctr: INT ← 300;
trans: YggTransaction.TransID;
inlokd: LIST OF DIDStuff;
outlokd: LIST OF DIDStuff;
linkType: ROPE;
linkDID: YggDID.DID;
IF NumberOfKnownDIDs <= 0 THEN LOOP;
inrand ← RandomChooseInt[randomStream, 0, MIN[16384, NumberOfKnownDIDs]];
outrand ← inrand;
WHILE outrand = inrand AND ctr > 0 DO
outrand ← RandomChooseInt[randomStream, 0, MIN[16384, NumberOfKnownDIDs]];
ctr ← ctr - 1;
ENDLOOP;
IF ctr <= 0 THEN LOOP;
FOR inlokd ← KnownDIDs, inlokd.rest UNTIL inlokd = NIL DO
inrand ← inrand - 1;
IF inrand <= 0 THEN EXIT;
ENDLOOP;
IF inlokd = NIL THEN LOOP;
FOR outlokd ← KnownDIDs, outlokd.rest UNTIL outlokd = NIL DO
outrand ← outrand - 1;
IF outrand <= 0 THEN EXIT;
ENDLOOP;
IF outlokd = NIL THEN LOOP;
IF YggDID.EqualDIDs[outlokd.first.did, inlokd.first.did] THEN LOOP;
linkType ← linkTypes[RandomChooseInt[randomStream, 0, 8]];
trans ← YggNav.StartTransaction[YggEnvironment.nullTransID] ;
linkDID ← YggNav.SnapLink[trans: trans, fromDID: outlokd.first.did, toDID: inlokd.first.did, linkType: linkType];
IF ~YggNav.EndTransaction[trans, TRUE] THEN ERROR;
outlokd.first.outlinks ← CONS[[linkType, linkDID, inlokd.first.did], outlokd.first.outlinks];
inlokd.first.inlinks ← CONS[[linkType, linkDID, outlokd.first.did], inlokd.first.inlinks];
IF noisy THEN out.PutF["add link from %g to %d, type= %g\n", IO.card[outlokd.first.did.didLow], IO.card[inlokd.first.did.didLow], IO.rope[linkType]];
};
ENDCASE;
ENDLOOP;
EXITS
failed => {result ← $Failure};
};
Initialization
Init: PROC = {
Commander.Register["NavTest", NavTestProc, "NavTest noTests"];
};
Init[];
END.