-- File [Ivy]<Nelson>Lupine>LupineMarshalTestDriver.mesa.
-- Last edited by BZM on 12-May-82 19:58:06.
DIRECTORY
Environment USING [wordsPerPage],
Heap USING [systemZone],
LupineExerciser USING [
Counter, BadExercise, Delay,
Exercise, ExerciseProc, Handle, PerformExercises,
Start, Stamp, Stop,
StartPrecisionTiming, StopPrecisionTiming, String ],
LupineMarshalTest --USING [ALL]--,
Process USING [Detach],
Rope USING [Flatten, Length, Text];
LupineMarshalTestDriver: PROGRAM
IMPORTS Heap, LupineExerciser, Test: LupineMarshalTest, Process, Rope
SHARES Rope
= BEGIN OPEN LupineExerciser;
PerformMarshalExercises: PROC =
BEGIN
-- PerformMarshalExercises must be forked so that all of the local constants
-- remain valid in the process required by LupineExerciser.PerformExercises.
Exercises: ARRAY [0..23) OF Exercise ← [
[routine: TimingOverhead, name: "timing overhead"L],
[routine: NullProcedure, name: "the null procedure"L],
[routine: BitsToSequence, name: "packed descriptor to packed sequence"L],
[routine: OneInteger, name: "1 integer procedure"L],
[routine: FourIntegers, name: "4 integer procedure"L],
[routine: TenIntegers, name: "10 integer procedure"L],
[routine: TenArray, name: "10 integer array procedure"L],
[routine: FortyArray, name: "40 integer array procedure"L],
[routine: HundredArray, name: "100 integer array procedure"L],
[routine: SignalReturn, name: "signal test (no signalling)"L],
[routine: SignalResume, name: "signal test (SIGNAL & RESUME)"L],
[routine: SignalUnwind, name: "signal test (ERROR & UNWIND)"L],
[routine: SimpleArithmetic, name: "perform simple VAR arithmetic"L],
[routine: FillArray, name: "fill a call-by-result array"L],
[routine: Read1PageFastFrame, name: "transfer 1 page (fast frame)"L],
[routine: Read1PageSlowFrame, name: "transfer 1 page (slow frame)"L],
[routine: Read2Pages, name: "transfer 2 pages"L],
[routine: Read4Pages, name: "transfer 4 pages"L],
[routine: Read8Pages, name: "transfer 8 pages"L],
[routine: CreateList, name: "create a list of integers"L],
[routine: StringCopy, name: "copy a string to a VAR string"L],
[routine: CharToVariantString, name: "variant record of string types"L],
[routine: StringsToAtoms, name: "descriptor of strings to list of atoms"L]
];
-- Cause remote binding now, so the transient won't affect timings.
Test.Null[]; Test.Null[]; Test.Null[];
PerformExercises[
nameOfExercisedInterface: "MarshalTest"L,
exercises: DESCRIPTOR[Exercises] ];
END;
-- For periodically causing glitches (eg, NIL) that Lupine claims to handle.
Periodically: PROC [test: Counter] RETURNS [--yes:-- BOOLEAN] =
INLINE {RETURN[ (test MOD 31) = 0 ]};
TimingOverhead: ExerciseProc =
BEGIN
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
--exerciser.Delay;
exerciser.StartPrecisionTiming;
NULL;
exerciser.StopPrecisionTiming;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
NullProcedure: ExerciseProc =
BEGIN
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
Test.Null[];
exerciser.StopPrecisionTiming;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
OneInteger: ExerciseProc =
BEGIN
a: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
a ← Test.One[test];
exerciser.StopPrecisionTiming;
IF checkResults AND a#test THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
FourIntegers: ExerciseProc =
BEGIN
a,b,c,d: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
[a,b,c,d] ← Test.Four[test+0,test+1,test+2,test+3];
exerciser.StopPrecisionTiming;
IF checkResults AND (a#test+0 OR b#test+1 OR c#test+2 OR d#test+3)
THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
TenIntegers: ExerciseProc =
BEGIN
a,b,c,d,e,f,g,h,i,j: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
[a,b,c,d,e,f,g,h,i,j] ← Test.Ten[
test+0,test+1,test+2,test+3,test+4,
test+5,test+6,test+7,test+8,test+9 ];
exerciser.StopPrecisionTiming;
IF checkResults AND
(a#test+0 OR b#test+1 OR c#test+2 OR d#test+3 OR e#test+4
OR f#test+5 OR g#test+6 OR h#test+7 OR i#test+8 OR j#test+9)
THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
TenArray: ExerciseProc =
BEGIN
array10: Test.Array10;
ten: Test.Array10 = ALL[10];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
array10 ← Test.TenArray[ten];
exerciser.StopPrecisionTiming;
IF checkResults AND ten#array10 THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
FortyArray: ExerciseProc =
BEGIN
array40: Test.Array40;
forty: Test.Array40 = ALL [40];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
array40 ← Test.FortyArray[forty];
exerciser.StopPrecisionTiming;
IF checkResults AND forty#array40 THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
HundredArray: ExerciseProc =
BEGIN
array100: Test.Array100;
hundred: Test.Array100 = ALL[100];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
array100 ← Test.HundredArray[hundred];
exerciser.StopPrecisionTiming;
IF checkResults AND hundred#array100 THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
SignalReturn: ExerciseProc =
BEGIN
out: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
out ← Test.SignalTest[ in: test, action: neither
! Test.Signal => {BadExercise; CONTINUE} ];
exerciser.StopPrecisionTiming;
IF checkResults AND out#test THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
SignalResume: ExerciseProc =
BEGIN
out: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
out ← Test.SignalTest[ in: test, action: signal
! Test.Signal => {
IF checkResults AND in#test THEN BadExercise;
RESUME[out: 2*in] } ];
exerciser.StopPrecisionTiming;
IF checkResults AND out#2*test THEN BadExercise;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
SignalUnwind: ExerciseProc =
BEGIN
out: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: Counter IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
out ← Test.SignalTest[ in: test, action: error
! Test.Signal => {
IF checkResults AND in#test THEN BadExercise;
CONTINUE } ];
exerciser.StopPrecisionTiming;
--Checking is never valid after an ERROR since out is undefined.
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
SimpleArithmetic: ExerciseProc =
BEGIN
sketchPad: Test.VARArithmetic;
sketchPadRecord: Test.ArithmeticRecord;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
sketchPadRecord.in ← test;
sketchPad ← IF Periodically[test] THEN NIL ELSE @sketchPadRecord;
exerciser.Delay;
exerciser.StartPrecisionTiming;
Test.SimpleArithmetic[pad: sketchPad];
exerciser.StopPrecisionTiming;
IF checkResults AND ~Periodically[test] THEN BEGIN
IF sketchPad↑ # Test.ArithmeticRecord[test, test+1, test*2]
THEN BadExercise;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
FillArray: ExerciseProc =
BEGIN
MaxVectorLength: INTEGER = 4*252; -- 252 is onePkt maximum.
vector: Test.RESULTArray;
vectorBody: ARRAY [0..MaxVectorLength) OF INTEGER;
vectorLength: INTEGER;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
vectorLength ← test MOD (MaxVectorLength+1);
vector ← IF Periodically[test]
THEN NIL ELSE DESCRIPTOR[BASE[vectorBody], vectorLength];
exerciser.Delay;
exerciser.StartPrecisionTiming;
Test.FillArray[in: test, out: vector];
exerciser.StopPrecisionTiming;
IF checkResults AND ~Periodically[test] THEN BEGIN
IF vectorLength # LENGTH[vector] THEN BadExercise;
FOR i: INTEGER IN [0..vectorLength) DO
IF vector[i] # test-i THEN BadExercise; ENDLOOP;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
Read1PageFastFrame: ExerciseProc =
{ReadPages[1, exerciser, name, trials, testsPerTrial, checkResults]};
Read1PageSlowFrame: ExerciseProc =
BEGIN
GrabFrames: PROC [grab: INTEGER] =
BEGIN
grabSpace: ARRAY [0..350) OF WORD;
IF grab > 0
THEN {grabSpace ← ALL[NULL]; GrabFrames[grab-1]}
ELSE ReadPages[
1, exerciser, name, trials, testsPerTrial, checkResults];
END;
GrabFrames[3];
END;
Read2Pages: ExerciseProc =
{ReadPages[2, exerciser, name, trials, testsPerTrial, checkResults]};
Read4Pages: ExerciseProc =
{ReadPages[4, exerciser, name, trials, testsPerTrial, checkResults]};
Read8Pages: ExerciseProc =
{ReadPages[8, exerciser, name, trials, testsPerTrial, checkResults]};
ReadPages: --Pages plus ExerciseProc-- PROCEDURE [
pages: Counter,
exerciser: Handle,
name: String,
trials: Counter,
testsPerTrial: Counter,
checkResults: BOOLEAN ] =
BEGIN
Buffer: TYPE = RECORD[SEQUENCE words: CARDINAL OF Test.Item];
bufferPtr: LONG POINTER TO Buffer ←
Heap.systemZone.NEW[Buffer[pages*Environment.wordsPerPage]];
buffer: Test.RESULTPages = DESCRIPTOR[bufferPtr↑];
BEGIN ENABLE UNWIND => Heap.systemZone.FREE[@bufferPtr];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
exerciser.Delay;
exerciser.StartPrecisionTiming;
Test.ReadPages[item: test, buffer: buffer];
exerciser.StopPrecisionTiming;
IF checkResults THEN BEGIN
IF bufferPtr.words # LENGTH[buffer] THEN BadExercise;
FOR i: CARDINAL IN [0..LENGTH[buffer]) DO
IF buffer[i] # test THEN BadExercise; ENDLOOP;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END; -- ENABLE UNWIND.
Heap.systemZone.FREE[@bufferPtr];
END;
CreateList: ExerciseProc =
BEGIN
MaxListLength: INTEGER = 2*127; -- 127 is onePkt maximum.
listLength: INTEGER;
outList: Test.IntList;
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
listLength ← test MOD (MaxListLength+1);
exerciser.Delay;
exerciser.StartPrecisionTiming;
outList ← Test.CreateList[in: test, length: listLength];
exerciser.StopPrecisionTiming;
IF checkResults THEN BEGIN
outLength: INTEGER ← 0;
FOR int: Test.IntList ← outList, int.rest UNTIL int = NIL DO
IF int.first # test-outLength THEN BadExercise;
outLength ← outLength + 1;
ENDLOOP;
IF outLength # listLength THEN BadExercise;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
StringCopy: ExerciseProc =
BEGIN
MaxStringLength: CARDINAL = 4*Test.MaxReadonlyStringLength;
-- MaxStringLength+1 (twoPkt threshold) tested 19-Feb-82 11:06:28.
string: LONG STRING;
inString: STRING = [MaxStringLength];
outString: STRING = [MaxStringLength];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
inChar: CHARACTER = LOOPHOLE[test MOD 128];
outChar: CHARACTER = LOOPHOLE[(test+11) MOD 128];
outString.length ← MaxStringLength;
inString.length ← test MOD (MaxStringLength+1);
FOR i: CARDINAL IN [0..MaxStringLength) DO
inString[i] ← inChar; outString[i] ← outChar;
ENDLOOP;
string ← IF Periodically[test] THEN NIL ELSE inString;
exerciser.Delay;
exerciser.StartPrecisionTiming;
Test.StringCopy[in: string, out: outString];
exerciser.StopPrecisionTiming;
IF checkResults THEN BEGIN
IF Periodically[test] THEN inString.length ← 0;
FOR i: CARDINAL IN [0..MaxStringLength) DO
IF outString[i] # (IF i < inString.length THEN inChar ELSE outChar)
THEN BadExercise;
ENDLOOP;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
CharToVariantString: ExerciseProc =
BEGIN
MaxStringLength: CARDINAL = 2*492;
-- 492 is the onePkt TEXT maximum; 493 was checked 19-Feb-82 10:40:08.
string: Test.StringSelection;
ropeString: Test.StringSelection[rope] = [string: rope[]];
textString: Test.StringSelection[text] = [string: text[]];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
char: CHARACTER = LOOPHOLE[test MOD 128];
length: INTEGER = test MOD (MaxStringLength+1);
type: Test.StringType = SELECT test MOD 13 FROM
0,5,8,9,11,12 => text, 1,2,4,6,7 => rope, 3,10 => nil, ENDCASE => ERROR;
makeNil: BOOLEAN = Periodically[test];
exerciser.Delay;
exerciser.StartPrecisionTiming;
string ← Test.CharToVariantString[
char: char, length: length, type: type, makeNil: makeNil ];
exerciser.StopPrecisionTiming;
IF checkResults THEN BEGIN
IF string.char # char OR string.length # length THEN BadExercise;
IF string.type # type THEN BadExercise;
WITH string: string SELECT FROM
nil => NULL;
rope =>
BEGIN
IF string.seal # ropeString.seal THEN BadExercise;
IF ~makeNil
THEN BEGIN OPEN Rope;
textRope: Text;
IF Length[string.rope] # length THEN BadExercise;
textRope ← Flatten[string.rope];
FOR i: INTEGER IN [0..length) DO
IF textRope.text[i] # char THEN BadExercise; ENDLOOP;
END
ELSE IF string.rope # NIL THEN BadExercise;
END;
text =>
BEGIN
IF string.seal # textString.seal THEN BadExercise;
IF ~makeNil
THEN BEGIN
IF string.text.length # length THEN BadExercise;
FOR i: INTEGER IN [0..length) DO
IF string.text[i] # char THEN BadExercise; ENDLOOP;
END
ELSE IF string.text # NIL THEN BadExercise;
END;
ENDCASE => ERROR;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END;
BitsToSequence: ExerciseProc =
BEGIN
MaxVectorLength: CARDINAL = 3*850;
BitVector: TYPE = PACKED ARRAY [0..MaxVectorLength) OF Test.Bits;
bitVectorPtr: LONG POINTER TO BitVector ← Heap.systemZone.NEW[BitVector];
Pattern: PROC [i: INTEGER] RETURNS [Test.Bits] =
INLINE {RETURN[ i MOD (LAST[Test.Bits]+1) ]};
BEGIN ENABLE UNWIND => Heap.systemZone.FREE[@bitVectorPtr];
exerciser.Start[name];
THROUGH [0..trials) DO
exerciser.Stamp;
FOR test: INTEGER IN [0..testsPerTrial) DO
length: INTEGER = test MOD (MaxVectorLength+1);
bitsIn: Test.BitDescriptor = DESCRIPTOR[bitVectorPtr, length];
bitsOut: REF READONLY Test.BitSequence;
FOR i: INTEGER DECREASING IN (length..0] DO
bitsIn[i] ← Pattern[i]; ENDLOOP;
exerciser.Delay;
exerciser.StartPrecisionTiming;
bitsOut ← Test.BitsToSequence[in: bitsIn];
exerciser.StopPrecisionTiming;
IF checkResults THEN BEGIN
IF bitsOut.length-1 # length THEN BadExercise;
FOR i: INTEGER IN [0..length) DO
IF i < LENGTH[bitsOut.fixed] AND
bitsOut.fixed[i+1] # bitsIn[i] THEN BadExercise;
IF bitsOut.dynamic[i+1] # bitsIn[i] THEN BadExercise;
ENDLOOP;
END;
ENDLOOP;
ENDLOOP;
exerciser.Stop;
END; -- ENABLE UNWIND.
Heap.systemZone.FREE[@bitVectorPtr];
END;
StringsToAtoms: ExerciseProc = {};
-- Module initialization.
Process.Detach[ FORK PerformMarshalExercises[] ];
END. -- LupineMarshalTestDriver.