#region CPL License /* Nuclex Framework Copyright (C) 2002-2010 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library 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 IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion #if UNITTEST using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using NUnit.Framework; using Nuclex.Input; using Nuclex.Testing.Xna; using Nuclex.UserInterface.Visuals; using Nuclex.UserInterface.Visuals.Flat; using ComponentEventHandler = System.EventHandler; namespace Nuclex.UserInterface { /// Unit Test for the GUI manager [TestFixture] internal class GuiManagerTest { #region class DummyVisualizer /// Dummy GUI visualizer for unit testing private class DummyVisualizer : IGuiVisualizer, IUpdateable { /// Raised when the Enabled property changes public event ComponentEventHandler EnabledChanged { add { } remove { } } /// Raised when the UpdateOrder property changes public event ComponentEventHandler UpdateOrderChanged { add { } remove { } } /// Renders an entire control tree starting at the provided control /// Screen containing the GUI that will be drawn public void Draw(Screen screen) { ++this.DrawCallCount; } /// /// Whether the game component's Update() method should be called in Game.Update() /// bool IUpdateable.Enabled { get { throw new NotImplementedException(); } } /// Called when the game component should be updated /// Snapshot of the game's timing state public void Update(GameTime gameTime) { ++this.UpdateCallCount; } /// /// When the game component should be updated relative to other game components. /// Lower values are updated first. /// int IUpdateable.UpdateOrder { get { return 0; } } /// Number of times the Draw() method has been called public int DrawCallCount; /// Number of times the Update() method has been called public int UpdateCallCount; } #endregion // class DummyVisualizer /// Called before each test is run [SetUp] public void Setup() { this.mockedGraphicsDeviceService = new MockedGraphicsDeviceService(); this.mockedGraphicsDeviceService.CreateDevice(); this.mockedInputService = new MockInputManager(); } /// Called after each test has run [TearDown] public void Teardown() { if (this.mockedGraphicsDeviceService != null) { this.mockedGraphicsDeviceService.DestroyDevice(); this.mockedGraphicsDeviceService = null; } } /// /// Verifies that an the GUI manager's standard constructor is working /// [Test] public void TestStandardConstructor() { var gameServices = new GameServiceContainer(); using (GuiManager guiManager = new GuiManager(gameServices)) { Assert.IsNotNull(gameServices.GetService(typeof(IGuiService))); } } /// /// Verifies that an the GUI manager's explicit constructor is working /// [Test] public void TestExplicitConstructor() { using ( GuiManager guiManager = new GuiManager( this.mockedGraphicsDeviceService, this.mockedInputService ) ) { Assert.IsNotNull(guiManager); // nonsense, avoids compiler warning } } /// /// Verifies that an the GUI manager's compatibility constructor is working /// [Test] public void TestCompatibilityConstructor() { var gameServices = new GameServiceContainer(); using ( GuiManager guiManager = new GuiManager( gameServices, this.mockedGraphicsDeviceService, this.mockedInputService ) ) { Assert.IsNotNull(gameServices.GetService(typeof(IGuiService))); } } /// Verifies that the GUI manager can be initialized [Test] public void TestInitialization() { var gameServices = new GameServiceContainer(); gameServices.AddService( typeof(IGraphicsDeviceService), this.mockedGraphicsDeviceService ); gameServices.AddService( typeof(IInputService), this.mockedInputService ); using (GuiManager guiManager = new GuiManager(gameServices)) { (guiManager as IGameComponent).Initialize(); } } /// /// Verifies that the screen can be assigned to the GUI manager before it /// has been initialized. /// [Test] public void TestAssignScreenBeforeInitialize() { var gameServices = new GameServiceContainer(); gameServices.AddService( typeof(IGraphicsDeviceService), this.mockedGraphicsDeviceService ); gameServices.AddService( typeof(IInputService), this.mockedInputService ); using (GuiManager guiManager = new GuiManager(gameServices)) { Screen screen = new Screen(); guiManager.Screen = screen; (guiManager as IGameComponent).Initialize(); Assert.AreSame(screen, guiManager.Screen); } } /// /// Verifies that the screen can be assigned to the GUI manager after it /// has been initialized. /// [Test] public void TestAssignScreenAfterInitialize() { var gameServices = new GameServiceContainer(); gameServices.AddService( typeof(IGraphicsDeviceService), this.mockedGraphicsDeviceService ); gameServices.AddService( typeof(IInputService), this.mockedInputService ); using (GuiManager guiManager = new GuiManager(gameServices)) { Screen screen = new Screen(); (guiManager as IGameComponent).Initialize(); guiManager.Screen = screen; Assert.AreSame(screen, guiManager.Screen); } } /// /// Verifies that the Update() method is forwarded to the visualizer to allow /// for animated GUIs /// [Test] public void TestVisualizerUpdate() { using (GuiManager guiManager = new GuiManager(new GameServiceContainer())) { DummyVisualizer dummy = new DummyVisualizer(); IGuiVisualizer visualizer = guiManager.Visualizer; guiManager.Visualizer = dummy; tryDispose(visualizer); Assert.AreEqual(0, dummy.UpdateCallCount); guiManager.Update(new GameTime()); Assert.AreEqual(1, dummy.UpdateCallCount); } } /// /// Verifies that the Draw() method works even when no screen is assigned /// [Test] public void TestDrawingWithoutScreen() { using (GuiManager guiManager = new GuiManager(new GameServiceContainer())) { guiManager.Draw(new GameTime()); // No exception means success } } /// /// Verifies that the Draw() method is forwarded to the visualizer /// [Test] public void TestDrawing() { using (GuiManager guiManager = new GuiManager(new GameServiceContainer())) { DummyVisualizer dummy = new DummyVisualizer(); IGuiVisualizer visualizer = guiManager.Visualizer; guiManager.Visualizer = dummy; tryDispose(visualizer); guiManager.Screen = new Screen(); Assert.AreEqual(0, dummy.DrawCallCount); guiManager.Draw(new GameTime()); Assert.AreEqual(1, dummy.DrawCallCount); } } /// /// Verifies that the GUI manager's visualizer can be retrieved and replaced /// [Test] public void TestVisualizerAssignment() { using (GuiManager guiManager = new GuiManager(new GameServiceContainer())) { IGuiVisualizer visualizer = new DummyVisualizer(); try { IGuiVisualizer newVisualizer = visualizer; Assert.AreNotSame(newVisualizer, guiManager.Visualizer); { IGuiVisualizer oldVisualizer = guiManager.Visualizer; guiManager.Visualizer = newVisualizer; visualizer = oldVisualizer; } Assert.AreSame(newVisualizer, guiManager.Visualizer); } finally { tryDispose(visualizer); } } } /// Tries to dispose an object that might implement IDisposable /// /// Type which might implement IDisposable /// /// /// Instance that will be disposed if it implement IDisposable /// /// True if the instance implemented IDisposable and was disposed private static bool tryDispose( PotentiallyDisposableType instance ) { IDisposable disposable = instance as IDisposable; if (disposable != null) { disposable.Dispose(); return true; } else { return false; } } /// Mocked graphics device service used in the tests private MockedGraphicsDeviceService mockedGraphicsDeviceService; /// Mocked input manager used in the tests private MockInputManager mockedInputService; } } // namespace Nuclex.UserInterface #endif // UNITTEST