PageRenderTime 37ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/tool/gecop/src/gecop.e

http://github.com/gobo-eiffel/gobo
Specman e | 625 lines | 523 code | 49 blank | 53 comment | 37 complexity | a8833f9657c09adc3d4e80a0fa145dad MD5 | raw file
  1. note
  2. description:
  3. "[
  4. Gobo Eiffel Cop.
  5. An Eiffel language conformance validation suite.
  6. ]"
  7. copyright: "Copyright (c) 2018-2021, Eric Bezault and others"
  8. license: "MIT License"
  9. date: "$Date$"
  10. revision: "$Revision$"
  11. class GECOP
  12. inherit
  13. GECOP_VERSION
  14. KL_SHARED_EXCEPTIONS
  15. KL_SHARED_ARGUMENTS
  16. KL_SHARED_FILE_SYSTEM
  17. KL_SHARED_EXECUTION_ENVIRONMENT
  18. KL_SHARED_OPERATING_SYSTEM
  19. KL_SHARED_STANDARD_FILES
  20. KL_IMPORTED_STRING_ROUTINES
  21. create
  22. execute,
  23. execute_with_arguments,
  24. execute_with_arguments_and_error_handler
  25. feature -- Execution
  26. execute
  27. -- Start 'gecop' execution, reading arguments from the command-line.
  28. do
  29. execute_with_arguments (Arguments.to_array)
  30. Exceptions.die (exit_code)
  31. rescue
  32. Exceptions.die (4)
  33. end
  34. execute_with_arguments (a_args: ARRAY [STRING])
  35. -- Start 'gecop' execution with arguments `a_args'.
  36. -- Set `exit_code'.
  37. require
  38. a_args_not_void: a_args /= Void
  39. no_void_arg: across a_args is l_arg all l_arg /= Void end
  40. local
  41. l_error_handler: UT_ERROR_HANDLER
  42. do
  43. create l_error_handler.make_standard
  44. execute_with_arguments_and_error_handler (a_args, l_error_handler)
  45. end
  46. execute_with_arguments_and_error_handler (a_args: ARRAY [STRING]; a_error_handler: UT_ERROR_HANDLER)
  47. -- Start 'gecop' execution.
  48. -- Set `exit_code'.
  49. require
  50. a_args_not_void: a_args /= Void
  51. no_void_arg: across a_args is l_arg all l_arg /= Void end
  52. a_error_handler_not_void: a_error_handler /= Void
  53. local
  54. l_validation_directory_name: STRING
  55. l_directory: KL_DIRECTORY
  56. l_relative_path: DS_ARRAYED_LIST [STRING]
  57. l_tested_eiffel_tool: STRING
  58. l_tester: TS_TESTER
  59. l_test_suite: TS_TEST_SUITE
  60. l_output_stream: KL_STRING_OUTPUT_STREAM
  61. l_output_string: STRING
  62. l_aggregate, l_diff: BOOLEAN
  63. l_set_up_mutex: MUTEX
  64. do
  65. Arguments.set_program_name ("gecop")
  66. create error_handler.make_standard
  67. parse_arguments (a_args)
  68. if exit_code = 0 and then not version_flag.was_found then
  69. if tool_option.was_found and then attached tool_option.parameter as l_tool_name then
  70. l_tested_eiffel_tool := l_tool_name
  71. else
  72. l_tested_eiffel_tool := default_tested_eiffel_tool
  73. end
  74. if validation_option.was_found and then attached validation_option.parameter as l_directory_name and then not l_directory_name.is_empty then
  75. l_validation_directory_name := l_directory_name
  76. else
  77. l_validation_directory_name := default_validation_dirname
  78. end
  79. l_validation_directory_name := Execution_environment.interpreted_string (l_validation_directory_name)
  80. create l_directory.make (l_validation_directory_name)
  81. l_directory.open_read
  82. if l_directory.is_open_read then
  83. create l_tester.make_default
  84. if tool_executable_option.was_found and then attached tool_executable_option.parameter as l_executable_filename and then not l_executable_filename.is_empty then
  85. l_tester.variables.set_value ("executable", l_executable_filename)
  86. end
  87. create l_test_suite.make ("validation", l_tester.variables)
  88. l_tester.set_suite (l_test_suite)
  89. create l_relative_path.make_default
  90. create l_set_up_mutex.make
  91. process_directory (l_directory, l_relative_path, l_tested_eiffel_tool, filter, l_tester, l_set_up_mutex)
  92. l_directory.close
  93. create l_output_stream.make_empty
  94. l_aggregate := not aggregate_option.was_found or else aggregate_option.parameter
  95. run_tests (l_tester, l_aggregate, l_output_stream)
  96. l_output_string := l_output_stream.string
  97. l_output_string := text_to_markdown (l_output_string)
  98. l_diff := not diff_option.was_found or else diff_option.parameter
  99. if l_diff then
  100. report_diff_with_last_run (l_output_string, l_validation_directory_name, l_tested_eiffel_tool)
  101. end
  102. if keep_testdir_flag.was_found then
  103. write_last_run_file (l_output_string, l_tested_eiffel_tool)
  104. else
  105. file_system.recursive_delete_directory (test_dirname)
  106. end
  107. else
  108. report_cannot_read_directory_error (l_validation_directory_name)
  109. exit_code := 1
  110. end
  111. end
  112. rescue
  113. exit_code := 4
  114. end
  115. feature {NONE} -- Processing
  116. process_directory (a_directory: KL_DIRECTORY; a_relative_path: DS_ARRAYED_LIST [STRING]; a_tested_eiffel_tool: STRING; a_filter: detachable RX_REGULAR_EXPRESSION; a_tester: TS_TESTER; a_set_up_mutex: detachable MUTEX)
  117. -- Traverse `a_directory' and recursively its subdirectories to find
  118. -- test cases to be added to `a_tester' (if matching `a_filter') and
  119. -- later run with `a_tested_eiffel_tool'.
  120. require
  121. a_directory_not_void: a_directory /= Void
  122. a_directory_open_read: a_directory.is_open_read
  123. a_relative_path_not_void: a_relative_path /= Void
  124. no_void_relative_path: not a_relative_path.has_void
  125. a_tested_eiffel_tool_not_void: a_tested_eiffel_tool /= Void
  126. a_filter_is_compiled: a_filter /= Void implies a_filter.is_compiled
  127. a_tester_not_void: a_tester /= Void
  128. local
  129. l_dirname: STRING
  130. l_entries: DS_ARRAYED_LIST [STRING]
  131. l_entry_name: STRING
  132. l_entry_fullname: STRING
  133. i, nb: INTEGER
  134. l_subdirectory: KL_DIRECTORY
  135. l_test_name: STRING
  136. l_test_case: EIFFEL_TEST_CASE
  137. l_test_suite: detachable TS_TEST_SUITE
  138. l_test_suite_name: STRING
  139. l_root_name: STRING
  140. l_comparator: UC_STRING_COMPARATOR
  141. l_sorter: DS_QUICK_SORTER [STRING]
  142. l_test_dirname: STRING
  143. do
  144. l_dirname := a_directory.name
  145. create l_entries.make_default
  146. from a_directory.read_entry until a_directory.end_of_input loop
  147. l_entry_name := a_directory.last_entry
  148. if l_entry_name.count > 0 and not STRING_.same_string (l_entry_name, file_system.relative_current_directory) and not STRING_.same_string (l_entry_name, file_system.relative_parent_directory) then
  149. l_entries.force_last (l_entry_name.twin)
  150. end
  151. a_directory.read_entry
  152. end
  153. create l_comparator
  154. create l_sorter.make (l_comparator)
  155. l_entries.sort (l_sorter)
  156. nb := l_entries.count
  157. from i := 1 until i > nb loop
  158. l_entry_name := l_entries.item (i)
  159. l_entry_fullname := file_system.pathname (l_dirname, l_entry_name)
  160. create l_subdirectory.make (l_entry_fullname)
  161. l_subdirectory.open_read
  162. if l_subdirectory.is_open_read then
  163. if a_relative_path.is_empty then
  164. l_test_name := l_entry_name
  165. l_test_suite_name := "validation"
  166. else
  167. if a_relative_path.count = 1 then
  168. l_test_suite_name := a_relative_path.first
  169. else
  170. l_root_name := a_relative_path.first
  171. a_relative_path.remove_first
  172. l_test_suite_name := unix_file_system.nested_pathname (l_root_name, a_relative_path.to_array)
  173. a_relative_path.force_first (l_root_name)
  174. end
  175. l_test_name := unix_file_system.pathname (l_test_suite_name, l_entry_name)
  176. end
  177. a_relative_path.force_last (l_entry_name)
  178. if l_entry_name.count >= 4 and then l_entry_name.starts_with ("test") then
  179. if a_filter = Void or else a_filter.matches (l_test_name) then
  180. if l_test_suite = Void then
  181. create l_test_suite.make (l_test_suite_name, a_tester.variables)
  182. a_tester.suite.put_test (l_test_suite)
  183. end
  184. l_test_dirname := file_system.nested_pathname (test_dirname, a_relative_path.to_array)
  185. create l_test_case.make (l_entry_fullname, l_test_dirname)
  186. l_test_case.set_test (l_test_name, agent l_test_case.compile_and_test (a_tested_eiffel_tool))
  187. l_test_case.set_variables (a_tester.variables)
  188. l_test_case.set_set_up_mutex (a_set_up_mutex)
  189. l_test_suite.put_test (l_test_case)
  190. end
  191. else
  192. process_directory (l_subdirectory, a_relative_path, a_tested_eiffel_tool, a_filter, a_tester, a_set_up_mutex)
  193. end
  194. a_relative_path.remove_last
  195. l_subdirectory.close
  196. end
  197. i := i + 1
  198. end
  199. end
  200. run_tests (a_tester: TS_TESTER; a_aggregate: BOOLEAN; a_output_file: KI_TEXT_OUTPUT_STREAM)
  201. -- Run tests in `a_tester'.
  202. -- Aggregate the test results if `a_aggregate' is true.
  203. -- Write the test results to the console window and to `a_output_file'.
  204. require
  205. a_tester_not_void: a_tester /= Void
  206. a_output_file_not_void: a_output_file /= Void
  207. a_output_file_open_write: a_output_file.is_open_write
  208. local
  209. l_summary: TS_SUMMARY
  210. l_tester: TS_TESTER
  211. l_test_suite: TS_TEST_SUITE
  212. l_has_test_suite: BOOLEAN
  213. l_has_test_case: BOOLEAN
  214. l_thread_count: INTEGER
  215. l_old_test_suite: TS_TEST_SUITE
  216. do
  217. if a_aggregate then
  218. std.output.put_new_line
  219. std.output.put_line ("Testing " + a_tester.suite.name + "...")
  220. std.output.put_line ("Running Test Cases")
  221. std.output.put_new_line
  222. create l_summary.make
  223. l_summary.set_sort_errors (True)
  224. l_thread_count := thread_count
  225. if l_thread_count > 1 then
  226. l_old_test_suite := a_tester.suite
  227. l_test_suite := {TS_TEST_SUITE_FACTORY}.new_test_suite (l_old_test_suite.name, l_old_test_suite.variables, l_thread_count)
  228. l_old_test_suite.add_test_cases_to_suite (l_test_suite)
  229. a_tester.set_suite (l_test_suite)
  230. a_tester.execute_with_summary (l_summary, std.output)
  231. a_tester.set_suite (l_old_test_suite)
  232. else
  233. a_tester.execute_with_summary (l_summary, std.output)
  234. end
  235. -- Write to `a_output_file'.
  236. a_output_file.put_new_line
  237. a_output_file.put_line ("Testing " + a_tester.suite.name + "...")
  238. a_output_file.put_line ("Running Test Cases")
  239. a_output_file.put_new_line
  240. l_summary.print_summary_without_assertions (a_tester.suite, a_output_file)
  241. if not l_summary.is_successful then
  242. a_output_file.put_new_line
  243. l_summary.print_errors (a_output_file)
  244. end
  245. else
  246. across a_tester.suite as l_tests loop
  247. if attached {TS_TEST_SUITE} l_tests.item as l_suite then
  248. create l_tester.make_default
  249. l_tester.set_suite (l_suite)
  250. run_tests (l_tester, False, a_output_file)
  251. l_has_test_suite := True
  252. else
  253. l_has_test_case := True
  254. end
  255. end
  256. if not l_has_test_suite then
  257. run_tests (a_tester, True, a_output_file)
  258. elseif l_has_test_case then
  259. create l_test_suite.make (a_tester.suite.name, a_tester.suite.variables)
  260. across a_tester.suite as l_tests loop
  261. if not attached {TS_TEST_SUITE} l_tests.item then
  262. l_test_suite.put_test (l_tests.item)
  263. end
  264. end
  265. create l_tester.make_default
  266. l_tester.set_suite (l_test_suite)
  267. run_tests (l_tester, True, a_output_file)
  268. end
  269. end
  270. end
  271. write_last_run_file (a_output_string: STRING; a_tested_eiffel_tool: STRING)
  272. -- Write `a_output_string' to last run file associated with `a_tested_eiffel_tool'.
  273. require
  274. a_output_string_not_void: a_output_string /= Void
  275. a_tested_eiffel_tool_not_void: a_tested_eiffel_tool /= Void
  276. local
  277. l_output_filename: STRING
  278. l_output_file: KL_TEXT_OUTPUT_FILE
  279. do
  280. if attached last_run_filename_suffix (a_tested_eiffel_tool) as l_last_run_filename_suffix then
  281. l_output_filename := file_system.pathname (test_dirname, "last_run" + l_last_run_filename_suffix + ".md")
  282. else
  283. l_output_filename := file_system.pathname (test_dirname, "last_run.log")
  284. end
  285. create l_output_file.make (l_output_filename)
  286. l_output_file.recursive_open_write
  287. if l_output_file.is_open_write then
  288. l_output_file.put_string (a_output_string)
  289. l_output_file.close
  290. else
  291. report_cannot_write_to_file_error (l_output_filename)
  292. exit_code := 1
  293. end
  294. end
  295. report_diff_with_last_run (a_output_string: STRING; a_validation_directory_name: STRING; a_tested_eiffel_tool: STRING)
  296. -- Report whether diffs were found in the test results `a_output_string'
  297. -- since last run for `a_tested_eiffel_tool'.
  298. require
  299. a_output_string_not_void: a_output_string /= Void
  300. a_validation_directory_name_not_void: a_validation_directory_name /= Void
  301. a_tested_eiffel_tool_not_void: a_tested_eiffel_tool /= Void
  302. local
  303. l_input_filename: STRING
  304. l_input_file: KL_TEXT_INPUT_FILE
  305. l_input_string: STRING
  306. l_has_diff: BOOLEAN
  307. do
  308. if attached last_run_filename_suffix (a_tested_eiffel_tool) as l_last_run_filename_suffix then
  309. l_input_filename := file_system.pathname (a_validation_directory_name, "last_run" + l_last_run_filename_suffix + ".md")
  310. create l_input_file.make (l_input_filename)
  311. l_input_file.open_read
  312. if l_input_file.is_open_read then
  313. create l_input_string.make (a_output_string.count)
  314. from
  315. l_input_file.read_string (4096)
  316. until
  317. l_input_file.end_of_file
  318. loop
  319. l_input_string.append_string (l_input_file.last_string)
  320. l_input_file.read_string (4096)
  321. end
  322. l_input_file.close
  323. l_has_diff := not l_input_string.same_string (a_output_string)
  324. else
  325. l_has_diff := True
  326. end
  327. else
  328. l_has_diff := True
  329. end
  330. std.output.put_new_line
  331. if l_has_diff then
  332. std.output.put_line ("DIFFS FOUND SINCE LAST RUN")
  333. else
  334. std.output.put_line ("No Diff since last run")
  335. end
  336. std.output.put_new_line
  337. end
  338. text_to_markdown (a_string: STRING): STRING
  339. -- Convert `a_string' to a Markdown hyperlinked text.
  340. -- This will allow to jump directly to the failing test case folder
  341. -- when browsing in a Markdown aware environment (like GitHub).
  342. require
  343. a_string_not_void: a_string /= Void
  344. local
  345. l_test_case_name_rexgexp: RX_PCRE_REGULAR_EXPRESSION
  346. do
  347. create l_test_case_name_rexgexp.make
  348. l_test_case_name_rexgexp.compile ("\[([^\]]+)\]")
  349. l_test_case_name_rexgexp.match (a_string)
  350. Result := l_test_case_name_rexgexp.replace_all ("\[[\1\](\1\)\]")
  351. Result.replace_substring_all ("_", "\_")
  352. Result.replace_substring_all ("...", "...</br>")
  353. Result.replace_substring_all ("#", " #")
  354. Result.replace_substring_all ("%NFAIL", "</br>%NFAIL")
  355. end
  356. feature -- Error handling
  357. error_handler: UT_ERROR_HANDLER
  358. -- Error handler
  359. report_cannot_read_directory_error (a_dirname: STRING)
  360. -- Report that `a_dirname' cannot be
  361. -- opened in read mode.
  362. require
  363. a_dirname_not_void: a_dirname /= Void
  364. local
  365. an_error: UT_CANNOT_READ_DIRECTORY_ERROR
  366. do
  367. create an_error.make (a_dirname)
  368. error_handler.report_error (an_error)
  369. end
  370. report_cannot_write_to_file_error (a_filename: STRING)
  371. -- Report that `a_filename' cannot be
  372. -- opened in write mode.
  373. require
  374. a_filename_not_void: a_filename /= Void
  375. local
  376. an_error: UT_CANNOT_WRITE_TO_FILE_ERROR
  377. do
  378. create an_error.make (a_filename)
  379. error_handler.report_error (an_error)
  380. end
  381. report_invalid_filter_regexp (a_filter_regexp: STRING)
  382. -- Report that `a_filter_pattern' is not a
  383. -- valid regular expression.
  384. require
  385. a_filter_regexp_not_void: a_filter_regexp /= Void
  386. local
  387. l_error: UT_INVALID_REGULAR_EXPRESSION_ERROR
  388. do
  389. create l_error.make (a_filter_regexp)
  390. error_handler.report_error (l_error)
  391. end
  392. report_version_number
  393. -- Report version number.
  394. local
  395. a_message: UT_VERSION_NUMBER
  396. do
  397. create a_message.make (Version_number)
  398. error_handler.report_info (a_message)
  399. end
  400. exit_code: INTEGER
  401. -- Exit code
  402. feature -- Access
  403. thread_count: INTEGER
  404. -- Number of threads to be used
  405. do
  406. Result := {EXECUTION_ENVIRONMENT}.available_cpu_count.as_integer_32
  407. if thread_option.was_found then
  408. Result := thread_option.parameter
  409. if Result <= 0 then
  410. Result := {EXECUTION_ENVIRONMENT}.available_cpu_count.as_integer_32 + Result
  411. end
  412. end
  413. if Result < 1 or not {PLATFORM}.is_thread_capable then
  414. Result := 1
  415. end
  416. ensure
  417. thread_count_not_negative: Result >= 1
  418. end
  419. filter: detachable RX_PCRE_REGULAR_EXPRESSION
  420. -- When specified, run only the test cases matching this regexp
  421. feature -- Argument parsing
  422. tool_option: AP_ENUMERATION_OPTION
  423. -- Option for '--tool=<eiffel_tool>'
  424. tool_executable_option: AP_STRING_OPTION
  425. -- Option for '--tool_executable=<executable_filename>'
  426. validation_option: AP_STRING_OPTION
  427. -- Option for '--validation=<directory_name>'
  428. filter_option: AP_STRING_OPTION
  429. -- Option for '--filter=<regexp>'
  430. aggregate_option: AP_BOOLEAN_OPTION
  431. -- Option for '--aggregate=<no|yes>'
  432. diff_option: AP_BOOLEAN_OPTION
  433. -- Option for '--diff=<no|yes>'
  434. keep_testdir_flag: AP_FLAG
  435. -- Flag for '--keep-testdir'
  436. thread_option: AP_INTEGER_OPTION
  437. -- Option for '--thread=<thread_count>'
  438. version_flag: AP_FLAG
  439. -- Flag for '--version'
  440. parse_arguments (a_args: ARRAY [STRING])
  441. -- Initialize options and parse arguments `a_args'.
  442. require
  443. a_args_not_void: a_args /= Void
  444. no_void_arg: across a_args is l_arg all l_arg /= Void end
  445. local
  446. l_parser: AP_PARSER
  447. l_list: AP_ALTERNATIVE_OPTIONS_LIST
  448. l_filter: like filter
  449. do
  450. create l_parser.make
  451. l_parser.set_application_description ("Gobo Eiffel Cop, an Eiffel language conformance validation suite.")
  452. l_parser.set_parameters_description ("")
  453. -- tool
  454. create tool_option.make_with_long_form ("tool")
  455. tool_option.set_description ("Eiffel tool to be tested against the validation suite. (default: ge)")
  456. tool_option.extend ("ge")
  457. tool_option.extend ("ise")
  458. tool_option.extend ("gec")
  459. tool_option.extend ("gelint")
  460. tool_option.extend ("ge_debug")
  461. tool_option.extend ("ge_lint")
  462. tool_option.extend ("ise_debug")
  463. tool_option.extend ("ise_dotnet")
  464. tool_option.extend ("ise_dotnet_debug")
  465. l_parser.options.force_last (tool_option)
  466. -- tool_executable
  467. create tool_executable_option.make_with_long_form ("tool-executable")
  468. tool_executable_option.set_description ("Executable filename (optionally with a pathname) of Eiffel tool to be tested. (default: gec|gelint|ec in the PATH)")
  469. tool_executable_option.set_parameter_description ("filename")
  470. l_parser.options.force_last (tool_executable_option)
  471. -- validation
  472. create validation_option.make_with_long_form ("validation")
  473. validation_option.set_description ("Directory containing the Eiffel validation suite. (default: $GOBO/tool/gecop/validation)")
  474. validation_option.set_parameter_description ("directory_name")
  475. l_parser.options.force_last (validation_option)
  476. -- filter
  477. create filter_option.make_with_long_form ("filter")
  478. filter_option.set_description ("When specified, run only the test cases matching this regexp. (default: no filter)")
  479. filter_option.set_parameter_description ("regexp")
  480. l_parser.options.force_last (filter_option)
  481. -- aggregate
  482. create aggregate_option.make_with_long_form ("aggregate")
  483. aggregate_option.set_description ("Should test results be aggregated into a single report? (default: yes)")
  484. aggregate_option.set_parameter_description ("no|yes")
  485. l_parser.options.force_last (aggregate_option)
  486. -- diff
  487. create diff_option.make_with_long_form ("diff")
  488. diff_option.set_description ("Should test results be compared with the previous run? (default: yes)")
  489. diff_option.set_parameter_description ("no|yes")
  490. l_parser.options.force_last (diff_option)
  491. -- keep-testdir
  492. create keep_testdir_flag.make_with_long_form ("keep-testdir")
  493. keep_testdir_flag.set_description ("Do no delete temporary directory after running the validation suite. (default: delete testdir)")
  494. l_parser.options.force_last (keep_testdir_flag)
  495. -- thread
  496. create thread_option.make_with_long_form ("thread")
  497. thread_option.set_description ("Number of threads to be used. Negative numbers -N mean %"number of CPUs - N%". (default: number of CPUs)")
  498. thread_option.set_parameter_description ("thread_count")
  499. if {PLATFORM}.is_thread_capable then
  500. l_parser.options.force_last (thread_option)
  501. end
  502. -- version
  503. create version_flag.make ('V', "version")
  504. version_flag.set_description ("Print the version number of gecop and exit.")
  505. create l_list.make (version_flag)
  506. l_parser.alternative_options_lists.force_last (l_list)
  507. -- Parsing.
  508. l_parser.parse_array (a_args)
  509. if version_flag.was_found then
  510. report_version_number
  511. exit_code := 0
  512. elseif not l_parser.parameters.is_empty then
  513. error_handler.report_info_message (l_parser.help_option.full_usage_instruction (l_parser))
  514. exit_code := 1
  515. elseif filter_option.was_found and then attached filter_option.parameter as l_filter_pattern and then not l_filter_pattern.is_empty then
  516. create l_filter.make
  517. if Operating_system.is_windows then
  518. l_filter.set_case_insensitive (True)
  519. end
  520. l_filter.compile (l_filter_pattern)
  521. if not l_filter.is_compiled then
  522. report_invalid_filter_regexp (l_filter_pattern)
  523. exit_code := 1
  524. else
  525. filter := l_filter
  526. end
  527. end
  528. ensure
  529. tool_option_not_void: tool_option /= Void
  530. tool_executable_option_not_void: tool_executable_option /= Void
  531. validation_option_not_void: validation_option /= Void
  532. filter_option_not_void: filter_option /= Void
  533. aggregate_option_not_void: aggregate_option /= Void
  534. diff_option_not_void: diff_option /= Void
  535. keep_testdir_flag_not_void: keep_testdir_flag /= Void
  536. thread_option_not_void: thread_option /= Void
  537. version_flag_not_void: version_flag /= Void
  538. end
  539. feature {NONE} -- Implementation
  540. last_run_filename_suffix (a_tested_eiffel_tool: STRING): detachable STRING
  541. -- Filename suffix for the 'last_run' file associated with `a_tested_eiffel_tool'
  542. do
  543. if a_tested_eiffel_tool.starts_with ("ise") then
  544. Result := "_ise"
  545. elseif a_tested_eiffel_tool.starts_with ("ge") then
  546. if a_tested_eiffel_tool.ends_with ("lint") then
  547. Result := "_gelint"
  548. else
  549. Result := "_gec"
  550. end
  551. end
  552. end
  553. feature {NONE} -- Constants
  554. default_validation_dirname: STRING
  555. -- Default validation directory name
  556. once
  557. Result := file_system.nested_pathname ("$GOBO", <<"tool", "gecop", "validation">>)
  558. ensure
  559. default_validation_dirname_not_void: Result /= Void
  560. end
  561. default_tested_eiffel_tool: STRING = "ge"
  562. -- Name of Eiffel tool to be tested by default
  563. test_dirname: STRING = "Tvalidation"
  564. -- Name of temporary directory where to run the test
  565. invariant
  566. error_handler_not_void: error_handler /= Void
  567. tool_option_not_void: tool_option /= Void
  568. tool_executable_option_not_void: tool_executable_option /= Void
  569. validation_option_not_void: validation_option /= Void
  570. filter_option_not_void: filter_option /= Void
  571. aggregate_option_not_void: aggregate_option /= Void
  572. diff_option_not_void: diff_option /= Void
  573. keep_testdir_flag_not_void: keep_testdir_flag /= Void
  574. thread_option_not_void: thread_option /= Void
  575. version_flag_not_void: version_flag /= Void
  576. end