SEBWIN-301: Added unit tests for basic service functionality.
This commit is contained in:
parent
3589b92b9d
commit
ac28eec94a
10 changed files with 520 additions and 28 deletions
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Communication;
|
||||
using SafeExamBrowser.Contracts.Communication.Data;
|
||||
using SafeExamBrowser.Contracts.Communication.Events;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Service.Communication;
|
||||
|
||||
namespace SafeExamBrowser.Service.UnitTests.Communication
|
||||
{
|
||||
[TestClass]
|
||||
public class ServiceHostTests
|
||||
{
|
||||
private Mock<IHostObject> hostObject;
|
||||
private Mock<IHostObjectFactory> hostObjectFactory;
|
||||
private Mock<ILogger> logger;
|
||||
private ServiceHost sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
hostObject = new Mock<IHostObject>();
|
||||
hostObjectFactory = new Mock<IHostObjectFactory>();
|
||||
logger = new Mock<ILogger>();
|
||||
|
||||
hostObjectFactory.Setup(f => f.CreateObject(It.IsAny<string>(), It.IsAny<ICommunication>())).Returns(hostObject.Object);
|
||||
|
||||
sut = new ServiceHost("net:pipe://some/address", hostObjectFactory.Object, logger.Object, 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Connect_MustAllowFirstConnnectionAndDenyFurtherRequests()
|
||||
{
|
||||
var response = sut.Connect();
|
||||
var response2 = sut.Connect();
|
||||
var response3 = sut.Connect();
|
||||
|
||||
Assert.IsTrue(response.ConnectionEstablished);
|
||||
Assert.IsFalse(sut.AllowConnection);
|
||||
Assert.IsFalse(response2.ConnectionEstablished);
|
||||
Assert.IsFalse(response3.ConnectionEstablished);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Disconnect_MustDisconnectAndThenAllowNewConnection()
|
||||
{
|
||||
var connect = sut.Connect();
|
||||
var disconnect = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connect.CommunicationToken.Value, Interlocutor = Interlocutor.Runtime });
|
||||
|
||||
Assert.IsTrue(sut.AllowConnection);
|
||||
Assert.IsTrue(disconnect.ConnectionTerminated);
|
||||
|
||||
var connect2 = sut.Connect();
|
||||
|
||||
Assert.IsFalse(sut.AllowConnection);
|
||||
Assert.IsTrue(connect2.ConnectionEstablished);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Send_MustHandleSessionStartRequest()
|
||||
{
|
||||
var args = default(SessionStartEventArgs);
|
||||
var sync = new AutoResetEvent(false);
|
||||
var configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() };
|
||||
var sessionStartRequested = false;
|
||||
|
||||
sut.SessionStartRequested += (a) => { args = a; sessionStartRequested = true; sync.Set(); };
|
||||
|
||||
var token = sut.Connect().CommunicationToken.Value;
|
||||
var message = new SessionStartMessage(configuration) { CommunicationToken = token };
|
||||
var response = sut.Send(message);
|
||||
|
||||
sync.WaitOne();
|
||||
|
||||
Assert.IsTrue(sessionStartRequested);
|
||||
Assert.IsNotNull(args);
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
|
||||
Assert.AreEqual(configuration.SessionId, args.Configuration.SessionId);
|
||||
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Send_MustHandleSessionStopRequest()
|
||||
{
|
||||
var args = default(SessionStopEventArgs);
|
||||
var sync = new AutoResetEvent(false);
|
||||
var sessionId = Guid.NewGuid();
|
||||
var sessionStopRequested = false;
|
||||
|
||||
sut.SessionStopRequested += (a) => { args = a; sessionStopRequested = true; sync.Set(); };
|
||||
|
||||
var token = sut.Connect().CommunicationToken.Value;
|
||||
var message = new SessionStopMessage(sessionId) { CommunicationToken = token };
|
||||
var response = sut.Send(message);
|
||||
|
||||
sync.WaitOne();
|
||||
|
||||
Assert.IsTrue(sessionStopRequested);
|
||||
Assert.IsNotNull(args);
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
|
||||
Assert.AreEqual(sessionId, args.SessionId);
|
||||
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Send_MustReturnUnknownMessageAsDefault()
|
||||
{
|
||||
var token = sut.Connect().CommunicationToken.Value;
|
||||
var message = new TestMessage { CommunicationToken = token } as Message;
|
||||
var response = sut.Send(message);
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
|
||||
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
|
||||
|
||||
message = new SimpleMessage(default(SimpleMessagePurport)) { CommunicationToken = token };
|
||||
response = sut.Send(message);
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
|
||||
Assert.AreEqual(SimpleResponsePurport.UnknownMessage, (response as SimpleResponse)?.Purport);
|
||||
}
|
||||
|
||||
private class TestMessage : Message { };
|
||||
}
|
||||
}
|
26
SafeExamBrowser.Service.UnitTests/Operations/EventStub.cs
Normal file
26
SafeExamBrowser.Service.UnitTests/Operations/EventStub.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||
{
|
||||
internal class EventStub : EventWaitHandle
|
||||
{
|
||||
public bool IsClosed { get; set; }
|
||||
|
||||
public EventStub() : base(false, EventResetMode.AutoReset)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
IsClosed = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Service.Operations;
|
||||
|
||||
namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class ServiceEventCleanupOperationTests
|
||||
{
|
||||
private Mock<ILogger> logger;
|
||||
private SessionContext sessionContext;
|
||||
private ServiceEventCleanupOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
logger = new Mock<ILogger>();
|
||||
sessionContext = new SessionContext();
|
||||
|
||||
sut = new ServiceEventCleanupOperation(logger.Object, sessionContext);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Perform_MustDoNothing()
|
||||
{
|
||||
var serviceEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
|
||||
sessionContext.ServiceEvent = serviceEvent;
|
||||
|
||||
var result = sut.Perform();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.AreSame(serviceEvent, sessionContext.ServiceEvent);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustCloseEvent()
|
||||
{
|
||||
var serviceEvent = new EventStub();
|
||||
|
||||
sessionContext.ServiceEvent = serviceEvent;
|
||||
|
||||
var result = sut.Revert();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.IsTrue(serviceEvent.IsClosed);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustNotFailIfEventNull()
|
||||
{
|
||||
var result = sut.Revert();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Service.Operations;
|
||||
|
||||
namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class SessionActivationOperationTests
|
||||
{
|
||||
private Mock<ILogger> logger;
|
||||
private SessionContext sessionContext;
|
||||
private SessionActivationOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
logger = new Mock<ILogger>();
|
||||
sessionContext = new SessionContext();
|
||||
|
||||
sut = new SessionActivationOperation(logger.Object, sessionContext);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Perform_MustSetServiceEvent()
|
||||
{
|
||||
sessionContext.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
|
||||
var wasSet = false;
|
||||
var task = Task.Run(() => wasSet = sessionContext.ServiceEvent.WaitOne(1000));
|
||||
var result = sut.Perform();
|
||||
|
||||
task.Wait();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.IsTrue(wasSet);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustDoNothing()
|
||||
{
|
||||
var result = sut.Revert();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Service.Operations;
|
||||
|
||||
namespace SafeExamBrowser.Service.UnitTests.Operations
|
||||
{
|
||||
[TestClass]
|
||||
public class SessionInitializationOperationTests
|
||||
{
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<Func<string, ILogObserver>> logWriterFactory;
|
||||
private Mock<IServiceHost> serviceHost;
|
||||
private Mock<Func<string, EventWaitHandle>> serviceEventFactory;
|
||||
private SessionContext sessionContext;
|
||||
private SessionInitializationOperation sut;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
logger = new Mock<ILogger>();
|
||||
logWriterFactory = new Mock<Func<string, ILogObserver>>();
|
||||
serviceHost = new Mock<IServiceHost>();
|
||||
serviceEventFactory = new Mock<Func<string, EventWaitHandle>>();
|
||||
sessionContext = new SessionContext();
|
||||
|
||||
logWriterFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new Mock<ILogObserver>().Object);
|
||||
serviceEventFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new EventStub());
|
||||
sessionContext.Configuration = new ServiceConfiguration
|
||||
{
|
||||
AppConfig = new AppConfig { ServiceEventName = $"{nameof(SafeExamBrowser)}-{nameof(SessionInitializationOperationTests)}" }
|
||||
};
|
||||
|
||||
sut = new SessionInitializationOperation(logger.Object, logWriterFactory.Object, serviceEventFactory.Object, serviceHost.Object, sessionContext);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Perform_MustDisableNewConnections()
|
||||
{
|
||||
var result = sut.Perform();
|
||||
|
||||
serviceHost.VerifySet(h => h.AllowConnection = false, Times.Once);
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Perform_MustInitializeServiceEvent()
|
||||
{
|
||||
var result = sut.Perform();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.IsInstanceOfType(sessionContext.ServiceEvent, typeof(EventWaitHandle));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustSetServiceEvent()
|
||||
{
|
||||
sessionContext.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
|
||||
var wasSet = false;
|
||||
var task = Task.Run(() => wasSet = sessionContext.ServiceEvent.WaitOne(1000));
|
||||
var result = sut.Revert();
|
||||
|
||||
task.Wait();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.IsTrue(wasSet);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustDeleteConfiguration()
|
||||
{
|
||||
sessionContext.Configuration = new ServiceConfiguration();
|
||||
sessionContext.ServiceEvent = new EventStub();
|
||||
|
||||
var result = sut.Revert();
|
||||
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
Assert.IsNull(sessionContext.Configuration);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Revert_MustEnableNewConnections()
|
||||
{
|
||||
sessionContext.ServiceEvent = new EventStub();
|
||||
|
||||
var result = sut.Revert();
|
||||
|
||||
serviceHost.VerifySet(h => h.AllowConnection = true, Times.Once);
|
||||
Assert.AreEqual(OperationResult.Success, result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -80,6 +80,11 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Communication\ServiceHostTests.cs" />
|
||||
<Compile Include="Operations\EventStub.cs" />
|
||||
<Compile Include="Operations\ServiceEventCleanupOperationTests.cs" />
|
||||
<Compile Include="Operations\SessionActivationOperationTests.cs" />
|
||||
<Compile Include="Operations\SessionInitializationOperationTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceControllerTests.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -87,6 +92,10 @@
|
|||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Communication\SafeExamBrowser.Communication.csproj">
|
||||
<Project>{c9416a62-0623-4d38-96aa-92516b32f02f}</Project>
|
||||
<Name>SafeExamBrowser.Communication</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47da5933-bef8-4729-94e6-abde2db12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
|
@ -96,10 +105,7 @@
|
|||
<Name>SafeExamBrowser.Service</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Communication\" />
|
||||
<Folder Include="Operations\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Communication.Events;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
|
@ -21,7 +23,7 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
private Mock<ILogger> logger;
|
||||
private Mock<IOperationSequence> bootstrapSequence;
|
||||
private SessionContext sessionContext;
|
||||
private Mock<IRepeatableOperationSequence> sessionSequence;
|
||||
private Mock<IOperationSequence> sessionSequence;
|
||||
private Mock<IServiceHost> serviceHost;
|
||||
private ServiceController sut;
|
||||
|
||||
|
@ -31,12 +33,86 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
logger = new Mock<ILogger>();
|
||||
bootstrapSequence = new Mock<IOperationSequence>();
|
||||
sessionContext = new SessionContext();
|
||||
sessionSequence = new Mock<IRepeatableOperationSequence>();
|
||||
sessionSequence = new Mock<IOperationSequence>();
|
||||
serviceHost = new Mock<IServiceHost>();
|
||||
|
||||
sut = new ServiceController(logger.Object, bootstrapSequence.Object, sessionSequence.Object, serviceHost.Object, sessionContext);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustStartNewSessionUponRequest()
|
||||
{
|
||||
var args = new SessionStartEventArgs { Configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() } };
|
||||
|
||||
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
|
||||
sut.TryStart();
|
||||
serviceHost.Raise(h => h.SessionStartRequested += null, args);
|
||||
|
||||
sessionSequence.Verify(s => s.TryPerform(), Times.Once);
|
||||
|
||||
Assert.IsNotNull(sessionContext.Configuration);
|
||||
Assert.AreEqual(args.Configuration.SessionId, sessionContext.Configuration.SessionId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustNotAllowNewSessionDuringActiveSession()
|
||||
{
|
||||
var args = new SessionStartEventArgs { Configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() } };
|
||||
|
||||
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
sessionContext.Configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() };
|
||||
|
||||
sut.TryStart();
|
||||
serviceHost.Raise(h => h.SessionStartRequested += null, args);
|
||||
|
||||
sessionSequence.Verify(s => s.TryPerform(), Times.Never);
|
||||
|
||||
Assert.AreNotEqual(args.Configuration.SessionId, sessionContext.Configuration.SessionId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustStopActiveSessionUponRequest()
|
||||
{
|
||||
var args = new SessionStopEventArgs { SessionId = Guid.NewGuid() };
|
||||
|
||||
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
sessionContext.Configuration = new ServiceConfiguration { SessionId = args.SessionId };
|
||||
|
||||
sut.TryStart();
|
||||
serviceHost.Raise(h => h.SessionStopRequested += null, args);
|
||||
|
||||
sessionSequence.Verify(s => s.TryRevert(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustNotStopSessionWithWrongId()
|
||||
{
|
||||
var args = new SessionStopEventArgs { SessionId = Guid.NewGuid() };
|
||||
|
||||
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
sessionContext.Configuration = new ServiceConfiguration { SessionId = Guid.NewGuid() };
|
||||
|
||||
sut.TryStart();
|
||||
serviceHost.Raise(h => h.SessionStopRequested += null, args);
|
||||
|
||||
sessionSequence.Verify(s => s.TryRevert(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Communication_MustNotStopSessionWithoutActiveSession()
|
||||
{
|
||||
var args = new SessionStopEventArgs { SessionId = Guid.NewGuid() };
|
||||
|
||||
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
|
||||
|
||||
sut.TryStart();
|
||||
serviceHost.Raise(h => h.SessionStopRequested += null, args);
|
||||
|
||||
sessionSequence.Verify(s => s.TryRevert(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Start_MustOnlyPerformBootstrapSequence()
|
||||
{
|
||||
|
@ -49,7 +125,6 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
bootstrapSequence.Verify(b => b.TryPerform(), Times.Once);
|
||||
bootstrapSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||
|
||||
Assert.IsTrue(success);
|
||||
|
@ -76,7 +151,6 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
bootstrapSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||
bootstrapSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||
|
||||
Assert.AreEqual(1, session);
|
||||
|
@ -104,7 +178,6 @@ namespace SafeExamBrowser.Service.UnitTests
|
|||
bootstrapSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||
bootstrapSequence.Verify(b => b.TryRevert(), Times.Once);
|
||||
sessionSequence.Verify(b => b.TryPerform(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRepeat(), Times.Never);
|
||||
sessionSequence.Verify(b => b.TryRevert(), Times.Never);
|
||||
|
||||
Assert.AreEqual(0, session);
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Communication.Hosts;
|
||||
using SafeExamBrowser.Communication.Proxies;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
|
@ -42,13 +45,10 @@ namespace SafeExamBrowser.Service
|
|||
var bootstrapOperations = new Queue<IOperation>();
|
||||
var sessionOperations = new Queue<IOperation>();
|
||||
|
||||
// TODO: bootstrapOperations.Enqueue(new RestoreOperation());
|
||||
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
|
||||
bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext));
|
||||
|
||||
sessionOperations.Enqueue(new SessionInitializationOperation(logger, CreateLogWriter, serviceHost, sessionContext));
|
||||
// TODO: sessionOperations.Enqueue(new RegistryOperation());
|
||||
// sessionOperations.Enqueue(new WindowsUpdateOperation());
|
||||
sessionOperations.Enqueue(new SessionInitializationOperation(logger, LogWriterFactory, ServiceEventFactory, serviceHost, sessionContext));
|
||||
sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext));
|
||||
|
||||
var bootstrapSequence = new OperationSequence(logger, bootstrapOperations);
|
||||
|
@ -82,7 +82,7 @@ namespace SafeExamBrowser.Service
|
|||
logFileWriter.Initialize();
|
||||
}
|
||||
|
||||
private ILogObserver CreateLogWriter(string filePath)
|
||||
private ILogObserver LogWriterFactory(string filePath)
|
||||
{
|
||||
var writer = new LogFileWriter(new DefaultLogFormatter(), filePath);
|
||||
|
||||
|
@ -90,5 +90,16 @@ namespace SafeExamBrowser.Service
|
|||
|
||||
return writer;
|
||||
}
|
||||
|
||||
private EventWaitHandle ServiceEventFactory(string eventName)
|
||||
{
|
||||
var securityIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
|
||||
var accessRule = new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
|
||||
var security = new EventWaitHandleSecurity();
|
||||
|
||||
security.AddAccessRule(accessRule);
|
||||
|
||||
return new EventWaitHandle(false, EventResetMode.AutoReset, eventName, out _, security);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
|
@ -19,18 +17,21 @@ namespace SafeExamBrowser.Service.Operations
|
|||
internal class SessionInitializationOperation : SessionOperation
|
||||
{
|
||||
private ILogger logger;
|
||||
private Func<string, ILogObserver> createLogWriter;
|
||||
private Func<string, ILogObserver> logWriterFactory;
|
||||
private Func<string, EventWaitHandle> serviceEventFactory;
|
||||
private IServiceHost serviceHost;
|
||||
private ILogObserver sessionWriter;
|
||||
|
||||
public SessionInitializationOperation(
|
||||
ILogger logger,
|
||||
Func<string, ILogObserver> createLogWriter,
|
||||
Func<string, ILogObserver> logWriterFactory,
|
||||
Func<string, EventWaitHandle> serviceEventFactory,
|
||||
IServiceHost serviceHost,
|
||||
SessionContext sessionContext) : base(sessionContext)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.createLogWriter = createLogWriter;
|
||||
this.logWriterFactory = logWriterFactory;
|
||||
this.serviceEventFactory = serviceEventFactory;
|
||||
this.serviceHost = serviceHost;
|
||||
}
|
||||
|
||||
|
@ -80,12 +81,6 @@ namespace SafeExamBrowser.Service.Operations
|
|||
|
||||
private void InitializeServiceEvent()
|
||||
{
|
||||
var securityIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
|
||||
var accessRule = new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
|
||||
var security = new EventWaitHandleSecurity();
|
||||
|
||||
security.AddAccessRule(accessRule);
|
||||
|
||||
if (Context.ServiceEvent != null)
|
||||
{
|
||||
logger.Info("Closing service event from previous session...");
|
||||
|
@ -94,13 +89,13 @@ namespace SafeExamBrowser.Service.Operations
|
|||
}
|
||||
|
||||
logger.Info("Attempting to create new service event...");
|
||||
Context.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Context.Configuration.AppConfig.ServiceEventName, out _, security);
|
||||
Context.ServiceEvent = serviceEventFactory.Invoke(Context.Configuration.AppConfig.ServiceEventName);
|
||||
logger.Info("Service event successfully created.");
|
||||
}
|
||||
|
||||
private void InitializeSessionWriter()
|
||||
{
|
||||
sessionWriter = createLogWriter.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath);
|
||||
sessionWriter = logWriterFactory.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath);
|
||||
logger.Subscribe(sessionWriter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,14 @@ namespace SafeExamBrowser.Service
|
|||
{
|
||||
if (SessionIsRunning)
|
||||
{
|
||||
StopSession();
|
||||
if (Session.SessionId == args.SessionId)
|
||||
{
|
||||
StopSession();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warn("Received session stop request with wrong session ID!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue