SEBWIN-219: Introduced OperationResult to be able to determine cause of operation procedure failures.

This commit is contained in:
dbuechel 2018-02-28 15:49:06 +01:00
parent f5ef7fa859
commit 40fd49126f
31 changed files with 419 additions and 306 deletions

View file

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq; using Moq;
using SafeExamBrowser.Client.Behaviour; using SafeExamBrowser.Client.Behaviour;
@ -33,139 +32,145 @@ namespace SafeExamBrowser.Client.UnitTests
private ClientController sut; private ClientController sut;
[TestInitialize]
public void Initialize()
{
displayMonitorMock = new Mock<IDisplayMonitor>();
loggerMock = new Mock<ILogger>();
processMonitorMock = new Mock<IProcessMonitor>();
operationSequenceMock = new Mock<IOperationSequence>();
runtimeProxyMock = new Mock<IRuntimeProxy>();
taskbarMock = new Mock<ITaskbar>();
uiFactoryMock = new Mock<IUserInterfaceFactory>();
windowMonitorMock= new Mock<IWindowMonitor>();
operationSequenceMock.Setup(o => o.TryPerform()).Returns(true);
sut = new ClientController(
displayMonitorMock.Object,
loggerMock.Object,
operationSequenceMock.Object,
processMonitorMock.Object,
runtimeProxyMock.Object,
new Action(() => { }),
taskbarMock.Object,
uiFactoryMock.Object,
windowMonitorMock.Object);
sut.TryStart();
}
[TestMethod] [TestMethod]
public void MustHandleDisplayChangeCorrectly() public void TODO()
{ {
var order = 0; Assert.Fail();
var workingArea = 0;
var taskbar = 0;
displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
displayMonitorMock.Raise(d => d.DisplayChanged += null);
displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once);
taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
Assert.IsTrue(workingArea == 1);
Assert.IsTrue(taskbar == 2);
} }
[TestMethod] //[TestInitialize]
public void MustHandleExplorerStartCorrectly() //public void Initialize()
{ //{
var order = 0; // displayMonitorMock = new Mock<IDisplayMonitor>();
var processManager = 0; // loggerMock = new Mock<ILogger>();
var workingArea = 0; // processMonitorMock = new Mock<IProcessMonitor>();
var taskbar = 0; // operationSequenceMock = new Mock<IOperationSequence>();
// runtimeProxyMock = new Mock<IRuntimeProxy>();
// taskbarMock = new Mock<ITaskbar>();
// uiFactoryMock = new Mock<IUserInterfaceFactory>();
// windowMonitorMock= new Mock<IWindowMonitor>();
processMonitorMock.Setup(p => p.CloseExplorerShell()).Callback(() => processManager = ++order); // operationSequenceMock.Setup(o => o.TryPerform()).Returns(true);
displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
processMonitorMock.Raise(p => p.ExplorerStarted += null); // sut = new ClientController(
// displayMonitorMock.Object,
// loggerMock.Object,
// operationSequenceMock.Object,
// processMonitorMock.Object,
// runtimeProxyMock.Object,
// new Action(() => { }),
// taskbarMock.Object,
// uiFactoryMock.Object,
// windowMonitorMock.Object);
processMonitorMock.Verify(p => p.CloseExplorerShell(), Times.Once); // sut.TryStart();
displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once); //}
taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
Assert.IsTrue(processManager == 1); //[TestMethod]
Assert.IsTrue(workingArea == 2); //public void MustHandleDisplayChangeCorrectly()
Assert.IsTrue(taskbar == 3); //{
} // var order = 0;
// var workingArea = 0;
// var taskbar = 0;
[TestMethod] // displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
public void MustHandleAllowedWindowChangeCorrectly() // taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
{
var window = new IntPtr(12345);
processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(true); // displayMonitorMock.Raise(d => d.DisplayChanged += null);
windowMonitorMock.Raise(w => w.WindowChanged += null, window); // displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once);
// taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once); // Assert.IsTrue(workingArea == 1);
windowMonitorMock.Verify(w => w.Hide(window), Times.Never); // Assert.IsTrue(taskbar == 2);
windowMonitorMock.Verify(w => w.Close(window), Times.Never); //}
}
[TestMethod] //[TestMethod]
public void MustHandleUnallowedWindowHideCorrectly() //public void MustHandleExplorerStartCorrectly()
{ //{
var order = 0; // var order = 0;
var belongs = 0; // var processManager = 0;
var hide = 0; // var workingArea = 0;
var window = new IntPtr(12345); // var taskbar = 0;
processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order); // processMonitorMock.Setup(p => p.CloseExplorerShell()).Callback(() => processManager = ++order);
windowMonitorMock.Setup(w => w.Hide(window)).Returns(true).Callback(() => hide = ++order); // displayMonitorMock.Setup(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight())).Callback(() => workingArea = ++order);
// taskbarMock.Setup(t => t.InitializeBounds()).Callback(() => taskbar = ++order);
windowMonitorMock.Raise(w => w.WindowChanged += null, window); // processMonitorMock.Raise(p => p.ExplorerStarted += null);
processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once); // processMonitorMock.Verify(p => p.CloseExplorerShell(), Times.Once);
windowMonitorMock.Verify(w => w.Hide(window), Times.Once); // displayMonitorMock.Verify(w => w.InitializePrimaryDisplay(taskbarMock.Object.GetAbsoluteHeight()), Times.Once);
windowMonitorMock.Verify(w => w.Close(window), Times.Never); // taskbarMock.Verify(t => t.InitializeBounds(), Times.Once);
Assert.IsTrue(belongs == 1); // Assert.IsTrue(processManager == 1);
Assert.IsTrue(hide == 2); // Assert.IsTrue(workingArea == 2);
} // Assert.IsTrue(taskbar == 3);
//}
[TestMethod] //[TestMethod]
public void MustHandleUnallowedWindowCloseCorrectly() //public void MustHandleAllowedWindowChangeCorrectly()
{ //{
var order = 0; // var window = new IntPtr(12345);
var belongs = 0;
var hide = 0;
var close = 0;
var window = new IntPtr(12345);
processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order); // processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(true);
windowMonitorMock.Setup(w => w.Hide(window)).Returns(false).Callback(() => hide = ++order);
windowMonitorMock.Setup(w => w.Close(window)).Callback(() => close = ++order);
windowMonitorMock.Raise(w => w.WindowChanged += null, window); // windowMonitorMock.Raise(w => w.WindowChanged += null, window);
processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once); // processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
windowMonitorMock.Verify(w => w.Hide(window), Times.Once); // windowMonitorMock.Verify(w => w.Hide(window), Times.Never);
windowMonitorMock.Verify(w => w.Close(window), Times.Once); // windowMonitorMock.Verify(w => w.Close(window), Times.Never);
//}
Assert.IsTrue(belongs == 1); //[TestMethod]
Assert.IsTrue(hide == 2); //public void MustHandleUnallowedWindowHideCorrectly()
Assert.IsTrue(close == 3); //{
} // var order = 0;
// var belongs = 0;
// var hide = 0;
// var window = new IntPtr(12345);
[TestCleanup] // processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order);
public void Cleanup() // windowMonitorMock.Setup(w => w.Hide(window)).Returns(true).Callback(() => hide = ++order);
{
// TODO sut.Stop(); // windowMonitorMock.Raise(w => w.WindowChanged += null, window);
}
// processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
// windowMonitorMock.Verify(w => w.Hide(window), Times.Once);
// windowMonitorMock.Verify(w => w.Close(window), Times.Never);
// Assert.IsTrue(belongs == 1);
// Assert.IsTrue(hide == 2);
//}
//[TestMethod]
//public void MustHandleUnallowedWindowCloseCorrectly()
//{
// var order = 0;
// var belongs = 0;
// var hide = 0;
// var close = 0;
// var window = new IntPtr(12345);
// processMonitorMock.Setup(p => p.BelongsToAllowedProcess(window)).Returns(false).Callback(() => belongs = ++order);
// windowMonitorMock.Setup(w => w.Hide(window)).Returns(false).Callback(() => hide = ++order);
// windowMonitorMock.Setup(w => w.Close(window)).Callback(() => close = ++order);
// windowMonitorMock.Raise(w => w.WindowChanged += null, window);
// processMonitorMock.Verify(p => p.BelongsToAllowedProcess(window), Times.Once);
// windowMonitorMock.Verify(w => w.Hide(window), Times.Once);
// windowMonitorMock.Verify(w => w.Close(window), Times.Once);
// Assert.IsTrue(belongs == 1);
// Assert.IsTrue(hide == 2);
// Assert.IsTrue(close == 3);
//}
//[TestCleanup]
//public void Cleanup()
//{
// // TODO sut.Stop();
//}
} }
} }

View file

@ -80,7 +80,7 @@ namespace SafeExamBrowser.Client.Behaviour
splashScreen = uiFactory.CreateSplashScreen(); splashScreen = uiFactory.CreateSplashScreen();
operations.ProgressIndicator = splashScreen; operations.ProgressIndicator = splashScreen;
var success = operations.TryPerform(); var success = operations.TryPerform() == OperationResult.Success;
if (success) if (success)
{ {

View file

@ -24,7 +24,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ITaskbar taskbar; private ITaskbar taskbar;
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public BrowserOperation( public BrowserOperation(
@ -41,7 +40,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.uiFactory = uiFactory; this.uiFactory = uiFactory;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing browser..."); logger.Info("Initializing browser...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeBrowser, true); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeBrowser, true);
@ -52,11 +51,13 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
browserController.RegisterApplicationButton(browserButton); browserController.RegisterApplicationButton(browserButton);
taskbar.AddApplication(browserButton); taskbar.AddApplication(browserButton);
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -19,7 +19,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public ClipboardOperation(ILogger logger, INativeMethods nativeMethods) public ClipboardOperation(ILogger logger, INativeMethods nativeMethods)
@ -28,14 +27,16 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.nativeMethods = nativeMethods; this.nativeMethods = nativeMethods;
} }
public void Perform() public OperationResult Perform()
{ {
EmptyClipboard(); EmptyClipboard();
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -22,7 +22,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private IRuntimeProxy runtime; private IRuntimeProxy runtime;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public ConfigurationOperation(ClientConfiguration configuration, ILogger logger, IRuntimeProxy runtime) public ConfigurationOperation(ClientConfiguration configuration, ILogger logger, IRuntimeProxy runtime)
@ -32,7 +31,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.runtime = runtime; this.runtime = runtime;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing application configuration..."); logger.Info("Initializing application configuration...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
@ -50,12 +49,16 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
catch (Exception e) catch (Exception e)
{ {
logger.Error("An unexpected error occurred while trying to retrieve the application configuration!", e); logger.Error("An unexpected error occurred while trying to retrieve the application configuration!", e);
return OperationResult.Failed;
} }
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -21,7 +21,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private ITaskbar taskbar; private ITaskbar taskbar;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, ITaskbar taskbar) public DisplayMonitorOperation(IDisplayMonitor displayMonitor, ILogger logger, ITaskbar taskbar)
@ -31,7 +30,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.taskbar = taskbar; this.taskbar = taskbar;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing working area..."); logger.Info("Initializing working area...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWorkingArea); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWorkingArea);
@ -39,11 +38,13 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
displayMonitor.PreventSleepMode(); displayMonitor.PreventSleepMode();
displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight()); displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight());
displayMonitor.StartMonitoringDisplayChanges(); displayMonitor.StartMonitoringDisplayChanges();
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -21,7 +21,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public KeyboardInterceptorOperation( public KeyboardInterceptorOperation(
@ -34,17 +33,19 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.nativeMethods = nativeMethods; this.nativeMethods = nativeMethods;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Starting keyboard interception..."); logger.Info("Starting keyboard interception...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartKeyboardInterception); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartKeyboardInterception);
nativeMethods.RegisterKeyboardHook(keyboardInterceptor); nativeMethods.RegisterKeyboardHook(keyboardInterceptor);
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -21,7 +21,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private IMouseInterceptor mouseInterceptor; private IMouseInterceptor mouseInterceptor;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public MouseInterceptorOperation( public MouseInterceptorOperation(
@ -34,17 +33,19 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.nativeMethods = nativeMethods; this.nativeMethods = nativeMethods;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Starting mouse interception..."); logger.Info("Starting mouse interception...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartMouseInterception); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartMouseInterception);
nativeMethods.RegisterMouseHook(mouseInterceptor); nativeMethods.RegisterMouseHook(mouseInterceptor);
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -19,7 +19,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private IProcessMonitor processMonitor; private IProcessMonitor processMonitor;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor) public ProcessMonitorOperation(ILogger logger, IProcessMonitor processMonitor)
@ -28,7 +27,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.processMonitor = processMonitor; this.processMonitor = processMonitor;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing process monitoring..."); logger.Info("Initializing process monitoring...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_WaitExplorerTermination, true); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_WaitExplorerTermination, true);
@ -39,11 +38,13 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeProcessMonitoring); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeProcessMonitoring);
// TODO: Implement process monitoring... // TODO: Implement process monitoring...
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -22,7 +22,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private IRuntimeProxy runtime; private IRuntimeProxy runtime;
private Guid token; private Guid token;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public RuntimeConnectionOperation(ILogger logger, IRuntimeProxy runtime, Guid token) public RuntimeConnectionOperation(ILogger logger, IRuntimeProxy runtime, Guid token)
@ -32,7 +31,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.token = token; this.token = token;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing runtime connection..."); logger.Info("Initializing runtime connection...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeRuntimeConnection); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeRuntimeConnection);
@ -46,20 +45,21 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
logger.Error("An unexpected error occurred while trying to connect to the runtime!", e); logger.Error("An unexpected error occurred while trying to connect to the runtime!", e);
} }
if (connected) if (!connected)
{ {
logger.Info("Successfully connected to the runtime.");
}
else
{
Abort = true;
logger.Error("Failed to connect to the runtime. Aborting startup..."); logger.Error("Failed to connect to the runtime. Aborting startup...");
return OperationResult.Failed;
} }
logger.Info("Successfully connected to the runtime.");
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -32,7 +32,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
private IText text; private IText text;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public TaskbarOperation( public TaskbarOperation(
@ -61,7 +60,7 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.wirelessNetwork = wirelessNetwork; this.wirelessNetwork = wirelessNetwork;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing taskbar..."); logger.Info("Initializing taskbar...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeTaskbar); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeTaskbar);
@ -85,11 +84,13 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
{ {
AddWirelessNetworkControl(); AddWirelessNetworkControl();
} }
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -19,7 +19,6 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
private ILogger logger; private ILogger logger;
private IWindowMonitor windowMonitor; private IWindowMonitor windowMonitor;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public WindowMonitorOperation(ILogger logger, IWindowMonitor windowMonitor) public WindowMonitorOperation(ILogger logger, IWindowMonitor windowMonitor)
@ -28,18 +27,20 @@ namespace SafeExamBrowser.Client.Behaviour.Operations
this.windowMonitor = windowMonitor; this.windowMonitor = windowMonitor;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing window monitoring..."); logger.Info("Initializing window monitoring...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWindowMonitoring); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeWindowMonitoring);
windowMonitor.HideAllWindows(); windowMonitor.HideAllWindows();
windowMonitor.StartMonitoringWindows(); windowMonitor.StartMonitoringWindows();
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -12,11 +12,6 @@ namespace SafeExamBrowser.Contracts.Behaviour.Operations
{ {
public interface IOperation public interface IOperation
{ {
/// <summary>
/// Determines whether the procedure to which this operation belongs to should be aborted.
/// </summary>
bool Abort { get; }
/// <summary> /// <summary>
/// The progress indicator to be used to show status information to the user. Will be ignored if <c>null</c>. /// The progress indicator to be used to show status information to the user. Will be ignored if <c>null</c>.
/// </summary> /// </summary>
@ -25,15 +20,15 @@ namespace SafeExamBrowser.Contracts.Behaviour.Operations
/// <summary> /// <summary>
/// Performs the operation. /// Performs the operation.
/// </summary> /// </summary>
void Perform(); OperationResult Perform();
/// <summary> /// <summary>
/// Repeats the operation. /// Repeats the operation.
/// </summary> /// </summary>
void Repeat(); OperationResult Repeat();
/// <summary> /// <summary>
/// Reverts all changes which were made when performing the operation. /// Reverts all changes which were made when executing the operation.
/// </summary> /// </summary>
void Revert(); void Revert();
} }

View file

@ -13,22 +13,23 @@ namespace SafeExamBrowser.Contracts.Behaviour.Operations
public interface IOperationSequence public interface IOperationSequence
{ {
/// <summary> /// <summary>
/// The progress indicator to be used when performing any action. Will be ignored if <c>null</c>. /// The progress indicator to be used when executing an operation. Will be ignored if <c>null</c>.
/// </summary> /// </summary>
IProgressIndicator ProgressIndicator { set; } IProgressIndicator ProgressIndicator { set; }
/// <summary> /// <summary>
/// Tries to perform the operations of this sequence. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise. /// Tries to perform the operations of this sequence.
/// </summary> /// </summary>
bool TryPerform(); OperationResult TryPerform();
/// <summary> /// <summary>
/// Tries to repeat the operations of this sequence. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise. /// Tries to repeat the operations of this sequence.
/// </summary> /// </summary>
bool TryRepeat(); OperationResult TryRepeat();
/// <summary> /// <summary>
/// Tries to revert the operations of this sequence. Returns <c>true</c> if the procedure was successful, <c>false</c> otherwise. /// Tries to revert the operations of this sequence. Returns <c>true</c> if all operations were reverted without errors,
/// otherwise <c>false</c>.
/// </summary> /// </summary>
bool TryRevert(); bool TryRevert();
} }

View file

@ -0,0 +1,28 @@
/*
* 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/.
*/
namespace SafeExamBrowser.Contracts.Behaviour.Operations
{
public enum OperationResult
{
/// <summary>
/// Indicates that the operation has been aborted due to an expected condition, e.g. as result of a user decision.
/// </summary>
Aborted,
/// <summary>
/// Indicates that the operation has failed due to an invalid or unexpected condition.
/// </summary>
Failed,
/// <summary>
/// Indicates that the operation has been executed successfully.
/// </summary>
Success
}
}

View file

@ -56,6 +56,7 @@
<Compile Include="Behaviour\IApplicationController.cs" /> <Compile Include="Behaviour\IApplicationController.cs" />
<Compile Include="Behaviour\IRuntimeController.cs" /> <Compile Include="Behaviour\IRuntimeController.cs" />
<Compile Include="Behaviour\Operations\IOperationSequence.cs" /> <Compile Include="Behaviour\Operations\IOperationSequence.cs" />
<Compile Include="Behaviour\Operations\OperationResult.cs" />
<Compile Include="Communication\IClientHost.cs" /> <Compile Include="Communication\IClientHost.cs" />
<Compile Include="Communication\ICommunication.cs" /> <Compile Include="Communication\ICommunication.cs" />
<Compile Include="Communication\IClientProxy.cs" /> <Compile Include="Communication\IClientProxy.cs" />

View file

@ -36,6 +36,10 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
@ -61,14 +65,15 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationB.SetupGet(o => o.Abort).Returns(true); operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Aborted);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryPerform(); var result = sut.TryPerform();
operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Perform(), Times.Once);
operationA.Verify(o => o.Revert(), Times.Once); operationA.Verify(o => o.Revert(), Times.Once);
@ -77,7 +82,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationC.Verify(o => o.Perform(), Times.Never); operationC.Verify(o => o.Perform(), Times.Never);
operationC.Verify(o => o.Revert(), Times.Never); operationC.Verify(o => o.Revert(), Times.Never);
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Aborted, result);
} }
[TestMethod] [TestMethod]
@ -88,12 +93,16 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryPerform(); var result = sut.TryPerform();
operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Perform(), Times.Once);
operationA.Verify(o => o.Revert(), Times.Never); operationA.Verify(o => o.Revert(), Times.Never);
@ -102,7 +111,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationC.Verify(o => o.Perform(), Times.Once); operationC.Verify(o => o.Perform(), Times.Once);
operationC.Verify(o => o.Revert(), Times.Never); operationC.Verify(o => o.Revert(), Times.Never);
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]
@ -114,18 +123,18 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Callback(() => a = ++current); operationA.Setup(o => o.Perform()).Returns(OperationResult.Success).Callback(() => a = ++current);
operationB.Setup(o => o.Perform()).Callback(() => b = ++current); operationB.Setup(o => o.Perform()).Returns(OperationResult.Success).Callback(() => b = ++current);
operationC.Setup(o => o.Perform()).Callback(() => c = ++current); operationC.Setup(o => o.Perform()).Returns(OperationResult.Success).Callback(() => c = ++current);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryPerform(); var result = sut.TryPerform();
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
Assert.IsTrue(a == 1); Assert.IsTrue(a == 1);
Assert.IsTrue(b == 2); Assert.IsTrue(b == 2);
Assert.IsTrue(c == 3); Assert.IsTrue(c == 3);
@ -140,6 +149,8 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationD = new Mock<IOperation>(); var operationD = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Throws<Exception>(); operationC.Setup(o => o.Perform()).Throws<Exception>();
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
@ -148,7 +159,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operations.Enqueue(operationD.Object); operations.Enqueue(operationD.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryPerform(); var result = sut.TryPerform();
operationA.Verify(o => o.Perform(), Times.Once); operationA.Verify(o => o.Perform(), Times.Once);
operationA.Verify(o => o.Revert(), Times.Once); operationA.Verify(o => o.Revert(), Times.Once);
@ -159,7 +170,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationD.Verify(o => o.Perform(), Times.Never); operationD.Verify(o => o.Perform(), Times.Never);
operationD.Verify(o => o.Revert(), Times.Never); operationD.Verify(o => o.Revert(), Times.Never);
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Failed, result);
} }
[TestMethod] [TestMethod]
@ -172,10 +183,12 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationD = new Mock<IOperation>(); var operationD = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationA.Setup(o => o.Revert()).Callback(() => a = ++current); operationA.Setup(o => o.Revert()).Callback(() => a = ++current);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Revert()).Callback(() => b = ++current); operationB.Setup(o => o.Revert()).Callback(() => b = ++current);
operationC.Setup(o => o.Revert()).Callback(() => c = ++current);
operationC.Setup(o => o.Perform()).Throws<Exception>(); operationC.Setup(o => o.Perform()).Throws<Exception>();
operationC.Setup(o => o.Revert()).Callback(() => c = ++current);
operationD.Setup(o => o.Revert()).Callback(() => d = ++current); operationD.Setup(o => o.Revert()).Callback(() => d = ++current);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
@ -184,9 +197,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operations.Enqueue(operationD.Object); operations.Enqueue(operationD.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryPerform(); var result = sut.TryPerform();
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Failed, result);
Assert.IsTrue(d == 0); Assert.IsTrue(d == 0);
Assert.IsTrue(c == 1); Assert.IsTrue(c == 1);
Assert.IsTrue(b == 2); Assert.IsTrue(b == 2);
@ -201,7 +214,10 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Throws<Exception>(); operationC.Setup(o => o.Perform()).Throws<Exception>();
operationC.Setup(o => o.Revert()).Throws<Exception>(); operationC.Setup(o => o.Revert()).Throws<Exception>();
operationB.Setup(o => o.Revert()).Throws<Exception>(); operationB.Setup(o => o.Revert()).Throws<Exception>();
operationA.Setup(o => o.Revert()).Throws<Exception>(); operationA.Setup(o => o.Revert()).Throws<Exception>();
@ -225,9 +241,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
public void MustSucceedWithEmptyQueue() public void MustSucceedWithEmptyQueue()
{ {
var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>()); var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>());
var success = sut.TryPerform(); var result = sut.TryPerform();
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
} }
@ -240,9 +256,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
indicatorMock.Setup(i => i.SetMaxValue(It.IsAny<int>())).Throws<Exception>(); indicatorMock.Setup(i => i.SetMaxValue(It.IsAny<int>())).Throws<Exception>();
sut.ProgressIndicator = indicatorMock.Object; sut.ProgressIndicator = indicatorMock.Object;
var success = sut.TryPerform(); var result = sut.TryPerform();
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Failed, result);
} }
#endregion #endregion
@ -257,14 +273,15 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationB.SetupGet(o => o.Abort).Returns(true); operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationB.Setup(o => o.Repeat()).Returns(OperationResult.Aborted);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryRepeat(); var result = sut.TryRepeat();
operationA.Verify(o => o.Repeat(), Times.Once); operationA.Verify(o => o.Repeat(), Times.Once);
operationA.Verify(o => o.Revert(), Times.Never); operationA.Verify(o => o.Revert(), Times.Never);
@ -273,7 +290,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationC.Verify(o => o.Repeat(), Times.Never); operationC.Verify(o => o.Repeat(), Times.Never);
operationC.Verify(o => o.Revert(), Times.Never); operationC.Verify(o => o.Revert(), Times.Never);
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Aborted, result);
} }
[TestMethod] [TestMethod]
@ -284,12 +301,16 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationB.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationC.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryRepeat(); var result = sut.TryRepeat();
operationA.Verify(o => o.Perform(), Times.Never); operationA.Verify(o => o.Perform(), Times.Never);
operationA.Verify(o => o.Repeat(), Times.Once); operationA.Verify(o => o.Repeat(), Times.Once);
@ -301,7 +322,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationC.Verify(o => o.Repeat(), Times.Once); operationC.Verify(o => o.Repeat(), Times.Once);
operationC.Verify(o => o.Revert(), Times.Never); operationC.Verify(o => o.Revert(), Times.Never);
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]
@ -313,18 +334,18 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Repeat()).Callback(() => a = ++current); operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success).Callback(() => a = ++current);
operationB.Setup(o => o.Repeat()).Callback(() => b = ++current); operationB.Setup(o => o.Repeat()).Returns(OperationResult.Success).Callback(() => b = ++current);
operationC.Setup(o => o.Repeat()).Callback(() => c = ++current); operationC.Setup(o => o.Repeat()).Returns(OperationResult.Success).Callback(() => c = ++current);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryRepeat(); var result = sut.TryRepeat();
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
Assert.IsTrue(a == 1); Assert.IsTrue(a == 1);
Assert.IsTrue(b == 2); Assert.IsTrue(b == 2);
Assert.IsTrue(c == 3); Assert.IsTrue(c == 3);
@ -339,6 +360,8 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationD = new Mock<IOperation>(); var operationD = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationB.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationC.Setup(o => o.Repeat()).Throws<Exception>(); operationC.Setup(o => o.Repeat()).Throws<Exception>();
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
@ -347,7 +370,7 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operations.Enqueue(operationD.Object); operations.Enqueue(operationD.Object);
var sut = new OperationSequence(loggerMock.Object, operations); var sut = new OperationSequence(loggerMock.Object, operations);
var success = sut.TryRepeat(); var result = sut.TryRepeat();
operationA.Verify(o => o.Repeat(), Times.Once); operationA.Verify(o => o.Repeat(), Times.Once);
operationA.Verify(o => o.Revert(), Times.Never); operationA.Verify(o => o.Revert(), Times.Never);
@ -358,25 +381,25 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
operationD.Verify(o => o.Repeat(), Times.Never); operationD.Verify(o => o.Repeat(), Times.Never);
operationD.Verify(o => o.Revert(), Times.Never); operationD.Verify(o => o.Revert(), Times.Never);
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Failed, result);
} }
[TestMethod] [TestMethod]
public void MustSucceedRepeatingWithEmptyQueue() public void MustSucceedRepeatingWithEmptyQueue()
{ {
var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>()); var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>());
var success = sut.TryRepeat(); var result = sut.TryRepeat();
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]
public void MustSucceedRepeatingWithoutCallingPerform() public void MustSucceedRepeatingWithoutCallingPerform()
{ {
var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>()); var sut = new OperationSequence(loggerMock.Object, new Queue<IOperation>());
var success = sut.TryRepeat(); var result = sut.TryRepeat();
Assert.IsTrue(success); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]
@ -388,9 +411,9 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
indicatorMock.Setup(i => i.SetMaxValue(It.IsAny<int>())).Throws<Exception>(); indicatorMock.Setup(i => i.SetMaxValue(It.IsAny<int>())).Throws<Exception>();
sut.ProgressIndicator = indicatorMock.Object; sut.ProgressIndicator = indicatorMock.Object;
var success = sut.TryRepeat(); var result = sut.TryRepeat();
Assert.IsFalse(success); Assert.AreEqual(OperationResult.Failed, result);
} }
#endregion #endregion
@ -405,6 +428,13 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);
operations.Enqueue(operationC.Object); operations.Enqueue(operationC.Object);
@ -431,6 +461,10 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationA.Setup(o => o.Revert()).Callback(() => a = ++current); operationA.Setup(o => o.Revert()).Callback(() => a = ++current);
operationB.Setup(o => o.Revert()).Callback(() => b = ++current); operationB.Setup(o => o.Revert()).Callback(() => b = ++current);
operationC.Setup(o => o.Revert()).Callback(() => c = ++current); operationC.Setup(o => o.Revert()).Callback(() => c = ++current);
@ -459,6 +493,10 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationA.Setup(o => o.Revert()).Throws<Exception>(); operationA.Setup(o => o.Revert()).Throws<Exception>();
operationB.Setup(o => o.Revert()).Throws<Exception>(); operationB.Setup(o => o.Revert()).Throws<Exception>();
operationC.Setup(o => o.Revert()).Throws<Exception>(); operationC.Setup(o => o.Revert()).Throws<Exception>();
@ -488,7 +526,10 @@ namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations
var operationC = new Mock<IOperation>(); var operationC = new Mock<IOperation>();
var operations = new Queue<IOperation>(); var operations = new Queue<IOperation>();
operationB.SetupGet(o => o.Abort).Returns(true); operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
operationA.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operationB.Setup(o => o.Perform()).Returns(OperationResult.Aborted);
operationB.Setup(o => o.Repeat()).Returns(OperationResult.Success);
operations.Enqueue(operationA.Object); operations.Enqueue(operationA.Object);
operations.Enqueue(operationB.Object); operations.Enqueue(operationB.Object);

View file

@ -19,7 +19,6 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
private ICommunicationHost host; private ICommunicationHost host;
private ILogger logger; private ILogger logger;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public CommunicationOperation(ICommunicationHost host, ILogger logger) public CommunicationOperation(ICommunicationHost host, ILogger logger)
@ -28,15 +27,17 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
this.logger = logger; this.logger = logger;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Starting communication host..."); logger.Info("Starting communication host...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartCommunicationHost); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartCommunicationHost);
host.Start(); host.Start();
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
if (!host.IsRunning) if (!host.IsRunning)
{ {
@ -46,6 +47,8 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
host.Stop(); host.Stop();
host.Start(); host.Start();
} }
return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -17,7 +17,6 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
private Func<IOperation> initialize; private Func<IOperation> initialize;
private IOperation operation; private IOperation operation;
public bool Abort { get; set; }
public IProgressIndicator ProgressIndicator { get; set; } public IProgressIndicator ProgressIndicator { get; set; }
public DelayedInitializationOperation(Func<IOperation> initialize) public DelayedInitializationOperation(Func<IOperation> initialize)
@ -25,21 +24,19 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
this.initialize = initialize; this.initialize = initialize;
} }
public void Perform() public OperationResult Perform()
{ {
operation = initialize.Invoke(); operation = initialize.Invoke();
operation.ProgressIndicator = ProgressIndicator; operation.ProgressIndicator = ProgressIndicator;
operation.Perform();
Abort = operation.Abort; return operation.Perform();
} }
public void Repeat() public OperationResult Repeat()
{ {
operation.ProgressIndicator = ProgressIndicator; operation.ProgressIndicator = ProgressIndicator;
operation.Repeat();
Abort = operation.Abort; return operation.Repeat();
} }
public void Revert() public void Revert()

View file

@ -18,7 +18,6 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
private Action repeat; private Action repeat;
private Action revert; private Action revert;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public DelegateOperation(Action perform, Action repeat = null, Action revert = null) public DelegateOperation(Action perform, Action repeat = null, Action revert = null)
@ -28,14 +27,18 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
this.revert = revert; this.revert = revert;
} }
public void Perform() public OperationResult Perform()
{ {
perform?.Invoke(); perform?.Invoke();
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
repeat?.Invoke(); repeat?.Invoke();
return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -22,7 +22,6 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
private ILogger logger; private ILogger logger;
private IText text; private IText text;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public I18nOperation(ILogger logger, IText text) public I18nOperation(ILogger logger, IText text)
@ -31,7 +30,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
this.text = text; this.text = text;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info($"Loading default text data (the currently active culture is '{CultureInfo.CurrentCulture.Name}')..."); logger.Info($"Loading default text data (the currently active culture is '{CultureInfo.CurrentCulture.Name}')...");
@ -40,11 +39,13 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
var textResource = new XmlTextResource(path); var textResource = new XmlTextResource(path);
text.Initialize(textResource); text.Initialize(textResource);
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -29,16 +29,16 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
this.operations = new Queue<IOperation>(operations); this.operations = new Queue<IOperation>(operations);
} }
public bool TryPerform() public OperationResult TryPerform()
{ {
var success = false; var result = OperationResult.Failed;
try try
{ {
Initialize(); Initialize();
success = Perform(); result = Perform();
if (!success) if (result != OperationResult.Success)
{ {
Revert(true); Revert(true);
} }
@ -48,24 +48,24 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
logger.Error("Failed to perform operations!", e); logger.Error("Failed to perform operations!", e);
} }
return success; return result;
} }
public bool TryRepeat() public OperationResult TryRepeat()
{ {
var success = false; var result = OperationResult.Failed;
try try
{ {
Initialize(); Initialize();
success = Repeat(); result = Repeat();
} }
catch (Exception e) catch (Exception e)
{ {
logger.Error("Failed to repeat operations!", e); logger.Error("Failed to repeat operations!", e);
} }
return success; return result;
} }
public bool TryRevert() public bool TryRevert()
@ -98,60 +98,60 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
} }
} }
private bool Perform() private OperationResult Perform()
{ {
foreach (var operation in operations) foreach (var operation in operations)
{ {
var result = OperationResult.Failed;
stack.Push(operation); stack.Push(operation);
try try
{ {
operation.ProgressIndicator = ProgressIndicator; operation.ProgressIndicator = ProgressIndicator;
operation.Perform(); result = operation.Perform();
} }
catch (Exception e) catch (Exception e)
{ {
logger.Error($"Failed to perform operation '{operation.GetType().Name}'!", e); logger.Error($"Caught unexpected exception while performing operation '{operation.GetType().Name}'!", e);
return false;
} }
if (operation.Abort) if (result != OperationResult.Success)
{ {
return false; return result;
} }
ProgressIndicator?.Progress(); ProgressIndicator?.Progress();
} }
return true; return OperationResult.Success;
} }
private bool Repeat() private OperationResult Repeat()
{ {
foreach (var operation in operations) foreach (var operation in operations)
{ {
var result = OperationResult.Failed;
try try
{ {
operation.ProgressIndicator = ProgressIndicator; operation.ProgressIndicator = ProgressIndicator;
operation.Repeat(); result = operation.Repeat();
} }
catch (Exception e) catch (Exception e)
{ {
logger.Error($"Failed to repeat operation '{operation.GetType().Name}'!", e); logger.Error($"Caught unexpected exception while repeating operation '{operation.GetType().Name}'!", e);
return false;
} }
if (operation.Abort) if (result != OperationResult.Success)
{ {
return false; return result;
} }
ProgressIndicator?.Progress(); ProgressIndicator?.Progress();
} }
return true; return OperationResult.Success;
} }
private bool Revert(bool regress = false) private bool Revert(bool regress = false)

View file

@ -10,6 +10,7 @@ using System;
using System.IO; using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq; using Moq;
using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.I18n;
@ -136,9 +137,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
sut = new ConfigurationOperation(repository.Object, logger.Object, info, text.Object, uiFactory.Object, null); sut = new ConfigurationOperation(repository.Object, logger.Object, info, text.Object, uiFactory.Object, null);
sut.Perform(); var result = sut.Perform();
Assert.IsTrue(sut.Abort); Assert.AreEqual(OperationResult.Aborted, result);
} }
[TestMethod] [TestMethod]
@ -148,9 +149,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
sut = new ConfigurationOperation(repository.Object, logger.Object, info, text.Object, uiFactory.Object, null); sut = new ConfigurationOperation(repository.Object, logger.Object, info, text.Object, uiFactory.Object, null);
sut.Perform(); var result = sut.Perform();
Assert.IsFalse(sut.Abort); Assert.AreEqual(OperationResult.Success, result);
} }
} }
} }

View file

@ -9,6 +9,7 @@
using System; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq; using Moq;
using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Configuration.Settings;
@ -82,26 +83,27 @@ namespace SafeExamBrowser.Runtime.UnitTests.Behaviour.Operations
} }
[TestMethod] [TestMethod]
public void MustAbortIfServiceMandatoryAndNotAvailable() public void MustFailIfServiceMandatoryAndNotAvailable()
{ {
service.Setup(s => s.Connect(null)).Returns(false); service.Setup(s => s.Connect(null)).Returns(false);
configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory }); configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Mandatory });
sut.Perform(); var result = sut.Perform();
Assert.IsTrue(sut.Abort); Assert.AreEqual(OperationResult.Failed, result);
} }
[TestMethod] [TestMethod]
public void MustNotAbortIfServiceOptionalAndNotAvailable() public void MustNotFailIfServiceOptionalAndNotAvailable()
{ {
service.Setup(s => s.Connect(null)).Returns(false); service.Setup(s => s.Connect(null)).Returns(false);
configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional }); configuration.SetupGet(s => s.CurrentSettings).Returns(new Settings { ServicePolicy = ServicePolicy.Optional });
sut.Perform(); var result = sut.Perform();
service.VerifySet(s => s.Ignore = true); service.VerifySet(s => s.Ignore = true);
Assert.IsFalse(sut.Abort);
Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]

View file

@ -26,7 +26,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
private string[] commandLineArgs; private string[] commandLineArgs;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public ConfigurationOperation( public ConfigurationOperation(
@ -45,7 +44,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
this.uiFactory = uiFactory; this.uiFactory = uiFactory;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info("Initializing application configuration..."); logger.Info("Initializing application configuration...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeConfiguration);
@ -60,8 +59,14 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient) if (settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
{ {
Abort = IsConfigurationSufficient(); var abort = IsConfigurationSufficient();
logger.Info($"The user chose to {(Abort ? "abort" : "continue")} the application startup after successful client configuration.");
logger.Info($"The user chose to {(abort ? "abort" : "continue")} after successful client configuration.");
if (abort)
{
return OperationResult.Aborted;
}
} }
} }
else else
@ -69,13 +74,17 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings..."); logger.Info("No valid settings file specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
settings = repository.LoadDefaultSettings(); settings = repository.LoadDefaultSettings();
} }
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// TODO: How will the new settings be retrieved? Uri passed to the repository? If yes, how does the Uri get here?! // TODO: How will the new settings be retrieved? Uri passed to the repository? If yes, how does the Uri get here?!
// -> IDEA: Use configuration repository as container? // -> IDEA: Use configuration repository as container?
// -> IDEA: Introduce IRepeatParams or alike? // -> IDEA: Introduce IRepeatParams or alike?
return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -21,7 +21,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
private IConfigurationRepository configuration; private IConfigurationRepository configuration;
private KioskMode kioskMode; private KioskMode kioskMode;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public KioskModeOperation(ILogger logger, IConfigurationRepository configuration) public KioskModeOperation(ILogger logger, IConfigurationRepository configuration)
@ -30,7 +29,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
this.configuration = configuration; this.configuration = configuration;
} }
public void Perform() public OperationResult Perform()
{ {
kioskMode = configuration.CurrentSettings.KioskMode; kioskMode = configuration.CurrentSettings.KioskMode;
@ -46,11 +45,15 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
DisableExplorerShell(); DisableExplorerShell();
break; break;
} }
return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// TODO: Depends on new kiosk mode! // TODO: Depends on new kiosk mode!
return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -25,7 +25,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
private IServiceProxy service; private IServiceProxy service;
private IText text; private IText text;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public ServiceConnectionOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service, IText text) public ServiceConnectionOperation(IConfigurationRepository configuration, ILogger logger, IServiceProxy service, IText text)
@ -36,7 +35,7 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
this.text = text; this.text = text;
} }
public void Perform() public OperationResult Perform()
{ {
logger.Info($"Initializing service connection..."); logger.Info($"Initializing service connection...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceConnection); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_InitializeServiceConnection);
@ -53,19 +52,22 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
if (mandatory && !connected) if (mandatory && !connected)
{ {
Abort = true;
logger.Error("Aborting startup because the service is mandatory but not available!"); logger.Error("Aborting startup because the service is mandatory but not available!");
return OperationResult.Failed;
} }
else
{ service.Ignore = !connected;
service.Ignore = !connected; logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "available." : "not available. All service-related operations will be ignored!")}");
logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "available." : "not available. All service-related operations will be ignored!")}");
} return OperationResult.Success;
} }
public void Repeat() public OperationResult Repeat()
{ {
// TODO: Re-check if mandatory, if so, try to connect (if not connected) - otherwise, no action required (except maybe logging of status?) // TODO: Re-check if mandatory, if so, try to connect (if not connected) - otherwise, no action required (except maybe logging of status?)
return OperationResult.Success;
} }
public void Revert() public void Revert()

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
@ -25,14 +26,14 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
{ {
} }
public override void Perform() public override OperationResult Perform()
{ {
StartSession(); return StartSession();
} }
public override void Repeat() public override OperationResult Repeat()
{ {
StartSession(); return StartSession();
} }
public override void Revert() public override void Revert()

View file

@ -30,7 +30,6 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
private IServiceProxy service; private IServiceProxy service;
private ISession session; private ISession session;
public bool Abort { get; private set; }
public IProgressIndicator ProgressIndicator { private get; set; } public IProgressIndicator ProgressIndicator { private get; set; }
public SessionSequenceOperation( public SessionSequenceOperation(
@ -49,11 +48,11 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
this.service = service; this.service = service;
} }
public abstract void Perform(); public abstract OperationResult Perform();
public abstract void Repeat(); public abstract OperationResult Repeat();
public abstract void Revert(); public abstract void Revert();
protected void StartSession() protected OperationResult StartSession()
{ {
logger.Info("Starting new session..."); logger.Info("Starting new session...");
ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true); ProgressIndicator?.UpdateText(TextKey.ProgressIndicator_StartSession, true);
@ -66,19 +65,20 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
sessionRunning = TryStartClient(); sessionRunning = TryStartClient();
if (sessionRunning) if (!sessionRunning)
{ {
logger.Info($"Successfully started new session with identifier '{session.Id}'.");
}
else
{
Abort = true;
logger.Info($"Failed to start new session! Reverting service session and aborting procedure..."); logger.Info($"Failed to start new session! Reverting service session and aborting procedure...");
service.StopSession(session.Id); service.StopSession(session.Id);
return OperationResult.Failed;
} }
logger.Info($"Successfully started new session with identifier '{session.Id}'.");
return OperationResult.Success;
} }
protected void StopSession() protected OperationResult StopSession()
{ {
if (sessionRunning) if (sessionRunning)
{ {
@ -96,6 +96,8 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
sessionRunning = false; sessionRunning = false;
logger.Info($"Successfully stopped session with identifier '{session.Id}'."); logger.Info($"Successfully stopped session with identifier '{session.Id}'.");
} }
return OperationResult.Success;
} }
private bool TryStartClient() private bool TryStartClient()

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
@ -25,14 +26,14 @@ namespace SafeExamBrowser.Runtime.Behaviour.Operations
{ {
} }
public override void Perform() public override OperationResult Perform()
{ {
// Nothing to do here... return OperationResult.Success;
} }
public override void Repeat() public override OperationResult Repeat()
{ {
StopSession(); return StopSession();
} }
public override void Revert() public override void Revert()

View file

@ -71,7 +71,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
splashScreen.Show(); splashScreen.Show();
var initialized = bootstrapSequence.TryPerform(); var initialized = bootstrapSequence.TryPerform() == OperationResult.Success;
if (initialized) if (initialized)
{ {
@ -101,7 +101,6 @@ namespace SafeExamBrowser.Runtime.Behaviour
if (sessionRunning) if (sessionRunning)
{ {
DeregisterSessionEvents();
StopSession(); StopSession();
} }
@ -141,9 +140,9 @@ namespace SafeExamBrowser.Runtime.Behaviour
DeregisterSessionEvents(); DeregisterSessionEvents();
} }
sessionRunning = initial ? sessionSequence.TryPerform() : sessionSequence.TryRepeat(); var result = initial ? sessionSequence.TryPerform() : sessionSequence.TryRepeat();
if (sessionRunning) if (result == OperationResult.Success)
{ {
RegisterSessionEvents(); RegisterSessionEvents();
@ -155,12 +154,17 @@ namespace SafeExamBrowser.Runtime.Behaviour
{ {
runtimeWindow.Hide(); runtimeWindow.Hide();
} }
sessionRunning = true;
} }
else else
{ {
logger.Info(">>>--- Session procedure was aborted! ---<<<"); logger.Info($">>>--- Session procedure {(result == OperationResult.Aborted ? "was aborted." : "has failed!")} ---<<<");
// TODO: Not when user chose to terminate after reconfiguration! Probably needs IOperationSequenceResult or alike...
uiFactory.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error); if (result == OperationResult.Failed)
{
uiFactory.Show(TextKey.MessageBox_SessionStartError, TextKey.MessageBox_SessionStartErrorTitle, icon: MessageBoxIcon.Error);
}
if (!initial) if (!initial)
{ {
@ -176,6 +180,8 @@ namespace SafeExamBrowser.Runtime.Behaviour
runtimeWindow.ShowProgressBar(); runtimeWindow.ShowProgressBar();
logger.Info(">>>--- Reverting session operations ---<<<"); logger.Info(">>>--- Reverting session operations ---<<<");
DeregisterSessionEvents();
var success = sessionSequence.TryRevert(); var success = sessionSequence.TryRevert();
if (success) if (success)