SEBWIN-353: Fixed bug with service session not being terminated when startup is aborted. Removed ignore flag from service proxy, as it did not serve any real purpose.

This commit is contained in:
dbuechel 2019-12-10 14:22:18 +01:00
parent 69c09dcb35
commit cf4e229fef
5 changed files with 144 additions and 169 deletions

View file

@ -16,12 +16,6 @@ namespace SafeExamBrowser.Communication.Contracts.Proxies
/// </summary> /// </summary>
public interface IServiceProxy : ICommunicationProxy public interface IServiceProxy : ICommunicationProxy
{ {
/// <summary>
/// Instructs the proxy to ignore all operations or simulate a connection, where applicable. To be set e.g. when the service
/// policy is optional and the service is not available.
/// </summary>
bool Ignore { set; }
/// <summary> /// <summary>
/// Instructs the service to start a system configuration update. /// Instructs the service to start a system configuration update.
/// </summary> /// </summary>

View file

@ -47,24 +47,6 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
sut.Connect(); sut.Connect();
} }
[TestMethod]
public void MustIgnoreConnectIfUnavailable()
{
sut.Ignore = true;
sut.Connect();
proxy.Verify(p => p.Connect(It.IsAny<Guid>()), Times.Never);
}
[TestMethod]
public void MustIgnoreDisconnectIfUnavailable()
{
sut.Ignore = true;
sut.Disconnect();
proxy.Verify(p => p.Disconnect(It.IsAny<DisconnectionMessage>()), Times.Never);
}
[TestMethod] [TestMethod]
public void MustCorrectlySendSystemConfigurationUpdate() public void MustCorrectlySendSystemConfigurationUpdate()
{ {
@ -87,15 +69,6 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
Assert.IsFalse(communication.Success); Assert.IsFalse(communication.Success);
} }
[TestMethod]
public void MustIgnoreSystemConfigurationUpdateIfUnavailable()
{
sut.Ignore = true;
sut.RunSystemConfigurationUpdate();
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
}
[TestMethod] [TestMethod]
public void MustCorrectlyStartSession() public void MustCorrectlyStartSession()
{ {
@ -120,17 +93,6 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
Assert.IsFalse(communication.Success); Assert.IsFalse(communication.Success);
} }
[TestMethod]
public void MustIgnoreStartSessionIfUnavaiable()
{
sut.Ignore = true;
var communication = sut.StartSession(null);
Assert.IsTrue(communication.Success);
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
}
[TestMethod] [TestMethod]
public void MustCorrectlyStopSession() public void MustCorrectlyStopSession()
{ {
@ -154,16 +116,5 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies
Assert.IsFalse(communication.Success); Assert.IsFalse(communication.Success);
} }
[TestMethod]
public void MustIgnoreStopSessionIfUnavaiable()
{
sut.Ignore = true;
var communication = sut.StopSession(Guid.Empty);
Assert.IsTrue(communication.Success);
proxy.Verify(p => p.Send(It.IsAny<Message>()), Times.Never);
}
} }
} }

View file

@ -20,39 +20,12 @@ namespace SafeExamBrowser.Communication.Proxies
/// </summary> /// </summary>
public class ServiceProxy : BaseProxy, IServiceProxy public class ServiceProxy : BaseProxy, IServiceProxy
{ {
public bool Ignore { private get; set; }
public ServiceProxy(string address, IProxyObjectFactory factory, ILogger logger, Interlocutor owner) : base(address, factory, logger, owner) public ServiceProxy(string address, IProxyObjectFactory factory, ILogger logger, Interlocutor owner) : base(address, factory, logger, owner)
{ {
} }
public override bool Connect(Guid? token = null, bool autoPing = true)
{
if (IgnoreOperation(nameof(Connect)))
{
return false;
}
return base.Connect(autoPing: autoPing);
}
public override bool Disconnect()
{
if (IgnoreOperation(nameof(Disconnect)))
{
return false;
}
return base.Disconnect();
}
public CommunicationResult RunSystemConfigurationUpdate() public CommunicationResult RunSystemConfigurationUpdate()
{ {
if (IgnoreOperation(nameof(RunSystemConfigurationUpdate)))
{
return new CommunicationResult(true);
}
try try
{ {
var response = Send(SimpleMessagePurport.UpdateSystemConfiguration); var response = Send(SimpleMessagePurport.UpdateSystemConfiguration);
@ -79,11 +52,6 @@ namespace SafeExamBrowser.Communication.Proxies
public CommunicationResult StartSession(ServiceConfiguration configuration) public CommunicationResult StartSession(ServiceConfiguration configuration)
{ {
if (IgnoreOperation(nameof(StartSession)))
{
return new CommunicationResult(true);
}
try try
{ {
var response = Send(new SessionStartMessage(configuration)); var response = Send(new SessionStartMessage(configuration));
@ -110,11 +78,6 @@ namespace SafeExamBrowser.Communication.Proxies
public CommunicationResult StopSession(Guid sessionId) public CommunicationResult StopSession(Guid sessionId)
{ {
if (IgnoreOperation(nameof(StopSession)))
{
return new CommunicationResult(true);
}
try try
{ {
var response = Send(new SessionStopMessage(sessionId)); var response = Send(new SessionStopMessage(sessionId));
@ -138,15 +101,5 @@ namespace SafeExamBrowser.Communication.Proxies
return new CommunicationResult(false); return new CommunicationResult(false);
} }
} }
private bool IgnoreOperation(string operationName)
{
if (Ignore)
{
Logger.Debug($"Skipping '{operationName}' operation because the ignore flag is set.");
}
return Ignore;
}
} }
} }

View file

@ -13,12 +13,12 @@ using Moq;
using SafeExamBrowser.Communication.Contracts.Hosts; using SafeExamBrowser.Communication.Contracts.Hosts;
using SafeExamBrowser.Communication.Contracts.Proxies; using SafeExamBrowser.Communication.Contracts.Proxies;
using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Service;
using SafeExamBrowser.Core.Contracts.OperationModel; using SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Operations; using SafeExamBrowser.Runtime.Operations;
using SafeExamBrowser.Runtime.Operations.Events; using SafeExamBrowser.Runtime.Operations.Events;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Service;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -27,14 +27,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestClass] [TestClass]
public class ServiceOperationTests public class ServiceOperationTests
{ {
private AppConfig appConfig; private SessionContext context;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<IRuntimeHost> runtimeHost; private Mock<IRuntimeHost> runtimeHost;
private Mock<IServiceProxy> service; private Mock<IServiceProxy> service;
private EventWaitHandle serviceEvent; private EventWaitHandle serviceEvent;
private SessionConfiguration session;
private SessionContext sessionContext;
private AppSettings settings;
private Mock<IUserInfo> userInfo; private Mock<IUserInfo> userInfo;
private ServiceOperation sut; private ServiceOperation sut;
@ -43,37 +40,35 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var serviceEventName = $"{nameof(SafeExamBrowser)}-{nameof(ServiceOperationTests)}"; var serviceEventName = $"{nameof(SafeExamBrowser)}-{nameof(ServiceOperationTests)}";
appConfig = new AppConfig();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
runtimeHost = new Mock<IRuntimeHost>(); runtimeHost = new Mock<IRuntimeHost>();
service = new Mock<IServiceProxy>(); service = new Mock<IServiceProxy>();
serviceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, serviceEventName); serviceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, serviceEventName);
session = new SessionConfiguration(); context = new SessionContext();
sessionContext = new SessionContext();
settings = new AppSettings();
userInfo = new Mock<IUserInfo>(); userInfo = new Mock<IUserInfo>();
appConfig.ServiceEventName = serviceEventName; context.Current = new SessionConfiguration();
sessionContext.Current = session; context.Current.AppConfig = new AppConfig();
sessionContext.Current.AppConfig = appConfig; context.Current.AppConfig.ServiceEventName = serviceEventName;
sessionContext.Next = session; context.Current.Settings = new AppSettings();
sessionContext.Next.AppConfig = appConfig; context.Next = new SessionConfiguration();
session.Settings = settings; context.Next.AppConfig = new AppConfig();
settings.Service.Policy = ServicePolicy.Mandatory; context.Next.AppConfig.ServiceEventName = serviceEventName;
context.Next.Settings = new AppSettings();
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, 0, userInfo.Object); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, context, 0, userInfo.Object);
} }
[TestMethod] [TestMethod]
public void Perform_MustConnectToService() public void Perform_MustConnectToService()
{ {
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
settings.Service.Policy = ServicePolicy.Mandatory; context.Next.Settings.Service.Policy = ServicePolicy.Mandatory;
sut.Perform(); sut.Perform();
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
settings.Service.Policy = ServicePolicy.Optional; context.Next.Settings.Service.Policy = ServicePolicy.Optional;
sut.Perform(); sut.Perform();
@ -83,13 +78,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Perform_MustStartSessionIfConnected() public void Perform_MustStartSessionIfConnected()
{ {
context.Next.SessionId = Guid.NewGuid();
context.Next.Settings.Service.Policy = ServicePolicy.Optional;
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set()); service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
var result = sut.Perform(); var result = sut.Perform();
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Once); service.Verify(s => s.StartSession(It.Is<ServiceConfiguration>(c => c.SessionId == context.Next.SessionId)), Times.Once);
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never); service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
userInfo.Verify(u => u.GetUserName(), Times.Once); userInfo.Verify(u => u.GetUserName(), Times.Once);
userInfo.Verify(u => u.GetUserSid(), Times.Once); userInfo.Verify(u => u.GetUserSid(), Times.Once);
@ -123,7 +120,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true);
service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true)); service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true));
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, context, TIMEOUT, userInfo.Object);
before = DateTime.Now; before = DateTime.Now;
var result = sut.Perform(); var result = sut.Perform();
@ -138,12 +135,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Perform_MustNotStartSessionIfNotConnected() public void Perform_MustNotStartSessionIfNotConnected()
{ {
context.Next.Settings.Service.Policy = ServicePolicy.Mandatory;
service.SetupGet(s => s.IsConnected).Returns(false); service.SetupGet(s => s.IsConnected).Returns(false);
service.Setup(s => s.Connect(null, true)).Returns(false); service.Setup(s => s.Connect(null, true)).Returns(false);
sut.Perform(); var result = sut.Perform();
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Never); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Never);
Assert.AreEqual(OperationResult.Failed, result);
} }
[TestMethod] [TestMethod]
@ -165,9 +165,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var errorShown = false; var errorShown = false;
context.Next.Settings.Service.Policy = ServicePolicy.Mandatory;
service.SetupGet(s => s.IsConnected).Returns(false); service.SetupGet(s => s.IsConnected).Returns(false);
service.Setup(s => s.Connect(null, true)).Returns(false); service.Setup(s => s.Connect(null, true)).Returns(false);
settings.Service.Policy = ServicePolicy.Mandatory;
sut.ActionRequired += (args) => errorShown = args is MessageEventArgs m && m.Icon == MessageBoxIcon.Error; sut.ActionRequired += (args) => errorShown = args is MessageEventArgs m && m.Icon == MessageBoxIcon.Error;
var result = sut.Perform(); var result = sut.Perform();
@ -179,13 +179,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Perform_MustNotFailIfServiceOptionalAndNotAvailable() public void Perform_MustNotFailIfServiceOptionalAndNotAvailable()
{ {
context.Next.Settings.Service.Policy = ServicePolicy.Optional;
service.SetupGet(s => s.IsConnected).Returns(false); service.SetupGet(s => s.IsConnected).Returns(false);
service.Setup(s => s.Connect(null, true)).Returns(false); service.Setup(s => s.Connect(null, true)).Returns(false);
settings.Service.Policy = ServicePolicy.Optional;
var result = sut.Perform(); var result = sut.Perform();
service.VerifySet(s => s.Ignore = true); service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Never);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
@ -194,9 +195,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
{ {
var warningShown = false; var warningShown = false;
context.Next.Settings.Service.Policy = ServicePolicy.Warn;
service.SetupGet(s => s.IsConnected).Returns(false); service.SetupGet(s => s.IsConnected).Returns(false);
service.Setup(s => s.Connect(null, true)).Returns(false); service.Setup(s => s.Connect(null, true)).Returns(false);
settings.Service.Policy = ServicePolicy.Warn;
sut.ActionRequired += (args) => warningShown = args is MessageEventArgs m && m.Icon == MessageBoxIcon.Warning; sut.ActionRequired += (args) => warningShown = args is MessageEventArgs m && m.Icon == MessageBoxIcon.Warning;
var result = sut.Perform(); var result = sut.Perform();
@ -208,18 +209,47 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
[TestMethod] [TestMethod]
public void Repeat_MustStopCurrentAndStartNewSession() public void Repeat_MustStopCurrentAndStartNewSession()
{ {
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set()); var order = 0;
PerformNormally(); var start1 = 0;
var stop1 = 0;
var start2 = 0;
var session1Id = Guid.NewGuid();
var session2Id = Guid.NewGuid();
context.Next.SessionId = session1Id;
service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Connect(null, true)).Returns(true);
service
.Setup(s => s.StartSession(It.Is<ServiceConfiguration>(c => c.SessionId == session1Id)))
.Returns(new CommunicationResult(true))
.Callback(() => { start1 = ++order; serviceEvent.Set(); });
service
.Setup(s => s.StartSession(It.Is<ServiceConfiguration>(c => c.SessionId == session2Id)))
.Returns(new CommunicationResult(true))
.Callback(() => { start2 = ++order; serviceEvent.Set(); });
service
.Setup(s => s.StopSession(It.IsAny<Guid>()))
.Returns(new CommunicationResult(true))
.Callback(() => { stop1 = ++order; serviceEvent.Set(); });
sut.Perform();
context.Current.SessionId = session1Id;
context.Next.SessionId = session2Id;
var result = sut.Repeat(); var result = sut.Repeat();
service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once); service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once);
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once); service.Verify(s => s.StopSession(It.Is<Guid>(id => id == session1Id)), Times.Once);
service.Verify(s => s.StartSession(It.IsAny<ServiceConfiguration>()), Times.Exactly(2)); service.Verify(s => s.StartSession(It.Is<ServiceConfiguration>(c => c.SessionId == session1Id)), Times.Once);
service.Verify(s => s.StartSession(It.Is<ServiceConfiguration>(c => c.SessionId == session2Id)), Times.Once);
service.Verify(s => s.Disconnect(), Times.Never); service.Verify(s => s.Disconnect(), Times.Never);
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never); service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Never);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.IsTrue(start1 == 1);
Assert.IsTrue(stop1 == 2);
Assert.IsTrue(start2 == 3);
} }
[TestMethod] [TestMethod]
@ -229,12 +259,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
service.Reset(); service.Reset();
service.SetupGet(s => s.IsConnected).Returns(false); service.SetupGet(s => s.IsConnected).Returns(false);
service.Setup(s => s.Connect(null, true)).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true).Callback(() => service.SetupGet(s => s.IsConnected).Returns(true));
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)); service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
var result = sut.Repeat(); var result = sut.Repeat();
service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once); service.Verify(s => s.Connect(It.IsAny<Guid?>(), It.IsAny<bool>()), Times.Once);
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Never);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
@ -264,7 +295,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var before = default(DateTime); var before = default(DateTime);
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)); service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, context, TIMEOUT, userInfo.Object);
PerformNormally(); PerformNormally();
@ -279,6 +310,19 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.IsTrue(after - before >= new TimeSpan(0, 0, 0, 0, TIMEOUT)); Assert.IsTrue(after - before >= new TimeSpan(0, 0, 0, 0, TIMEOUT));
} }
[TestMethod]
public void Repeat_MustNotStopSessionIfNoSessionRunning()
{
service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.StartSession(It.IsAny<ServiceConfiguration>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
var result = sut.Repeat();
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Never);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod] [TestMethod]
public void Revert_MustDisconnect() public void Revert_MustDisconnect()
{ {
@ -295,24 +339,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod]
public void Revert_MustStopSessionIfConnected()
{
service.Setup(s => s.Disconnect()).Returns(true);
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(true));
PerformNormally();
var result = sut.Revert();
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Once);
service.Verify(s => s.Disconnect(), Times.Once);
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod] [TestMethod]
public void Revert_MustHandleCommunicationFailureWhenStoppingSession() public void Revert_MustHandleCommunicationFailureWhenStoppingSession()
{ {
@ -369,7 +395,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var before = default(DateTime); var before = default(DateTime);
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)); service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true));
sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT, userInfo.Object); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, context, TIMEOUT, userInfo.Object);
PerformNormally(); PerformNormally();
@ -391,13 +417,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var result = sut.Revert(); var result = sut.Revert();
service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Never); service.Verify(s => s.StopSession(It.IsAny<Guid>()), Times.Never);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod] [TestMethod]
public void Revert_MustNotStopSessionIfNoSessionRunning() public void Revert_MustNotStopSessionIfNoSessionRunning()
{ {
sessionContext.Current = null; context.Current = null;
context.Next = null;
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);
service.Setup(s => s.Disconnect()).Returns(true); service.Setup(s => s.Disconnect()).Returns(true);
@ -417,6 +445,50 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod]
public void Revert_MustStopSessionIfConnected()
{
context.Next.SessionId = Guid.NewGuid();
service.Setup(s => s.Disconnect()).Returns(true);
service.Setup(s => s.StopSession(It.IsAny<Guid>())).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(true));
PerformNormally();
var result = sut.Revert();
service.Verify(s => s.StopSession(It.Is<Guid>(id => id == context.Next.SessionId)), Times.Once);
service.Verify(s => s.Disconnect(), Times.Once);
service.Verify(s => s.RunSystemConfigurationUpdate(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Revert_MustStopSessionIfNewSessionNotCompletelyStarted()
{
var sessionId = Guid.NewGuid();
context.Current.SessionId = Guid.NewGuid();
context.Next.SessionId = sessionId;
PerformNormally();
context.Current.SessionId = default(Guid);
context.Next.SessionId = default(Guid);
service.Setup(s => s.StopSession(It.Is<Guid>(id => id == sessionId))).Returns(new CommunicationResult(true)).Callback(() => serviceEvent.Set());
service.Setup(s => s.RunSystemConfigurationUpdate()).Returns(new CommunicationResult(true));
service.Setup(s => s.Disconnect()).Returns(true);
var result = sut.Revert();
service.Verify(s => s.StopSession(It.Is<Guid>(id => id == sessionId)), Times.Once);
service.Verify(s => s.StopSession(It.Is<Guid>(id => id == default(Guid))), Times.Never);
service.Verify(s => s.Disconnect(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
private void PerformNormally() private void PerformNormally()
{ {
service.SetupGet(s => s.IsConnected).Returns(true); service.SetupGet(s => s.IsConnected).Returns(true);

View file

@ -12,12 +12,12 @@ using System.Threading;
using SafeExamBrowser.Communication.Contracts.Hosts; using SafeExamBrowser.Communication.Contracts.Hosts;
using SafeExamBrowser.Communication.Contracts.Proxies; using SafeExamBrowser.Communication.Contracts.Proxies;
using SafeExamBrowser.Configuration.Contracts; using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Settings.Service;
using SafeExamBrowser.Core.Contracts.OperationModel; using SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events; using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Operations.Events; using SafeExamBrowser.Runtime.Operations.Events;
using SafeExamBrowser.Settings.Service;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.MessageBox;
@ -28,6 +28,8 @@ namespace SafeExamBrowser.Runtime.Operations
private ILogger logger; private ILogger logger;
private IRuntimeHost runtimeHost; private IRuntimeHost runtimeHost;
private IServiceProxy service; private IServiceProxy service;
private string serviceEventName;
private Guid? sessionId;
private int timeout_ms; private int timeout_ms;
private IUserInfo userInfo; private IUserInfo userInfo;
@ -54,9 +56,9 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info($"Initializing service..."); logger.Info($"Initializing service...");
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession); StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession);
var success = TryEstablishConnection(); var success = TryInitializeConnection();
if (service.IsConnected) if (success && service.IsConnected)
{ {
success = TryStartSession(); success = TryStartSession();
} }
@ -69,15 +71,15 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info($"Initializing service..."); logger.Info($"Initializing service...");
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession); StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServiceSession);
var success = false; var success = true;
if (service.IsConnected) if (service.IsConnected && sessionId.HasValue)
{ {
success = TryStopSession(); success = TryStopSession();
} }
else else if (!service.IsConnected)
{ {
success = TryEstablishConnection(); success = TryInitializeConnection();
} }
if (success && service.IsConnected) if (success && service.IsConnected)
@ -97,7 +99,7 @@ namespace SafeExamBrowser.Runtime.Operations
if (service.IsConnected) if (service.IsConnected)
{ {
if (Context.Current != null) if (sessionId.HasValue)
{ {
success &= TryStopSession(true); success &= TryStopSession(true);
} }
@ -108,7 +110,7 @@ namespace SafeExamBrowser.Runtime.Operations
return success ? OperationResult.Success : OperationResult.Failed; return success ? OperationResult.Success : OperationResult.Failed;
} }
private bool TryEstablishConnection() private bool TryInitializeConnection()
{ {
var mandatory = Context.Next.Settings.Service.Policy == ServicePolicy.Mandatory; var mandatory = Context.Next.Settings.Service.Policy == ServicePolicy.Mandatory;
var warn = Context.Next.Settings.Service.Policy == ServicePolicy.Warn; var warn = Context.Next.Settings.Service.Policy == ServicePolicy.Warn;
@ -117,8 +119,7 @@ namespace SafeExamBrowser.Runtime.Operations
if (success) if (success)
{ {
service.Ignore = !connected; logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "connected." : "not connected.")}");
logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "connected." : "not connected. All service-related operations will be ignored!")}");
if (!connected && warn) if (!connected && warn)
{ {
@ -182,6 +183,8 @@ namespace SafeExamBrowser.Runtime.Operations
if (started) if (started)
{ {
sessionId = Context.Next.SessionId;
serviceEventName = Context.Next.AppConfig.ServiceEventName;
logger.Info("Successfully started new service session."); logger.Info("Successfully started new service session.");
} }
else else
@ -203,14 +206,16 @@ namespace SafeExamBrowser.Runtime.Operations
logger.Info("Stopping current service session..."); logger.Info("Stopping current service session...");
var communication = service.StopSession(Context.Current.SessionId); var communication = service.StopSession(sessionId.Value);
if (communication.Success) if (communication.Success)
{ {
success = TryWaitForServiceEvent(Context.Current.AppConfig.ServiceEventName); success = TryWaitForServiceEvent(serviceEventName);
if (success) if (success)
{ {
sessionId = default(Guid?);
serviceEventName = default(string);
logger.Info("Successfully stopped service session."); logger.Info("Successfully stopped service session.");
} }
else else