-- File [Ivy]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.