2013-06-24 13:41:48 +02:00
/ * Copyright ( c ) Citrix Systems Inc .
* All rights reserved .
*
* Redistribution and use in source and binary forms ,
* with or without modification , are permitted provided
* that the following conditions are met :
*
* * Redistributions of source code must retain the above
* copyright notice , this list of conditions and the
* following disclaimer .
* * Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the
* following disclaimer in the documentation and / or other
* materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ,
* INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Threading ;
using NUnit.Framework ;
using XenAdmin.Controls ;
2013-08-26 12:42:32 +02:00
using XenAdmin.Controls.MainWindowControls ;
2013-06-24 13:41:48 +02:00
using XenAPI ;
using System.Windows.Forms ;
using XenAdmin.Core ;
using System.Reflection ;
using XenAdmin ;
using XenAdmin.XenSearch ;
namespace XenAdminTests.TreeTests
{
[TestFixture, Category(TestCategories.UICategoryB)]
public class MainWindowTreeTests : MainWindowLauncher_TestFixture
{
public MainWindowTreeTests ( )
: base ( "state1.xml" )
{ }
/// <summary>
/// Checks that all nodes matched by the specified Predicate are expanded and the rest are collapsed. Returns true if this
/// is the case.
/// </summary>
private bool CheckExpandedNodes ( Predicate < VirtualTreeNode > match )
{
return CheckExpandedNodes ( match , null ) ;
}
/// <summary>
/// Asserts that all nodes matched by the specified Predicate are expanded and the rest are collapsed.
/// </summary>
private bool CheckExpandedNodes ( Predicate < VirtualTreeNode > match , string assertMessage )
{
return MWWaitFor ( delegate
{
foreach ( VirtualTreeNode n in MainWindowWrapper . TreeView . AllNodes )
{
if ( match ( n ) & & n . Nodes . Count > 0 )
{
if ( ! n . IsExpanded )
{
return false ;
}
}
else if ( n . IsExpanded )
{
return false ;
}
}
return true ;
} , assertMessage ) ;
}
private void SetExpandedNodes ( Predicate < VirtualTreeNode > match )
{
MW ( delegate
{
foreach ( VirtualTreeNode n in MainWindowWrapper . TreeView . AllNodes )
{
if ( match ( n ) )
{
n . Expand ( ) ;
}
else
{
n . Collapse ( ) ;
}
}
} ) ;
}
[Test]
public void TestPersistenceBetweenServerAndOrgView ( )
{
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
// collapse all nodes in server view.
MW ( MainWindowWrapper . TreeView . CollapseAll ) ;
// wait for all nodes to become collapsed.
CheckExpandedNodes ( n = > false , "Couldn't collapse all nodes." ) ;
// expand root node and pool node.
MW ( ( ) = >
{
VirtualTreeNode poolNode = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 0 ] ;
Assert . AreEqual ( "Hottub" , poolNode . Text ) ;
MainWindowWrapper . TreeView . Nodes [ 0 ] . Expand ( ) ;
poolNode . Expand ( ) ;
} ) ;
// wait for those nodes to become expanded
CheckExpandedNodes ( n = > n = = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 0 ] | | n . Tag = = null , "Could expand nodes." ) ;
// expand host nodes in server view.
MW ( ( ) = >
{
VirtualTreeNode poolNode = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 0 ] ;
poolNode . Nodes [ 0 ] . Expand ( ) ;
poolNode . Nodes [ 1 ] . Expand ( ) ;
} ) ;
// check hosts nodes got expanded.
CheckExpandedNodes ( n = >
{
VirtualTreeNode poolNode = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 0 ] ;
return n . Tag = = null | | n = = poolNode | | n = = poolNode . Nodes [ 0 ] | | n = = poolNode . Nodes [ 1 ] ;
} , "Couldn't expand host nodes." ) ;
2013-08-28 15:44:46 +02:00
// now go into objects view.
PutInNavigationMode ( NavigationPane . NavigationMode . Objects ) ;
2013-06-24 13:41:48 +02:00
// collapse all nodes
MW ( MainWindowWrapper . TreeView . CollapseAll ) ;
// wait for all nodes to become collapsed.
CheckExpandedNodes ( n = > false , "Couldn't collapse all nodes." ) ;
2013-08-28 15:44:46 +02:00
// expand root node and snapshots nodes in folder view.
2013-06-24 13:41:48 +02:00
MW ( ( ) = >
{
MainWindowWrapper . TreeView . Nodes [ 0 ] . Expand ( ) ;
2013-10-08 11:17:57 +02:00
MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 3 ] . Expand ( ) ;
VirtualTreeNode typesNode = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 3 ] ;
2013-08-28 15:44:46 +02:00
Assert . AreEqual ( "Snapshots" , typesNode . Text ) ;
2013-06-24 13:41:48 +02:00
typesNode . Expand ( ) ;
} ) ;
// wait for those nodes to become expanded.
2013-08-28 15:44:46 +02:00
CheckExpandedNodes ( n = > n = = MainWindowWrapper . TreeView . Nodes [ 0 ]
2013-10-08 11:17:57 +02:00
| | n = = MainWindowWrapper . TreeView . Nodes [ 0 ] . Nodes [ 3 ] , "Couldn't expand nodes." ) ;
2013-06-24 13:41:48 +02:00
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
if ( ! CheckExpandedNodes ( n = > n . Tag = = null | | n . Tag is Pool | | n . Tag is Host ) )
{
2013-07-01 17:59:42 +02:00
var expandedNodes = MW ( ( ) = > GetAllTreeNodes ( ) . FindAll ( n = > n . IsExpanded ) . ConvertAll ( n = > n . Text ) ) ;
Assert . Fail ( "Nodes not correctly persisted in infrastructure view. Expanded nodes were: " + string . Join ( ", " , expandedNodes . ToArray ( ) ) + ". They should have only been XenCenter, Hottub, inflames, incubus." ) ;
2013-06-24 13:41:48 +02:00
}
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Objects ) ;
2013-06-24 13:41:48 +02:00
2013-10-08 11:17:57 +02:00
if ( ! CheckExpandedNodes ( n = > n . Parent = = null | | n . Text = = "Objects by Type" | | n . Text = = "Snapshots" ) )
2013-06-24 13:41:48 +02:00
{
2013-07-01 17:59:42 +02:00
var expandedNodes = MW ( ( ) = > GetAllTreeNodes ( ) . FindAll ( n = > n . IsExpanded ) . ConvertAll ( n = > n . Text ) ) ;
Assert . Fail ( "Nodes not correctly persisted in organization view. Expanded nodes were: " + string . Join ( ", " , expandedNodes . ToArray ( ) ) + ". They should have only been Objects, Types." ) ;
}
2013-06-24 13:41:48 +02:00
}
[Test]
public void TestMigratedVMStaysSelectedAndBecomesVisible ( )
{
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
// this VM is at pool level.
VM vm = GetAnyVM ( v = > v . name_label = = "Windows Server 2008 (1)" ) ;
SelectInTree ( vm ) ;
MWWaitFor ( ( ) = > MainWindowWrapper . MainToolStripItems . StartVMToolStripButton . Enabled , "Start button didn't become enabled." ) ;
// start the VM
MW ( MainWindowWrapper . MainToolStripItems . StartVMToolStripButton . PerformClick ) ;
// wait for the VM which was at the pool level to become running on one of the hosts.
MWWaitFor ( ( ) = >
{
VirtualTreeNode n = FindInTree ( vm ) ;
return n . Parent . Tag is Host & & n . IsSelected & & n . Parent . IsExpanded & & ( ( TreeNode ) n ) . TreeView ! = null ;
} , "Node didn't get migrated correctly." ) ;
}
[Test]
2013-08-28 15:44:46 +02:00
[Ignore]
2013-06-24 13:41:48 +02:00
public void TestPersistenceWhenAddingThenRemovingTextSearch ( )
{
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
Thread . Sleep ( 1000 ) ;
// expand root, pool and host nodes.
SetExpandedNodes ( n = > n . Tag is Host | | n . Tag is Pool | | n . Tag = = null ) ;
Thread . Sleep ( 1000 ) ;
// apply a random search
ApplyTreeSearch ( "DVD" ) ;
Thread . Sleep ( 1000 ) ;
// test that all the nodes were expanded for the search.
CheckExpandedNodes ( n = > true , "Not all nodes were expanded for search" ) ;
Thread . Sleep ( 1000 ) ;
// now remove the search
ApplyTreeSearch ( string . Empty ) ;
Thread . Sleep ( 1000 ) ;
// now check the original nodes expansion state has been restored.
CheckExpandedNodes ( n = > n . Tag = = null | | n . Tag is Pool | | n . Tag is Host , "Nodes weren't correctly persisted" ) ;
}
[Test]
public void TestPersistenceWhenAddingThenRemovingSavedSearch ( )
{
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
// expand root and pool nodes.
SetExpandedNodes ( n = > n . Tag is Pool | | n . Tag = = null ) ;
// apply a random saved search
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . SavedSearch ) ;
2013-06-24 13:41:48 +02:00
// test that all the nodes were expanded for the saved search.
CheckExpandedNodes ( n = > true , "Not all nodes were expanded for search" ) ;
// now remove the saved search by going back into server
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Infrastructure ) ;
2013-06-24 13:41:48 +02:00
// now check the original nodes expansion state has been restored.
CheckExpandedNodes ( n = > n . Tag = = null | | n . Tag is Pool , "Nodes weren't correctly persisted" ) ;
}
private short GetTreeUpdateCount ( )
{
return ( short ) typeof ( Control ) . GetField ( "updateCount" , BindingFlags . Instance | BindingFlags . NonPublic ) . GetValue ( MainWindowWrapper . TreeView ) ;
}
[Test]
public void TestBeginUpdateOnlyCalledIfNecessary ( )
{
2013-08-28 15:44:46 +02:00
PutInNavigationMode ( NavigationPane . NavigationMode . Objects ) ;
2013-06-24 13:41:48 +02:00
MW ( delegate
{
MainWindowTreeBuilder builder = new MainWindowTreeBuilder ( MainWindowWrapper . TreeView ) ;
2013-08-26 12:42:32 +02:00
VirtualTreeNode newRoot = builder . CreateNewRootNode ( TreeSearch . DefaultTreeSearch , NavigationPane . NavigationMode . Objects ) ;
2013-07-01 17:59:42 +02:00
MainWindowWrapper . TreeView . UpdateRootNodes ( new [ ] { newRoot } ) ; // update once to set all the node names properly
2013-06-24 13:41:48 +02:00
MainWindowWrapper . TreeView . EndUpdate ( ) ;
short updateCount = GetTreeUpdateCount ( ) ;
2013-07-01 17:59:42 +02:00
MainWindowWrapper . TreeView . UpdateRootNodes ( new [ ] { newRoot } ) ; // update again: nothing should change this time
2013-06-24 13:41:48 +02:00
short updateCount2 = GetTreeUpdateCount ( ) ;
Assert . AreEqual ( updateCount , updateCount2 , "BeginUpdate shouldn't have been called." ) ;
// this time there is a different node, so an update should occur
2013-08-26 12:42:32 +02:00
newRoot = builder . CreateNewRootNode ( TreeSearch . DefaultTreeSearch , NavigationPane . NavigationMode . Objects ) ;
2013-06-24 13:41:48 +02:00
newRoot . Nodes [ 0 ] . Text = "bla" ;
2013-07-01 17:59:42 +02:00
MainWindowWrapper . TreeView . UpdateRootNodes ( new [ ] { newRoot } ) ;
2013-06-24 13:41:48 +02:00
short updateCount3 = GetTreeUpdateCount ( ) ;
Assert . AreEqual ( updateCount2 + 1 , updateCount3 , "BeginUpdate should have been called exactly once" ) ;
MainWindowWrapper . TreeView . EndUpdate ( ) ;
Assert . AreEqual ( 0 , GetTreeUpdateCount ( ) , "FlickFreeTreeView didn't pass EndUpdate down to TreeView." ) ;
} ) ;
}
}
}