From 196836b7eb45df8b92291b9295d21b9c5b46c353 Mon Sep 17 00:00:00 2001 From: dbuechel Date: Thu, 1 Feb 2018 08:37:12 +0100 Subject: [PATCH] SEBWIN-219: Changed and simplified implementation of operation mechanism to allow reconfiguration (i.e. repeating operations). --- SafeExamBrowser.Client/App.cs | 26 +-- .../Behaviour/Operations/BrowserOperation.cs | 8 +- .../Operations/ClientControllerOperation.cs | 8 +- .../Operations/ClipboardOperation.cs | 9 +- .../Operations/DisplayMonitorOperation.cs | 9 +- .../KeyboardInterceptorOperation.cs | 10 +- .../Operations/MouseInterceptorOperation.cs | 9 +- .../Operations/ProcessMonitorOperation.cs | 9 +- .../Behaviour/Operations/TaskbarOperation.cs | 8 +- .../Operations/WindowMonitorOperation.cs | 9 +- SafeExamBrowser.Client/CompositionRoot.cs | 5 +- .../Behaviour/IRuntimeController.cs | 13 +- .../Behaviour/IShutdownController.cs | 20 -- .../Behaviour/IStartupController.cs | 21 -- .../Behaviour/{ => Operations}/IOperation.cs | 11 +- .../Operations/IOperationSequence.cs | 30 +++ .../SafeExamBrowser.Contracts.csproj | 5 +- .../OperationSequenceTests.cs} | 191 +++++++++++++++--- .../Behaviour/ShutdownControllerTests.cs | 148 -------------- .../SafeExamBrowser.Core.UnitTests.csproj | 3 +- .../Behaviour/Operations/I18nOperation.cs | 9 +- .../OperationSequence.cs} | 113 ++++++----- .../Behaviour/ShutdownController.cs | 98 --------- .../SafeExamBrowser.Core.csproj | 3 +- .../Operations/ConfigurationOperationTests.cs | 4 +- .../Operations/ServiceOperationTests.cs | 4 +- SafeExamBrowser.Runtime/App.cs | 10 +- .../Operations/ConfigurationOperation.cs | 13 +- .../Operations/KioskModeOperation.cs | 17 +- .../Behaviour/Operations/ServiceOperation.cs | 44 ++-- .../Behaviour/RuntimeController.cs | 49 +++-- SafeExamBrowser.Runtime/CompositionRoot.cs | 7 +- 32 files changed, 461 insertions(+), 462 deletions(-) delete mode 100644 SafeExamBrowser.Contracts/Behaviour/IShutdownController.cs delete mode 100644 SafeExamBrowser.Contracts/Behaviour/IStartupController.cs rename SafeExamBrowser.Contracts/Behaviour/{ => Operations}/IOperation.cs (75%) create mode 100644 SafeExamBrowser.Contracts/Behaviour/Operations/IOperationSequence.cs rename SafeExamBrowser.Core.UnitTests/Behaviour/{StartupControllerTests.cs => Operations/OperationSequenceTests.cs} (57%) delete mode 100644 SafeExamBrowser.Core.UnitTests/Behaviour/ShutdownControllerTests.cs rename SafeExamBrowser.Core/Behaviour/{StartupController.cs => Operations/OperationSequence.cs} (61%) delete mode 100644 SafeExamBrowser.Core/Behaviour/ShutdownController.cs diff --git a/SafeExamBrowser.Client/App.cs b/SafeExamBrowser.Client/App.cs index 1a1870d6..6addc121 100644 --- a/SafeExamBrowser.Client/App.cs +++ b/SafeExamBrowser.Client/App.cs @@ -12,7 +12,7 @@ using System.ComponentModel; using System.Linq; using System.Threading; using System.Windows; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; namespace SafeExamBrowser.Client { @@ -61,18 +61,18 @@ namespace SafeExamBrowser.Client instances.BuildObjectGraph(); - var success = instances.StartupController.TryInitializeApplication(instances.StartupOperations); + //var success = instances.StartupController.TryInitializeApplication(instances.StartupOperations); - if (success) - { - MainWindow = instances.Taskbar; - MainWindow.Closing += MainWindow_Closing; - MainWindow.Show(); - } - else - { - Shutdown(); - } + //if (success) + //{ + // MainWindow = instances.Taskbar; + // MainWindow.Closing += MainWindow_Closing; + // MainWindow.Show(); + //} + //else + //{ + // Shutdown(); + //} } private void MainWindow_Closing(object sender, CancelEventArgs e) @@ -80,7 +80,7 @@ namespace SafeExamBrowser.Client var operations = new Queue(instances.StartupOperations.Reverse()); MainWindow.Hide(); - instances.ShutdownController.FinalizeApplication(operations); + //instances.ShutdownController.FinalizeApplication(operations); } } } diff --git a/SafeExamBrowser.Client/Behaviour/Operations/BrowserOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/BrowserOperation.cs index 26073740..45bf8879 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/BrowserOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/BrowserOperation.cs @@ -7,6 +7,7 @@ */ using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -23,7 +24,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ITaskbar taskbar; private IUserInterfaceFactory uiFactory; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public BrowserOperation( @@ -53,6 +54,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations taskbar.AddApplication(browserButton); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Terminating browser..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/ClientControllerOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/ClientControllerOperation.cs index b48984cb..b21e680b 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/ClientControllerOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/ClientControllerOperation.cs @@ -7,6 +7,7 @@ */ using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; @@ -18,7 +19,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private IClientController controller; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public ClientControllerOperation(IClientController controller, ILogger logger) @@ -35,6 +36,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations controller.Start(); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Stopping event handling..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/ClipboardOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/ClipboardOperation.cs index a33fef9a..58982947 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/ClipboardOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/ClipboardOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; @@ -19,7 +19,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private INativeMethods nativeMethods; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public ClipboardOperation(ILogger logger, INativeMethods nativeMethods) @@ -33,6 +33,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations EmptyClipboard(); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { EmptyClipboard(); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/DisplayMonitorOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/DisplayMonitorOperation.cs index 3a0df0da..e9ae0c49 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/DisplayMonitorOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/DisplayMonitorOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; @@ -21,7 +21,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private ITaskbar taskbar; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, ITaskbar taskbar) @@ -41,6 +41,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations displayMonitor.StartMonitoringDisplayChanges(); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Restoring working area..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/KeyboardInterceptorOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/KeyboardInterceptorOperation.cs index 23e01fa3..cb2216fb 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/KeyboardInterceptorOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/KeyboardInterceptorOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; @@ -21,7 +21,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private INativeMethods nativeMethods; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public KeyboardInterceptorOperation( @@ -40,7 +40,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations SplashScreen.UpdateText(TextKey.SplashScreen_StartKeyboardInterception); nativeMethods.RegisterKeyboardHook(keyboardInterceptor); - + } + + public void Repeat() + { + // Nothing to do here... } public void Revert() diff --git a/SafeExamBrowser.Client/Behaviour/Operations/MouseInterceptorOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/MouseInterceptorOperation.cs index d5d3c977..70b29cca 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/MouseInterceptorOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/MouseInterceptorOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; @@ -21,7 +21,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private IMouseInterceptor mouseInterceptor; private INativeMethods nativeMethods; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public MouseInterceptorOperation( @@ -42,6 +42,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations nativeMethods.RegisterMouseHook(mouseInterceptor); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Stopping mouse interception..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/ProcessMonitorOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/ProcessMonitorOperation.cs index 9f76d206..815a02ee 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/ProcessMonitorOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/ProcessMonitorOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; @@ -19,7 +19,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private IProcessMonitor processMonitor; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor) @@ -41,6 +41,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations // TODO } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Stopping process monitoring..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/TaskbarOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/TaskbarOperation.cs index bb065669..7fe7ca4b 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/TaskbarOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/TaskbarOperation.cs @@ -8,6 +8,7 @@ using SafeExamBrowser.Client.Notifications; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; @@ -31,7 +32,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private IUserInterfaceFactory uiFactory; private IText text; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public TaskbarOperation( @@ -82,6 +83,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations } } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Terminating taskbar..."); diff --git a/SafeExamBrowser.Client/Behaviour/Operations/WindowMonitorOperation.cs b/SafeExamBrowser.Client/Behaviour/Operations/WindowMonitorOperation.cs index f519388f..e8d370ae 100644 --- a/SafeExamBrowser.Client/Behaviour/Operations/WindowMonitorOperation.cs +++ b/SafeExamBrowser.Client/Behaviour/Operations/WindowMonitorOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; @@ -19,7 +19,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations private ILogger logger; private IWindowMonitor windowMonitor; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public WindowMonitorOperation(ILogger logger, IWindowMonitor windowMonitor) @@ -37,6 +37,11 @@ namespace SafeExamBrowser.Client.Behaviour.Operations windowMonitor.StartMonitoringWindows(); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { logger.Info("Stopping window monitoring..."); diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index c81d5985..300b806b 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -11,6 +11,7 @@ using SafeExamBrowser.Browser; using SafeExamBrowser.Configuration; using SafeExamBrowser.Configuration.Settings; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; @@ -47,8 +48,8 @@ namespace SafeExamBrowser.Client private IUserInterfaceFactory uiFactory; private IWindowMonitor windowMonitor; - internal IShutdownController ShutdownController { get; private set; } - internal IStartupController StartupController { get; private set; } + //internal IShutdownController ShutdownController { get; private set; } + //internal IStartupController StartupController { get; private set; } internal Queue StartupOperations { get; private set; } internal Taskbar Taskbar { get; private set; } diff --git a/SafeExamBrowser.Contracts/Behaviour/IRuntimeController.cs b/SafeExamBrowser.Contracts/Behaviour/IRuntimeController.cs index 4b8e7c3e..a885540e 100644 --- a/SafeExamBrowser.Contracts/Behaviour/IRuntimeController.cs +++ b/SafeExamBrowser.Contracts/Behaviour/IRuntimeController.cs @@ -6,18 +6,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using System.Collections.Generic; +using SafeExamBrowser.Contracts.Behaviour.Operations; + namespace SafeExamBrowser.Contracts.Behaviour { - public interface IRuntimeController : IStartupController + public interface IRuntimeController { /// - /// Reverts any changes performed during the startup or runtime and releases all used resources. + /// Reverts any changes, releases all used resources and terminates the runtime. /// - void FinalizeApplication(); + void Terminate(); /// - /// Initializes a new session and starts performing the runtime logic / event handling. + /// Tries to start the runtime. Returns true if successful, otherwise false. /// - void StartSession(); + bool TryStart(Queue operations); } } diff --git a/SafeExamBrowser.Contracts/Behaviour/IShutdownController.cs b/SafeExamBrowser.Contracts/Behaviour/IShutdownController.cs deleted file mode 100644 index 636be789..00000000 --- a/SafeExamBrowser.Contracts/Behaviour/IShutdownController.cs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System.Collections.Generic; - -namespace SafeExamBrowser.Contracts.Behaviour -{ - public interface IShutdownController - { - /// - /// Reverts any changes performed during the startup or runtime and releases all used resources. - /// - void FinalizeApplication(Queue operations); - } -} diff --git a/SafeExamBrowser.Contracts/Behaviour/IStartupController.cs b/SafeExamBrowser.Contracts/Behaviour/IStartupController.cs deleted file mode 100644 index 337670ef..00000000 --- a/SafeExamBrowser.Contracts/Behaviour/IStartupController.cs +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System.Collections.Generic; - -namespace SafeExamBrowser.Contracts.Behaviour -{ - public interface IStartupController - { - /// - /// Tries to initialize the application according to the given queue of operations. - /// Returns true if the initialization was successful, false otherwise. - /// - bool TryInitializeApplication(Queue operations); - } -} diff --git a/SafeExamBrowser.Contracts/Behaviour/IOperation.cs b/SafeExamBrowser.Contracts/Behaviour/Operations/IOperation.cs similarity index 75% rename from SafeExamBrowser.Contracts/Behaviour/IOperation.cs rename to SafeExamBrowser.Contracts/Behaviour/Operations/IOperation.cs index b6c103e5..39ebc29a 100644 --- a/SafeExamBrowser.Contracts/Behaviour/IOperation.cs +++ b/SafeExamBrowser.Contracts/Behaviour/Operations/IOperation.cs @@ -8,14 +8,14 @@ using SafeExamBrowser.Contracts.UserInterface; -namespace SafeExamBrowser.Contracts.Behaviour +namespace SafeExamBrowser.Contracts.Behaviour.Operations { public interface IOperation { /// - /// Determines whether the startup procedure to which this operation belongs should be aborted. + /// Determines whether the procedure to which this operation belongs should be aborted. /// - bool AbortStartup { get; } + bool Abort { get; } /// /// The splash screen to be used to show status information to the user. @@ -27,6 +27,11 @@ namespace SafeExamBrowser.Contracts.Behaviour /// void Perform(); + /// + /// Repeats the operation. + /// + void Repeat(); + /// /// Reverts all changes which were made when performing the operation. /// diff --git a/SafeExamBrowser.Contracts/Behaviour/Operations/IOperationSequence.cs b/SafeExamBrowser.Contracts/Behaviour/Operations/IOperationSequence.cs new file mode 100644 index 00000000..240b63e6 --- /dev/null +++ b/SafeExamBrowser.Contracts/Behaviour/Operations/IOperationSequence.cs @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System.Collections.Generic; + +namespace SafeExamBrowser.Contracts.Behaviour.Operations +{ + public interface IOperationSequence + { + /// + /// Tries to perform the given sequence of operations. Returns true if the procedure was successful, false otherwise. + /// + bool TryPerform(Queue operations); + + /// + /// Tries to repeat all operations of this sequence. Returns true if the procedure was successful, false otherwise. + /// + bool TryRepeat(); + + /// + /// Tries to revert all operations of this sequence. Returns true if the procedure was successful, false otherwise. + /// + bool TryRevert(); + } +} diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj index 612cea5a..bb6d9e5e 100644 --- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj +++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj @@ -55,6 +55,7 @@ + @@ -65,7 +66,7 @@ - + @@ -77,8 +78,6 @@ - - diff --git a/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs b/SafeExamBrowser.Core.UnitTests/Behaviour/Operations/OperationSequenceTests.cs similarity index 57% rename from SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs rename to SafeExamBrowser.Core.UnitTests/Behaviour/Operations/OperationSequenceTests.cs index b1527a95..3f7c68bf 100644 --- a/SafeExamBrowser.Core.UnitTests/Behaviour/StartupControllerTests.cs +++ b/SafeExamBrowser.Core.UnitTests/Behaviour/Operations/OperationSequenceTests.cs @@ -10,40 +10,39 @@ using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; -using SafeExamBrowser.Core.Behaviour; +using SafeExamBrowser.Core.Behaviour.Operations; -namespace SafeExamBrowser.Core.UnitTests.Behaviour +namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations { [TestClass] - public class StartupControllerTests + public class OperationSequenceTests { private Mock loggerMock; private Mock runtimeInfoMock; - private Mock systemInfoMock; private Mock textMock; private Mock uiFactoryMock; - private IStartupController sut; + private IOperationSequence sut; [TestInitialize] public void Initialize() { loggerMock = new Mock(); runtimeInfoMock = new Mock(); - systemInfoMock = new Mock(); textMock = new Mock(); uiFactoryMock = new Mock(); - uiFactoryMock.Setup(f => f.CreateSplashScreen(runtimeInfoMock.Object, textMock.Object)).Returns(new Mock().Object); - sut = new StartupController(loggerMock.Object, runtimeInfoMock.Object, systemInfoMock.Object, textMock.Object, uiFactoryMock.Object); + sut = new OperationSequence(loggerMock.Object, runtimeInfoMock.Object, textMock.Object, uiFactoryMock.Object); } + #region Perform Tests + [TestMethod] public void MustCorrectlyAbortProcess() { @@ -52,13 +51,13 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour var operationC = new Mock(); var operations = new Queue(); - operationB.SetupGet(o => o.AbortStartup).Returns(true); + operationB.SetupGet(o => o.Abort).Returns(true); operations.Enqueue(operationA.Object); operations.Enqueue(operationB.Object); operations.Enqueue(operationC.Object); - var result = sut.TryInitializeApplication(operations); + var success = sut.TryPerform(operations); operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Revert(), Times.Once); @@ -67,7 +66,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operationC.Verify(o => o.Perform(), Times.Never); operationC.Verify(o => o.Revert(), Times.Never); - Assert.IsFalse(result); + Assert.IsFalse(success); } [TestMethod] @@ -82,7 +81,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operations.Enqueue(operationB.Object); operations.Enqueue(operationC.Object); - var result = sut.TryInitializeApplication(operations); + var success = sut.TryPerform(operations); operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Revert(), Times.Never); @@ -91,7 +90,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operationC.Verify(o => o.Perform(), Times.Once); operationC.Verify(o => o.Revert(), Times.Never); - Assert.IsTrue(result); + Assert.IsTrue(success); } [TestMethod] @@ -111,8 +110,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operations.Enqueue(operationB.Object); operations.Enqueue(operationC.Object); - sut.TryInitializeApplication(operations); + var success = sut.TryPerform(operations); + Assert.IsTrue(success); Assert.IsTrue(a == 1); Assert.IsTrue(b == 2); Assert.IsTrue(c == 3); @@ -134,7 +134,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operations.Enqueue(operationC.Object); operations.Enqueue(operationD.Object); - var result = sut.TryInitializeApplication(operations); + var success = sut.TryPerform(operations); operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Revert(), Times.Once); @@ -145,11 +145,11 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operationD.Verify(o => o.Perform(), Times.Never); operationD.Verify(o => o.Revert(), Times.Never); - Assert.IsFalse(result); + Assert.IsFalse(success); } [TestMethod] - public void MustRevertOperationsInSequence() + public void MustRevertOperationsInSequenceAfterPerformError() { int current = 0, a = 0, b = 0, c = 0, d = 0; var operationA = new Mock(); @@ -169,8 +169,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operations.Enqueue(operationC.Object); operations.Enqueue(operationD.Object); - sut.TryInitializeApplication(operations); + var success = sut.TryPerform(operations); + Assert.IsFalse(success); Assert.IsTrue(d == 0); Assert.IsTrue(c == 1); Assert.IsTrue(b == 2); @@ -178,7 +179,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour } [TestMethod] - public void MustContinueToRevertOperationsInCaseOfError() + public void MustContinueToRevertOperationsAfterPerformError() { var operationA = new Mock(); var operationB = new Mock(); @@ -194,7 +195,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour operations.Enqueue(operationB.Object); operations.Enqueue(operationC.Object); - var result = sut.TryInitializeApplication(operations); + var result = sut.TryPerform(operations); operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Revert(), Times.Once); @@ -207,7 +208,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour [TestMethod] public void MustSucceedWithEmptyQueue() { - var result = sut.TryInitializeApplication(new Queue()); + var result = sut.TryPerform(new Queue()); Assert.IsTrue(result); } @@ -217,7 +218,151 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour public void MustNotFailInCaseOfUnexpectedError() { uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny(), It.IsAny())).Throws(new Exception()); - sut.TryInitializeApplication(new Queue()); + + var success = sut.TryPerform(new Queue()); + + Assert.IsFalse(success); } + + #endregion + + #region Repeat Tests + + [TestMethod] + public void Fail() + { + // TODO + Assert.Fail(); + } + + #endregion + + #region Revert Tests + + [TestMethod] + public void MustRevertOperations() + { + var operationA = new Mock(); + var operationB = new Mock(); + var operationC = new Mock(); + var operations = new Queue(); + + operations.Enqueue(operationA.Object); + operations.Enqueue(operationB.Object); + operations.Enqueue(operationC.Object); + + sut.TryPerform(operations); + + var success = sut.TryRevert(); + + operationA.Verify(o => o.Revert(), Times.Once); + operationB.Verify(o => o.Revert(), Times.Once); + operationC.Verify(o => o.Revert(), Times.Once); + + Assert.IsTrue(success); + } + + [TestMethod] + public void MustRevertOperationsInSequence() + { + int current = 0, a = 0, b = 0, c = 0; + var operationA = new Mock(); + var operationB = new Mock(); + var operationC = new Mock(); + var operations = new Queue(); + + operationA.Setup(o => o.Revert()).Callback(() => a = ++current); + operationB.Setup(o => o.Revert()).Callback(() => b = ++current); + operationC.Setup(o => o.Revert()).Callback(() => c = ++current); + + operations.Enqueue(operationA.Object); + operations.Enqueue(operationB.Object); + operations.Enqueue(operationC.Object); + + sut.TryPerform(operations); + + var success = sut.TryRevert(); + + Assert.IsTrue(success); + Assert.IsTrue(c == 1); + Assert.IsTrue(b == 2); + Assert.IsTrue(a == 3); + } + + [TestMethod] + public void MustContinueToRevertOperationsInCaseOfError() + { + var operationA = new Mock(); + var operationB = new Mock(); + var operationC = new Mock(); + var operations = new Queue(); + + operationA.Setup(o => o.Revert()).Throws(); + operationB.Setup(o => o.Revert()).Throws(); + operationC.Setup(o => o.Revert()).Throws(); + + operations.Enqueue(operationA.Object); + operations.Enqueue(operationB.Object); + operations.Enqueue(operationC.Object); + + sut.TryPerform(operations); + + var success = sut.TryRevert(); + + operationA.Verify(o => o.Revert(), Times.Once); + operationB.Verify(o => o.Revert(), Times.Once); + operationC.Verify(o => o.Revert(), Times.Once); + + Assert.IsFalse(success); + } + + [TestMethod] + public void MustOnlyRevertPerformedOperations() + { + var operationA = new Mock(); + var operationB = new Mock(); + var operationC = new Mock(); + var operations = new Queue(); + + operationB.SetupGet(o => o.Abort).Returns(true); + + operations.Enqueue(operationA.Object); + operations.Enqueue(operationB.Object); + operations.Enqueue(operationC.Object); + + sut.TryPerform(operations); + + var success = sut.TryRevert(); + + operationA.Verify(o => o.Revert(), Times.Once); + operationB.Verify(o => o.Revert(), Times.Once); + operationC.Verify(o => o.Revert(), Times.Never); + + Assert.IsTrue(success); + } + + [TestMethod] + public void MustNotFailWithEmptyQueueWhenReverting() + { + sut.TryPerform(new Queue()); + sut.TryRevert(); + } + + [TestMethod] + public void MustNotFailWithoutPerformWhenReverting() + { + var success = sut.TryRevert(); + + Assert.IsTrue(success); + } + + [TestMethod] + public void MustNotFailInCaseOfUnexpectedErrorWhenReverting() + { + uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny(), It.IsAny())).Throws(new Exception()); + sut.TryRevert(); + } + + #endregion } } diff --git a/SafeExamBrowser.Core.UnitTests/Behaviour/ShutdownControllerTests.cs b/SafeExamBrowser.Core.UnitTests/Behaviour/ShutdownControllerTests.cs deleted file mode 100644 index 35f0397a..00000000 --- a/SafeExamBrowser.Core.UnitTests/Behaviour/ShutdownControllerTests.cs +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SafeExamBrowser.Contracts.Behaviour; -using SafeExamBrowser.Contracts.Configuration; -using SafeExamBrowser.Contracts.I18n; -using SafeExamBrowser.Contracts.Logging; -using SafeExamBrowser.Contracts.UserInterface; -using SafeExamBrowser.Core.Behaviour; - -namespace SafeExamBrowser.Core.UnitTests.Behaviour -{ - [TestClass] - public class ShutdownControllerTests - { - private Mock loggerMock; - private Mock runtimeInfoMock; - private Mock textMock; - private Mock uiFactoryMock; - - private IShutdownController sut; - - [TestInitialize] - public void Initialize() - { - loggerMock = new Mock(); - runtimeInfoMock = new Mock(); - textMock = new Mock(); - uiFactoryMock = new Mock(); - - uiFactoryMock.Setup(f => f.CreateSplashScreen(runtimeInfoMock.Object, textMock.Object)).Returns(new Mock().Object); - - sut = new ShutdownController(loggerMock.Object, runtimeInfoMock.Object, textMock.Object, uiFactoryMock.Object); - } - - [TestMethod] - public void MustRevertOperations() - { - var operationA = new Mock(); - var operationB = new Mock(); - var operationC = new Mock(); - var operations = new Queue(); - - operations.Enqueue(operationA.Object); - operations.Enqueue(operationB.Object); - operations.Enqueue(operationC.Object); - - sut.FinalizeApplication(operations); - - operationA.Verify(o => o.Revert(), Times.Once); - operationA.Verify(o => o.Perform(), Times.Never); - operationB.Verify(o => o.Revert(), Times.Once); - operationB.Verify(o => o.Perform(), Times.Never); - operationC.Verify(o => o.Revert(), Times.Once); - operationC.Verify(o => o.Perform(), Times.Never); - } - - [TestMethod] - public void MustRevertOperationsInSequence() - { - int current = 0, a = 0, b = 0, c = 0; - var operationA = new Mock(); - var operationB = new Mock(); - var operationC = new Mock(); - var operations = new Queue(); - - operationA.Setup(o => o.Revert()).Callback(() => a = ++current); - operationB.Setup(o => o.Revert()).Callback(() => b = ++current); - operationC.Setup(o => o.Revert()).Callback(() => c = ++current); - - operations.Enqueue(operationA.Object); - operations.Enqueue(operationB.Object); - operations.Enqueue(operationC.Object); - - sut.FinalizeApplication(operations); - - Assert.IsTrue(a == 1); - Assert.IsTrue(b == 2); - Assert.IsTrue(c == 3); - } - - [TestMethod] - public void MustContinueToRevertOperationsInCaseOfError() - { - var operationA = new Mock(); - var operationB = new Mock(); - var operationC = new Mock(); - var operations = new Queue(); - - operationA.Setup(o => o.Revert()).Throws(); - operationB.Setup(o => o.Revert()).Throws(); - operationC.Setup(o => o.Revert()).Throws(); - - operations.Enqueue(operationA.Object); - operations.Enqueue(operationB.Object); - operations.Enqueue(operationC.Object); - - sut.FinalizeApplication(operations); - - operationA.Verify(o => o.Revert(), Times.Once); - operationB.Verify(o => o.Revert(), Times.Once); - operationC.Verify(o => o.Revert(), Times.Once); - } - - [TestMethod] - public void MustNotEvaluateAbortFlag() - { - var operationA = new Mock(); - var operationB = new Mock(); - var operationC = new Mock(); - var operations = new Queue(); - - operationB.SetupGet(o => o.AbortStartup).Returns(true); - - operations.Enqueue(operationA.Object); - operations.Enqueue(operationB.Object); - operations.Enqueue(operationC.Object); - - sut.FinalizeApplication(operations); - - operationA.Verify(o => o.Revert(), Times.Once); - operationB.Verify(o => o.Revert(), Times.Once); - operationC.Verify(o => o.Revert(), Times.Once); - } - - [TestMethod] - public void MustNotFailWithEmptyQueue() - { - sut.FinalizeApplication(new Queue()); - } - - [TestMethod] - public void MustNotFailInCaseOfUnexpectedError() - { - uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny(), It.IsAny())).Throws(new Exception()); - sut.FinalizeApplication(new Queue()); - } - } -} diff --git a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj index 7e8cf15e..b78f2aad 100644 --- a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj +++ b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj @@ -79,8 +79,7 @@ - - + diff --git a/SafeExamBrowser.Core/Behaviour/Operations/I18nOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/I18nOperation.cs index 7d8e1ccc..c702824a 100644 --- a/SafeExamBrowser.Core/Behaviour/Operations/I18nOperation.cs +++ b/SafeExamBrowser.Core/Behaviour/Operations/I18nOperation.cs @@ -9,7 +9,7 @@ using System.Globalization; using System.IO; using System.Reflection; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; @@ -22,7 +22,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations private ILogger logger; private IText text; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public I18nOperation(ILogger logger, IText text) @@ -42,6 +42,11 @@ namespace SafeExamBrowser.Core.Behaviour.Operations text.Initialize(textResource); } + public void Repeat() + { + // Nothing to do here... + } + public void Revert() { // Nothing to do here... diff --git a/SafeExamBrowser.Core/Behaviour/StartupController.cs b/SafeExamBrowser.Core/Behaviour/Operations/OperationSequence.cs similarity index 61% rename from SafeExamBrowser.Core/Behaviour/StartupController.cs rename to SafeExamBrowser.Core/Behaviour/Operations/OperationSequence.cs index 881bbc14..eefd3ba6 100644 --- a/SafeExamBrowser.Core/Behaviour/StartupController.cs +++ b/SafeExamBrowser.Core/Behaviour/Operations/OperationSequence.cs @@ -9,35 +9,33 @@ using System; using System.Collections.Generic; using System.Linq; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface; -namespace SafeExamBrowser.Core.Behaviour +namespace SafeExamBrowser.Core.Behaviour.Operations { - public class StartupController : IStartupController + public class OperationSequence : IOperationSequence { private ILogger logger; private IRuntimeInfo runtimeInfo; private ISplashScreen splashScreen; - private ISystemInfo systemInfo; private IText text; private IUserInterfaceFactory uiFactory; private Stack stack = new Stack(); - public StartupController(ILogger logger, IRuntimeInfo runtimeInfo, ISystemInfo systemInfo, IText text, IUserInterfaceFactory uiFactory) + public OperationSequence(ILogger logger, IRuntimeInfo runtimeInfo, IText text, IUserInterfaceFactory uiFactory) { this.logger = logger; this.runtimeInfo = runtimeInfo; - this.systemInfo = systemInfo; this.text = text; this.uiFactory = uiFactory; } - public bool TryInitializeApplication(Queue operations) + public bool TryPerform(Queue operations) { var success = false; @@ -50,18 +48,62 @@ namespace SafeExamBrowser.Core.Behaviour { RevertOperations(); } - - Finish(success); } catch (Exception e) { - LogAndShowException(e); - Finish(false); + logger.Error($"Failed to perform operations!", e); + } + finally + { + Finish(); } return success; } + public bool TryRepeat() + { + throw new NotImplementedException(); + } + + public bool TryRevert() + { + var success = false; + + try + { + Initialize(); + success = RevertOperations(false); + } + catch (Exception e) + { + logger.Error($"Failed to revert operations!", e); + } + finally + { + Finish(); + } + + return success; + } + + private void Initialize(int? operationCount = null) + { + splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text); + + if (operationCount.HasValue) + { + splashScreen.SetMaxProgress(operationCount.Value); + } + else + { + splashScreen.SetIndeterminate(); + } + + splashScreen.UpdateText(TextKey.SplashScreen_StartupProcedure); + splashScreen.Show(); + } + private bool Perform(Queue operations) { foreach (var operation in operations) @@ -75,12 +117,12 @@ namespace SafeExamBrowser.Core.Behaviour } catch (Exception e) { - LogAndShowException(e); + logger.Error($"Failed to perform operation '{operation.GetType().Name}'!", e); return false; } - if (operation.AbortStartup) + if (operation.Abort) { return false; } @@ -91,8 +133,10 @@ namespace SafeExamBrowser.Core.Behaviour return true; } - private void RevertOperations() + private bool RevertOperations(bool regress = true) { + var success = true; + while (stack.Any()) { var operation = stack.Pop(); @@ -104,41 +148,20 @@ namespace SafeExamBrowser.Core.Behaviour catch (Exception e) { logger.Error($"Failed to revert operation '{operation.GetType().Name}'!", e); + success = false; } - splashScreen.Regress(); - } - } - - private void Initialize(int operationCount) - { - logger.Info("--- Initiating startup procedure ---"); - - splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text); - splashScreen.SetMaxProgress(operationCount); - splashScreen.UpdateText(TextKey.SplashScreen_StartupProcedure); - splashScreen.Show(); - } - - private void LogAndShowException(Exception e) - { - logger.Error($"Failed to initialize application!", e); - uiFactory.Show(text.Get(TextKey.MessageBox_StartupError), text.Get(TextKey.MessageBox_StartupErrorTitle), icon: MessageBoxIcon.Error); - logger.Info("Reverting operations..."); - } - - private void Finish(bool success = true) - { - if (success) - { - logger.Info("--- Application successfully initialized! ---"); - logger.Log(string.Empty); - } - else - { - logger.Info("--- Startup procedure aborted! ---"); + if (regress) + { + splashScreen.Regress(); + } } + return success; + } + + private void Finish() + { splashScreen?.Close(); } } diff --git a/SafeExamBrowser.Core/Behaviour/ShutdownController.cs b/SafeExamBrowser.Core/Behaviour/ShutdownController.cs deleted file mode 100644 index 0c38c73e..00000000 --- a/SafeExamBrowser.Core/Behaviour/ShutdownController.cs +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using System.Collections.Generic; -using SafeExamBrowser.Contracts.Behaviour; -using SafeExamBrowser.Contracts.Configuration; -using SafeExamBrowser.Contracts.I18n; -using SafeExamBrowser.Contracts.Logging; -using SafeExamBrowser.Contracts.UserInterface; - -namespace SafeExamBrowser.Core.Behaviour -{ - public class ShutdownController : IShutdownController - { - private ILogger logger; - private IRuntimeInfo runtimeInfo; - private ISplashScreen splashScreen; - private IText text; - private IUserInterfaceFactory uiFactory; - - public ShutdownController(ILogger logger, IRuntimeInfo runtimeInfo, IText text, IUserInterfaceFactory uiFactory) - { - this.logger = logger; - this.runtimeInfo = runtimeInfo; - this.text = text; - this.uiFactory = uiFactory; - } - - public void FinalizeApplication(Queue operations) - { - try - { - Initialize(); - Revert(operations); - Finish(); - } - catch (Exception e) - { - LogAndShowException(e); - Finish(false); - } - } - - private void Revert(Queue operations) - { - foreach (var operation in operations) - { - operation.SplashScreen = splashScreen; - - try - { - operation.Revert(); - } - catch (Exception e) - { - logger.Error($"Failed to revert operation '{operation.GetType().Name}'!", e); - } - } - } - - private void Initialize() - { - logger.Log(string.Empty); - logger.Info("--- Initiating shutdown procedure ---"); - - splashScreen = uiFactory.CreateSplashScreen(runtimeInfo, text); - splashScreen.SetIndeterminate(); - splashScreen.UpdateText(TextKey.SplashScreen_ShutdownProcedure); - splashScreen.Show(); - } - - private void LogAndShowException(Exception e) - { - logger.Error($"Failed to finalize application!", e); - uiFactory.Show(text.Get(TextKey.MessageBox_ShutdownError), text.Get(TextKey.MessageBox_ShutdownErrorTitle), icon: MessageBoxIcon.Error); - } - - private void Finish(bool success = true) - { - if (success) - { - logger.Info("--- Application successfully finalized! ---"); - } - else - { - logger.Info("--- Shutdown procedure failed! ---"); - } - - splashScreen?.Close(); - } - } -} diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj index 70a90245..33514868 100644 --- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj +++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj @@ -56,8 +56,7 @@ - - + diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs index eb4b89ea..ec118d33 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ConfigurationOperationTests.cs @@ -166,7 +166,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations sut.Perform(); - Assert.IsTrue(sut.AbortStartup); + Assert.IsTrue(sut.Abort); } [TestMethod] @@ -181,7 +181,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations sut.Perform(); - Assert.IsFalse(sut.AbortStartup); + Assert.IsFalse(sut.Abort); } } } diff --git a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs index 02953f5a..1c5ef75a 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Behaviour/Operations/ServiceOperationTests.cs @@ -91,7 +91,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations sut.Perform(); - Assert.IsTrue(sut.AbortStartup); + Assert.IsTrue(sut.Abort); } [TestMethod] @@ -103,7 +103,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations sut.Perform(); service.VerifySet(s => s.Ignore = true); - Assert.IsFalse(sut.AbortStartup); + Assert.IsFalse(sut.Abort); } [TestMethod] diff --git a/SafeExamBrowser.Runtime/App.cs b/SafeExamBrowser.Runtime/App.cs index 292d35e8..297b5f4f 100644 --- a/SafeExamBrowser.Runtime/App.cs +++ b/SafeExamBrowser.Runtime/App.cs @@ -60,13 +60,9 @@ namespace SafeExamBrowser.Runtime instances.BuildObjectGraph(); instances.LogStartupInformation(); - var success = instances.RuntimeController.TryInitializeApplication(instances.StartupOperations); + var success = instances.RuntimeController.TryStart(instances.StartupOperations); - if (success) - { - instances.RuntimeController.StartSession(); - } - else + if (!success) { Shutdown(); } @@ -74,7 +70,7 @@ namespace SafeExamBrowser.Runtime protected override void OnExit(ExitEventArgs e) { - instances.RuntimeController.FinalizeApplication(); + instances.RuntimeController.Terminate(); instances.LogShutdownInformation(); base.OnExit(e); diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs index 90c92195..cb0922a1 100644 --- a/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs +++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ConfigurationOperation.cs @@ -8,7 +8,7 @@ using System; using System.IO; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; @@ -26,7 +26,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations private IUserInterfaceFactory uiFactory; private string[] commandLineArgs; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public ConfigurationOperation( @@ -60,8 +60,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient && UserWantsToAbortStartup()) { - AbortStartup = true; - logger.Info($"The user chose to {(AbortStartup ? "abort" : "continue")} the application startup after successful client configuration."); + Abort = true; + logger.Info($"The user chose to {(Abort ? "abort" : "continue")} the application startup after successful client configuration."); } } else @@ -71,6 +71,11 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations } } + public void Repeat() + { + // TODO + } + public void Revert() { // Nothing to do here... diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/KioskModeOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/KioskModeOperation.cs index 8014d41d..65e4739f 100644 --- a/SafeExamBrowser.Runtime/Behaviour/Operations/KioskModeOperation.cs +++ b/SafeExamBrowser.Runtime/Behaviour/Operations/KioskModeOperation.cs @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -20,7 +20,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations private ISettingsRepository settingsRepository; private KioskMode kioskMode; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public KioskModeOperation(ILogger logger, ISettingsRepository settingsRepository) @@ -46,6 +46,11 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations } } + public void Repeat() + { + // TODO + } + public void Revert() { logger.Info($"Reverting kiosk mode '{kioskMode}'..."); @@ -63,22 +68,22 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations private void CreateNewDesktop() { - + // TODO } private void CloseNewDesktop() { - + // TODO } private void DisableExplorerShell() { - + // TODO } private void RestartExplorerShell() { - + // TODO } } } diff --git a/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs b/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs index 48437fd6..a1573080 100644 --- a/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs +++ b/SafeExamBrowser.Runtime/Behaviour/Operations/ServiceOperation.cs @@ -7,7 +7,7 @@ */ using System; -using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.I18n; @@ -25,7 +25,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations private ISettingsRepository settingsRepository; private IText text; - public bool AbortStartup { get; private set; } + public bool Abort { get; private set; } public ISplashScreen SplashScreen { private get; set; } public ServiceOperation(ILogger logger, IServiceProxy service, ISettingsRepository settingsRepository, IText text) @@ -48,34 +48,26 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations } catch (Exception e) { - var message = "Failed to connect to the service component!"; - - if (serviceMandatory) - { - logger.Error(message, e); - } - else - { - logger.Info($"{message} Reason: {e.Message}"); - } + LogException(e); } if (serviceMandatory && !serviceAvailable) { - AbortStartup = true; + Abort = true; logger.Info("Aborting startup because the service is mandatory but not available!"); } - else if (!serviceAvailable) - { - service.Ignore = true; - logger.Info("All service-related operations will be ignored, since the service is optional and not available."); - } else { - logger.Info($"The service is {(serviceMandatory ? "mandatory" : "optional")} and available."); + service.Ignore = !serviceAvailable; + logger.Info($"The service is {(serviceMandatory ? "mandatory" : "optional")} and {(serviceAvailable ? "available." : "not available. All service-related operations will be ignored!")}"); } } + public void Repeat() + { + // TODO + } + public void Revert() { logger.Info("Closing service connection..."); @@ -93,5 +85,19 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations } } } + + private void LogException(Exception e) + { + var message = "Failed to connect to the service component!"; + + if (serviceMandatory) + { + logger.Error(message, e); + } + else + { + logger.Info($"{message} Reason: {e.Message}"); + } + } } } diff --git a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs index e5bfd7c2..e3e14c5f 100644 --- a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs @@ -8,8 +8,8 @@ using System; using System.Collections.Generic; -using System.Linq; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; @@ -21,52 +21,56 @@ namespace SafeExamBrowser.Runtime.Behaviour { internal class RuntimeController : IRuntimeController { - private Queue operations; private ILogger logger; private IRuntimeInfo runtimeInfo; private IRuntimeWindow runtimeWindow; private IServiceProxy serviceProxy; private ISettingsRepository settingsRepository; - private IShutdownController shutdownController; - private IStartupController startupController; + private IOperationSequence operationSequence; private Action terminationCallback; private IText text; private IUserInterfaceFactory uiFactory; public RuntimeController( ILogger logger, + IOperationSequence operationSequence, IRuntimeInfo runtimeInfo, IServiceProxy serviceProxy, ISettingsRepository settingsRepository, - IShutdownController shutdownController, - IStartupController startupController, Action terminationCallback, IText text, IUserInterfaceFactory uiFactory) { this.logger = logger; + this.operationSequence = operationSequence; this.runtimeInfo = runtimeInfo; this.serviceProxy = serviceProxy; this.settingsRepository = settingsRepository; - this.shutdownController = shutdownController; - this.startupController = startupController; this.terminationCallback = terminationCallback; this.text = text; this.uiFactory = uiFactory; - - operations = new Queue(); } - public bool TryInitializeApplication(Queue operations) + public bool TryStart(Queue operations) { - var success = startupController.TryInitializeApplication(operations); + logger.Info("--- Initiating startup procedure ---"); + + var success = operationSequence.TryPerform(operations); runtimeWindow = uiFactory.CreateRuntimeWindow(runtimeInfo, text); if (success) { - this.operations = new Queue(operations); + logger.Info("--- Application successfully initialized! ---"); + logger.Log(string.Empty); logger.Subscribe(runtimeWindow); + + StartSession(); + } + else + { + logger.Info("--- Application startup aborted! ---"); + logger.Log(string.Empty); } return success; @@ -95,9 +99,11 @@ namespace SafeExamBrowser.Runtime.Behaviour { runtimeWindow.Hide(); } + + terminationCallback.Invoke(); } - public void FinalizeApplication() + public void Terminate() { StopSession(); @@ -108,7 +114,20 @@ namespace SafeExamBrowser.Runtime.Behaviour logger.Unsubscribe(runtimeWindow); runtimeWindow.Close(); - shutdownController.FinalizeApplication(new Queue(operations.Reverse())); + + logger.Log(string.Empty); + logger.Info("--- Initiating shutdown procedure ---"); + + var success = operationSequence.TryRevert(); + + if (success) + { + logger.Info("--- Application successfully finalized! ---"); + } + else + { + logger.Info("--- Shutdown procedure failed! ---"); + } } private void StopSession() diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index 0c58fc06..36526141 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -14,9 +14,9 @@ using System.Windows; using SafeExamBrowser.Configuration; using SafeExamBrowser.Configuration.Settings; using SafeExamBrowser.Contracts.Behaviour; +using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Logging; -using SafeExamBrowser.Core.Behaviour; using SafeExamBrowser.Core.Behaviour.Operations; using SafeExamBrowser.Core.Communication; using SafeExamBrowser.Core.I18n; @@ -52,11 +52,10 @@ namespace SafeExamBrowser.Runtime InitializeLogging(); var text = new Text(logger); + var operationSequence = new OperationSequence(logger, runtimeInfo, text, uiFactory); var serviceProxy = new ServiceProxy(new ModuleLogger(logger, typeof(ServiceProxy)), "net.pipe://localhost/safeexambrowser/service"); - var shutdownController = new ShutdownController(logger, runtimeInfo, text, uiFactory); - var startupController = new StartupController(logger, runtimeInfo, systemInfo, text, uiFactory); - RuntimeController = new RuntimeController(new ModuleLogger(logger, typeof(RuntimeController)), runtimeInfo, serviceProxy, settingsRepository, shutdownController, startupController, Application.Current.Shutdown, text, uiFactory); + RuntimeController = new RuntimeController(logger, operationSequence, runtimeInfo, serviceProxy, settingsRepository, Application.Current.Shutdown, text, uiFactory); StartupOperations = new Queue(); StartupOperations.Enqueue(new I18nOperation(logger, text));