/* 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.Threading; using NUnit.Framework; using XenAdmin; using XenAdmin.Controls; using XenAdmin.Network; using XenAdmin.ServerDBs; using XenAPI; namespace XenAdminTests { // IMPORTANT: Do not derive directly from this class. Either derive your TestFixture from // MainWindowLauncher_TestFixture, or your SetUpFixture from MainWindowLauncher_SetUpFixture and // your TestFixture from MainWindowTester. public abstract class MainWindowLauncher : MainWindowTester { private static log4net.ILog log = null; private string[] databases; private bool readOnly = false; private static Thread oldMainWindowThread; public MainWindowLauncher(params string[] databases) { this.databases = databases; } public MainWindowLauncher( bool readOnly, params string[] databases) { this.databases = databases; this.readOnly = readOnly; } public MainWindowLauncher() : this(new string[0]) { } private Thread mainWindowThread; private void CreateMainWindow() { object oldMainWindow = Program.MainWindow; if (oldMainWindowThread != null && oldMainWindowThread.IsAlive) { log.DebugFormat("Cleaning leftover MainWindowThread from previous test"); RemoveStateDBs(); KillMainWindow(); oldMainWindowThread.Join(); } mainWindowThread = new Thread(() => Program.Main(new string[0])); mainWindowThread.Name = "MainWindowThread"; mainWindowThread.SetApartmentState(ApartmentState.STA); mainWindowThread.Start(); oldMainWindowThread = mainWindowThread; while (Program.MainWindow == null || !Program.MainWindow.IsHandleCreated || Program.MainWindow == oldMainWindow) Thread.Sleep(500); } protected void ConnectToStateDBs(params string[] names) { ConnectToStateDBs(readOnly, names); } protected void ConnectToStateDBs(bool readOnly, params string[] names) { if (names.Length > 0) { List connections = new List(); foreach (string name in names) { connections.Add(MW(() => LoadDB(name, readOnly ? "readonly" : "root"))); } MWWaitFor(() => TreeViewContainsConnections(connections), "Couldn't connect to db."); } } protected bool TreeViewContainsConnections(IEnumerable connections) { List connectionsList = new List(connections); foreach (VirtualTreeNode n in MainWindowWrapper.TreeView.AllNodes) { IXenObject x = n.Tag as IXenObject; if (x != null && !(x is Host)) { connectionsList.RemoveAll(c => c == x.Connection); } } return connectionsList.Count == 0; } protected void RemoveStateDBs() { foreach (IXenConnection c in ConnectionsManager.XenConnectionsCopy) { MW(() => c.Cache.Clear()); c.EndConnect(false); c.Dispose(); } lock (ConnectionsManager.ConnectionsLock) { ConnectionsManager.XenConnections.Clear(); } DbProxy.RemoveAll(); } private IXenConnection LoadDB(string name) { return LoadDB(name, "root"); } private IXenConnection LoadDB(string name, string username) { var connection = new XenConnection { Username = username, Password = "", Hostname = TestResource(name), FriendlyName = name, Port = 443, SaveDisconnected = true }; lock (ConnectionsManager.ConnectionsLock) { ConnectionsManager.XenConnections.Add(connection); } XenConnectionUI.BeginConnect(connection, false, null, false); return connection; } private void KillMainWindow() { if (Program.MainWindow != null) { MW(Program.MainWindow.Hide); MW(Program.MainWindow.Close); MW(Program.MainWindow.Dispose); } Thread.Sleep(3000); // We need to give it a short time to clean up before launching another one } protected void _SetUp() { XenAdminConfigManager.Provider = new WinformsXenAdminConfigProvider(); Program.RunInAutomatedTestMode = true; if (log == null) log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); log.DebugFormat("Starting test {0}...", GetType().Name); CreateMainWindow(); log.DebugFormat("MainWindow created for test {0}. Connecting to databases...", GetType().Name); ConnectToStateDBs(readOnly, databases); } protected void _TearDown() { log.DebugFormat("Cleaning up after test {0}...", GetType().Name); RemoveStateDBs(); KillMainWindow(); mainWindowThread.Join(); log.DebugFormat("Clean up complete after test {0}.", GetType().Name); } } public abstract class MainWindowLauncher_TestFixture : MainWindowLauncher { public MainWindowLauncher_TestFixture(params string[] databases) : base(databases) { } public MainWindowLauncher_TestFixture(bool readOnly, params string[] databases) : base(readOnly, databases) { } [TestFixtureSetUp] public void SetUp() { base._SetUp(); } [TestFixtureTearDown] public void TearDown() { base._TearDown(); } } public abstract class MainWindowLauncher_SetUpFixture : MainWindowLauncher { public MainWindowLauncher_SetUpFixture(params string[] databases) : base(databases) { } [SetUp] public void SetUp() { base._SetUp(); } [TearDown] public void TearDown() { base._TearDown(); } } }