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); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -159,10 +159,17 @@ namespace SafeExamBrowser.Service | |||
| 		private void ServiceHost_SessionStopRequested(SessionStopEventArgs args) | ||||
| 		{ | ||||
| 			if (SessionIsRunning) | ||||
| 			{ | ||||
| 				if (Session.SessionId == args.SessionId) | ||||
| 				{ | ||||
| 					StopSession(); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					logger.Warn("Received session stop request with wrong session ID!"); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				logger.Warn("Received session stop request, even though no session is currently running!"); | ||||
| 			} | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 dbuechel
						dbuechel