note description: "[ Objects that print source code for extracted test sets. ]" author: "" date: "$Date$" revision: "$Revision$" class TEST_EXTRACTED_SOURCE_WRITER inherit TEST_CLASS_SOURCE_WRITER redefine root_feature_name, ancestor_names, put_indexing end TEST_CAPTURE_OBSERVER rename prepare as prepare_observer redefine is_ready, is_capturing_objects, is_capturing_invocations, on_prepare, on_prepare_for_objects, on_clean, on_invocation_capture, on_object_capture end UT_STRING_FORMATTER export {NONE} all end create make feature {NONE} -- Initialization make -- Initialize `Current'. do create class_name.make_empty create used_routine_names.make (10) end feature -- Access class_name: STRING -- ancestor_names: ARRAY [STRING] -- do Result := << extracted_ancestor_name >> end root_feature_name: STRING = "" -- used_routine_names: TAG_HASH_TABLE [NATURAL] -- Routine names which have been used in the current class -- -- keys: routine names -- values: number of times routine name was used feature {NONE} -- Access object_counter: NATURAL -- Number of objects that have been captured feature {TEST_CAPTURER} -- Status report is_ready: BOOLEAN -- do Result := Precursor and is_writing end is_capturing_invocations: BOOLEAN -- do Result := Precursor and is_writing end is_capturing_objects: BOOLEAN -- do Result := Precursor and is_writing end feature -- Status setting prepare (a_file: KI_TEXT_OUTPUT_STREAM; a_class_name: STRING) -- Prepare printing a new axtracted application state to `a_file'. require not_writing: not is_writing a_file_open_write: a_file.is_open_write do create stream.make (a_file) class_name := a_class_name ensure writing: is_writing end feature {NONE} -- Query test_routine_name (a_feature: E_FEATURE): STRING -- Valid test routine name for feature in `a_stack_element'. local i: INTEGER_32 l_custom_symbol: STRING_8 l_symbol: STRING do if a_feature.is_prefix then Result := "prefix_" if a_feature.prefix_symbol_32.as_string_8.is_equal ("+") then Result.append ("plus") elseif a_feature.prefix_symbol_32.as_string_8.is_equal ("-") then Result.append ("minus") else -- Replace all non-alpha-numeric characters with valid representations. from create l_custom_symbol.make_empty l_symbol := a_feature.prefix_symbol_32.as_string_8 i := 1 until i > l_symbol.count loop if l_symbol.item (i).is_alpha_numeric then l_custom_symbol.append_character (l_symbol.item (i)) else inspect l_symbol.item (i) when '#' then l_custom_symbol.append_string ("_symb_number_") when '|' then l_custom_symbol.append_string ("_symb_vertbar_") when '@' then l_custom_symbol.append_string ("_symb_at_") when '&' then l_custom_symbol.append_string ("_symb_amp_") else l_custom_symbol.append_string ("_symb_" + l_symbol.item (i).code.out + "_") end end i := i + 1 end Result.append (l_custom_symbol) end elseif a_feature.is_infix then Result := "infix_" l_symbol := a_feature.infix_symbol_32.as_string_8 if l_symbol.is_equal ("+") then Result.append ("plus") elseif l_symbol.is_equal ("-") then Result.append ("minus") elseif l_symbol.is_equal ("*") then Result.append ("multiply") elseif l_symbol.is_equal ("/") then Result.append ("division") elseif l_symbol.is_equal ("<") then Result.append ("less") elseif l_symbol.is_equal (">") then Result.append ("greater") elseif l_symbol.is_equal ("<=") then Result.append ("less_or_equal") elseif l_symbol.is_equal (">=") then Result.append ("greater_or_equal") elseif l_symbol.is_equal ("//") then Result.append ("integer_division") elseif l_symbol.is_equal ("\\") then Result.append ("modulo") elseif l_symbol.is_equal ("^") then Result.append ("power") else -- Replace all non-alpha-numeric characters with valid representations. from create l_custom_symbol.make_empty l_symbol := a_feature.infix_symbol_32.as_string_8 i := 1 until i > l_symbol.count loop if l_symbol.item (i).is_alpha_numeric then l_custom_symbol.append_character (l_symbol.item (i)) else inspect l_symbol.item (i) when '#' then l_custom_symbol.append_string ("_symb_number_") when '|' then l_custom_symbol.append_string ("_symb_vertbar_") when '@' then l_custom_symbol.append_string ("_symb_at_") when '&' then l_custom_symbol.append_string ("_symb_amp_") else l_custom_symbol.append_character ('_') end end i := i + 1 end Result.append (l_custom_symbol) end else -- |FIXME: Unicode encoding handling. create Result.make_from_string (a_feature.name_32.as_string_8) end ensure result_not_empty: not Result.is_empty end feature {TEST_CAPTURER} -- Events on_invocation_capture (a_stack_element: TEST_CAPTURED_STACK_ELEMENT) -- local l_feat: E_FEATURE l_name: STRING l_count: NATURAL l_list: LIST [STRING] i: INTEGER do l_feat := a_stack_element.called_feature l_name := test_routine_name (l_feat) used_routine_names.search (l_name) l_count := 1 if used_routine_names.has (l_name) then l_count := used_routine_names.found_item + 1 end used_routine_names.force (l_count, l_name) stream.indent stream.put_string ("test_") stream.put_string (l_name) if l_count > 1 then stream.put_character ('_') stream.put_line (l_count.out) else stream.put_line ("") end stream.indent put_indexing_keyword stream.indent stream.put_line ("testing: %"type/extracted%"") stream.put_string ("testing: %"covers/{") stream.put_string (a_stack_element.called_feature.associated_class.name) stream.put_string ("}.") stream.put_string (l_name) stream.put_line ("%"") stream.dedent stream.put_line ("do") stream.indent stream.put_string ("run_extracted_test (agent ") if a_stack_element.is_creation_procedure or a_stack_element.is_xfix then if l_feat.argument_count > 0 or a_stack_element.is_xfix then stream.put_string ("(") from l_list := a_stack_element.types l_list.start i := 1 until l_list.after loop stream.put_string ("an_arg") stream.put_integer (i) stream.put_string (": ") stream.put_string (l_list.item_for_iteration) l_list.forth i := i + 1 if not l_list.after then stream.put_string ("; ") end end stream.put_line (")") else stream.put_line ("") end stream.indent if a_stack_element.is_creation_procedure or a_stack_element.is_xfix then stream.put_line ("local") stream.indent stream.put_line ("l_result: ANY") stream.dedent end stream.put_line ("do") stream.indent stream.put_string ("l_result := ") if l_feat.is_prefix then stream.put_string (l_feat.prefix_symbol_32.as_string_8) stream.put_line (" an_arg1") elseif l_feat.is_infix then stream.put_string ("an_arg1 ") stream.put_string (l_feat.infix_symbol_32.as_string_8) stream.put_line (" an_arg2") else stream.put_string ("create {") stream.put_string (a_stack_element.type) stream.put_string ("}.") -- |FIXME: Handle encoding stream.put_string (l_feat.name_32.as_string_8) if a_stack_element.operands.count > 0 then stream.put_character ('(') from i := 1 until i > l_feat.argument_count loop stream.put_string ("an_arg" + i.out) if i < l_feat.argument_count then stream.put_string (", ") end i := i + 1 end stream.put_character (')') end stream.put_line ("") end stream.dedent stream.put_string ("end") stream.dedent else stream.put_character ('{') stream.put_string (a_stack_element.type) stream.put_character ('}') stream.put_character ('.') -- |FIXME: Unicode encoding stream.put_string (l_feat.name_32.as_string_8) end stream.put_string (", [") from l_list := a_stack_element.operands l_list.start until l_list.after loop put_value (l_list.item_for_iteration) l_list.forth if not l_list.after then stream.put_string (", ") end end stream.put_line ("])") stream.dedent stream.put_line ("end%N") stream.dedent stream.dedent end on_object_capture (a_object: TEST_CAPTURED_OBJECT) -- local l_long_string: BOOLEAN do object_counter := object_counter + 1 check valid_id: a_object.id = object_counter end if object_counter > 1 then stream.put_line (",") end stream.put_string ("[{") stream.put_string (a_object.type) l_long_string := a_object.is_string and then a_object.string.count > max_string_length if l_long_string then stream.put_line ("}, [%"%%") else stream.put_line ("}, [") end stream.indent stream.indent if l_long_string then put_manifest_string (a_object.string) elseif a_object.is_string then stream.put_character ('"') put_eiffel_string (stream.output_stream, a_object.string) stream.put_character ('"') stream.put_line ("") elseif a_object.has_attributes then put_attributes (a_object.attributes) else put_items (a_object.items) end stream.dedent if l_long_string then stream.put_string ("%%%"], ") else stream.put_string ("], ") end stream.put_string (a_object.is_invariant_applicable.out) stream.put_character (']') stream.dedent end feature {NONE} -- Events on_prepare -- do put_indexing put_class_header end on_prepare_for_objects -- do stream.put_line ("feature {NONE} -- Access%N") stream.indent stream.put_line ("context: ARRAY [TUPLE [type: TYPE [ANY]; attributes: TUPLE; inv: BOOLEAN]]") stream.indent stream.indent stream.put_line ("-- ") stream.dedent stream.put_line ("do") stream.indent stream.put_line ("Result := <<") stream.indent object_counter := 0 end on_clean -- do stream.put_new_line stream.dedent stream.put_line (">>") stream.dedent stream.put_line ("end") stream.dedent stream.dedent stream.put_new_line stream.put_line ("end") used_routine_names.wipe_out end feature {NONE} -- Output put_indexing -- Append indexing clause. do put_indexing_keyword stream.indent stream.put_line ("description: %"Regression tests reproducing application state of a previous execution.%"") stream.put_line ("author: %"Testing tool%"") stream.dedent stream.put_line ("") end put_manifest_string (a_string: STRING) local i: INTEGER do from i := 1 until i > a_string.count loop stream.put_character ('%%') put_eiffel_string (stream.output_stream, a_string.substring (i, (i + max_string_length - 1).min (a_string.count))) stream.put_line ("%%") i := i + max_string_length end end put_attributes (a_table: HASH_TABLE [STRING, STRING]) do from a_table.start until a_table.after loop stream.put_character ('"') stream.put_string (a_table.key_for_iteration) stream.put_string ("%", ") put_value (a_table.item_for_iteration) a_table.forth if a_table.after then stream.put_line ("") else stream.put_line (",") end end end put_items (a_list: LIST [STRING]) local l_count: INTEGER do from a_list.start until a_list.after loop put_value (a_list.item_for_iteration) l_count := l_count + a_list.item_for_iteration.count a_list.forth if a_list.after then stream.put_line ("") else if l_count + a_list.item_for_iteration.count > max_string_length then stream.put_line (",") l_count := 0 else stream.put_string (", ") end end end end put_value (a_value: STRING) do if a_value.is_natural then stream.put_character ('"') stream.put_character ('#') stream.put_string (a_value) stream.put_character ('"') else stream.put_string (a_value) end end feature {NONE} -- Constants max_string_length: INTEGER = 80 extracted_ancestor_name: STRING = "EQA_EXTRACTED_TEST_SET" ;note copyright: "Copyright (c) 1984-2010, Eiffel Software" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end