Extended unit tests for runtime component.

This commit is contained in:
Damian Büchel 2021-07-30 18:38:41 +02:00
parent a0a577991f
commit 8b4d081c0f
4 changed files with 582 additions and 34 deletions

View file

@ -15,9 +15,9 @@ using SafeExamBrowser.Communication.Contracts.Data;
using SafeExamBrowser.Communication.Contracts.Events;
using SafeExamBrowser.Communication.Contracts.Hosts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Communication;
using SafeExamBrowser.Settings;
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
namespace SafeExamBrowser.Runtime.UnitTests.Communication
@ -188,6 +188,60 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication
Assert.AreEqual(configuration.Settings.Security.AdminPasswordHash, (response as ConfigurationResponse)?.Configuration.Settings.Security.AdminPasswordHash);
}
[TestMethod]
public void MustHandleExamSelectionCorrectly()
{
var args = default(ExamSelectionReplyEventArgs);
var examId = "abc123";
var requestId = Guid.NewGuid();
var sync = new AutoResetEvent(false);
sut.AllowConnection = true;
sut.AuthenticationToken = Guid.Empty;
sut.ExamSelectionReceived += (a) => { args = a; sync.Set(); };
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new ExamSelectionReplyMessage(requestId, true, examId) { CommunicationToken = token };
var response = sut.Send(message);
sync.WaitOne();
Assert.IsNotNull(args);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
Assert.IsTrue(args.Success);
Assert.AreEqual(examId, args.SelectedExamId);
Assert.AreEqual(requestId, args.RequestId);
}
[TestMethod]
public void MustHandleServerFailureActionCorrectly()
{
var args = default(ServerFailureActionReplyEventArgs);
var requestId = Guid.NewGuid();
var sync = new AutoResetEvent(false);
sut.AllowConnection = true;
sut.AuthenticationToken = Guid.Empty;
sut.ServerFailureActionReceived += (a) => { args = a; sync.Set(); };
var token = sut.Connect(Guid.Empty).CommunicationToken.Value;
var message = new ServerFailureActionReplyMessage(true, false, true, requestId) { CommunicationToken = token };
var response = sut.Send(message);
sync.WaitOne();
Assert.IsNotNull(args);
Assert.IsNotNull(response);
Assert.IsInstanceOfType(response, typeof(SimpleResponse));
Assert.AreEqual(SimpleResponsePurport.Acknowledged, (response as SimpleResponse)?.Purport);
Assert.IsFalse(args.Fallback);
Assert.IsTrue(args.Abort);
Assert.IsTrue(args.Retry);
Assert.AreEqual(requestId, args.RequestId);
}
[TestMethod]
public void MustHandleShutdownRequestCorrectly()
{

View file

@ -31,7 +31,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
private Mock<IFileSystem> fileSystem;
private Mock<ILogger> logger;
private Mock<IServerProxy> server;
private AppSettings settings;
private Mock<IConfigurationRepository> configuration;
private ServerOperation sut;
@ -44,13 +43,14 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
fileSystem = new Mock<IFileSystem>();
logger = new Mock<ILogger>();
server = new Mock<IServerProxy>();
settings = new AppSettings();
context.Current = new SessionConfiguration();
context.Current.AppConfig = new AppConfig();
context.Current.Settings = new AppSettings();
context.Next = new SessionConfiguration();
context.Next.AppConfig = new AppConfig();
context.Next.Settings = settings;
context.Next.Settings = new AppSettings();
sut = new ServerOperation(new string[0], configuration.Object, fileSystem.Object, logger.Object, context, server.Object);
}
@ -68,11 +68,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var getConnection = 0;
var getExams = 0;
var initialize = 0;
var serverSettings = settings.Server;
var initialSettings = context.Next.Settings;
var serverSettings = context.Next.Settings.Server;
configuration
.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>()))
.Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
fileSystem.Setup(f => f.Delete(It.IsAny<string>())).Callback(() => delete = ++counter);
server.Setup(s => s.Connect()).Returns(new ServerResponse(true)).Callback(() => connect = ++counter);
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>())).Callback(() => initialize = ++counter);
@ -85,7 +87,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>()))
.Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")))
.Callback(() => getConfiguration = ++counter);
settings.SessionMode = SessionMode.Server;
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
@ -119,9 +120,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.AreEqual(exam.Url, context.Next.Settings.Browser.StartUrl);
Assert.AreSame(examSettings, context.Next.Settings);
Assert.AreSame(serverSettings, context.Next.Settings.Server);
Assert.AreNotSame(settings, context.Next.Settings);
Assert.AreNotSame(initialSettings, context.Next.Settings);
Assert.AreEqual(OperationResult.Success, result);
Assert.AreEqual(SessionMode.Server, settings.SessionMode);
Assert.AreEqual(SessionMode.Server, context.Next.Settings.SessionMode);
}
[TestMethod]
@ -130,14 +131,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var initialSettings = context.Next.Settings;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.UnexpectedError);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
settings.SessionMode = SessionMode.Server;
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
@ -162,7 +164,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.AreNotEqual(exam.Id, context.Next.AppConfig.ServerExamId);
Assert.AreNotEqual(exam.Url, context.Next.Settings.Browser.StartUrl);
Assert.AreNotSame(examSettings, context.Next.Settings);
Assert.AreSame(settings, context.Next.Settings);
Assert.AreSame(initialSettings, context.Next.Settings);
Assert.AreEqual(OperationResult.Failed, result);
Assert.AreEqual(SessionMode.Server, context.Next.Settings.SessionMode);
}
@ -176,12 +178,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var messageShown = false;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(false, default(Uri)));
settings.SessionMode = SessionMode.Server;
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
@ -219,12 +221,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
var messageShown = false;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(false, default(Uri)));
settings.SessionMode = SessionMode.Server;
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
@ -254,13 +256,44 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Perform_MustAutomaticallySelectExam()
{
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var serverSettings = context.Next.Settings.Server;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
context.Next.Settings.Server.ExamId = "some id";
fileSystem.Setup(f => f.Delete(It.IsAny<string>()));
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, new [] { exam }));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
sut.ActionRequired += (args) => Assert.Fail();
var result = sut.Perform();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Once);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Perform_MustDoNothingIfNormalSession()
{
var eventFired = false;
var initialSettings = context.Next.Settings;
settings.SessionMode = SessionMode.Normal;
sut.ActionRequired += (_) => eventFired = true;
context.Next.Settings.SessionMode = SessionMode.Normal;
sut.ActionRequired += (_) => Assert.Fail();
var result = sut.Perform();
@ -268,20 +301,253 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
fileSystem.VerifyNoOtherCalls();
server.VerifyNoOtherCalls();
Assert.IsFalse(eventFired);
Assert.AreSame(settings, context.Next.Settings);
Assert.AreSame(initialSettings, context.Next.Settings);
Assert.AreEqual(SessionMode.Normal, context.Next.Settings.SessionMode);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Repeat_MustDoNothingIfNormalSession()
public void Repeat_MustCorrectlyInitializeServerSession()
{
var eventFired = false;
var connect = 0;
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var counter = 0;
var delete = 0;
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSelection = 0;
var examSettings = new AppSettings();
var getConfiguration = 0;
var getConnection = 0;
var getExams = 0;
var initialize = 0;
var initialSettings = context.Next.Settings;
var serverSettings = context.Next.Settings.Server;
context.Current.Settings.SessionMode = SessionMode.Normal;
settings.SessionMode = SessionMode.Normal;
sut.ActionRequired += (_) => eventFired = true;
configuration
.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>()))
.Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
fileSystem.Setup(f => f.Delete(It.IsAny<string>())).Callback(() => delete = ++counter);
server.Setup(s => s.Connect()).Returns(new ServerResponse(true)).Callback(() => connect = ++counter);
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>())).Callback(() => initialize = ++counter);
server.Setup(s => s.GetConnectionInfo()).Returns(connection).Callback(() => getConnection = ++counter);
server
.Setup(s => s.GetAvailableExams(It.IsAny<string>()))
.Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)))
.Callback(() => getExams = ++counter);
server
.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>()))
.Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")))
.Callback(() => getConfiguration = ++counter);
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
{
e.Success = true;
e.SelectedExam = exam;
examSelection = ++counter;
}
};
var result = sut.Repeat();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Once);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Once);
Assert.AreEqual(1, initialize);
Assert.AreEqual(2, connect);
Assert.AreEqual(3, getExams);
Assert.AreEqual(4, examSelection);
Assert.AreEqual(5, getConfiguration);
Assert.AreEqual(6, getConnection);
Assert.AreEqual(7, delete);
Assert.AreEqual(connection.Api, context.Next.AppConfig.ServerApi);
Assert.AreEqual(connection.ConnectionToken, context.Next.AppConfig.ServerConnectionToken);
Assert.AreEqual(connection.Oauth2Token, context.Next.AppConfig.ServerOauth2Token);
Assert.AreEqual(exam.Id, context.Next.AppConfig.ServerExamId);
Assert.AreEqual(exam.Url, context.Next.Settings.Browser.StartUrl);
Assert.AreSame(examSettings, context.Next.Settings);
Assert.AreSame(serverSettings, context.Next.Settings.Server);
Assert.AreNotSame(initialSettings, context.Next.Settings);
Assert.AreEqual(OperationResult.Success, result);
Assert.AreEqual(SessionMode.Server, context.Next.Settings.SessionMode);
}
[TestMethod]
public void Repeat_MustFailIfSettingsCouldNotBeLoaded()
{
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var initialSettings = context.Next.Settings;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.UnexpectedError);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
{
e.Success = true;
e.SelectedExam = exam;
}
};
var result = sut.Repeat();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Once);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Once);
Assert.AreNotEqual(connection.Api, context.Next.AppConfig.ServerApi);
Assert.AreNotEqual(connection.ConnectionToken, context.Next.AppConfig.ServerConnectionToken);
Assert.AreNotEqual(connection.Oauth2Token, context.Next.AppConfig.ServerOauth2Token);
Assert.AreNotEqual(exam.Id, context.Next.AppConfig.ServerExamId);
Assert.AreNotEqual(exam.Url, context.Next.Settings.Browser.StartUrl);
Assert.AreNotSame(examSettings, context.Next.Settings);
Assert.AreSame(initialSettings, context.Next.Settings);
Assert.AreEqual(OperationResult.Failed, result);
Assert.AreEqual(SessionMode.Server, context.Next.Settings.SessionMode);
}
[TestMethod]
public void Repeat_MustCorrectlyAbort()
{
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var messageShown = false;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(false, default(Uri)));
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
{
e.Success = true;
e.SelectedExam = exam;
}
if (args is ServerFailureEventArgs s)
{
s.Abort = true;
messageShown = true;
}
};
var result = sut.Repeat();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Never);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Never);
Assert.IsTrue(messageShown);
Assert.AreEqual(OperationResult.Aborted, result);
}
[TestMethod]
public void Repeat_MustCorrectlyFallback()
{
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var messageShown = false;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, default(IEnumerable<Exam>)));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(false, default(Uri)));
sut.ActionRequired += (args) =>
{
if (args is ExamSelectionEventArgs e)
{
e.Success = true;
e.SelectedExam = exam;
}
if (args is ServerFailureEventArgs s)
{
s.Fallback = true;
messageShown = true;
}
};
var result = sut.Repeat();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Never);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Never);
Assert.IsTrue(messageShown);
Assert.AreEqual(SessionMode.Normal, context.Next.Settings.SessionMode);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Repeat_MustAutomaticallySelectExam()
{
var connection = new ConnectionInfo { Api = "some API", ConnectionToken = "some token", Oauth2Token = "some OAuth2 token" };
var exam = new Exam { Id = "some id", LmsName = "some LMS", Name = "some name", Url = "some URL" };
var examSettings = new AppSettings();
var serverSettings = context.Next.Settings.Server;
configuration.Setup(c => c.TryLoadSettings(It.IsAny<Uri>(), out examSettings, It.IsAny<PasswordParameters>())).Returns(LoadStatus.Success);
context.Next.Settings.SessionMode = SessionMode.Server;
context.Next.Settings.Server.ExamId = "some id";
fileSystem.Setup(f => f.Delete(It.IsAny<string>()));
server.Setup(s => s.Connect()).Returns(new ServerResponse(true));
server.Setup(s => s.Initialize(It.IsAny<ServerSettings>()));
server.Setup(s => s.GetConnectionInfo()).Returns(connection);
server.Setup(s => s.GetAvailableExams(It.IsAny<string>())).Returns(new ServerResponse<IEnumerable<Exam>>(true, new[] { exam }));
server.Setup(s => s.GetConfigurationFor(It.IsAny<Exam>())).Returns(new ServerResponse<Uri>(true, new Uri("file:///configuration.seb")));
sut.ActionRequired += (args) => Assert.Fail();
var result = sut.Repeat();
fileSystem.Verify(f => f.Delete(It.IsAny<string>()), Times.Once);
server.Verify(s => s.Connect(), Times.Once);
server.Verify(s => s.Initialize(It.IsAny<ServerSettings>()), Times.Once);
server.Verify(s => s.GetAvailableExams(It.IsAny<string>()), Times.Once);
server.Verify(s => s.GetConfigurationFor(It.Is<Exam>(e => e == exam)), Times.Once);
server.Verify(s => s.GetConnectionInfo(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Repeat_MustKeepExistingServerSession()
{
context.Current.AppConfig.ServerApi = "api";
context.Current.AppConfig.ServerConnectionToken = "token";
context.Current.AppConfig.ServerExamId = "id";
context.Current.AppConfig.ServerOauth2Token = "oauth2";
context.Current.Settings.SessionMode = SessionMode.Server;
context.Next.Settings.SessionMode = SessionMode.Server;
var result = sut.Repeat();
@ -289,19 +555,68 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
fileSystem.VerifyNoOtherCalls();
server.VerifyNoOtherCalls();
Assert.IsFalse(eventFired);
Assert.AreSame(settings, context.Next.Settings);
Assert.AreEqual(context.Current.AppConfig.ServerApi, context.Next.AppConfig.ServerApi);
Assert.AreEqual(context.Current.AppConfig.ServerConnectionToken, context.Next.AppConfig.ServerConnectionToken);
Assert.AreEqual(context.Current.AppConfig.ServerExamId, context.Next.AppConfig.ServerExamId);
Assert.AreEqual(context.Current.AppConfig.ServerOauth2Token, context.Next.AppConfig.ServerOauth2Token);
Assert.AreSame(context.Current.Settings.Server, context.Next.Settings.Server);
Assert.AreEqual(OperationResult.Success, result);
Assert.AreEqual(SessionMode.Server, context.Next.Settings.SessionMode);
}
[TestMethod]
public void Repeat_MustDoNothingIfNormalSession()
{
var initialSettings = context.Next.Settings;
context.Current.Settings.SessionMode = SessionMode.Normal;
context.Next.Settings.SessionMode = SessionMode.Normal;
sut.ActionRequired += (_) => Assert.Fail();
var result = sut.Repeat();
configuration.VerifyNoOtherCalls();
fileSystem.VerifyNoOtherCalls();
server.VerifyNoOtherCalls();
Assert.AreSame(initialSettings, context.Next.Settings);
Assert.AreEqual(SessionMode.Normal, context.Next.Settings.SessionMode);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Revert_MustDisconnectFromServer()
{
context.Current.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Disconnect()).Returns(new ServerResponse(true));
var result = sut.Revert();
fileSystem.VerifyNoOtherCalls();
server.Verify(s => s.Disconnect(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
[TestMethod]
public void Revert_MustFailWhenDisconnectionUnsuccesful()
{
context.Current.Settings.SessionMode = SessionMode.Server;
server.Setup(s => s.Disconnect()).Returns(new ServerResponse(false));
var result = sut.Revert();
fileSystem.VerifyNoOtherCalls();
server.Verify(s => s.Disconnect(), Times.Once);
Assert.AreEqual(OperationResult.Failed, result);
}
[TestMethod]
public void Revert_MustDoNothingIfNormalSession()
{
var eventFired = false;
context.Current.Settings.SessionMode = SessionMode.Normal;
sut.ActionRequired += (_) => eventFired = true;
sut.ActionRequired += (_) => Assert.Fail();
var result = sut.Revert();
@ -309,7 +624,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
fileSystem.VerifyNoOtherCalls();
server.VerifyNoOtherCalls();
Assert.IsFalse(eventFired);
Assert.AreEqual(OperationResult.Success, result);
}
}

View file

@ -7,6 +7,8 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Communication.Contracts.Data;
@ -19,6 +21,7 @@ using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Operations.Events;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings;
using SafeExamBrowser.Settings.Security;
using SafeExamBrowser.Settings.Service;
@ -216,6 +219,57 @@ namespace SafeExamBrowser.Runtime.UnitTests
Assert.IsTrue(args.AbortStartup);
}
[TestMethod]
public void Operations_MustRequestServerExamSelectionViaDialogOnDefaultDesktop()
{
var args = new ExamSelectionEventArgs(Enumerable.Empty<Exam>());
var examSelectionDialog = new Mock<IExamSelectionDialog>();
var result = new ExamSelectionDialogResult { SelectedExam = new Exam(), Success = true };
currentSettings.Security.KioskMode = KioskMode.DisableExplorerShell;
examSelectionDialog.Setup(p => p.Show(It.IsAny<IWindow>())).Returns(result);
uiFactory.Setup(u => u.CreateExamSelectionDialog(It.IsAny<IEnumerable<Exam>>())).Returns(examSelectionDialog.Object);
sut.TryStart();
sessionSequence.Raise(s => s.ActionRequired += null, args);
clientProxy.VerifyNoOtherCalls();
examSelectionDialog.Verify(p => p.Show(It.IsAny<IWindow>()), Times.Once);
uiFactory.Verify(u => u.CreateExamSelectionDialog(It.IsAny<IEnumerable<Exam>>()), Times.Once);
Assert.AreEqual(true, args.Success);
Assert.AreEqual(result.SelectedExam, args.SelectedExam);
}
[TestMethod]
public void Operations_MustRequestServerExamSelectionViaClientOnNewDesktop()
{
var args = new ExamSelectionEventArgs(new[] { new Exam { Id = "abc1234" } });
var examSelectionReceived = new Action<IEnumerable<(string, string, string, string)>, Guid>((e, id) =>
{
runtimeHost.Raise(r => r.ExamSelectionReceived += null, new ExamSelectionReplyEventArgs
{
RequestId = id,
SelectedExamId = "abc1234",
Success = true
});
});
currentSettings.Security.KioskMode = KioskMode.CreateNewDesktop;
clientProxy
.Setup(c => c.RequestExamSelection(It.IsAny<IEnumerable<(string, string, string, string)>>(), It.IsAny<Guid>()))
.Returns(new CommunicationResult(true))
.Callback(examSelectionReceived);
sut.TryStart();
sessionSequence.Raise(s => s.ActionRequired += null, args);
clientProxy.Verify(c => c.RequestExamSelection(It.IsAny<IEnumerable<(string, string, string, string)>>(), It.IsAny<Guid>()), Times.Once);
uiFactory.Verify(u => u.CreateExamSelectionDialog(It.IsAny<IEnumerable<Exam>>()), Times.Never);
Assert.AreEqual("abc1234", args.SelectedExam.Id);
}
[TestMethod]
public void Operations_MustRequestPasswordViaDialogOnDefaultDesktop()
{
@ -244,7 +298,7 @@ namespace SafeExamBrowser.Runtime.UnitTests
var args = new PasswordRequiredEventArgs();
var passwordReceived = new Action<PasswordRequestPurpose, Guid>((p, id) =>
{
runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { RequestId = id, Success = true });
runtimeHost.Raise(r => r.PasswordReceived += null, new PasswordReplyEventArgs { Password = "test", RequestId = id, Success = true });
});
currentSettings.Security.KioskMode = KioskMode.CreateNewDesktop;
@ -255,6 +309,61 @@ namespace SafeExamBrowser.Runtime.UnitTests
clientProxy.Verify(c => c.RequestPassword(It.IsAny<PasswordRequestPurpose>(), It.IsAny<Guid>()), Times.Once);
uiFactory.Verify(u => u.CreatePasswordDialog(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
Assert.AreEqual("test", args.Password);
}
[TestMethod]
public void Operations_MustRequestServerFailureActionViaDialogOnDefaultDesktop()
{
var args = new ServerFailureEventArgs(default(string), default(bool));
var failureDialog = new Mock<IServerFailureDialog>();
var result = new ServerFailureDialogResult { Fallback = true, Success = true };
currentSettings.Security.KioskMode = KioskMode.DisableExplorerShell;
failureDialog.Setup(p => p.Show(It.IsAny<IWindow>())).Returns(result);
uiFactory.Setup(u => u.CreateServerFailureDialog(It.IsAny<string>(), It.IsAny<bool>())).Returns(failureDialog.Object);
sut.TryStart();
sessionSequence.Raise(s => s.ActionRequired += null, args);
clientProxy.VerifyNoOtherCalls();
failureDialog.Verify(p => p.Show(It.IsAny<IWindow>()), Times.Once);
uiFactory.Verify(u => u.CreateServerFailureDialog(It.IsAny<string>(), It.IsAny<bool>()), Times.Once);
Assert.AreEqual(result.Abort, args.Abort);
Assert.AreEqual(result.Fallback, args.Fallback);
Assert.AreEqual(result.Retry, args.Retry);
}
[TestMethod]
public void Operations_MustRequestServerFailureActionViaClientOnNewDesktop()
{
var args = new ServerFailureEventArgs(default(string), default(bool));
var failureActionReceived = new Action<string, bool, Guid>((m, f, id) =>
{
runtimeHost.Raise(r => r.ServerFailureActionReceived += null, new ServerFailureActionReplyEventArgs
{
RequestId = id,
Fallback = true
});
});
currentSettings.Security.KioskMode = KioskMode.CreateNewDesktop;
clientProxy
.Setup(c => c.RequestServerFailureAction(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<Guid>()))
.Returns(new CommunicationResult(true))
.Callback(failureActionReceived);
sut.TryStart();
sessionSequence.Raise(s => s.ActionRequired += null, args);
clientProxy.Verify(c => c.RequestServerFailureAction(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<Guid>()), Times.Once);
uiFactory.Verify(u => u.CreateServerFailureDialog(It.IsAny<string>(), It.IsAny<bool>()), Times.Never);
Assert.IsFalse(args.Abort);
Assert.IsTrue(args.Fallback);
Assert.IsFalse(args.Retry);
}
[TestMethod]
@ -383,6 +492,39 @@ namespace SafeExamBrowser.Runtime.UnitTests
runtimeWindow.Verify(s => s.UpdateStatus(It.Is<TextKey>(k => k == key), It.IsAny<bool>()), Times.Once);
}
[TestMethod]
public void Session_MustHideRuntimeWindowWhenUsingDisableExplorerShell()
{
currentSettings.Security.KioskMode = KioskMode.DisableExplorerShell;
StartSession();
runtimeWindow.Verify(w => w.Hide(), Times.AtLeastOnce);
runtimeWindow.Reset();
sessionSequence.Reset();
sessionSequence.Setup(b => b.TryRepeat()).Returns(OperationResult.Aborted);
runtimeHost.Raise(h => h.ReconfigurationRequested += null, new ReconfigurationEventArgs());
runtimeWindow.Verify(w => w.Hide(), Times.AtLeastOnce);
}
[TestMethod]
public void Session_MustShowMessageBoxOnFailure()
{
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);
sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed);
sessionContext.Current = null;
sut.TryStart();
messageBox.Verify(m => m.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>(), It.IsAny<IWindow>()), Times.AtLeastOnce);
StartSession();
messageBox.Reset();
sessionSequence.Reset();
sessionSequence.Setup(b => b.TryRepeat()).Returns(OperationResult.Failed);
runtimeHost.Raise(h => h.ReconfigurationRequested += null, new ReconfigurationEventArgs());
messageBox.Verify(m => m.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxAction>(), It.IsAny<MessageBoxIcon>(), It.IsAny<IWindow>()), Times.AtLeastOnce);
}
[TestMethod]
public void ServiceProxy_MustShutdownWhenConnectionLostAndMandatory()
{
@ -578,6 +720,47 @@ namespace SafeExamBrowser.Runtime.UnitTests
shutdown.Verify(s => s(), Times.Never);
}
[TestMethod]
public void Startup_MustUpdateProgressForBootstrapSequence()
{
var args = new ProgressChangedEventArgs
{
CurrentValue = 12,
IsIndeterminate = true,
MaxValue = 100,
Progress = true,
Regress = true
};
bootstrapSequence
.Setup(b => b.TryPerform())
.Returns(OperationResult.Success)
.Callback(() => { bootstrapSequence.Raise(s => s.ProgressChanged += null, args); });
var success = sut.TryStart();
splashScreen.Verify(s => s.SetValue(It.Is<int>(i => i == args.CurrentValue)), Times.Once);
splashScreen.Verify(s => s.SetIndeterminate(), Times.Once);
splashScreen.Verify(s => s.SetMaxValue(It.Is<int>(i => i == args.MaxValue)), Times.Once);
splashScreen.Verify(s => s.Progress(), Times.Once);
splashScreen.Verify(s => s.Regress(), Times.Once);
}
[TestMethod]
public void Startup_MustUpdateStatusForBootstrapSequence()
{
var key = TextKey.OperationStatus_InitializeBrowser;
bootstrapSequence
.Setup(b => b.TryPerform())
.Returns(OperationResult.Success)
.Callback(() => { bootstrapSequence.Raise(s => s.StatusChanged += null, key); });
var success = sut.TryStart();
splashScreen.Verify(s => s.UpdateStatus(It.Is<TextKey>(k => k == key), true), Times.Once);
}
private void StartSession()
{
bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success);

View file

@ -108,23 +108,20 @@ namespace SafeExamBrowser.Runtime.Operations
}
}
}
else
{
logger.Info("The user aborted the exam selection.");
result = OperationResult.Aborted;
}
}
}
if (abort)
{
result = OperationResult.Aborted;
logger.Info("The user aborted the server operation.");
}
if (fallback)
{
Context.Next.Settings.SessionMode = SessionMode.Normal;
result = OperationResult.Success;
logger.Info("The user chose to fallback and start a normal session.");
}
}