SEBWIN-219: Changed and simplified implementation of operation mechanism to allow reconfiguration (i.e. repeating operations).
This commit is contained in:
parent
18b8f66300
commit
196836b7eb
32 changed files with 461 additions and 462 deletions
|
@ -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<IOperation>(instances.StartupOperations.Reverse());
|
||||
|
||||
MainWindow.Hide();
|
||||
instances.ShutdownController.FinalizeApplication(operations);
|
||||
//instances.ShutdownController.FinalizeApplication(operations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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...");
|
||||
|
|
|
@ -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<IOperation> StartupOperations { get; private set; }
|
||||
internal Taskbar Taskbar { get; private set; }
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
void FinalizeApplication();
|
||||
void Terminate();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new session and starts performing the runtime logic / event handling.
|
||||
/// Tries to start the runtime. Returns <c>true</c> if successful, otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
void StartSession();
|
||||
bool TryStart(Queue<IOperation> operations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Reverts any changes performed during the startup or runtime and releases all used resources.
|
||||
/// </summary>
|
||||
void FinalizeApplication(Queue<IOperation> operations);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to initialize the application according to the given queue of operations.
|
||||
/// Returns <c>true</c> if the initialization was successful, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
bool TryInitializeApplication(Queue<IOperation> operations);
|
||||
}
|
||||
}
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Behaviour
|
||||
namespace SafeExamBrowser.Contracts.Behaviour.Operations
|
||||
{
|
||||
public interface IOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
bool AbortStartup { get; }
|
||||
bool Abort { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The splash screen to be used to show status information to the user.
|
||||
|
@ -27,6 +27,11 @@ namespace SafeExamBrowser.Contracts.Behaviour
|
|||
/// </summary>
|
||||
void Perform();
|
||||
|
||||
/// <summary>
|
||||
/// Repeats the operation.
|
||||
/// </summary>
|
||||
void Repeat();
|
||||
|
||||
/// <summary>
|
||||
/// Reverts all changes which were made when performing the operation.
|
||||
/// </summary>
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to perform the given sequence of operations. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
bool TryPerform(Queue<IOperation> operations);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to repeat all operations of this sequence. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
bool TryRepeat();
|
||||
|
||||
/// <summary>
|
||||
/// Tries to revert all operations of this sequence. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
bool TryRevert();
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Behaviour\IApplicationController.cs" />
|
||||
<Compile Include="Behaviour\IRuntimeController.cs" />
|
||||
<Compile Include="Behaviour\Operations\IOperationSequence.cs" />
|
||||
<Compile Include="Communication\ICommunication.cs" />
|
||||
<Compile Include="Communication\IClientProxy.cs" />
|
||||
<Compile Include="Communication\IRuntimeProxy.cs" />
|
||||
|
@ -65,7 +66,7 @@
|
|||
<Compile Include="Configuration\IRuntimeInfo.cs" />
|
||||
<Compile Include="Configuration\Settings\ConfigurationMode.cs" />
|
||||
<Compile Include="Behaviour\INotificationController.cs" />
|
||||
<Compile Include="Behaviour\IOperation.cs" />
|
||||
<Compile Include="Behaviour\Operations\IOperation.cs" />
|
||||
<Compile Include="Behaviour\IClientController.cs" />
|
||||
<Compile Include="Configuration\IIconResource.cs" />
|
||||
<Compile Include="Configuration\IApplicationInfo.cs" />
|
||||
|
@ -77,8 +78,6 @@
|
|||
<Compile Include="Configuration\Settings\IKeyboardSettings.cs" />
|
||||
<Compile Include="Configuration\Settings\IMouseSettings.cs" />
|
||||
<Compile Include="Configuration\Settings\ISettings.cs" />
|
||||
<Compile Include="Behaviour\IShutdownController.cs" />
|
||||
<Compile Include="Behaviour\IStartupController.cs" />
|
||||
<Compile Include="Configuration\Settings\ISettingsRepository.cs" />
|
||||
<Compile Include="Configuration\Settings\ITaskbarSettings.cs" />
|
||||
<Compile Include="Configuration\Settings\KioskMode.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<ILogger> loggerMock;
|
||||
private Mock<IRuntimeInfo> runtimeInfoMock;
|
||||
private Mock<ISystemInfo> systemInfoMock;
|
||||
private Mock<IText> textMock;
|
||||
private Mock<IUserInterfaceFactory> uiFactoryMock;
|
||||
|
||||
private IStartupController sut;
|
||||
private IOperationSequence sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
loggerMock = new Mock<ILogger>();
|
||||
runtimeInfoMock = new Mock<IRuntimeInfo>();
|
||||
systemInfoMock = new Mock<ISystemInfo>();
|
||||
textMock = new Mock<IText>();
|
||||
uiFactoryMock = new Mock<IUserInterfaceFactory>();
|
||||
|
||||
uiFactoryMock.Setup(f => f.CreateSplashScreen(runtimeInfoMock.Object, textMock.Object)).Returns(new Mock<ISplashScreen>().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<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>();
|
||||
|
@ -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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
|
@ -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<IOperation>());
|
||||
var result = sut.TryPerform(new Queue<IOperation>());
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
@ -217,7 +218,151 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour
|
|||
public void MustNotFailInCaseOfUnexpectedError()
|
||||
{
|
||||
uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny<IRuntimeInfo>(), It.IsAny<IText>())).Throws(new Exception());
|
||||
sut.TryInitializeApplication(new Queue<IOperation>());
|
||||
|
||||
var success = sut.TryPerform(new Queue<IOperation>());
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
operationA.Setup(o => o.Revert()).Throws<Exception>();
|
||||
operationB.Setup(o => o.Revert()).Throws<Exception>();
|
||||
operationC.Setup(o => o.Revert()).Throws<Exception>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>());
|
||||
sut.TryRevert();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotFailWithoutPerformWhenReverting()
|
||||
{
|
||||
var success = sut.TryRevert();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotFailInCaseOfUnexpectedErrorWhenReverting()
|
||||
{
|
||||
uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny<IRuntimeInfo>(), It.IsAny<IText>())).Throws(new Exception());
|
||||
sut.TryRevert();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -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<ILogger> loggerMock;
|
||||
private Mock<IRuntimeInfo> runtimeInfoMock;
|
||||
private Mock<IText> textMock;
|
||||
private Mock<IUserInterfaceFactory> uiFactoryMock;
|
||||
|
||||
private IShutdownController sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
loggerMock = new Mock<ILogger>();
|
||||
runtimeInfoMock = new Mock<IRuntimeInfo>();
|
||||
textMock = new Mock<IText>();
|
||||
uiFactoryMock = new Mock<IUserInterfaceFactory>();
|
||||
|
||||
uiFactoryMock.Setup(f => f.CreateSplashScreen(runtimeInfoMock.Object, textMock.Object)).Returns(new Mock<ISplashScreen>().Object);
|
||||
|
||||
sut = new ShutdownController(loggerMock.Object, runtimeInfoMock.Object, textMock.Object, uiFactoryMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustRevertOperations()
|
||||
{
|
||||
var operationA = new Mock<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
operationA.Setup(o => o.Revert()).Throws<Exception>();
|
||||
operationB.Setup(o => o.Revert()).Throws<Exception>();
|
||||
operationC.Setup(o => o.Revert()).Throws<Exception>();
|
||||
|
||||
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<IOperation>();
|
||||
var operationB = new Mock<IOperation>();
|
||||
var operationC = new Mock<IOperation>();
|
||||
var operations = new Queue<IOperation>();
|
||||
|
||||
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<IOperation>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotFailInCaseOfUnexpectedError()
|
||||
{
|
||||
uiFactoryMock.Setup(l => l.CreateSplashScreen(It.IsAny<IRuntimeInfo>(), It.IsAny<IText>())).Throws(new Exception());
|
||||
sut.FinalizeApplication(new Queue<IOperation>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -79,8 +79,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Behaviour\Operations\I18nOperationTests.cs" />
|
||||
<Compile Include="Behaviour\StartupControllerTests.cs" />
|
||||
<Compile Include="Behaviour\ShutdownControllerTests.cs" />
|
||||
<Compile Include="Behaviour\Operations\OperationSequenceTests.cs" />
|
||||
<Compile Include="I18n\TextTests.cs" />
|
||||
<Compile Include="I18n\XmlTextResourceTests.cs" />
|
||||
<Compile Include="Logging\DefaultLogFormatterTests.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...
|
||||
|
|
|
@ -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<IOperation> stack = new Stack<IOperation>();
|
||||
|
||||
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<IOperation> operations)
|
||||
public bool TryPerform(Queue<IOperation> 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<IOperation> 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();
|
||||
}
|
||||
}
|
|
@ -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<IOperation> operations)
|
||||
{
|
||||
try
|
||||
{
|
||||
Initialize();
|
||||
Revert(operations);
|
||||
Finish();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogAndShowException(e);
|
||||
Finish(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void Revert(Queue<IOperation> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,8 +56,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Behaviour\Operations\I18nOperation.cs" />
|
||||
<Compile Include="Behaviour\ShutdownController.cs" />
|
||||
<Compile Include="Behaviour\StartupController.cs" />
|
||||
<Compile Include="Behaviour\Operations\OperationSequence.cs" />
|
||||
<Compile Include="Communication\BaseProxy.cs" />
|
||||
<Compile Include="Communication\Messages\Message.cs" />
|
||||
<Compile Include="Communication\ServiceProxy.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<IOperation> 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<IOperation>();
|
||||
}
|
||||
|
||||
public bool TryInitializeApplication(Queue<IOperation> operations)
|
||||
public bool TryStart(Queue<IOperation> 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<IOperation>(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<IOperation>(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()
|
||||
|
|
|
@ -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<IOperation>();
|
||||
StartupOperations.Enqueue(new I18nOperation(logger, text));
|
||||
|
|
Loading…
Reference in a new issue