FoxTest.Mod 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. MODULE FoxTest; (** AUTHOR "fof"; PURPOSE "Fox tester"; *)
  2. (* (c) fof ETH Zürich, 2008 *)
  3. IMPORT Basic := FoxBasic, TestSuite, Diagnostics, Streams, Commands, Shell, Options, Files, Strings, Versioning, CompilerInterface, Texts, TextUtilities, Modules, KernelLog;
  4. TYPE
  5. Command = ARRAY 256 OF CHAR;
  6. Tester = OBJECT (TestSuite.Tester)
  7. VAR
  8. log: Streams.Writer;
  9. fileLog: Streams.Writer;
  10. mayTrap: BOOLEAN;
  11. commandFlags: SET;
  12. command, prolog, epilog: Command;
  13. fileName: Files.FileName;
  14. dots: LONGINT;
  15. PROCEDURE &InitTester (log, logFileWriter: Streams.Writer; diagnostics: Diagnostics.Diagnostics; mayTrap: BOOLEAN; CONST prolog, command, epilog: Command; CONST fileName: ARRAY OF CHAR);
  16. BEGIN
  17. Init (diagnostics); SELF.log := log; SELF.mayTrap := mayTrap; SELF.fileLog := logFileWriter;
  18. COPY(prolog, SELF.prolog);
  19. COPY(epilog, SELF.epilog);
  20. COPY(command, SELF.command);
  21. COPY(fileName, SELF.fileName);
  22. commandFlags := {Commands.Wait};
  23. IF log = NIL THEN INCL(commandFlags, Commands.Silent) END;
  24. END InitTester;
  25. PROCEDURE Handle* (r: Streams.Reader; position: LONGINT; CONST name: ARRAY OF CHAR; type: TestSuite.TestType): INTEGER;
  26. VAR result: INTEGER; msg: ARRAY 128 OF CHAR; res: WORD; f: Files.File; w: Files.Writer; ch: CHAR;
  27. BEGIN
  28. result := TestSuite.Failure;
  29. IF log # NIL THEN log.String ("testing: "); log.String (name); log.String("@"); log.Int(position,0); log.Ln; log.Update; END;
  30. (* prepare tester input as a file for all test cases *)
  31. f := Files.New(fileName);
  32. NEW(w,f,0);
  33. WHILE r.Available() > 0 DO
  34. r.Char(ch); w.Char(ch)
  35. END;
  36. w.Update;
  37. Files.Register(f);
  38. IF log = NIL THEN KernelLog.Char("."); INC(dots); IF dots MOD 256 = 0 THEN KernelLog.Ln END; END;
  39. res := Commands.Ok;
  40. IF prolog # "" THEN
  41. Commands.Call(prolog, commandFlags, res, msg);
  42. IF (res # Commands.Ok) & (log # NIL) THEN
  43. log.String("prolog failed: "); log.String(msg); log.Ln;
  44. END;
  45. END;
  46. IF (command # "") & (res = Commands.Ok) THEN
  47. Commands.Call(command, commandFlags, res, msg);
  48. IF res = Commands.Ok THEN
  49. result := TestSuite.Positive
  50. ELSIF (res < 3500) & (res >= 3440) THEN (* loader error *)
  51. result := TestSuite.Failure
  52. ELSIF ~mayTrap & (res = Commands.CommandTrapped) THEN (* command error, trap *)
  53. result := TestSuite.Failure
  54. ELSE
  55. result := TestSuite.Negative
  56. END;
  57. IF (result # type) & (log # NIL) THEN
  58. log.String (msg); log.Ln;
  59. END;
  60. ELSIF (command # "") THEN result := TestSuite.Failure
  61. END;
  62. IF epilog # "" THEN
  63. Commands.Call(epilog, commandFlags, res, msg);
  64. END;
  65. IF fileLog # NIL THEN
  66. IF result = type THEN
  67. fileLog.String("success: ")
  68. ELSE
  69. fileLog.String("failure: ")
  70. END;
  71. fileLog.String(name); fileLog.Ln;
  72. END;
  73. FINALLY
  74. RETURN result;
  75. END Handle;
  76. END Tester;
  77. PROCEDURE GetOptions(): Options.Options;
  78. VAR options: Options.Options;
  79. BEGIN
  80. NEW(options);
  81. options.Add("p","prolog", Options.String);
  82. options.Add("e","epilog", Options.String);
  83. options.Add("c","command", Options.String);
  84. options.Add("v","verbose",Options.Flag);
  85. options.Add("t","mayTrap",Options.Flag);
  86. options.Add("f","fileName",Options.String);
  87. options.Add("l","logFile",Options.String);
  88. options.Add("r","result",Options.String);
  89. RETURN options
  90. END GetOptions;
  91. PROCEDURE DriveTest (options: Options.Options; diagnostics: Diagnostics.Diagnostics; reader: Streams.Reader; error, writer: Streams.Writer): BOOLEAN;
  92. VAR
  93. tester: Tester; prolog, epilog, command: Command;
  94. verbose, mayTrap: BOOLEAN; report: TestSuite.StreamReport; fileName, logFileName: Files.FileName; logFileWriter, log:Streams.Writer;
  95. testname, resultname: Files.FileName;
  96. baseOptions: Options.Options; ch: CHAR; string: ARRAY 256 OF CHAR; stringReader: Streams.StringReader;
  97. BEGIN
  98. reader.SetPos(0);
  99. WHILE reader.Available() >0 DO
  100. reader.SkipWhitespace;
  101. reader.Char(ch);
  102. IF (ch = "#") THEN
  103. IF reader.GetString(string) & Strings.StartsWith("options",0,string) THEN
  104. reader.Ln(string);
  105. NEW(stringReader, LEN(string));
  106. stringReader.Set(string);
  107. baseOptions := GetOptions();
  108. IF baseOptions.Parse(stringReader, error) THEN
  109. Options.Merge(options, baseOptions);
  110. ELSE
  111. RETURN FALSE;
  112. END;
  113. ELSE
  114. reader.SkipLn()
  115. END;
  116. ELSE
  117. reader.SkipLn()
  118. END;
  119. END;
  120. IF ~options.GetString("p", prolog) THEN prolog := "" END;
  121. IF ~options.GetString("c", command) THEN command := "" END;
  122. IF ~options.GetString("e", epilog) THEN epilog := "" END;
  123. IF ~options.GetString("f", fileName) THEN fileName := "TesterInput.txt" END;
  124. mayTrap := options.GetFlag("t");
  125. verbose := options.GetFlag("verbose");
  126. IF options.GetString("l",logFileName) THEN
  127. logFileWriter := Versioning.NewLogWriter(logFileName, "Test",testname);
  128. logFileWriter.Ln;
  129. logFileWriter.String("prolog= "); logFileWriter.String(prolog); logFileWriter.Ln;
  130. logFileWriter.String("command= "); logFileWriter.String(command); logFileWriter.Ln;
  131. logFileWriter.Ln;
  132. END;
  133. IF ~options.GetString("r",resultname) THEN resultname := "" END;
  134. IF verbose THEN log := writer ELSE log := NIL END;
  135. NEW (tester, log, logFileWriter, diagnostics, mayTrap, prolog, command, epilog, fileName);
  136. NEW (report, writer);
  137. reader.SetPos(0);
  138. IF ~TestSuite.DriveByReader(reader, error, resultname, tester) THEN RETURN FALSE END;
  139. tester.Print (report);
  140. IF logFileWriter # NIL THEN
  141. NEW(report, logFileWriter);
  142. tester.Print(report);
  143. logFileWriter.Update;
  144. writer.String("testing logged in "); writer.String(logFileName); writer.Ln;
  145. END;
  146. writer.Update;
  147. RETURN report.failed = 0;
  148. END DriveTest;
  149. PROCEDURE Compile* (context: Commands.Context);
  150. VAR writer: Streams.Writer; options: Options.Options;diagnostics: Diagnostics.StreamDiagnostics; testname: Files.FileName; test: Files.File;
  151. reader: Files.Reader;
  152. BEGIN
  153. IF (context.caller # NIL) & (context.caller IS Shell.Shell) THEN
  154. writer := context.out
  155. ELSE
  156. writer := Basic.GetDebugWriter("Oberon Compiler Test Results")
  157. END;
  158. options := GetOptions();
  159. IF options.Parse(context.arg, context.error) THEN
  160. NEW (diagnostics, writer);
  161. IF context.arg.GetString (testname) THEN
  162. test := Files.Old (testname);
  163. IF test = NIL THEN
  164. context.error.String ("Failed to open test file "); context.error.String (testname); context.error.Ln;
  165. RETURN;
  166. END;
  167. ELSE
  168. context.result := Commands.CommandParseError;
  169. END;
  170. Files.OpenReader(reader, test, 0);
  171. IF ~DriveTest (options, diagnostics, reader, context.error, writer) THEN
  172. context.result := Commands.CommandError;
  173. END;
  174. ELSE
  175. context.result := Commands.CommandError;
  176. END;
  177. END Compile;
  178. PROCEDURE GetTextReader(text: Texts.Text): Streams.Reader;
  179. VAR
  180. buffer : POINTER TO ARRAY OF CHAR;
  181. length: LONGINT; reader: Streams.StringReader;
  182. BEGIN
  183. ASSERT((text # NIL));
  184. text.AcquireRead;
  185. length := text.GetLength();
  186. text.ReleaseRead;
  187. IF length = 0 THEN length := 1 END;
  188. NEW(buffer, length);
  189. TextUtilities.TextToStr(text, buffer^);
  190. (* prepare the reader *)
  191. NEW(reader, LEN(buffer)); reader.SetRaw(buffer^, 0, LEN(buffer));
  192. RETURN reader
  193. END GetTextReader;
  194. PROCEDURE RunTests(
  195. text : Texts.Text;
  196. CONST source: ARRAY OF CHAR;
  197. pos: LONGINT; (* ignore *)
  198. CONST pc,opt: ARRAY OF CHAR;
  199. log: Streams.Writer; diagnostics : Diagnostics.Diagnostics; VAR error: BOOLEAN);
  200. VAR
  201. reader: Streams.Reader;
  202. options: Options.Options;
  203. optionReader: Streams.StringReader;
  204. BEGIN
  205. ASSERT((text # NIL) & (diagnostics # NIL));
  206. reader := GetTextReader(text);
  207. options := GetOptions();
  208. NEW(optionReader, LEN(opt));
  209. optionReader.Set(opt);
  210. IF options.Parse(optionReader, log) THEN
  211. error := ~DriveTest (options, diagnostics, reader, log, log);
  212. ELSE
  213. error := TRUE;
  214. END;
  215. END RunTests;
  216. PROCEDURE Cleanup;
  217. BEGIN
  218. CompilerInterface.Unregister("TestTool");
  219. END Cleanup;
  220. BEGIN
  221. CompilerInterface.Register("TestTool", "Run test cases against Fox compiler", "Test", RunTests);
  222. Modules.InstallTermHandler(Cleanup);
  223. END FoxTest.
  224. System.Free FoxTest TestSuite Versioning ~
  225. FoxTest.Compile Oberon.Execution.Test Oberon.Execution.AMD64TestDiff ~
  226. FoxTest.Compile Oberon.Compilation.Test Oberon.Compilation.AMD64TestDiff ~
  227. FoxTest.Compile MathVectors.Test MathVectors.Test.Diff ~
  228. FoxTest.Compile
  229. --verbose
  230. --fileName="TesterInput.Mod"
  231. --prolog="Compiler.Compile TesterInput.Mod"
  232. --command="System.Free Test Dummy B A;System.Load Test"
  233. --logFile="FoxExecutionTest.Log"
  234. MathVectors.Test MathVectors.Test.Diff ~