-- FileTestImpl.mesa
-- written by Bill Paxton, April 1981
-- last edit by Bill Paxton, 15-Oct-81 15:00:51

-- This package provides random testing for filing Text nodes

DIRECTORY
EditTest,
TextEdit,
TextFind,
TextLooks,
TextLooksSupport,
RopeEdit,
TextNode,
NodeProps,
PutGet,
GetTree,
RunReader,
RopeReader,
Rope,
RopeInline,
CheckNode,
TreeCheck,
FileByteStream;

FileTestImpl: PROGRAM
	IMPORTS EditTest, TextEdit, RopeEdit,
		PutGet, GetTree, RunReader, RopeReader, Rope,
		NodeProps, TextNode, TreeCheck,
		CheckNode, FileByteStream
	EXPORTS EditTest =
BEGIN
OPEN
	rI:Rope,
	editI:TextEdit,
	findI:TextFind,
	looksI:TextLooks,
	looksSI:TextLooksSupport,
	ropeI:RopeEdit,
	nodeI:TextNode,
	propsI:NodeProps,
	runrdrI:RunReader,
	roperdrI:RopeReader,
	pgI:PutGet,
	checkI:CheckNode,
	streamI:FileByteStream,
	EditTest;

-- ***** Filing operations

fileNameA: Rope ← rI.FromString["file1.tioga"];
fileNameB: Rope ← rI.FromString["file2.tioga"];
fileName: Rope ← fileNameA;

PutGet: PUBLIC PROC = {
	newAlpha, newBeta: Node;
	fromFile, child: editI.Ref;
	oldAlphaSize, oldBetaSize, endAlpha: Offset;
	oldAlphaRope, newAlphaRope, oldBetaRope, newBetaRope: Rope;
	oldAlphaRuns, newAlphaRuns, oldBetaRuns, newBetaRuns: Runs;
	IF TRUE --OneInN[4]-- THEN RETURN;
	oldAlphaSize ← editI.Size[alpha];
	oldBetaSize ← editI.Size[beta];
	oldAlphaRope ← editI.GetRope[alpha];
	oldAlphaRuns ← editI.GetRuns[alpha];
	oldBetaRope ← editI.GetRope[beta];
	oldBetaRuns ← editI.GetRuns[beta];
	endAlpha ← pgI.ToFile[fileName,alpha];
--temp	[] ← pgI.ToFile[fileName,beta,endAlpha];
	fromFile ← pgI.FromFile[fileName,0,endAlpha];
	IF(child ← nodeI.FirstChild[fromFile]) # NIL THEN fromFile ← child;
	WITH n:fromFile SELECT FROM text => newAlpha ← @n; ENDCASE => ERROR;
	newAlphaRope ← editI.GetRope[newAlpha];
	newAlphaRuns ← editI.GetRuns[newAlpha];
	checkI.CheckTextNode[newAlpha];
	CheckSize[newAlpha,oldAlphaSize];
	CheckRopes[newAlphaRope,0,oldAlphaRope,0,oldAlphaSize];
	CheckRuns[newAlphaRuns,0,oldAlphaRuns,0,oldAlphaSize];
	IF newAlpha.typename # alpha.typename THEN ERROR;
	RETURN; --temp
	fromFile ← pgI.FromFile[fileName,endAlpha];
	IF(child ← nodeI.FirstChild[fromFile]) # NIL THEN fromFile ← child;
	WITH n:fromFile SELECT FROM text => newBeta ← @n; ENDCASE => ERROR;
	newBetaRope ← editI.GetRope[newBeta];
	newBetaRuns ← editI.GetRuns[newBeta];
	checkI.CheckTextNode[newBeta];
	CheckSize[newBeta,oldBetaSize];
	CheckRopes[newBetaRope,0,oldBetaRope,0,oldBetaSize];
	CheckRuns[newBetaRuns,0,oldBetaRuns,0,oldBetaSize];
	IF newBeta.typename # beta.typename THEN ERROR;
	fileName ← IF fileName=fileNameA THEN fileNameB ELSE fileNameA;
	};

PutGetToRope: PUBLIC PROC = {
	newAlpha, newBeta: Node;
	oldAlphaSize, oldBetaSize, endAlpha: Offset;
	outputAlpha, outputBeta, output: Rope;
	fromRope: editI.Ref;
	oldAlphaRope, newAlphaRope, oldBetaRope, newBetaRope: Rope;
	oldAlphaRuns, newAlphaRuns, oldBetaRuns, newBetaRuns: Runs;
	IF TRUE --OneInN[4]-- THEN RETURN;
	oldAlphaSize ← editI.Size[alpha];
	oldBetaSize ← editI.Size[beta];
	oldAlphaRope ← editI.GetRope[alpha];
	oldAlphaRuns ← editI.GetRuns[alpha];
	oldBetaRope ← editI.GetRope[beta];
	oldBetaRuns ← editI.GetRuns[beta];
	outputAlpha ← pgI.ToRope[alpha];
	endAlpha ← ropeI.Size[outputAlpha];
	outputBeta ← pgI.ToRope[beta];
	output ← ropeI.Concat[outputAlpha,outputBeta];
	fromRope ← pgI.FromRope[output,0,endAlpha];
	WITH n:fromRope SELECT FROM text => newAlpha ← @n; ENDCASE => ERROR;
	newAlphaRope ← editI.GetRope[newAlpha];
	newAlphaRuns ← editI.GetRuns[newAlpha];
	checkI.CheckTextNode[newAlpha];
	CheckSize[newAlpha,oldAlphaSize];
	CheckRopes[newAlphaRope,0,oldAlphaRope,0,oldAlphaSize];
	CheckRuns[newAlphaRuns,0,oldAlphaRuns,0,oldAlphaSize];
	IF newAlpha.typename # alpha.typename THEN ERROR;
	fromRope ← pgI.FromRope[output,endAlpha];
	WITH n:fromRope SELECT FROM text => newBeta ← @n; ENDCASE => ERROR;
	newBetaRope ← editI.GetRope[newBeta];
	newBetaRuns ← editI.GetRuns[newBeta];
	checkI.CheckTextNode[newBeta];
	CheckSize[newBeta,oldBetaSize];
	CheckRopes[newBetaRope,0,oldBetaRope,0,oldBetaSize];
	CheckRuns[newBetaRuns,0,oldBetaRuns,0,oldBetaSize];
	IF newBeta.typename # beta.typename THEN ERROR;
	};

PutGetToStream: PUBLIC PROC = {
	stream: streamI.Handle;
	newAlpha, newBeta: Node;
	oldAlphaSize, oldBetaSize, alphaChars, betaChars: Offset;
	fromStream: editI.Ref;
	oldAlphaRope, newAlphaRope, oldBetaRope, newBetaRope: Rope;
	oldAlphaRuns, newAlphaRuns, oldBetaRuns, newBetaRuns: Runs;
	IF TRUE --OneInN[4]-- THEN RETURN;
	stream ← streamI.Open[fileName,write];
	streamI.SetLength[stream,0];
	oldAlphaSize ← editI.Size[alpha];
	oldBetaSize ← editI.Size[beta];
	oldAlphaRope ← editI.GetRope[alpha];
	oldAlphaRuns ← editI.GetRuns[alpha];
	oldBetaRope ← editI.GetRope[beta];
	oldBetaRuns ← editI.GetRuns[beta];
	streamI.PutChar[stream,'1];
	alphaChars ← pgI.ToStream[stream,alpha];
	streamI.PutChar[stream,'2];
	betaChars ← pgI.ToStream[stream,beta];
	streamI.PutChar[stream,'3];
	streamI.Close[stream,TRUE];
	stream ← streamI.Open[fileName,read];
	IF streamI.GetChar[stream] # '1 THEN ERROR;
	fromStream ← pgI.FromStream[stream,alphaChars];
	WITH n:fromStream SELECT FROM text => newAlpha ← @n; ENDCASE => ERROR;
	newAlphaRope ← editI.GetRope[newAlpha];
	newAlphaRuns ← editI.GetRuns[newAlpha];
	checkI.CheckTextNode[newAlpha];
	CheckSize[newAlpha,oldAlphaSize];
	CheckRopes[newAlphaRope,0,oldAlphaRope,0,oldAlphaSize];
	CheckRuns[newAlphaRuns,0,oldAlphaRuns,0,oldAlphaSize];
	IF newAlpha.typename # alpha.typename THEN ERROR;
	IF streamI.GetChar[stream] # '2 THEN ERROR;
	fromStream ← pgI.FromStream[stream,betaChars];
	WITH n:fromStream SELECT FROM text => newBeta ← @n; ENDCASE => ERROR;
	newBetaRope ← editI.GetRope[newBeta];
	newBetaRuns ← editI.GetRuns[newBeta];
	checkI.CheckTextNode[newBeta];
	CheckSize[newBeta,oldBetaSize];
	CheckRopes[newBetaRope,0,oldBetaRope,0,oldBetaSize];
	CheckRuns[newBetaRuns,0,oldBetaRuns,0,oldBetaSize];
	IF newBeta.typename # beta.typename THEN ERROR;
	IF streamI.GetChar[stream] # '3 THEN ERROR;
	IF ~streamI.EndOf[stream] THEN ERROR;
	streamI.Close[stream,TRUE];
	fileName ← IF fileName=fileNameA THEN fileNameB ELSE fileNameA;
	};

PutGetRope: PUBLIC PROC = {
	newAlpha, newBeta: Node;
	fromFile: editI.Ref;
	oldAlphaRope, newAlphaRope, oldBetaRope, newBetaRope: Rope;
	oldAlphaSize, oldBetaSize, endAlpha: Offset;
	IF TRUE --OneInN[4]-- THEN RETURN;
	oldAlphaSize ← editI.Size[alpha];
	oldBetaSize ← editI.Size[beta];
	oldAlphaRope ← editI.GetRope[alpha];
	oldBetaRope ← editI.GetRope[beta];
	endAlpha ← oldAlphaSize;
	ropeI.ToFile[fileName,oldAlphaRope];
--temp	ropeI.ToFile[fileName,oldBetaRope,endAlpha];
	fromFile ← pgI.FromFile[fileName,0,endAlpha];
	fromFile ← nodeI.FirstChild[fromFile];
	WITH x:fromFile SELECT FROM text => newAlpha ← @x; ENDCASE => ERROR;
	newAlphaRope ← editI.GetRope[newAlpha];
	IF editI.GetRuns[newAlpha] # NIL THEN ERROR;
	checkI.CheckTextNode[newAlpha];
	CheckSize[newAlpha,oldAlphaSize];
	CheckRopes[newAlphaRope,0,oldAlphaRope,0,oldAlphaSize];
	newAlphaRope ← ropeI.FromFile[fileName,0,endAlpha];
	IF ropeI.Size[newAlphaRope] # oldAlphaSize THEN ERROR;
	CheckRopes[newAlphaRope,0,oldAlphaRope,0,oldAlphaSize];
	RETURN; --temp
	fromFile ← pgI.FromFile[fileName,endAlpha];
	fromFile ← nodeI.FirstChild[fromFile];
	WITH x:fromFile SELECT FROM text => newBeta ← @x; ENDCASE => ERROR;
	newBetaRope ← editI.GetRope[newBeta];
	IF editI.GetRuns[newBeta] # NIL THEN ERROR;
	checkI.CheckTextNode[newBeta];
	CheckSize[newBeta,oldBetaSize];
	CheckRopes[newBetaRope,0,oldBetaRope,0,oldBetaSize];
	newBetaRope ← ropeI.FromFile[fileName,endAlpha];
	IF ropeI.Size[newBetaRope] # oldBetaSize THEN ERROR;
	CheckRopes[newBetaRope,0,oldBetaRope,0,oldBetaSize];
	fileName ← IF fileName=fileNameA THEN fileNameB ELSE fileNameA;
	};

treeFileFlag: BOOLEAN ← FALSE;	
treeFileName: Rope ← rI.FromString["TestTree.Text"];
PutGetTree: PUBLIC PROC = {
	node: Node;
	new: Node;
	fromFile: editI.Ref;
	IF TRUE --treeFileFlag-- THEN RETURN;
	treeFileFlag ← TRUE; -- only do this test once
	node ← GetTree.ReadIndent[treeFileName];
	TreeCheck.Verify[node];
	[] ← pgI.ToFile[fileName,node];
	fromFile ← pgI.FromFile[fileName];
	TreeCheck.Verify[fromFile];
	WITH n:fromFile SELECT FROM text => new ← @n; ENDCASE => ERROR;
	CheckTrees[node,new];
	fileName ← IF fileName=fileNameA THEN fileNameB ELSE fileNameA;
	};

CheckTrees: PROC [t1,t2: editI.Ref] = { -- ERROR if trees not equal
	x1, x2: editI.Ref;
	WITH n1:t1 SELECT FROM
		text => WITH n2:t2 SELECT FROM
			text => { -- must have same text&looks
				size: Offset ← editI.Size[@n1];
				IF editI.Size[@n2] # size THEN ERROR;
				CheckRopes[n1.rope,0,n2.rope,0,size]; 
				CheckRuns[n1.runs,0,n2.runs,0,size] };
			ENDCASE => ERROR;
		other => WITH n2:t2 SELECT FROM
			other => NULL;
			ENDCASE => ERROR;
		ENDCASE => ERROR;
	IF t1.typename # t2.typename THEN ERROR;
	IF (t1.hasprefix OR t2.hasprefix) AND
		propsI.GetPrefixObject[t1]#propsI.GetPrefixObject[t2]
			THEN ERROR;
	IF (t1.haspostfix OR t2.haspostfix) AND
		propsI.GetPostfixObject[t1]#propsI.GetPostfixObject[t2]
			THEN ERROR;
	x1 ← t1.child; x2 ← t2.child;
	DO -- check children
		IF x1=NIL THEN IF x2=NIL THEN RETURN ELSE ERROR;
		IF x2=NIL THEN ERROR;
		CheckTrees[x1,x2];
		x1 ← nodeI.Next[x1]; x2 ← nodeI.Next[x2];
		ENDLOOP };

bigFileFlag: BOOLEAN ← FALSE;	
GetBigFile: PUBLIC PROC = {
	rope: Rope;
	IF TRUE --bigFileFlag-- THEN RETURN; -- only do this once or will fill up VM
	rope ← ropeI.FromFile[rI.FromString["bigfile.text"],0,LAST[Offset],TRUE];
	checkI.CheckRope[rope];
	bigFileFlag ← TRUE
	};
	
END.