TestFiles.Mod 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. MODULE TestFiles; (** AUTHOR "staubesv"; PURPOSE "Files tester"; *)
  2. IMPORT Commands, Options, Random, Strings, TestSuite, Streams, Files;
  3. CONST
  4. Integer = 0;
  5. Boolean = 1;
  6. Char = 2;
  7. String = 3;
  8. TYPE
  9. Tester = OBJECT (TestSuite.Tester)
  10. VAR
  11. log: Streams.Writer;
  12. file : Files.File;
  13. rider : Files.Rider;
  14. reader : Files.Reader;
  15. path : ARRAY 512 OF CHAR;
  16. lastCommandWasComment : BOOLEAN;
  17. readerBytesLength : LONGINT; (* last results from Reader.Bytes(... VAR len) *)
  18. byte : CHAR; (* last byte read *)
  19. buffer : Strings.String; (* last bytes read *)
  20. PROCEDURE &InitTester *(log: Streams.Writer; CONST path : ARRAY OF CHAR);
  21. BEGIN
  22. ASSERT(log # NIL);
  23. SELF.log := log;
  24. COPY(path, SELF.path);
  25. Strings.TrimWS(SELF.path);
  26. Reset;
  27. END InitTester;
  28. PROCEDURE Reset;
  29. BEGIN
  30. file := NIL;
  31. rider.eof := FALSE;
  32. rider.res := 0;
  33. rider.apos := 0;
  34. rider.bpos := 0;
  35. rider.hint := NIL;
  36. rider.file := NIL;
  37. rider.fs := NIL;
  38. reader := NIL;
  39. readerBytesLength := 0;
  40. byte := 0X;
  41. buffer := NIL;
  42. lastCommandWasComment := FALSE;
  43. END Reset;
  44. PROCEDURE OpenFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
  45. VAR fullname : Files.FileName;
  46. BEGIN
  47. COPY(path, fullname); Strings.Append(fullname, filename);
  48. log.String("Files.Old '"); log.String(fullname); log.String("' ... "); log.Update;
  49. file := Files.Old(fullname);
  50. IF (file # NIL) THEN
  51. Files.OpenReader(reader, file, 0);
  52. log.String("Ok");
  53. ELSE
  54. error := TRUE;
  55. log.String("Failed");
  56. END;
  57. END OpenFile;
  58. PROCEDURE CreateFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
  59. VAR fullname : Files.FileName;
  60. BEGIN
  61. COPY(path, fullname); Strings.Append(fullname, filename);
  62. log.String("Files.New '"); log.String(fullname); log.String("' ... "); log.Update;
  63. file := Files.New(fullname);
  64. IF (file # NIL) THEN
  65. Files.OpenReader(reader, file, 0);
  66. log.String("Ok");
  67. ELSE
  68. error := TRUE;
  69. log.String("Failed.");
  70. END;
  71. END CreateFile;
  72. PROCEDURE DeleteFile(CONST filename : ARRAY OF CHAR; VAR error : BOOLEAN);
  73. VAR fullname : Files.FileName; res : WORD;
  74. BEGIN
  75. COPY(path, fullname); Strings.Append(fullname, filename);
  76. log.String("DELETE '"); log.String(fullname); log.String("' ... "); log.Update;
  77. Files.Delete(fullname, res);
  78. IF (res = Files.Ok) THEN
  79. log.String("Ok");
  80. ELSE
  81. error := TRUE;
  82. log.String("File not found");
  83. END;
  84. END DeleteFile;
  85. PROCEDURE RegisterFile(VAR error : BOOLEAN);
  86. BEGIN
  87. log.String("Register current file ... "); log.Update;
  88. IF CheckOpen(error) THEN
  89. Files.Register(file);
  90. log.String("Ok");
  91. ELSE
  92. log.String("Failed");
  93. END;
  94. END RegisterFile;
  95. PROCEDURE CheckOpen(VAR error : BOOLEAN) : BOOLEAN;
  96. BEGIN
  97. IF (file = NIL) THEN
  98. log.String("Error: no open file");
  99. error := TRUE;
  100. ELSE
  101. error := FALSE;
  102. END;
  103. RETURN ~error;
  104. END CheckOpen;
  105. PROCEDURE FileSet(position : LONGINT; VAR error : BOOLEAN);
  106. BEGIN
  107. log.String("File.Pos := "); log.Int(position, 0); log.String(" ... "); log.Update;
  108. IF CheckOpen(error) THEN
  109. file.Set(rider, position);
  110. log.String("Ok");
  111. END;
  112. END FileSet;
  113. PROCEDURE GetInteger(r : Streams.Reader; VAR integer : LONGINT) : BOOLEAN;
  114. BEGIN
  115. r.SkipWhitespace; r.Int(integer, FALSE);
  116. IF (r.res # Streams.Ok) THEN
  117. log.Ln; log.String("Parse error: Expected integer value, pos = "); log.Int(r.Pos(), 0); log.Ln;
  118. END;
  119. RETURN (r.res = Streams.Ok);
  120. END GetInteger;
  121. PROCEDURE GetString(r : Streams.Reader; VAR string : Strings.String) : BOOLEAN;
  122. VAR value : ARRAY 1024 OF CHAR;
  123. BEGIN
  124. r.SkipWhitespace; r.String(value);
  125. IF (r.res # Streams.Ok) THEN
  126. string := NIL;
  127. log.Ln; log.String("Parse error: Expected string value, pos = "); log.Int(r.Pos(), 0); log.Ln;
  128. ELSE
  129. string := Strings.NewString(value);
  130. END;
  131. RETURN (r.res = Streams.Ok);
  132. END GetString;
  133. PROCEDURE GetBoolean(r : Streams.Reader; VAR boolean : BOOLEAN) : BOOLEAN;
  134. VAR string : ARRAY 8 OF CHAR;
  135. BEGIN
  136. r.SkipWhitespace; r.String(string);
  137. IF (string = "TRUE") THEN boolean := TRUE;
  138. ELSIF (string = "FALSE") THEN boolean := FALSE;
  139. ELSE
  140. log.Ln; log.String("Parse error : Expected boolean value, pos = "); log.Int(r.Pos(), 0); log.Ln;
  141. END;
  142. RETURN (string = "TRUE") OR (string = "FALSE");
  143. END GetBoolean;
  144. PROCEDURE GetChar(r : Streams.Reader; VAR char : CHAR) : BOOLEAN;
  145. BEGIN
  146. r.SkipWhitespace; r.Char(char);
  147. IF (r.res # Streams.Ok) THEN
  148. log.Ln; log.String("Parse error: Expected character value, pos = "); log.Int(r.Pos(), 0); log.Ln;
  149. END;
  150. RETURN (r.res = Streams.Ok);
  151. END GetChar;
  152. PROCEDURE GetIndex(CONST string : ARRAY OF CHAR; VAR index : LONGINT) : BOOLEAN;
  153. VAR variable : ARRAY 64 OF CHAR;
  154. BEGIN
  155. ASSERT(Strings.Match("buffer*", string));
  156. COPY(string, variable);
  157. Strings.Delete(variable, 0, 6);
  158. IF (variable[0] = "[") & (variable[Strings.Length(variable)-1] = "]") THEN
  159. Strings.Delete(variable, 0, 1);
  160. variable[Strings.Length(variable)-1] := 0X;
  161. IF IsNumber(variable) THEN
  162. Strings.StrToInt(variable, index);
  163. RETURN TRUE;
  164. ELSE
  165. log.String("Parse error: Expected integer as index in "); log.String(string);
  166. END;
  167. ELSE
  168. log.String("Parse error: Expected index brackets [] in "); log.String(string);
  169. END;
  170. RETURN FALSE;
  171. END GetIndex;
  172. PROCEDURE Assert(r : Streams.Reader; VAR error, parseError : BOOLEAN);
  173. VAR variable : ARRAY 32 OF CHAR; index : LONGINT;
  174. PROCEDURE CheckInteger(CONST name : ARRAY OF CHAR; variable : LONGINT; r : Streams.Reader; VAR error, parseError : BOOLEAN);
  175. VAR operator : ARRAY 4 OF CHAR; value : LONGINT;
  176. BEGIN
  177. r.SkipWhitespace; r.String(operator);
  178. IF GetInteger(r, value) THEN
  179. IF (operator = "=") THEN error := variable # value;
  180. ELSIF (operator = "#") THEN error := variable = value;
  181. ELSIF (operator = "<") THEN error := variable >= value;
  182. ELSIF (operator = "<=") THEN error := variable > value;
  183. ELSIF (operator = ">") THEN error := variable <= value;
  184. ELSIF (operator = ">=") THEN error := variable < value;
  185. ELSE
  186. parseError := TRUE;
  187. log.String("Parse error: Unsupported integer operator: "); log.String(operator);
  188. log.String(", pos = "); log.Int(r.Pos(), 0);
  189. END;
  190. ELSE
  191. parseError := TRUE;
  192. END;
  193. IF ~parseError THEN
  194. log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" "); log.Int(value, 0); log.String(" ... ");
  195. IF ~error THEN log.String("Ok"); ELSE log.String("Failed ("); log.Int(variable, 0); log.String(")"); END;
  196. END;
  197. END CheckInteger;
  198. PROCEDURE CheckBoolean(CONST name : ARRAY OF CHAR; variable : BOOLEAN; r : Streams.Reader; VAR error, parseError : BOOLEAN);
  199. VAR operator : ARRAY 4OF CHAR; value : BOOLEAN;
  200. BEGIN
  201. r.SkipWhitespace; r.String(operator);
  202. IF GetBoolean(r, value) THEN
  203. IF (operator = "=") THEN
  204. error := variable # value;
  205. ELSIF (operator = "#") THEN
  206. error := variable = value;
  207. ELSE
  208. parseError := TRUE;
  209. log.String("Parse error: Unsupported boolean operator: "); log.String(operator);
  210. log.String(", pos = "); log.Int(r.Pos(), 0);
  211. END;
  212. ELSE
  213. parseError := TRUE;
  214. END;
  215. IF ~parseError THEN
  216. log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
  217. IF value THEN log.String("TRUE"); ELSE log.String("FALSE"); END; log.String(" ... ");
  218. IF ~error THEN log.String("Ok"); ELSE log.String("Failed"); END;
  219. END;
  220. END CheckBoolean;
  221. PROCEDURE CheckChar(CONST name : ARRAY OF CHAR; variable : CHAR; r : Streams.Reader; VAR error, parseError : BOOLEAN);
  222. VAR operator : ARRAY 4 OF CHAR; value : CHAR;
  223. BEGIN
  224. r.SkipWhitespace; r.String(operator);
  225. IF GetChar(r, value) THEN
  226. IF (operator = "=") THEN error := variable # value;
  227. ELSIF (operator = "#") THEN error := variable = value;
  228. ELSE
  229. parseError := TRUE;
  230. log.String("Parse error: Unsupported character operator: "); log.String(operator);
  231. END;
  232. ELSE
  233. parseError := TRUE;
  234. END;
  235. IF ~parseError THEN
  236. log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
  237. log.Int(ORD(value), 0); log.String(" ... ");
  238. IF ~error THEN log.String("Ok"); ELSE log.String("Failed ("); log.Int(ORD(variable), 0); log.String(")"); END;
  239. END;
  240. END CheckChar;
  241. PROCEDURE CheckString(CONST name : ARRAY OF CHAR; CONST variable : Strings.String; r : Streams.Reader; VAR error, parseError : BOOLEAN);
  242. VAR operator : ARRAY 4 OF CHAR; value : Strings.String; i : LONGINT;
  243. BEGIN
  244. r.SkipWhitespace; r.String(operator);
  245. IF GetString(r, value) THEN
  246. ASSERT(value # NIL);
  247. IF (operator = "=") THEN
  248. error := ~StringsAreEqual(value, buffer);
  249. ELSIF (operator = "#") THEN
  250. error := StringsAreEqual(value, buffer);
  251. ELSE
  252. parseError := TRUE;
  253. log.String("Parse error: Unsupported string operator: "); log.String(operator);
  254. END;
  255. ELSE
  256. parseError := TRUE;
  257. END;
  258. IF ~parseError THEN
  259. log.String("ASSERT "); log.String(name); log.Char(" "); log.String(operator); log.Char(" ");
  260. i := 0;
  261. WHILE (i < LEN(value)) & (i < 20) & (value[i] # 0X) DO log.Char(value[i]); INC(i); END;
  262. log.String(" ... ");
  263. IF ~error THEN log.String("Ok"); ELSE log.String("Failed"); END;
  264. END;
  265. END CheckString;
  266. BEGIN
  267. variable := "";
  268. r.SkipWhitespace; r.String(variable);
  269. IF (variable # "") THEN
  270. IF (variable = "rider.res") THEN
  271. CheckInteger(variable, rider.res, r, error, parseError);
  272. ELSIF (variable = "rider.eof") THEN
  273. CheckBoolean(variable, rider.eof, r, error, parseError);
  274. ELSIF (variable = "reader.res") THEN
  275. CheckInteger(variable, reader.res, r, error, parseError);
  276. ELSIF (variable = "byte") THEN
  277. CheckChar(variable, byte, r, error, parseError);
  278. ELSIF (variable = "readerBytesLength") THEN
  279. CheckInteger(variable, readerBytesLength, r, error, parseError);
  280. ELSIF (variable = "buffer") THEN
  281. CheckString(variable, buffer, r, error, parseError);
  282. ELSIF Strings.Match("buffer*", variable) THEN
  283. IF GetIndex(variable, index) THEN
  284. IF (buffer # NIL) & (index < LEN(buffer)) THEN
  285. CheckChar(variable, buffer[index], r, error, parseError);
  286. ELSE
  287. error := TRUE;
  288. END;
  289. ELSE
  290. parseError := TRUE;
  291. END;
  292. ELSIF (variable = "File.Length()") & CheckOpen(error) THEN
  293. CheckInteger(variable, file.Length(), r, error, parseError);
  294. ELSIF (variable = "File.Pos()") & CheckOpen(error) THEN
  295. CheckInteger(variable, file.Pos(rider), r, error, parseError);
  296. ELSIF (variable = "Reader.Available()") & CheckOpen(error) THEN
  297. CheckInteger(variable, reader.Available(), r, error, parseError);
  298. ELSIF (variable = "Reader.Pos()") & CheckOpen(error) THEN
  299. CheckInteger(variable, reader.Pos(), r, error, parseError);
  300. ELSE
  301. parseError := TRUE;
  302. log.String("Parse error: Unknown variable "); log.String(variable);
  303. log.String(", pos = "); log.Int(r.Pos(), 0);
  304. END;
  305. ELSE
  306. parseError := TRUE;
  307. log.String("Parse error: Expected variable name in ASSERT, pos = "); log.Int(r.Pos(), 0);
  308. END;
  309. END Assert;
  310. PROCEDURE Set(r : Streams.Reader; VAR error, parseError : BOOLEAN);
  311. VAR
  312. variable, to : ARRAY 32 OF CHAR;
  313. charValue : CHAR; integerValue : LONGINT; booleanValue : BOOLEAN; stringValue : Strings.String;
  314. set, i : LONGINT; index : LONGINT;
  315. BEGIN
  316. r.SkipWhitespace; r.String(variable);
  317. IF (variable = "rider.res") OR (variable = "rider.eof") OR (variable = "byte") OR (variable = "readerBytesLength") OR
  318. (variable = "buffer") OR Strings.Match("buffer*", variable) THEN
  319. r.SkipWhitespace; r.String(to);
  320. IF (to = "TO") THEN
  321. IF (variable = "rider.res") THEN
  322. set := Integer;
  323. IF GetInteger(r, integerValue) THEN rider.res := integerValue; ELSE parseError := TRUE; END;
  324. ELSIF (variable = "rider.eof") THEN
  325. set := Boolean;
  326. IF GetBoolean(r, booleanValue) THEN rider.eof := booleanValue; ELSE parseError := TRUE; END;
  327. ELSIF (variable = "reader.res") THEN
  328. set := Integer;
  329. IF GetInteger(r, integerValue) THEN reader.res := integerValue; ELSE parseError := TRUE; END;
  330. ELSIF (variable = "byte") THEN
  331. set := Char;
  332. IF GetChar(r, charValue) THEN byte := charValue; ELSE parseError := TRUE; END;
  333. ELSIF (variable = "readerBytesLength") THEN
  334. set := Integer;
  335. IF GetInteger(r, integerValue) THEN readerBytesLength := integerValue; ELSE parseError := TRUE; END;
  336. ELSIF (variable = "buffer") THEN
  337. set := String;
  338. IF GetString(r, stringValue) THEN
  339. ASSERT((stringValue # NIL) & (stringValue[LEN(stringValue)-1] = 0X));
  340. IF (buffer # NIL) & (LEN(buffer) >= LEN(stringValue)-1) THEN
  341. FOR i := 0 TO LEN(stringValue)-2 DO (* don-t include 0X *)
  342. buffer[i] := stringValue[i];
  343. END;
  344. ELSE
  345. error := TRUE;
  346. END;
  347. ELSE
  348. parseError := TRUE;
  349. END;
  350. ELSIF Strings.Match("buffer*", variable) THEN
  351. IF GetIndex(variable, index) THEN
  352. IF (buffer # NIL) & (index < LEN(buffer)) THEN
  353. IF GetChar(r, charValue) THEN
  354. buffer[index] := charValue;
  355. ELSE
  356. parseError := TRUE;
  357. END;
  358. ELSE
  359. error := TRUE;
  360. END;
  361. ELSE
  362. parseError := TRUE;
  363. END;
  364. END;
  365. IF ~parseError THEN
  366. log.String("SET "); log.String(variable); log.String(" to ");
  367. IF (set = Boolean) THEN
  368. IF booleanValue THEN log.String("TRUE"); ELSE log.String("FALSE"); END;
  369. ELSIF (set = Integer) THEN
  370. log.Int(integerValue, 0);
  371. ELSIF (set = Char) THEN
  372. log.Int(ORD(charValue), 0);
  373. ELSIF (set = String) THEN
  374. IF (stringValue # NIL) THEN
  375. i := 0;
  376. WHILE (i < LEN(stringValue)) & (i < 20) & (stringValue[i] # 0X) DO
  377. log.Char(stringValue[i]); INC(i);
  378. END;
  379. IF (i < LEN(stringValue)) & (stringValue[i] # 0X) THEN
  380. log.String(" ... ");
  381. END;
  382. ELSE
  383. log.String("NIL");
  384. END;
  385. END;
  386. IF ~error THEN log.String(" ... Ok"); ELSE log.String(" ... Failed"); END;
  387. END;
  388. ELSE
  389. parseError := TRUE;
  390. log.String("Parse error: Expected TO, pos = "); log.Int(r.Pos(), 0);
  391. END;
  392. ELSE
  393. parseError := TRUE;
  394. log.String("Parse error: Unknown variable in SET: "); log.String(variable); log.Int(r.Pos(), 0);
  395. END;
  396. END Set;
  397. PROCEDURE FileReadByte(VAR error : BOOLEAN);
  398. BEGIN
  399. IF CheckOpen(error) THEN
  400. log.String("File.Read ... "); log.Update;
  401. file.Read(rider, byte);
  402. log.String("value="); log.Int(ORD(byte), 0); log.String(", Ok");
  403. END;
  404. END FileReadByte;
  405. PROCEDURE FileWriteByte(VAR error : BOOLEAN);
  406. BEGIN
  407. IF CheckOpen(error) THEN
  408. log.String("File.Write: "); log.Int(ORD(byte), 0); log.String(" ... "); log.Update;
  409. file.Write(rider, byte);
  410. log.String("Ok");
  411. END;
  412. END FileWriteByte;
  413. PROCEDURE FileReadBytes(offset, length : LONGINT; VAR error : BOOLEAN);
  414. BEGIN
  415. IF CheckOpen(error) THEN
  416. log.String("File.ReadBytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String(" ... "); log.Update;
  417. file.ReadBytes(rider, buffer^, offset, length);
  418. log.String("Ok");
  419. END;
  420. END FileReadBytes;
  421. PROCEDURE FileWriteBytes(offset, length : LONGINT; VAR error : BOOLEAN);
  422. BEGIN
  423. IF CheckOpen(error) THEN
  424. log.String("File.WriteBytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String(" ... "); log.Update;
  425. file.WriteBytes(rider, buffer^, offset, length);
  426. log.String("Ok");
  427. END;
  428. END FileWriteBytes;
  429. PROCEDURE ReaderGet(VAR error : BOOLEAN);
  430. BEGIN
  431. IF CheckOpen(error) THEN
  432. log.String("Reader.Get ... "); log.Update;
  433. byte := reader.Get();
  434. log.String("value="); log.Int(ORD(byte), 0); log.String(", Ok");
  435. END;
  436. END ReaderGet;
  437. PROCEDURE ReaderBytes(offset, length : LONGINT; VAR error : BOOLEAN);
  438. BEGIN
  439. IF CheckOpen(error) THEN
  440. log.String("Reader.Bytes "); log.Int(offset, 0); log.String(" "); log.Int(length, 0); log.String("... "); log.Update;
  441. reader.Bytes(buffer^, offset, length, readerBytesLength);
  442. log.Int(readerBytesLength, 0); log.String(" bytes read, Ok");
  443. END;
  444. END ReaderBytes;
  445. PROCEDURE ReaderSetPos(position : LONGINT; VAR error : BOOLEAN);
  446. BEGIN
  447. IF CheckOpen(error) THEN
  448. log.String("Reader.SetPos "); log.Int(position, 0); log.String(" ... "); log.Update;
  449. reader.SetPos(position);
  450. log.String("Ok");
  451. END;
  452. END ReaderSetPos;
  453. PROCEDURE InitBuffer(length : LONGINT);
  454. PROCEDURE Clear;
  455. VAR i : LONGINT;
  456. BEGIN
  457. FOR i := 0 TO LEN(buffer)-1 DO
  458. buffer[i] := 0X;
  459. END;
  460. END Clear;
  461. BEGIN
  462. log.String("INITBUFFER "); log.Int(length, 0); log.String(" ... "); log.Update;
  463. IF (length = 0) THEN
  464. buffer := NIL;
  465. ELSIF (buffer # NIL) & (LEN(buffer) = length) THEN
  466. Clear;
  467. ELSE
  468. NEW(buffer, length);
  469. Clear;
  470. END;
  471. log.String("Ok");
  472. END InitBuffer;
  473. PROCEDURE CallCommand(r : Streams.Reader; VAR error, parseError : BOOLEAN);
  474. VAR
  475. context : Commands.Context;
  476. arg : Streams.StringReader;
  477. commandStr : ARRAY 128 OF CHAR; parameterStr : Strings.String;
  478. msg : ARRAY 128 OF CHAR;
  479. pos : SIZE; res : WORD;
  480. BEGIN
  481. NEW(parameterStr, 4096); Strings.Truncate(parameterStr^, 0);
  482. r.SkipWhitespace; r.String(commandStr);
  483. r.Ln(parameterStr^);
  484. Strings.TrimWS(parameterStr^);
  485. pos := Strings.Pos("<path>", parameterStr^);
  486. WHILE (pos >= 0) DO
  487. Strings.Delete(parameterStr^, pos, Strings.Length("<path>"));
  488. Strings.Insert(path, parameterStr^, pos);
  489. pos := Strings.Pos("<path>", parameterStr^);
  490. END;
  491. log.String("CALL '"); log.String(parameterStr^); log.String("' ... "); log.Update;
  492. IF (commandStr # "") THEN
  493. NEW(arg, Strings.Length(parameterStr^));
  494. arg.SetRaw(parameterStr^, 0, Strings.Length(parameterStr^));
  495. NEW(context, NIL, arg, log, log, SELF);
  496. Commands.Activate(commandStr, context, {Commands.Wait}, res, msg);
  497. IF (res = Commands.Ok) THEN
  498. log.String("Ok");
  499. ELSE
  500. error := TRUE;
  501. log.String("Failed, "); log.String(msg); log.String(", res: "); log.Int(res, 0);
  502. END;
  503. ELSE
  504. parseError := TRUE;
  505. log.String("Parse error: Expected argument for CALL");
  506. END;
  507. END CallCommand;
  508. PROCEDURE ProcessCommand(r : Streams.Reader; VAR error, parseError, finished : BOOLEAN);
  509. VAR
  510. filename : Files.FileName;
  511. string : ARRAY 64 OF CHAR;
  512. offset, length, position : LONGINT;
  513. BEGIN
  514. error := FALSE; parseError := FALSE;
  515. IF ~r.GetString(string) THEN finished := TRUE; RETURN; ELSE finished := FALSE; END;
  516. IF ~lastCommandWasComment THEN log.String(" "); ELSE lastCommandWasComment := FALSE; END;
  517. IF (string = "Files.Old") THEN (* Files.Old <filename> *)
  518. r.SkipWhitespace; r.String(filename);
  519. OpenFile(filename, error);
  520. ELSIF (string = "Files.New") THEN (* Files.New <filename> *)
  521. r.SkipWhitespace; r.String(filename);
  522. CreateFile(filename, error);
  523. ELSIF (string = "DELETE") THEN (* DELETE <filename> (does not cause error) *)
  524. r.SkipWhitespace; r.String(filename);
  525. DeleteFile(filename, error); error := FALSE;
  526. ELSIF (string = "REGISTER") THEN (* REGISTER *)
  527. RegisterFile(error);
  528. ELSIF (string = "File.Set") & GetInteger(r, position) THEN (* File.Set <position> *)
  529. FileSet(position, error);
  530. ELSIF (string = "SET") THEN (* SET variable TO value *)
  531. Set(r, error, parseError);
  532. ELSIF (string = "ASSERT") THEN (* ASSERT <variable> <operator> <value> *)
  533. Assert(r, error, parseError);
  534. ELSIF (string = "File.Read") THEN (* File.Read *)
  535. FileReadByte(error);
  536. ELSIF (string = "File.ReadBytes") & GetInteger(r, offset) & GetInteger(r, length) THEN (* File.ReadBytes offset length *)
  537. FileReadBytes(offset, length, error);
  538. ELSIF (string = "File.Write") THEN (* File.Write *)
  539. FileWriteByte(error);
  540. ELSIF (string = "File.WriteBytes") & GetInteger(r, offset) & GetInteger(r, length) THEN (* File.WriteBytes offset length *)
  541. FileWriteBytes(offset, length, error);
  542. ELSIF (string = "Reader.Get") THEN (* Reader.Get *)
  543. ReaderGet(error);
  544. ELSIF (string = "Reader.Bytes") & GetInteger(r, offset) & GetInteger(r, length) THEN (* Reader.Bytes offset length *)
  545. ReaderBytes(offset, length, error);
  546. ELSIF (string = "Reader.SetPos") & GetInteger(r, position) THEN (* Reader.SetPosition position *)
  547. ReaderSetPos(position, error);
  548. ELSIF (string = "INITBUFFER") & GetInteger(r, length) THEN (* INITBUFFER length *)
  549. InitBuffer(length);
  550. ELSIF (string = "CALL") THEN
  551. CallCommand(r, error, parseError);
  552. ELSIF (string[0] = "#") THEN (* comment *)
  553. lastCommandWasComment := TRUE;
  554. r.SkipLn;
  555. ELSE
  556. log.Ln; log.String("Parse Error: Expected command, but found: "); log.String(string); log.String(", pos = "); log.Int(r.Pos(), 0); log.Ln;
  557. parseError := TRUE;
  558. END;
  559. IF ~parseError & (string[0] # "#") THEN log.Ln; log.Update; END;
  560. END ProcessCommand;
  561. PROCEDURE Handle*(r: Streams.Reader; pos : LONGINT; CONST name: ARRAY OF CHAR; testType: TestSuite.TestType): INTEGER;
  562. VAR result: INTEGER; error, parseError, finished, trapped: BOOLEAN;
  563. BEGIN
  564. trapped := TRUE;
  565. Reset;
  566. error := FALSE; parseError := FALSE;
  567. result := TestSuite.Failure;
  568. log.String ("testing: "); log.String (name); log.Update; log.Ln;
  569. REPEAT
  570. ProcessCommand(r, error, parseError, finished);
  571. log.Update;
  572. UNTIL (error OR parseError OR finished);
  573. trapped := FALSE;
  574. IF parseError THEN result := TestSuite.Failure;
  575. ELSIF error THEN result := TestSuite.Negative;
  576. ELSE result := TestSuite.Positive;
  577. END;
  578. FINALLY
  579. IF trapped THEN log.String("TRAP"); END;
  580. log.Ln; log.Update;
  581. RETURN result;
  582. END Handle;
  583. END Tester;
  584. (* string is 0X terminated, buffer is NOT 0X terminated *)
  585. PROCEDURE StringsAreEqual(string, buffer : Strings.String) : BOOLEAN;
  586. VAR i : LONGINT;
  587. BEGIN
  588. IF (string # NIL) & (buffer # NIL) & (string[LEN(string)-1] = 0X) & (LEN(string) = LEN(buffer) + 1) THEN
  589. i := 0;
  590. WHILE (i < LEN(string) - 1) & (string[i] = buffer[i]) DO INC(i); END;
  591. RETURN (i >= LEN(string) - 1);
  592. END;
  593. RETURN FALSE;
  594. END StringsAreEqual;
  595. PROCEDURE IsNumber(CONST string : ARRAY OF CHAR) : BOOLEAN;
  596. VAR i : LONGINT;
  597. BEGIN
  598. IF ("0" <= string[0]) & (string[0] <= "9") THEN
  599. FOR i := 1 TO Strings.Length(string)-1 DO
  600. IF (string[i] < "0") & ("9" < string[i]) THEN
  601. RETURN FALSE;
  602. END;
  603. END;
  604. RETURN TRUE;
  605. END;
  606. RETURN FALSE;
  607. END IsNumber;
  608. PROCEDURE Test*(context : Commands.Context); (** [Options] TestFile(input) [TestResultFile] ~ *)
  609. VAR options : Options.Options; tester: Tester; report: TestSuite.StreamReport; path : Files.FileName;
  610. BEGIN
  611. NEW(options);
  612. options.Add("p", "path", Options.String);
  613. IF options.Parse(context.arg, context.error) THEN
  614. IF ~options.GetString("path", path) THEN path := ""; END;
  615. NEW(tester, context.out, path);
  616. NEW(report, context.out);
  617. TestSuite.Drive(context, tester);
  618. tester.Print(report);
  619. END;
  620. END Test;
  621. PROCEDURE RandomReadWrite*(context : Commands.Context); (** path filename seed nofRuns ~ *)
  622. VAR
  623. path, filename, fullname : Files.FileName;
  624. seed, run, nofRuns, position, lastPosition, length0, temp, lastPercent : LONGINT;
  625. char, lastChar, ch : CHAR;
  626. file : Files.File; rider : Files.Rider;
  627. random : Random.Generator;
  628. BEGIN
  629. context.arg.SkipWhitespace; context.arg.String(path);
  630. context.arg.SkipWhitespace; context.arg.String(filename);
  631. context.arg.SkipWhitespace; context.arg.Int(seed, FALSE);
  632. context.arg.SkipWhitespace; context.arg.Int(nofRuns, FALSE);
  633. COPY(path, fullname); Strings.Append(fullname, filename);
  634. context.out.String(" RandomReadWrite on file '"); context.out.String(fullname); context.out.String("' (");
  635. context.out.Int(nofRuns, 0); context.out.String(" runs)' ... ");
  636. context.out.Update;
  637. file := Files.Old(fullname);
  638. IF (file # NIL) THEN
  639. NEW(random);
  640. random.InitSeed(seed);
  641. length0 := file.Length();
  642. run := 0;
  643. lastChar := 0X; lastPosition := 0; lastPercent := 0;
  644. context.out.String("0% "); context.out.Update;
  645. WHILE (run <= nofRuns) DO
  646. IF (100 * run DIV nofRuns >= lastPercent + 10) THEN
  647. lastPercent := lastPercent + 10;
  648. context.out.Int(lastPercent, 0); context.out.String("% "); context.out.Update;
  649. END;
  650. position := random.Dice(length0);
  651. temp := random.Dice(255) + 1;
  652. char := CHR(temp);
  653. file.Set(rider, position);
  654. ASSERT(file.Pos(rider) = position);
  655. file.Write(rider, char);
  656. ASSERT(rider.res = 0);
  657. ASSERT(rider.eof = FALSE);
  658. ASSERT(file.Length() = length0);
  659. IF (lastChar # 0X) THEN
  660. file.Set(rider, lastPosition);
  661. ASSERT(file.Pos(rider) = lastPosition);
  662. file.Read(rider, ch);
  663. ASSERT(rider.res = 0);
  664. ASSERT(rider.eof = FALSE);
  665. ASSERT(file.Length() = length0);
  666. ASSERT(ch = lastChar);
  667. END;
  668. lastChar := char;
  669. lastPosition := position;
  670. INC(run);
  671. END;
  672. context.out.String("Ok"); context.out.Ln;
  673. ELSE
  674. context.out.String("Failed (File not found)"); context.out.Ln; context.out.Update;
  675. HALT(99);
  676. END;
  677. END RandomReadWrite;
  678. PROCEDURE CreateTestFiles*(context : Commands.Context); (** [path] ~ *)
  679. VAR path : Files.FileName; i : LONGINT;
  680. PROCEDURE CreateFile(CONST path, filename : ARRAY OF CHAR; size : LONGINT);
  681. VAR file : Files.File; rider : Files.Rider; fullname : Files.FileName;
  682. BEGIN
  683. COPY(path, fullname); Strings.Append(fullname, filename);
  684. context.out.String("Create test file '"); context.out.String(fullname); context.out.String("' ... ");
  685. context.out.Update;
  686. file := Files.New(fullname);
  687. IF (file # NIL) THEN
  688. file.Set(rider, 0);
  689. FOR i := 1 TO size DO
  690. IF (i MOD 2 = 0) THEN file.Write(rider, 1X) ELSE file.Write(rider, 0FFX); END;
  691. END;
  692. Files.Register(file);
  693. context.out.String("Ok");
  694. ELSE
  695. context.out.String("Failed");
  696. END;
  697. context.out.Ln;
  698. END CreateFile;
  699. BEGIN
  700. path := ""; context.arg.SkipWhitespace; context.arg.String(path);
  701. CreateFile(path, "TestFile0.Bin", 0);
  702. CreateFile(path, "TestFile4096.Bin", 4096);
  703. CreateFile(path, "TestFile8192.Bin", 8192);
  704. END CreateTestFiles;
  705. END TestFiles.
  706. TestFiles.CreateTestFiles ~
  707. System.Free TestFiles TestSuite~
  708. WMUtilities.Call TestFiles.Test Files.Test ~ Verbose testing mode
  709. WMUtilities.Call TestFiles.Test Files.Test Files.Test.tmp ~ Regression testing mode
  710. System.DoCommands
  711. VirtualDisks.InstallRamdisk TEST 163840 ~
  712. Partitions.WriteMBR TEST#0 OBEMBR.Bin ~
  713. System.Show AosFS File System ~ System.Ln ~
  714. Partitions.Create TEST#1 76 9999 ~
  715. Partitions.Format TEST#1 AosFS ~
  716. Partitions.Mount TEST#1 AosFS TEST ~
  717. WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
  718. FSTools.Unmount TEST ~
  719. System.Show FatFS File System ~ System.Ln ~
  720. Partitions.ChangeType TEST#1 76 12 ~
  721. Partitions.Format TEST#1 FatFS ~
  722. Partitions.Mount TEST#1 FatFS TEST ~
  723. WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
  724. FSTools.Unmount TEST ~
  725. System.Show SSFS File System ~ System.Ln ~
  726. SSFS.Format TEST#1 ~
  727. SSFS.Mount TEST TEST#1 ~
  728. WMUtilities.Call --blocking TestFiles.Test --path="TEST:" Files.Test ~
  729. SSFS.Unmount TEST ~
  730. VirtualDisks.Uninstall TEST ~
  731. ~~