MODULE TestFiles;
IMPORT Commands, Options, Random, Strings, TestSuite, Streams, Files;
CONST
Integer = 0;
Boolean = 1;
Char = 2;
String = 3;
TYPE
Tester = OBJECT (TestSuite.Tester)
VAR
log: Streams.Writer;
file : Files.File;
rider : Files.Rider;
reader : Files.Reader;
path : ARRAY 512 OF CHAR;
lastCommandWasComment : BOOLEAN;
readerBytesLength : LONGINT;
byte : CHAR;
buffer : Strings.String;
PROCEDURE &InitTester *(log: Streams.Writer; CONST path : ARRAY OF CHAR);
BEGIN
ASSERT(log # NIL);
SELF.log := log;
COPY(path, SELF.path);
Strings.TrimWS(SELF.path);
Reset;
END InitTester;
PROCEDURE Reset;
BEGIN
file := NIL;
rider.eof := FALSE;
rider.res := 0;
rider.apos := 0;
rider.bpos := 0;
rider.hint := NIL;
rider.file := NIL;
rider.fs := NIL;
reader := NIL;
readerBytesLength := 0;
byte := 0X;
buffer := NIL;
lastCommandWasComment := FALSE;
END Reset;
PROCEDURE OpenFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
VAR fullname : Files.FileName;
BEGIN
COPY(path, fullname); Strings.Append(fullname, filename);
log.String("Files.Old '"); log.String(fullname); log.String("' ... "); log.Update;
file := Files.Old(fullname);
IF (file # NIL) THEN
Files.OpenReader(reader, file, 0);
log.String("Ok");
ELSE
error := TRUE;
log.String("Failed");
END;
END OpenFile;
PROCEDURE CreateFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
VAR fullname : Files.FileName;
BEGIN
COPY(path, fullname); Strings.Append(fullname, filename);
log.String("Files.New '"); log.String(fullname); log.String("' ... "); log.Update;
file := Files.New(fullname);
IF (file # NIL) THEN
Files.OpenReader(reader, file, 0);
log.String("Ok");
ELSE
error := TRUE;
log.String("Failed.");
END;
END CreateFile;
PROCEDURE DeleteFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
VAR fullname : Files.FileName; res : LONGINT;
BEGIN
COPY(path, fullname); Strings.Append(fullname, filename);
log.String("DELETE '"); log.String(fullname); log.String("' ... "); log.Update;
Files.Delete(fullname, res);
IF (res = Files.Ok) THEN
log.String("Ok");
ELSE
error := TRUE;
log.String("File not found");
END;
END DeleteFile;
PROCEDURE RegisterFile(VAR error : BOOLEAN);
BEGIN
log.String("Register current file ... "); log.Update;
IF CheckOpen(error) THEN
Files.Register(file);
log.String("Ok");
ELSE
log.String("Failed");
END;
END RegisterFile;
PROCEDURE CheckOpen(VAR error : BOOLEAN) : BOOLEAN;
BEGIN
IF (file = NIL) THEN
log.String("Error: no open file");
error := TRUE;
ELSE
error := FALSE;
END;
RETURN ~error;
END CheckOpen;
PROCEDURE FileSet(position : LONGINT; VAR error : BOOLEAN);
BEGIN
log.String("File.Pos := "); log.Int(position, 0); log.String(" ... "); log.Update;
IF CheckOpen(error) THEN
file.Set(rider, position);
log.String("Ok");
END;
END FileSet;
PROCEDURE GetInteger(r : Streams.Reader; VAR integer : LONGINT) : BOOLEAN;
BEGIN
r.SkipWhitespace; r.Int(integer, FALSE);
IF (r.res # Streams.Ok) THEN
log.Ln; log.String("Parse error: Expected integer value, pos = "); log.Int(r.Pos(), 0); log.Ln;
END;
RETURN (r.res = Streams.Ok);
END GetInteger;
PROCEDURE GetString(r : Streams.Reader; VAR string : Strings.String) : BOOLEAN;
VAR value : ARRAY 1024 OF CHAR;
BEGIN
r.SkipWhitespace; r.String(value);
IF (r.res # Streams.Ok) THEN
string := NIL;
log.Ln; log.String("Parse error: Expected string value, pos = "); log.Int(r.Pos(), 0); log.Ln;
ELSE
string := Strings.NewString(value);
END;
RETURN (r.res = Streams.Ok);
END GetString;
PROCEDURE GetBoolean(r : Streams.Reader; VAR boolean : BOOLEAN) : BOOLEAN;
VAR string : ARRAY 8 OF CHAR;
BEGIN
r.SkipWhitespace; r.String(string);
IF (string = "TRUE") THEN boolean := TRUE;
ELSIF (string = "FALSE") THEN boolean := FALSE;
ELSE
log.Ln; log.String("Parse error : Expected boolean value, pos = "); log.Int(r.Pos(), 0); log.Ln;
END;
RETURN (string = "TRUE") OR (string = "FALSE");
END GetBoolean;
PROCEDURE GetChar(r : Streams.Reader; VAR char : CHAR) : BOOLEAN;
BEGIN
r.SkipWhitespace; r.Char(char);
IF (r.res # Streams.Ok) THEN
log.Ln; log.String("Parse error: Expected character value, pos = "); log.Int(r.Pos(), 0); log.Ln;
END;
RETURN (r.res = Streams.Ok);
END GetChar;
PROCEDURE GetIndex(CONST string : ARRAY OF CHAR; VAR index : LONGINT) : BOOLEAN;
VAR variable : ARRAY 64 OF CHAR;
BEGIN
ASSERT(Strings.Match("buffer*", string));
COPY(string, variable);
Strings.Delete(variable, 0, 6);
IF (variable[0] = "[") & (variable[Strings.Length(variable)-1] = "]") THEN
Strings.Delete(variable, 0, 1);
variable[Strings.Length(variable)-1] := 0X;
IF IsNumber(variable) THEN
Strings.StrToInt(variable, index);
RETURN TRUE;
ELSE
log.String("Parse error: Expected integer as index in "); log.String(string);
END;
ELSE
log.String("Parse error: Expected index brackets [] in "); log.String(string);
END;
RETURN FALSE;
END GetIndex;
PROCEDURE Assert(r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR variable : ARRAY 32 OF CHAR; index : LONGINT;
PROCEDURE CheckInteger(CONST name : ARRAY OF CHAR; variable : LONGINT; r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR operator : ARRAY 4 OF CHAR; value : LONGINT;
BEGIN
r.SkipWhitespace; r.String(operator);
IF GetInteger(r, value) THEN
IF (operator = "=") THEN error := variable # value;
ELSIF (operator = "#") THEN error := variable = value;
ELSIF (operator = "<") THEN error := variable >= value;
ELSIF (operator = "<=") THEN error := variable > value;
ELSIF (operator = ">") THEN error := variable <= value;
ELSIF (operator = ">=") THEN error := variable < value;
ELSE
parseError := TRUE;
log.String("Parse error: Unsupported integer operator: "); log.String(operator);
log.String(", pos = "); log.Int(r.Pos(), 0);
END;
ELSE
parseError := TRUE;
END;
IF ~parseError THEN
log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" "); log.Int(value, 0); log.String(" ... ");
IF ~error THEN log.String("Ok"); ELSE log.String("Failed ("); log.Int(variable, 0); log.String(")"); END;
END;
END CheckInteger;
PROCEDURE CheckBoolean(CONST name : ARRAY OF CHAR; variable : BOOLEAN; r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR operator : ARRAY 4OF CHAR; value : BOOLEAN;
BEGIN
r.SkipWhitespace; r.String(operator);
IF GetBoolean(r, value) THEN
IF (operator = "=") THEN
error := variable # value;
ELSIF (operator = "#") THEN
error := variable = value;
ELSE
parseError := TRUE;
log.String("Parse error: Unsupported boolean operator: "); log.String(operator);
log.String(", pos = "); log.Int(r.Pos(), 0);
END;
ELSE
parseError := TRUE;
END;
IF ~parseError THEN
log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
IF value THEN log.String("TRUE"); ELSE log.String("FALSE"); END; log.String(" ... ");
IF ~error THEN log.String("Ok"); ELSE log.String("Failed"); END;
END;
END CheckBoolean;
PROCEDURE CheckChar(CONST name : ARRAY OF CHAR; variable : CHAR; r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR operator : ARRAY 4 OF CHAR; value : CHAR;
BEGIN
r.SkipWhitespace; r.String(operator);
IF GetChar(r, value) THEN
IF (operator = "=") THEN error := variable # value;
ELSIF (operator = "#") THEN error := variable = value;
ELSE
parseError := TRUE;
log.String("Parse error: Unsupported character operator: "); log.String(operator);
END;
ELSE
parseError := TRUE;
END;
IF ~parseError THEN
log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
log.Int(ORD(value), 0); log.String(" ... ");
IF ~error THEN log.String("Ok"); ELSE log.String("Failed ("); log.Int(ORD(variable), 0); log.String(")"); END;
END;
END CheckChar;
PROCEDURE CheckString(CONST name : ARRAY OF CHAR; CONST variable : Strings.String; r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR operator : ARRAY 4 OF CHAR; value : Strings.String; i : LONGINT;
BEGIN
r.SkipWhitespace; r.String(operator);
IF GetString(r, value) THEN
ASSERT(value # NIL);
IF (operator = "=") THEN
error := ~StringsAreEqual(value, buffer);
ELSIF (operator = "#") THEN
error := StringsAreEqual(value, buffer);
ELSE
parseError := TRUE;
log.String("Parse error: Unsupported string operator: "); log.String(operator);
END;
ELSE
parseError := TRUE;
END;
IF ~parseError THEN
log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
i := 0;
WHILE (i < LEN(value)) & (i < 20) & (value[i] # 0X) DO log.Char(value[i]); INC(i); END;
log.String(" ... ");
IF ~error THEN log.String("Ok"); ELSE log.String("Failed"); END;
END;
END CheckString;
BEGIN
variable := "";
r.SkipWhitespace; r.String(variable);
IF (variable # "") THEN
IF (variable = "rider.res") THEN
CheckInteger(variable, rider.res, r, error, parseError);
ELSIF (variable = "rider.eof") THEN
CheckBoolean(variable, rider.eof, r, error, parseError);
ELSIF (variable = "reader.res") THEN
CheckInteger(variable, reader.res, r, error, parseError);
ELSIF (variable = "byte") THEN
CheckChar(variable, byte, r, error, parseError);
ELSIF (variable = "readerBytesLength") THEN
CheckInteger(variable, readerBytesLength, r, error, parseError);
ELSIF (variable = "buffer") THEN
CheckString(variable, buffer, r, error, parseError);
ELSIF Strings.Match("buffer*", variable) THEN
IF GetIndex(variable, index) THEN
IF (buffer # NIL) & (index < LEN(buffer)) THEN
CheckChar(variable, buffer[index], r, error, parseError);
ELSE
error := TRUE;
END;
ELSE
parseError := TRUE;
END;
ELSIF (variable = "File.Length()") & CheckOpen(error) THEN
CheckInteger(variable, file.Length(), r, error, parseError);
ELSIF (variable = "File.Pos()") & CheckOpen(error) THEN
CheckInteger(variable, file.Pos(rider), r, error, parseError);
ELSIF (variable = "Reader.Available()") & CheckOpen(error) THEN
CheckInteger(variable, reader.Available(), r, error, parseError);
ELSIF (variable = "Reader.Pos()") & CheckOpen(error) THEN
CheckInteger(variable, reader.Pos(), r, error, parseError);
ELSE
parseError := TRUE;
log.String("Parse error: Unknown variable "); log.String(variable);
log.String(", pos = "); log.Int(r.Pos(), 0);
END;
ELSE
parseError := TRUE;
log.String("Parse error: Expected variable name in ASSERT, pos = "); log.Int(r.Pos(), 0);
END;
END Assert;
PROCEDURE Set(r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR
variable, to : ARRAY 32 OF CHAR;
charValue : CHAR; integerValue : LONGINT; booleanValue : BOOLEAN; stringValue : Strings.String;
set, i : LONGINT; index : LONGINT;
BEGIN
r.SkipWhitespace; r.String(variable);
IF (variable = "rider.res") OR (variable = "rider.eof") OR (variable = "byte") OR (variable = "readerBytesLength") OR
(variable = "buffer") OR Strings.Match("buffer*", variable) THEN
r.SkipWhitespace; r.String(to);
IF (to = "TO") THEN
IF (variable = "rider.res") THEN
set := Integer;
IF GetInteger(r, integerValue) THEN rider.res := integerValue; ELSE parseError := TRUE; END;
ELSIF (variable = "rider.eof") THEN
set := Boolean;
IF GetBoolean(r, booleanValue) THEN rider.eof := booleanValue; ELSE parseError := TRUE; END;
ELSIF (variable = "reader.res") THEN
set := Integer;
IF GetInteger(r, integerValue) THEN reader.res := integerValue; ELSE parseError := TRUE; END;
ELSIF (variable = "byte") THEN
set := Char;
IF GetChar(r, charValue) THEN byte := charValue; ELSE parseError := TRUE; END;
ELSIF (variable = "readerBytesLength") THEN
set := Integer;
IF GetInteger(r, integerValue) THEN readerBytesLength := integerValue; ELSE parseError := TRUE; END;
ELSIF (variable = "buffer") THEN
set := String;
IF GetString(r, stringValue) THEN
ASSERT((stringValue # NIL) & (stringValue[LEN(stringValue)-1] = 0X));
IF (buffer # NIL) & (LEN(buffer) >= LEN(stringValue)-1) THEN
FOR i := 0 TO LEN(stringValue)-2 DO
buffer[i] := stringValue[i];
END;
ELSE
error := TRUE;
END;
ELSE
parseError := TRUE;
END;
ELSIF Strings.Match("buffer*", variable) THEN
IF GetIndex(variable, index) THEN
IF (buffer # NIL) & (index < LEN(buffer)) THEN
IF GetChar(r, charValue) THEN
buffer[index] := charValue;
ELSE
parseError := TRUE;
END;
ELSE
error := TRUE;
END;
ELSE
parseError := TRUE;
END;
END;
IF ~parseError THEN
log.String("SET "); log.String(variable); log.String(" to ");
IF (set = Boolean) THEN
IF booleanValue THEN log.String("TRUE"); ELSE log.String("FALSE"); END;
ELSIF (set = Integer) THEN
log.Int(integerValue, 0);
ELSIF (set = Char) THEN
log.Int(ORD(charValue), 0);
ELSIF (set = String) THEN
IF (stringValue # NIL) THEN
i := 0;
WHILE (i < LEN(stringValue)) & (i < 20) & (stringValue[i] # 0X) DO
log.Char(stringValue[i]); INC(i);
END;
IF (i < LEN(stringValue)) & (stringValue[i] # 0X) THEN
log.String(" ... ");
END;
ELSE
log.String("NIL");
END;
END;
IF ~error THEN log.String(" ... Ok"); ELSE log.String(" ... Failed"); END;
END;
ELSE
parseError := TRUE;
log.String("Parse error: Expected TO, pos = "); log.Int(r.Pos(), 0);
END;
ELSE
parseError := TRUE;
log.String("Parse error: Unknown variable in SET: "); log.String(variable); log.Int(r.Pos(), 0);
END;
END Set;
PROCEDURE FileReadByte(VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("File.Read ... "); log.Update;
file.Read(rider, byte);
log.String("value="); log.Int(ORD(byte), 0); log.String(", Ok");
END;
END FileReadByte;
PROCEDURE FileWriteByte(VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("File.Write: "); log.Int(ORD(byte), 0); log.String(" ... "); log.Update;
file.Write(rider, byte);
log.String("Ok");
END;
END FileWriteByte;
PROCEDURE FileReadBytes(offset, length : LONGINT; VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("File.ReadBytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String(" ... "); log.Update;
file.ReadBytes(rider, buffer^, offset, length);
log.String("Ok");
END;
END FileReadBytes;
PROCEDURE FileWriteBytes(offset, length : LONGINT; VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("File.WriteBytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String(" ... "); log.Update;
file.WriteBytes(rider, buffer^, offset, length);
log.String("Ok");
END;
END FileWriteBytes;
PROCEDURE ReaderGet(VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("Reader.Get ... "); log.Update;
byte := reader.Get();
log.String("value="); log.Int(ORD(byte), 0); log.String(", Ok");
END;
END ReaderGet;
PROCEDURE ReaderBytes(offset, length : LONGINT; VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("Reader.Bytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String("... "); log.Update;
reader.Bytes(buffer^, offset, length, readerBytesLength);
log.Int(readerBytesLength, 0); log.String(" bytes read, Ok");
END;
END ReaderBytes;
PROCEDURE ReaderSetPos(position : LONGINT; VAR error : BOOLEAN);
BEGIN
IF CheckOpen(error) THEN
log.String("Reader.SetPos "); log.Int(position, 0); log.String(" ... "); log.Update;
reader.SetPos(position);
log.String("Ok");
END;
END ReaderSetPos;
PROCEDURE InitBuffer(length : LONGINT);
PROCEDURE Clear;
VAR i : LONGINT;
BEGIN
FOR i := 0 TO LEN(buffer)-1 DO
buffer[i] := 0X;
END;
END Clear;
BEGIN
log.String("INITBUFFER "); log.Int(length, 0); log.String(" ... "); log.Update;
IF (length = 0) THEN
buffer := NIL;
ELSIF (buffer # NIL) & (LEN(buffer) = length) THEN
Clear;
ELSE
NEW(buffer, length);
Clear;
END;
log.String("Ok");
END InitBuffer;
PROCEDURE CallCommand(r : Streams.Reader; VAR error, parseError : BOOLEAN);
VAR
context : Commands.Context;
arg : Streams.StringReader;
commandStr : ARRAY 128 OF CHAR; parameterStr : Strings.String;
msg : ARRAY 128 OF CHAR;
pos, res : LONGINT;
BEGIN
NEW(parameterStr, 4096); Strings.Truncate(parameterStr^, 0);
r.SkipWhitespace; r.String(commandStr);
r.Ln(parameterStr^);
Strings.TrimWS(parameterStr^);
pos := Strings.Pos("<path>", parameterStr^);
WHILE (pos >= 0) DO
Strings.Delete(parameterStr^, pos, Strings.Length("<path>"));
Strings.Insert(path, parameterStr^, pos);
pos := Strings.Pos("<path>", parameterStr^);
END;
log.String("CALL '"); log.String(parameterStr^); log.String("' ... "); log.Update;
IF (commandStr # "") THEN
NEW(arg, Strings.Length(parameterStr^));
arg.SetRaw(parameterStr^, 0, Strings.Length(parameterStr^));
NEW(context, NIL, arg, log, log, SELF);
Commands.Activate(commandStr, context, {Commands.Wait}, res, msg);
IF (res = Commands.Ok) THEN
log.String("Ok");
ELSE
error := TRUE;
log.String("Failed, "); log.String(msg); log.String(", res: "); log.Int(res, 0);
END;
ELSE
parseError := TRUE;
log.String("Parse error: Expected argument for CALL");
END;
END CallCommand;
PROCEDURE ProcessCommand(r : Streams.Reader; VAR error, parseError, finished : BOOLEAN);
VAR
filename : Files.FileName;
string : ARRAY 64 OF CHAR;
offset, length, position : LONGINT;
BEGIN
error := FALSE; parseError := FALSE;
IF ~r.GetString(string) THEN finished := TRUE; RETURN; ELSE finished := FALSE; END;
IF ~lastCommandWasComment THEN log.String(" "); ELSE lastCommandWasComment := FALSE; END;
IF (string = "Files.Old") THEN
r.SkipWhitespace; r.String(filename);
OpenFile(filename, error);
ELSIF (string = "Files.New") THEN
r.SkipWhitespace; r.String(filename);
CreateFile(filename, error);
ELSIF (string = "DELETE") THEN
r.SkipWhitespace; r.String(filename);
DeleteFile(filename, error); error := FALSE;
ELSIF (string = "REGISTER") THEN
RegisterFile(error);
ELSIF (string = "File.Set") & GetInteger(r, position) THEN
FileSet(position, error);
ELSIF (string = "SET") THEN
Set(r, error, parseError);
ELSIF (string = "ASSERT") THEN
Assert(r, error, parseError);
ELSIF (string = "File.Read") THEN
FileReadByte(error);
ELSIF (string = "File.ReadBytes") & GetInteger(r, offset) & GetInteger(r, length) THEN
FileReadBytes(offset, length, error);
ELSIF (string = "File.Write") THEN
FileWriteByte(error);
ELSIF (string = "File.WriteBytes") & GetInteger(r, offset) & GetInteger(r, length) THEN
FileWriteBytes(offset, length, error);
ELSIF (string = "Reader.Get") THEN
ReaderGet(error);
ELSIF (string = "Reader.Bytes") & GetInteger(r, offset) & GetInteger(r, length) THEN
ReaderBytes(offset, length, error);
ELSIF (string = "Reader.SetPos") & GetInteger(r, position) THEN
ReaderSetPos(position, error);
ELSIF (string = "INITBUFFER") & GetInteger(r, length) THEN
InitBuffer(length);
ELSIF (string = "CALL") THEN
CallCommand(r, error, parseError);
ELSIF (string[0] = "#") THEN
lastCommandWasComment := TRUE;
r.SkipLn;
ELSE
log.Ln; log.String("Parse Error: Expected command, but found: "); log.String(string); log.String(", pos = "); log.Int(r.Pos(), 0); log.Ln;
parseError := TRUE;
END;
IF ~parseError & (string[0] # "#") THEN log.Ln; log.Update; END;
END ProcessCommand;
PROCEDURE Handle (r: Streams.Reader; pos : LONGINT; CONST name: ARRAY OF CHAR; testType: TestSuite.TestType): INTEGER;
VAR result: INTEGER; error, parseError, finished, trapped: BOOLEAN;
BEGIN
trapped := TRUE;
Reset;
error := FALSE; parseError := FALSE;
result := TestSuite.Failure;
log.String ("testing: "); log.String (name); log.Update; log.Ln;
REPEAT
ProcessCommand(r, error, parseError, finished);
log.Update;
UNTIL (error OR parseError OR finished);
trapped := FALSE;
IF parseError THEN result := TestSuite.Failure;
ELSIF error THEN result := TestSuite.Negative;
ELSE result := TestSuite.Positive;
END;
FINALLY
IF trapped THEN log.String("TRAP"); END;
log.Ln; log.Update;
RETURN result;
END Handle;
END Tester;
PROCEDURE StringsAreEqual(string, buffer : Strings.String) : BOOLEAN;
VAR i : LONGINT;
BEGIN
IF (string # NIL) & (buffer # NIL) & (string[LEN(string)-1] = 0X) & (LEN(string) = LEN(buffer) + 1) THEN
i := 0;
WHILE (i < LEN(string) - 1) & (string[i] = buffer[i]) DO INC(i); END;
RETURN (i >= LEN(string) - 1);
END;
RETURN FALSE;
END StringsAreEqual;
PROCEDURE IsNumber(CONST string : ARRAY OF CHAR) : BOOLEAN;
VAR i : LONGINT;
BEGIN
IF ("0" <= string[0]) & (string[0] <= "9") THEN
FOR i := 1 TO Strings.Length(string)-1 DO
IF (string[i] < "0") & ("9" < string[i]) THEN
RETURN FALSE;
END;
END;
RETURN TRUE;
END;
RETURN FALSE;
END IsNumber;
PROCEDURE Test*(context : Commands.Context);
VAR options : Options.Options; tester: Tester; report: TestSuite.StreamReport; path : Files.FileName;
BEGIN
NEW(options);
options.Add("p", "path", Options.String);
IF options.Parse(context.arg, context.out) THEN
IF ~options.GetString("path", path) THEN path := ""; END;
NEW(tester, context.out, path);
NEW(report, context.out);
TestSuite.Drive(context, tester);
tester.Print(report);
END;
END Test;
PROCEDURE RandomReadWrite*(context : Commands.Context);
VAR
path, filename, fullname : Files.FileName;
seed, run, nofRuns, position, lastPosition, length0, temp, lastPercent : LONGINT;
char, lastChar, ch : CHAR;
file : Files.File; rider : Files.Rider;
random : Random.Generator;
BEGIN
context.arg.SkipWhitespace; context.arg.String(path);
context.arg.SkipWhitespace; context.arg.String(filename);
context.arg.SkipWhitespace; context.arg.Int(seed, FALSE);
context.arg.SkipWhitespace; context.arg.Int(nofRuns, FALSE);
COPY(path, fullname); Strings.Append(fullname, filename);
context.out.String(" RandomReadWrite on file '"); context.out.String(fullname); context.out.String("' (");
context.out.Int(nofRuns, 0); context.out.String(" runs)' ... ");
context.out.Update;
file := Files.Old(fullname);
IF (file # NIL) THEN
NEW(random);
random.InitSeed(seed);
length0 := file.Length();
run := 0;
lastChar := 0X; lastPosition := 0; lastPercent := 0;
context.out.String("0% "); context.out.Update;
WHILE (run <= nofRuns) DO
IF (100 * run DIV nofRuns >= lastPercent + 10) THEN
lastPercent := lastPercent + 10;
context.out.Int(lastPercent, 0); context.out.String("% "); context.out.Update;
END;
position := random.Dice(length0);
temp := random.Dice(255) + 1;
char := CHR(temp);
file.Set(rider, position);
ASSERT(file.Pos(rider) = position);
file.Write(rider, char);
ASSERT(rider.res = 0);
ASSERT(rider.eof = FALSE);
ASSERT(file.Length() = length0);
IF (lastChar # 0X) THEN
file.Set(rider, lastPosition);
ASSERT(file.Pos(rider) = lastPosition);
file.Read(rider, ch);
ASSERT(rider.res = 0);
ASSERT(rider.eof = FALSE);
ASSERT(file.Length() = length0);
ASSERT(ch = lastChar);
END;
lastChar := char;
lastPosition := position;
INC(run);
END;
context.out.String("Ok"); context.out.Ln;
ELSE
context.out.String("Failed (File not found)"); context.out.Ln; context.out.Update;
HALT(99);
END;
END RandomReadWrite;
PROCEDURE CreateTestFiles*(context : Commands.Context);
VAR path : Files.FileName; i : LONGINT;
PROCEDURE CreateFile(CONST path, filename : ARRAY OF CHAR; size : LONGINT);
VAR file : Files.File; rider : Files.Rider; fullname : Files.FileName;
BEGIN
COPY(path, fullname); Strings.Append(fullname, filename);
context.out.String("Create test file '"); context.out.String(fullname); context.out.String("' ... ");
context.out.Update;
file := Files.New(fullname);
IF (file # NIL) THEN
file.Set(rider, 0);
FOR i := 1 TO size DO
IF (i MOD 2 = 0) THEN file.Write(rider, 1X) ELSE file.Write(rider, 0FFX); END;
END;
Files.Register(file);
context.out.String("Ok");
ELSE
context.out.String("Failed");
END;
context.out.Ln;
END CreateFile;
BEGIN
path := ""; context.arg.SkipWhitespace; context.arg.String(path);
CreateFile(path, "TestFile0.Bin", 0);
CreateFile(path, "TestFile4096.Bin", 4096);
CreateFile(path, "TestFile8192.Bin", 8192);
END CreateTestFiles;
END TestFiles.
TestFiles.CreateTestFiles ~
SystemTools.Free TestFiles TestSuite~
WMUtilities.Call TestFiles.Test Files.Test ~ Verbose testing mode
WMUtilities.Call TestFiles.Test Files.Test Files.Test.tmp ~ Regression testing mode
SystemTools.DoCommands
VirtualDisks.InstallRamdisk TEST 163840 ~
Partitions.WriteMBR TEST#0 OBEMBR.Bin ~
SystemTools.Show AosFS File System ~ SystemTools.Ln ~
Partitions.Create TEST#1 76 9999 ~
Partitions.Format TEST#1 AosFS ~
Partitions.Mount TEST#1 AosFS TEST ~
WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
FSTools.Unmount TEST ~
SystemTools.Show FatFS File System ~ SystemTools.Ln ~
Partitions.ChangeType TEST#1 76 12 ~
Partitions.Format TEST#1 FatFS ~
Partitions.Mount TEST#1 FatFS TEST ~
WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
FSTools.Unmount TEST ~
SystemTools.Show SSFS File System ~ SystemTools.Ln ~
SSFS.Format TEST#1 ~
SSFS.Mount TEST TEST#1 ~
WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
SSFS.Unmount TEST ~
VirtualDisks.Uninstall TEST ~
~~