note
	description: "[
		Objects creating directories and files in a system test set environment.
	]"
	author: ""
	date: "$Date: 2017-12-03 17:18:24 +0000 (Sun, 03 Dec 2017) $"
	revision: "$Revision: 101089 $"

class 
	EQA_FILE_SYSTEM

create 
	make

feature {NONE} -- Initialization

	make (an_asserter: like asserter)
			-- Initialize Current.
			--
			-- an_asserter: Asserter used to raise an exception to report unexpected behaviour.
		require
			an_asserter_attached: an_asserter /= Void
		do
			asserter := an_asserter
		end
	
feature -- Access

	asserter: EQA_ASSERTIONS
			-- Asserter used to raise an exception to report unexpected behaviour.
	
feature -- Command

	copy_file (a_src: FILE; a_env: EQA_ENVIRONMENT; a_dest: FILE; a_substitute: BOOLEAN)
			-- Append lines of file a_src, with environment
			-- variables substituted according to a_env (but
			-- only if substitute is true) to file a_dest.
		require
			source_not_void: a_src /= Void
			destination_not_void: a_dest /= Void
			environment_not_void: a_env /= Void
			source_is_closed: a_src.is_closed
			destination_is_closed: a_dest.is_closed
		local
			l_line: STRING_8
			u: UTF_CONVERTER
		do
			from
				a_src.open_read
				a_dest.open_write
			until
				a_src.end_of_file
			loop
				a_src.read_line
				if a_substitute then
					l_line := u.string_32_to_utf_8_string_8 (a_env.substitute (a_src.last_string))
				else
					l_line := a_src.last_string
				end
				if not a_src.end_of_file then
					a_dest.put_string (l_line)
					a_dest.new_line
				elseif not l_line.is_empty then
					a_dest.put_string (l_line)
				end
			end
			a_src.close
			a_dest.flush
			a_dest.close
		end
	
feature -- Query: Path

	build_path (a_dir: READABLE_STRING_GENERAL; a_path: detachable EQA_SYSTEM_PATH): STRING_32
			-- Build an absolute path name given a base directory and an optional path
			--
			-- a_dir: A base dir in form of an absolute path.
			-- a_path: A relative path to append to a_dir.
			-- Result: Absolute path that results from appending items in a_path to a_dir
		require
			a_dir_attached: a_dir /= Void
			a_dir_not_empty: not a_dir.is_empty
		do
			Result := build_partial_path (a_path, a_dir, 0)
		ensure
			result_attached: Result /= Void
		end

	build_path_from_key (a_key: READABLE_STRING_GENERAL; a_path: detachable EQA_SYSTEM_PATH): STRING_32
			-- Build an absolte path name given the key of an defined absolte path
			--
			-- Note: will raise exception if value for a_key is not defined.
			--
			-- a_key: Key for which an absolute base dir is defined in EQA_ENVIRONMENT
			-- a_path: An optional relative path to append to the resulting path.
			-- Result: Absolute path that results from appending items in a_path to base dir.
		require
			a_key_attached: a_key /= Void
			a_key_not_empty: not a_key.is_empty
		local
			l_environment: EQA_ENVIRONMENT
		do
			create l_environment
			Result := build_partial_path (a_path, l_environment.item_attached (a_key, asserter), 0)
		ensure
			result_attached: Result /= Void
		end

	build_source_path (a_path: detachable EQA_SYSTEM_PATH): STRING_32
			-- Build the actual path name relative to the source directory for given path
			--
			-- Note: will raise exception if {EQA_TEST_SET}.source_path_key is not defined.
			--
			-- a_path: Optional path for which path name should be built.
			-- Result: Path name relative to source directory.
		do
			Result := build_path_from_key ({EQA_TEST_SET}.source_path_key, a_path)
		ensure
			result_attached: Result /= Void
		end

	build_target_path (a_path: detachable EQA_SYSTEM_PATH): STRING_32
			-- Build the actual path name relative to the target directory for given path.
			--
			-- Note: will raise exception if {EQA_TEST_SET}.target_path_key is not defined.
			--
			-- a_path: Optional path for which path name should be built
			-- Result: Path name relative to target directory.
		do
			Result := build_path_from_key ({EQA_TEST_SET}.target_path_key, a_path)
		ensure
			result_attached: Result /= Void
		end
	
feature -- Query: Content

	has_same_content_as_string (a_path: EQA_SYSTEM_PATH; a_string: READABLE_STRING_8): BOOLEAN
			-- Does target file for path have same content as given string?
			--
			-- a_path: Path relative to target_directory of file
			-- a_string: String to be compared with content of file
			-- Result: True if file has same content as a_string, False otherwise
			--
			-- Note: if file does not exists or is not readable an exception is raised.
		require
			a_path_attached: a_path /= Void
			a_path_not_empty: not a_path.is_empty
			a_string_attached: a_string /= Void
		local
			l_filename: like build_target_path
			l_file: PLAIN_TEXT_FILE
			i, l_count: INTEGER_32
		do
			l_filename := build_target_path (a_path)
			create l_file.make_with_name (l_filename)
			assert ("file_exists", l_file.exists)
			assert ("file_readable", l_file.is_readable)
			l_file.open_read
			from
				i := 1
				l_count := a_string.count
				Result := True
				l_file.read_character
			until
				i > l_count or l_file.end_of_file or not Result
			loop
				Result := a_string.item (i) = l_file.last_character
				l_file.read_character
				i := i + 1
			end
			if Result then
				Result := i > l_count and l_file.end_of_file
			end
			l_file.close
		end

	has_same_content_as_path (a_first_path, a_second_path: EQA_SYSTEM_PATH): BOOLEAN
			-- Do target files for given paths have the same content?
			--
			-- a_first: Relative path of first file.
			-- a_second: Relative path of second file.
			-- Result: True if both files existed and are readable and have identical content, False
			--           otherwise
			--
			-- Note: if files do not exist or are not readable an exception is raised.
		require
			a_first_path_attached: a_first_path /= Void
			a_first_path_not_empty: not a_first_path.is_empty
			a_second_path_attached: a_second_path /= Void
			a_second_path_not_empty: not a_second_path.is_empty
		local
			l_filename1, l_filename2: like build_target_path
			l_file1, l_file2: PLAIN_TEXT_FILE
		do
			l_filename1 := build_target_path (a_first_path)
			l_filename2 := build_target_path (a_second_path)
			create l_file1.make_with_name (l_filename1)
			create l_file2.make_with_name (l_filename2)
			assert ("file1_exists", l_file1.exists)
			assert ("file2_exists", l_file2.exists)
			assert ("file1_readable", l_file1.readable)
			assert ("file2_readable", l_file2.readable)
			l_file1.open_read
			l_file2.open_read
			from
				l_file1.read_character
				l_file2.read_character
				Result := True
			until
				l_file1.end_of_file or l_file2.end_of_file or not Result
			loop
				Result := l_file1.last_character = l_file2.last_character
				l_file1.read_character
				l_file2.read_character
			end
			if Result then
				Result := l_file1.end_of_file and l_file2.end_of_file
			end
			l_file1.close
			l_file2.close
		end

	executable_file_exists (s: detachable READABLE_STRING_GENERAL): detachable STRING_32
			-- If file s does not exist or is not a file or
			-- is not executable, string describing the
			-- problem.  Void otherwise
		local
			f: RAW_FILE
		do
			if s /= Void then
				create f.make_with_name (s)
				if not f.exists then
					Result := {STRING_32}"file " + s + " not found"
				elseif not f.is_plain then
					Result := {STRING_32}"file " + s + " not a plain file"
				elseif not f.is_executable then
					Result := {STRING_32}"file " + s + " not executable"
				end
			else
				Result := {STRING_32}"file (Void file name) not found"
			end
		end
	
feature {NONE} -- Query

	build_partial_path (a_path: detachable EQA_SYSTEM_PATH; a_prefix: READABLE_STRING_GENERAL; a_strip: INTEGER_32): STRING_32
			-- Build a partial path name relative to to a given directory.
			--
			-- a_path: Path for which path name should be built
			-- a_prefix: Absolute directory name to which a_path is relative.
			-- a_strip: Number of items at the end of a_path to be neglected.
			-- Result: Path name relative to target directory.
		require
			a_prefix_attached: a_prefix /= Void
			a_strip_not_negative: a_strip >= 0
			a_stip_not_too_large: a_strip > 0 implies (attached a_path and then a_strip <= a_path.count)
		local
			i, l_count: INTEGER_32
			l_path: PATH
		do
			create l_path.make_from_string (a_prefix)
			if a_path /= Void then
				from
					l_count := a_path.count - a_strip
					i := 1
				until
					i > l_count
				loop
					l_path := l_path.extended (a_path.item (i))
					i := i + 1
				end
			end
			create Result.make_from_string (l_path.name)
		ensure
			result_attached: Result /= Void
		end
	
feature -- Basic

	delete_directory_tree (a_dir_name: READABLE_STRING_GENERAL)
			-- Try to delete the directory tree rooted at
			-- a_dir_name.  Ignore any errors
		require
			directory_not_void: a_dir_name /= Void
		local
			l_dir: DIRECTORY
			l_retried: BOOLEAN
		do
			if not l_retried then
				create l_dir.make (a_dir_name)
				l_dir.recursive_delete
			end
		rescue
			l_retried := True
			retry
		end
	
feature {NONE} -- Implementation

	frozen assert (a_tag: READABLE_STRING_GENERAL; a_condition: BOOLEAN)
			-- Assert a_condition using asserter from current test set.
		require
			a_tag_attached: a_tag /= Void
		do
			asserter.assert (a_tag, a_condition)
		end
	
feature -- Constants

	Source_directory_key: STRING_32 = "SOURCE_DIRECTORY"

	Target_directory_key: STRING_32 = "EQA_TARGET_DIRECTORY"
	
note
	copyright: "Copyright (c) 1984-2017, Eiffel Software and others"
	license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
	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 -- class EQA_FILE_SYSTEM

Generated by ISE EiffelStudio