--------------------------------------------------------------------
-- Class: TREE_NODE_TEST2
--------------------------------------------------------------------
-- Original Author: Justin Finnerty
-- Original Date:
-- Current Date: $Date: 2005/09/03 03:08:27 $
-- Current Author: $Author: finnerty $
-- Revision: $Revision: 2.2 $
-- Log: $Log: tree_node_test2.e,v $
-- Log: Revision 2.2  2005/09/03 03:08:27  finnerty
-- Log: Updated to conform to cursors/containers in the GOBO library and
-- Log: test programs compile with SE and VE.
-- Log:
-- Log: Revision 2.1  2005/09/03 01:40:00  finnerty
-- Log: Updated to conform to cursors/containers in the GOBO library
-- Log:
-- Log: Revision 2.0  2005/08/26 23:19:46  finnerty
-- Log: == alpha version ==
-- Log:
-- Log: Revision 1.3  2005/08/07 01:24:37  finnerty
-- Log: Added testing of cursor for traversing the tree in preorder and `unlink' now that it is visible to any.
-- Log:
-- Log: Revision 1.2  2005/08/06 12:32:12  finnerty
-- Log: Added testing of cursor for traversing the tree in preorder.
-- Log:
-- Log: Revision 1.1  2005/08/04 09:49:55  finnerty
-- Log: Test suite for the tree_node (and indirectly the quadlink_node) class as a client of tree_node. No common ancestory before ANY.
-- Log:
--------------------------------------------------------------------
indexing
	-----------------------------------------------------------------
	-- Class categorising information
	-----------------------------------------------------------------
	namespace: "candidate"
	cluster: "demangler"
	description: "Test suite for the tree_node class as non-inheriting client"
class TREE_NODE_TEST2
	-----------------------------------------------------------------
	-- Description of class
	-- -----------------------------------------------------------------
	-- This class test the tree_node class.
inherit
	KL_SHARED_STANDARD_FILES
creation {ANY}
	-- restrict constructors to an object of FSO_FACTORY type
	main

feature {TREE_NODE_TEST2}
	-----------------------------------------------------------------
	-- creation methods. These are restricted to only be valid during 
	-- object creation as they make no sense at any other time.
	-----------------------------------------------------------------
	main is
			-- Create a small tree
		local
			a_root, a_node1, a_node2: TREE_NODE
			l_index: INTEGER
			l_iter: BILINEAR_CURSOR[TREE_NODE]
		do
			-- Our attributes
			!!a_root.make
			from
				l_index := 0
			variant
				L_loopmax - l_index
			until
				l_index >= L_loopmax
			loop
				!!a_node1.make
				!!a_node2.make_child_of(a_node1)
				a_node1.put_parent(a_root)
				l_index := l_index + 1
				test_bool("new node has_sibling (or index <= 1)", True, l_index <= 1 or else a_node1.has_sibling)
				test_bool("new node has more than one sibling (or index <= 2)", True, l_index <= 2 or else a_node1.next_sibling /= a_node1.previous_sibling)
			end
			test_integer("Loop repetitions", L_loopmax, l_index)
			
			std.output.put_string("----------------------------------------%N")
				std.output.put_string("Tree construction complete%N")

				test_bool("has_sibling on root", False, a_root.has_sibling)
				test_bool("has_parent on root", False, a_root.has_parent)
				test_bool("has_children on root", True, a_root.has_children)
				a_node1 := a_root.first_child
				test_bool("has_sibling on root.first_child", True, a_node1.has_sibling)
				test_bool("has_parent on root.first_child", True, a_node1.has_parent)
				test_bool("has_children on root.first_child", True, a_node1.has_children)
			
				test_bool("root.last_child /= root.first_child", True, a_root.first_child /= a_root.last_child)
				-- --------------------------------------
				-- Compile failures with quadlink_node methods renamed in
				-- tree_node
				-- --------------------------------------
				-- a_node1 := a_root.up
				-- a_node1 := a_root.down
				-- a_node1 := a_root.left
				-- a_node1 := a_root.right
				-- test_bool("quadlink has_down", True, a_root.has_down)
				-- test_bool("quadlink has_up", True, a_root.has_up)
				-- test_bool("quadlink has_right", True, a_root.has_right)
			
				-- --------------------------------------
				-- Test QUADLINK_NODE methods only accessible through inheritance
				-- --------------------------------------
				-- test_bool("quadlink has_left", False, a_root.has_left)
		
			   -- --------------------------------------
			   -- Compile failures with quadlink_node methods, accessible 
			   -- through inheritance. These methods, if allowed, lead to 
			   -- exceptions of the invariant.
			   -- --------------------------------------
			 -- a_root.insert_down(a_node1)
			-- a_root.insert_left(a_node1)
			-- a_root.insert_right(a_node1)
			-- a_root.insert_up(a_node1)
			-- a_root.extract_vertical
		
			-- --------------------------------------
			-- Runtime exceptions with quadlink_node methods, accessible 
			-- through inheritance. These methods, although allowed, lead to 
			-- exceptions of the invariant if not used correctly.
			-- --------------------------------------
			-- a_root.set_down(a_node1)
			-- a_root.set_left(a_node1)
			-- a_root.set_right(a_node1)
			-- a_root.set_up(a_node1)

			   std.output.put_string("----------------------------------------%N")
				std.output.put_string("Tree navigation complete%N")

				std.output.put_string("Moved to leaf node without siblings: root.first_child.first_child%N")
				a_node1 := a_root.first_child.first_child
				test_bool("has_sibling on a_node", False, a_node1.has_sibling)
				test_bool("has_parent on a_node", True, a_node1.has_parent)
				test_bool("has_children on a_node", False, a_node1.has_children)
				test_bool("a_node.parent.first_child = a_node.parent.last_child (= a_node)", True, a_node1.parent.first_child = a_node1.parent.last_child)

				std.output.put_string("Moved to root.first_child, counting siblings%N")
				a_node1 := a_root.first_child
				test_bool("has_sibling on root.first_child", True, a_node1.has_sibling)
				test_bool("root.first_child has more than one sibling", True, a_node1.next_sibling /= a_node1.previous_sibling)
			   from
					l_index := 1
					a_node1 := a_root.first_child
				variant
					2*L_loopmax - l_index
				until
					a_node1 = a_root.last_child
				loop
					l_index := l_index + 1
					test_bool("Current node has root as parent", True, a_root = a_node1.parent)
					test_bool("Current node has children", True, a_node1.has_children)
					test_integer("Current depth is one:", 1, a_node1.depth)
					if a_node1.has_children then
						test_bool("Current node's child has no children", False, a_node1.first_child.has_children)
						test_integer("Current node's child depth is two:", 2, a_node1.first_child.depth)
					end
					a_node1 := a_node1.next_sibling
				end
				test_integer("Count of root's children", l_index, a_root.count)

			   std.output.put_string("----------------------------------------%N")
				std.output.put_string("Tree manipulation%N")
			std.output.put_string("----------------------------------------%N")
				std.output.put_string("Tree is made of a root node with many children. All %N")
			   std.output.put_string("children have exactly one child (according to how we %N")
			   std.output.put_string("constructed them). The manipulation will move root's %N")
			   std.output.put_string("first_child to be a direct child of root's last_child.%N")
			   -- std.output.put_string("%N")
				std.output.put_string("- Before move -%N")
				a_node1 := a_root.last_child
					a_node2 := a_root.first_child			
				test_bool("Child to move should have children", True, a_node2.has_children)
				test_bool("Child to move should have siblings", True, a_node2.has_sibling)
				test_bool("Current parent should have children", True, a_root.has_children)
				test_bool("Target parent should have children", True, a_node2.has_children)
				test_bool("Target and mover should not be the same", True, a_node2 /= a_node1)
				std.output.put_string("- After move -%N")
				a_node2.put_parent(a_node1)				
				test_bool("Moved child should still have children", True, a_node2.has_children)
				test_bool("Moved child should still have siblings", True, a_node2.has_sibling)
				test_bool("Target parent should have children", True, a_node1.has_children)
				test_bool("Target parent should have more than one child", True, a_node1.first_child /= a_node1.last_child)
				test_integer("Count of root's children decreased by 1", L_loopmax - 1, a_root.count)
				std.output.put_string("----------------------------------------%N")

					std.output.put_string("Iterate over all children%N")
				from
					l_index := 1
					l_iter := a_root.new_cursor
				variant
					3*L_loopmax - l_index
				until
					l_iter.off
				loop
					l_index := l_index + 1
					l_iter.forth
				end
				test_integer("Forward count of all children", 2*L_loopmax + 2, l_index)
				from
					l_index := 1
					l_iter.start
				variant
					3*L_loopmax - l_index
				until
					l_iter.off
				loop
					l_index := l_index + 1
					l_iter.forth
				end
				test_integer("Forward count from `start' of all children", 2*L_loopmax + 2, l_index)
				from
					l_index := 1
					l_iter.finish
				variant
					3*L_loopmax - l_index
				until
					l_iter.off
				loop
					l_index := l_index + 1
					if l_index = L_loopmax then
						a_node1 := l_iter.item
					end
					l_iter.back
				end
				test_integer("Reverse count from `finish' of all children", 2*L_loopmax + 2, l_index)
				from
					l_index := 1
					l_iter := a_node1.new_cursor
				variant
					3*L_loopmax - l_index
				until
					l_iter.off
				loop
					l_index := l_index + 1
					l_iter.back
				end
				test_integer("Reverse count from `anode1' of all children", L_loopmax + 4, l_index)

				from
					l_index := 1
					l_iter := a_node1.new_cursor
				variant
					3*L_loopmax - l_index
				until
					l_iter.off
				loop
					l_index := l_index + 1
					l_iter.forth
				end
				test_integer("Forward count from `anode1' of all children", L_loopmax, l_index)
				std.output.put_string("----------------------------------------%N")
				std.output.put_string("About to explode all nodes to independent objects  %N")
			std.output.put_string("using unlink.%N")
			std.output.put_string(" - Before - %N")
			
			a_node1 := a_root.first_child.next_sibling.next_sibling
			a_node2 := a_root.first_child.first_child		
				test_bool("Root should have children", True, a_root.has_children)
				test_bool("Root should have no sibling", False, a_root.has_sibling)
				test_bool("Root should have no parent", False, a_root.has_parent)
				test_bool("Root.third_child should have children", True, a_node1.has_children)
				test_bool("Root.third_child should have sibling", True, a_node1.has_sibling)
				test_bool("Root.third_child should have parent", True, a_node1.has_parent)
				test_bool("Root.first_child.first_child should have no children", False, a_node2.has_children)
				test_bool("Root.first_child.first_child should have no sibling", False, a_node2.has_sibling)
				test_bool("Root.first_child should have parent", True, a_node2.has_parent)
				a_root.unlink
			std.output.put_string(" - After - %N")
			test_bool("Root should have no children", False, a_root.has_children)
				test_bool("Root should have no sibling", False, a_root.has_sibling)
				test_bool("Root should have no parent", False, a_root.has_parent)
				test_bool("(old)Root.third_child should have children", False, a_node1.has_children)
				test_bool("(old)Root.third_child should have sibling", False, a_node1.has_sibling)
				test_bool("(old)Root.third_child should have parent", False, a_node1.has_parent)
				test_bool("(old)Root.first_child.first_child should have no children", False, a_node2.has_children)
				test_bool("(old)Root.first_child.first_child should have no sibling", False, a_node2.has_sibling)
				test_bool("(old)Root.first_child should have parent", False, a_node2.has_parent)
			end

	test_bool(a_title: STRING; a_expect, a_result: BOOLEAN) is
			-- Pretty print test result
		do
			std.output.put_string("----------------------------------------%N")
			std.output.put_string("Name of test: ")
			std.output.put_string(a_title)
			std.output.put_string("%NExpected result: ")
			std.output.put_boolean(a_expect)
			std.output.put_string("%NActual result  : ")
			std.output.put_boolean(a_result)
			if a_expect = a_result then
				std.output.put_string("%N              + Test past + %N")
			else
				std.output.put_string("%N           *** Test failed **** %N")
			end
		end
	
	test_integer(a_title: STRING; a_expect, a_result: INTEGER) is
			-- Pretty print test result
		do
			std.output.put_string("----------------------------------------%N")
			std.output.put_string("Name of test: ")
			std.output.put_string(a_title)
			std.output.put_string("%NExpected result: ")
			std.output.put_integer(a_expect)
			std.output.put_string("%NActual result  : ")
			std.output.put_integer(a_result)
			if a_expect = a_result then
				std.output.put_string("%N              + Test past + %N")
			else
				std.output.put_string("%N           *** Test failed **** %N")
			end
		end
	
	L_loopmax: INTEGER is 10
			
end -- class TREE_NODE_TEST2
