1010using System . Collections . Generic ;
1111using Microsoft . VisualStudio . TestTools . UnitTesting ;
1212using Moq ;
13+ using SafeExamBrowser . Communication . Contracts . Events ;
1314using SafeExamBrowser . Communication . Contracts . Hosts ;
15+ using SafeExamBrowser . Communication . Contracts . Proxies ;
1416using SafeExamBrowser . Configuration . Contracts ;
1517using SafeExamBrowser . Configuration . Contracts . Cryptography ;
1618using SafeExamBrowser . Core . Contracts . OperationModel ;
2123using SafeExamBrowser . Server . Contracts ;
2224using SafeExamBrowser . Server . Contracts . Data ;
2325using SafeExamBrowser . Settings ;
26+ using SafeExamBrowser . Settings . Security ;
2427using SafeExamBrowser . Settings . Server ;
2528using SafeExamBrowser . SystemComponents . Contracts ;
2629using SafeExamBrowser . UserInterface . Contracts ;
@@ -33,9 +36,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations.Session
3336 [ TestClass ]
3437 public class ServerOperationTests
3538 {
39+ private Mock < ClientBridge > clientBridge ;
40+ private Mock < IClientProxy > clientProxy ;
3641 private RuntimeContext context ;
3742 private Mock < IFileSystem > fileSystem ;
3843 private Mock < IConfigurationRepository > repository ;
44+ private Mock < IRuntimeHost > runtimeHost ;
3945 private Mock < IServerProxy > server ;
4046 private Mock < IUserInterfaceFactory > uiFactory ;
4147
@@ -45,11 +51,15 @@ public class ServerOperationTests
4551 public void Initialize ( )
4652 {
4753 context = new RuntimeContext ( ) ;
54+ clientProxy = new Mock < IClientProxy > ( ) ;
4855 fileSystem = new Mock < IFileSystem > ( ) ;
4956 repository = new Mock < IConfigurationRepository > ( ) ;
57+ runtimeHost = new Mock < IRuntimeHost > ( ) ;
5058 server = new Mock < IServerProxy > ( ) ;
5159 uiFactory = new Mock < IUserInterfaceFactory > ( ) ;
60+ clientBridge = new Mock < ClientBridge > ( runtimeHost . Object , context ) ;
5261
62+ context . ClientProxy = clientProxy . Object ;
5363 context . Current = new SessionConfiguration ( ) ;
5464 context . Current . AppConfig = new AppConfig ( ) ;
5565 context . Current . Settings = new AppSettings ( ) ;
@@ -58,7 +68,7 @@ public void Initialize()
5868 context . Next . Settings = new AppSettings ( ) ;
5969
6070 var dependencies = new Dependencies (
61- new ClientBridge ( Mock . Of < IRuntimeHost > ( ) , context ) ,
71+ clientBridge . Object ,
6272 Mock . Of < ILogger > ( ) ,
6373 Mock . Of < IMessageBox > ( ) ,
6474 Mock . Of < IRuntimeWindow > ( ) ,
@@ -178,7 +188,7 @@ public void Perform_MustFailIfSettingsCouldNotBeLoaded()
178188 }
179189
180190 [ TestMethod ]
181- public void Perform_MustCorrectlyAbort ( )
191+ public void Perform_MustCorrectlyAbortWithReturnValue ( )
182192 {
183193 var connection = new ConnectionInfo { Api = "some API" , ConnectionToken = "some token" , Oauth2Token = "some OAuth2 token" } ;
184194 var exam = new Exam { Id = "some id" , LmsName = "some LMS" , Name = "some name" , Url = "some URL" } ;
@@ -215,6 +225,33 @@ public void Perform_MustCorrectlyAbort()
215225 Assert . AreEqual ( OperationResult . Aborted , result ) ;
216226 }
217227
228+ [ TestMethod ]
229+ public void Perform_MustCorrectlyAbortWithoutReturnValue ( )
230+ {
231+ var messageShown = false ;
232+ var serverDialog = new Mock < IServerFailureDialog > ( ) ;
233+
234+ context . Next . Settings . SessionMode = SessionMode . Server ;
235+ server . Setup ( s => s . Connect ( ) ) . Returns ( new ServerResponse ( false ) ) ;
236+ serverDialog
237+ . Setup ( d => d . Show ( It . IsAny < IWindow > ( ) ) )
238+ . Returns ( new ServerFailureDialogResult { Abort = true } )
239+ . Callback ( ( ) => messageShown = true ) ;
240+ uiFactory . Setup ( f => f . CreateServerFailureDialog ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) ) ) . Returns ( serverDialog . Object ) ;
241+
242+ var result = sut . Perform ( ) ;
243+
244+ fileSystem . Verify ( f => f . Delete ( It . IsAny < string > ( ) ) , Times . Never ) ;
245+ server . Verify ( s => s . Connect ( ) , Times . Once ) ;
246+ server . Verify ( s => s . Initialize ( It . IsAny < ServerSettings > ( ) ) , Times . Once ) ;
247+ server . Verify ( s => s . GetAvailableExams ( It . IsAny < string > ( ) ) , Times . Never ) ;
248+ server . Verify ( s => s . GetConfigurationFor ( It . IsAny < Exam > ( ) ) , Times . Never ) ;
249+ server . Verify ( s => s . GetConnectionInfo ( ) , Times . Never ) ;
250+
251+ Assert . IsTrue ( messageShown ) ;
252+ Assert . AreEqual ( OperationResult . Aborted , result ) ;
253+ }
254+
218255 [ TestMethod ]
219256 public void Perform_MustCorrectlyFallback ( )
220257 {
@@ -254,6 +291,47 @@ public void Perform_MustCorrectlyFallback()
254291 Assert . AreEqual ( OperationResult . Success , result ) ;
255292 }
256293
294+ [ TestMethod ]
295+ public void Perform_MustCorrectlyRetry ( )
296+ {
297+ const int RETRIES = 5 ;
298+
299+ var connection = new ConnectionInfo { Api = "some API" , ConnectionToken = "some token" , Oauth2Token = "some OAuth2 token" } ;
300+ var count = 0 ;
301+ var exam = new Exam { Id = "some id" , LmsName = "some LMS" , Name = "some name" , Url = "some URL" } ;
302+ var examDialog = new Mock < IExamSelectionDialog > ( ) ;
303+ var examSettings = new AppSettings ( ) ;
304+ var messageShown = false ;
305+ var serverDialog = new Mock < IServerFailureDialog > ( ) ;
306+
307+ examDialog . Setup ( d => d . Show ( It . IsAny < IWindow > ( ) ) ) . Returns ( new ExamSelectionDialogResult { SelectedExam = exam , Success = true } ) ;
308+ repository . Setup ( c => c . TryLoadSettings ( It . IsAny < Uri > ( ) , out examSettings , It . IsAny < PasswordParameters > ( ) ) ) . Returns ( LoadStatus . Success ) ;
309+ context . Next . Settings . SessionMode = SessionMode . Server ;
310+ server . Setup ( s => s . Connect ( ) ) . Returns ( new ServerResponse ( true ) ) ;
311+ server . Setup ( s => s . Initialize ( It . IsAny < ServerSettings > ( ) ) ) ;
312+ server . Setup ( s => s . GetConnectionInfo ( ) ) . Returns ( connection ) ;
313+ server . Setup ( s => s . GetAvailableExams ( It . IsAny < string > ( ) ) ) . Returns ( new ServerResponse < IEnumerable < Exam > > ( true , default ) ) ;
314+ server . Setup ( s => s . GetConfigurationFor ( It . IsAny < Exam > ( ) ) ) . Returns ( new ServerResponse < Uri > ( false , default ) ) ;
315+ serverDialog
316+ . Setup ( d => d . Show ( It . IsAny < IWindow > ( ) ) )
317+ . Returns ( ( ) => new ServerFailureDialogResult { Retry = ++ count < RETRIES } )
318+ . Callback ( ( ) => messageShown = true ) ;
319+ uiFactory . Setup ( f => f . CreateExamSelectionDialog ( It . IsAny < IEnumerable < Exam > > ( ) ) ) . Returns ( examDialog . Object ) ;
320+ uiFactory . Setup ( f => f . CreateServerFailureDialog ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) ) ) . Returns ( serverDialog . Object ) ;
321+
322+ var result = sut . Perform ( ) ;
323+
324+ fileSystem . Verify ( f => f . Delete ( It . IsAny < string > ( ) ) , Times . Never ) ;
325+ server . Verify ( s => s . Connect ( ) , Times . Once ) ;
326+ server . Verify ( s => s . Initialize ( It . IsAny < ServerSettings > ( ) ) , Times . Once ) ;
327+ server . Verify ( s => s . GetAvailableExams ( It . IsAny < string > ( ) ) , Times . Once ) ;
328+ server . Verify ( s => s . GetConfigurationFor ( It . Is < Exam > ( e => e == exam ) ) , Times . Exactly ( RETRIES ) ) ;
329+ server . Verify ( s => s . GetConnectionInfo ( ) , Times . Never ) ;
330+
331+ Assert . IsTrue ( messageShown ) ;
332+ Assert . AreEqual ( OperationResult . Aborted , result ) ;
333+ }
334+
257335 [ TestMethod ]
258336 public void Perform_MustAutomaticallySelectExam ( )
259337 {
@@ -341,7 +419,74 @@ public void Perform_MustSetCustomBrowserExamKey()
341419
342420 Assert . AreEqual ( browserExamKey , context . Next . Settings . Browser . CustomBrowserExamKey ) ;
343421 Assert . AreEqual ( OperationResult . Success , result ) ;
422+ }
423+
424+ [ TestMethod ]
425+ public void Perform_MustUseClientBridgeForExamSelectionIfRequired ( )
426+ {
427+ var connection = new ConnectionInfo { Api = "some API" , ConnectionToken = "some token" , Oauth2Token = "some OAuth2 token" } ;
428+ var examSettings = new AppSettings ( ) ;
429+
430+ clientProxy
431+ . Setup ( p => p . RequestExamSelection ( It . IsAny < IEnumerable < ( string , string , string , string ) > > ( ) , It . IsAny < Guid > ( ) ) )
432+ . Returns ( new CommunicationResult ( true ) )
433+ . Callback < IEnumerable < ( string , string , string , string ) > , Guid > ( ( exams , id ) =>
434+ {
435+ runtimeHost . Raise ( r => r . ExamSelectionReceived += default , new ExamSelectionReplyEventArgs ( ) { RequestId = id , Success = true } ) ;
436+ } ) ;
437+ context . Current . Settings . Security . KioskMode = KioskMode . CreateNewDesktop ;
438+ context . Next . Settings . SessionMode = SessionMode . Server ;
439+ repository . Setup ( c => c . TryLoadSettings ( It . IsAny < Uri > ( ) , out examSettings , It . IsAny < PasswordParameters > ( ) ) ) . Returns ( LoadStatus . Success ) ;
440+ server . Setup ( s => s . Connect ( ) ) . Returns ( new ServerResponse ( true ) ) ;
441+ server . Setup ( s => s . Initialize ( It . IsAny < ServerSettings > ( ) ) ) ;
442+ server . Setup ( s => s . GetConnectionInfo ( ) ) . Returns ( connection ) ;
443+ server . Setup ( s => s . GetAvailableExams ( It . IsAny < string > ( ) ) ) . Returns ( new ServerResponse < IEnumerable < Exam > > ( true , new [ ] { new Exam ( ) } ) ) ;
444+ server . Setup ( s => s . GetConfigurationFor ( It . IsAny < Exam > ( ) ) ) . Returns ( new ServerResponse < Uri > ( true , new Uri ( "file:///configuration.seb" ) ) ) ;
445+ server . Setup ( s => s . SendSelectedExam ( It . IsAny < Exam > ( ) ) ) . Returns ( new ServerResponse < string > ( true , default ) ) ;
446+
447+ var result = sut . Perform ( ) ;
448+
449+ clientProxy . Verify ( p => p . RequestExamSelection ( It . IsAny < IEnumerable < ( string , string , string , string ) > > ( ) , It . IsAny < Guid > ( ) ) , Times . Once ) ;
450+ uiFactory . VerifyNoOtherCalls ( ) ;
344451
452+ Assert . AreEqual ( OperationResult . Success , result ) ;
453+ }
454+
455+ [ TestMethod ]
456+ public void Perform_MustUseClientBridgeForFailureActionIfRequired ( )
457+ {
458+ var connection = new ConnectionInfo { Api = "some API" , ConnectionToken = "some token" , Oauth2Token = "some OAuth2 token" } ;
459+ var examSettings = new AppSettings ( ) ;
460+
461+ clientProxy
462+ . Setup ( p => p . RequestExamSelection ( It . IsAny < IEnumerable < ( string , string , string , string ) > > ( ) , It . IsAny < Guid > ( ) ) )
463+ . Returns ( new CommunicationResult ( true ) )
464+ . Callback < IEnumerable < ( string , string , string , string ) > , Guid > ( ( exams , id ) =>
465+ {
466+ runtimeHost . Raise ( r => r . ExamSelectionReceived += default , new ExamSelectionReplyEventArgs ( ) { RequestId = id , Success = true } ) ;
467+ } ) ;
468+ clientProxy
469+ . Setup ( p => p . RequestServerFailureAction ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) , It . IsAny < Guid > ( ) ) )
470+ . Returns ( new CommunicationResult ( true ) )
471+ . Callback < string , bool , Guid > ( ( m , f , id ) =>
472+ {
473+ runtimeHost . Raise ( r => r . ServerFailureActionReceived += default , new ServerFailureActionReplyEventArgs ( ) { RequestId = id , Fallback = true } ) ;
474+ } ) ;
475+ context . Current . Settings . Security . KioskMode = KioskMode . CreateNewDesktop ;
476+ context . Next . Settings . SessionMode = SessionMode . Server ;
477+ repository . Setup ( c => c . TryLoadSettings ( It . IsAny < Uri > ( ) , out examSettings , It . IsAny < PasswordParameters > ( ) ) ) . Returns ( LoadStatus . Success ) ;
478+ server . Setup ( s => s . Connect ( ) ) . Returns ( new ServerResponse ( true ) ) ;
479+ server . Setup ( s => s . Initialize ( It . IsAny < ServerSettings > ( ) ) ) ;
480+ server . Setup ( s => s . GetConnectionInfo ( ) ) . Returns ( connection ) ;
481+ server . Setup ( s => s . GetAvailableExams ( It . IsAny < string > ( ) ) ) . Returns ( new ServerResponse < IEnumerable < Exam > > ( true , new [ ] { new Exam ( ) } ) ) ;
482+ server . Setup ( s => s . GetConfigurationFor ( It . IsAny < Exam > ( ) ) ) . Returns ( new ServerResponse < Uri > ( false , default ) ) ;
483+
484+ var result = sut . Perform ( ) ;
485+
486+ clientProxy . Verify ( p => p . RequestServerFailureAction ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) , It . IsAny < Guid > ( ) ) , Times . Once ) ;
487+ uiFactory . VerifyNoOtherCalls ( ) ;
488+
489+ Assert . AreEqual ( OperationResult . Success , result ) ;
345490 }
346491
347492 [ TestMethod ]
@@ -414,6 +559,21 @@ public void Repeat_MustCorrectlyInitializeServerSession()
414559 Assert . AreEqual ( SessionMode . Server , context . Next . Settings . SessionMode ) ;
415560 }
416561
562+ [ TestMethod ]
563+ public void Repeat_MustCorrectlyFinalizeServerSession ( )
564+ {
565+ context . Current . Settings . SessionMode = SessionMode . Server ;
566+ context . Next . Settings . SessionMode = SessionMode . Normal ;
567+ server . Setup ( s => s . Disconnect ( ) ) . Returns ( new ServerResponse ( true ) ) ;
568+
569+ var result = sut . Repeat ( ) ;
570+
571+ fileSystem . VerifyNoOtherCalls ( ) ;
572+ server . Verify ( s => s . Disconnect ( ) , Times . Once ) ;
573+
574+ Assert . AreEqual ( OperationResult . Success , result ) ;
575+ }
576+
417577 [ TestMethod ]
418578 public void Repeat_MustFailIfSettingsCouldNotBeLoaded ( )
419579 {
0 commit comments