Continued scaffolding:
- Implemented basic logging - Added basic settings - Moved contracts to separate assembly
This commit is contained in:
parent
e1032ad211
commit
f9723d2c9e
29 changed files with 635 additions and 73 deletions
15
SafeExamBrowser.Contracts/Configuration/ISettings.cs
Normal file
15
SafeExamBrowser.Contracts/Configuration/ISettings.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Configuration
|
||||
{
|
||||
public interface ISettings
|
||||
{
|
||||
string LogFolderPath { get; }
|
||||
}
|
||||
}
|
15
SafeExamBrowser.Contracts/I18n/IText.cs
Normal file
15
SafeExamBrowser.Contracts/I18n/IText.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.I18n
|
||||
{
|
||||
public interface IText
|
||||
{
|
||||
string Get(Key key);
|
||||
}
|
||||
}
|
|
@ -7,9 +7,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Core.I18n;
|
||||
|
||||
namespace SafeExamBrowser.Core.Contracts
|
||||
namespace SafeExamBrowser.Contracts.I18n
|
||||
{
|
||||
public interface ITextResource
|
||||
{
|
|
@ -6,11 +6,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Core.I18n
|
||||
namespace SafeExamBrowser.Contracts.I18n
|
||||
{
|
||||
public enum Key
|
||||
{
|
||||
MessageBox_FatalErrorTitle,
|
||||
MessageBox_SingleInstance,
|
||||
MessageBox_SingleInstanceTitle
|
||||
}
|
|
@ -6,16 +6,14 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Core.I18n
|
||||
namespace SafeExamBrowser.Contracts.Logging
|
||||
{
|
||||
class NullTextResource : ITextResource
|
||||
public interface ILogMessage : ICloneable
|
||||
{
|
||||
public IDictionary<Key, string> LoadText()
|
||||
{
|
||||
return new Dictionary<Key, string>();
|
||||
}
|
||||
DateTime DateTime { get; }
|
||||
LogLevel Severity { get; }
|
||||
string Message { get; }
|
||||
}
|
||||
}
|
15
SafeExamBrowser.Contracts/Logging/ILogObserver.cs
Normal file
15
SafeExamBrowser.Contracts/Logging/ILogObserver.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Logging
|
||||
{
|
||||
public interface ILogObserver
|
||||
{
|
||||
void Notify(ILogMessage message);
|
||||
}
|
||||
}
|
22
SafeExamBrowser.Contracts/Logging/ILogger.cs
Normal file
22
SafeExamBrowser.Contracts/Logging/ILogger.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.Collections.Generic;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Warn(string message);
|
||||
void Error(string message);
|
||||
void Subscribe(ILogObserver observer);
|
||||
void Unsubscribe(ILogObserver observer);
|
||||
IList<ILogMessage> GetLog();
|
||||
}
|
||||
}
|
17
SafeExamBrowser.Contracts/Logging/LogLevel.cs
Normal file
17
SafeExamBrowser.Contracts/Logging/LogLevel.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Contracts.Logging
|
||||
{
|
||||
public enum LogLevel
|
||||
{
|
||||
Info = 1,
|
||||
Warn = 2,
|
||||
Error = 3
|
||||
}
|
||||
}
|
36
SafeExamBrowser.Contracts/Properties/AssemblyInfo.cs
Normal file
36
SafeExamBrowser.Contracts/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SafeExamBrowser.Contracts")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SafeExamBrowser.Contracts")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("47da5933-bef8-4729-94e6-abde2db12262")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
55
SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
Normal file
55
SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SafeExamBrowser.Contracts</RootNamespace>
|
||||
<AssemblyName>SafeExamBrowser.Contracts</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Configuration\ISettings.cs" />
|
||||
<Compile Include="I18n\IText.cs" />
|
||||
<Compile Include="I18n\Key.cs" />
|
||||
<Compile Include="Logging\ILogger.cs" />
|
||||
<Compile Include="Logging\ILogMessage.cs" />
|
||||
<Compile Include="Logging\ILogObserver.cs" />
|
||||
<Compile Include="Logging\LogLevel.cs" />
|
||||
<Compile Include="UserInterface\ITaskbar.cs" />
|
||||
<Compile Include="I18n\ITextResource.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -6,7 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
namespace SafeExamBrowser.Core.Contracts
|
||||
namespace SafeExamBrowser.Contracts.UserInterface
|
||||
{
|
||||
public interface ITaskbar
|
||||
{
|
|
@ -7,35 +7,30 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Core.I18n;
|
||||
|
||||
namespace SafeExamBrowser.Core.UnitTests
|
||||
namespace SafeExamBrowser.Core.UnitTests.I18n
|
||||
{
|
||||
[TestClass]
|
||||
public class TextTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void MustNeverBeNull()
|
||||
{
|
||||
Assert.IsNotNull(Text.Instance);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNeverReturnNull()
|
||||
{
|
||||
var text = Text.Instance.Get((Key) (-1));
|
||||
var resource = new Mock<ITextResource>();
|
||||
var sut = new Text(resource.Object);
|
||||
|
||||
resource.Setup(r => r.LoadText()).Returns<IDictionary<Key, string>>(null);
|
||||
|
||||
var text = sut.Get((Key)(-1));
|
||||
|
||||
Assert.IsNotNull(text);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void MustNotAllowBeingNull()
|
||||
{
|
||||
Text.Instance = null;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void MustNotAllowNullResource()
|
||||
|
|
152
SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs
Normal file
152
SafeExamBrowser.Core.UnitTests/Logging/LoggerTests.cs
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Core.Logging;
|
||||
|
||||
namespace SafeExamBrowser.Core.UnitTests.Logging
|
||||
{
|
||||
[TestClass]
|
||||
public class LoggerTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void MustAddMessagesToLog()
|
||||
{
|
||||
var sut = new Logger();
|
||||
var info = "I'm an info message";
|
||||
var warn = "I'm a warning!";
|
||||
var error = "I AM AN ERROR!!";
|
||||
|
||||
sut.Info(info);
|
||||
sut.Warn(warn);
|
||||
sut.Error(error);
|
||||
|
||||
var log = sut.GetLog();
|
||||
|
||||
Assert.IsTrue(log.Count == 3);
|
||||
|
||||
Assert.IsTrue(info.Equals(log[0].Message));
|
||||
Assert.IsTrue(log[0].Severity == LogLevel.Info);
|
||||
|
||||
Assert.IsTrue(warn.Equals(log[1].Message));
|
||||
Assert.IsTrue(log[1].Severity == LogLevel.Warn);
|
||||
|
||||
Assert.IsTrue(error.Equals(log[2].Message));
|
||||
Assert.IsTrue(log[2].Severity == LogLevel.Error);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustReturnCopyOfLog()
|
||||
{
|
||||
var sut = new Logger();
|
||||
var info = "I'm an info message";
|
||||
var warn = "I'm a warning!";
|
||||
var error = "I AM AN ERROR!!";
|
||||
|
||||
sut.Info(info);
|
||||
sut.Warn(warn);
|
||||
sut.Error(error);
|
||||
|
||||
var log1 = sut.GetLog();
|
||||
var log2 = sut.GetLog();
|
||||
|
||||
Assert.AreNotSame(log1, log2);
|
||||
|
||||
foreach (var message in log1)
|
||||
{
|
||||
Assert.AreNotSame(message, log2[log1.IndexOf(message)]);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void MustNotAllowNullObserver()
|
||||
{
|
||||
var sut = new Logger();
|
||||
|
||||
sut.Subscribe(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotSubscribeSameObserverMultipleTimes()
|
||||
{
|
||||
var sut = new Logger();
|
||||
var observer = new Mock<ILogObserver>();
|
||||
|
||||
observer.Setup(o => o.Notify(It.IsAny<ILogMessage>()));
|
||||
|
||||
sut.Subscribe(observer.Object);
|
||||
sut.Subscribe(observer.Object);
|
||||
sut.Subscribe(observer.Object);
|
||||
|
||||
sut.Info("Blubb");
|
||||
|
||||
observer.Verify(o => o.Notify(It.IsAny<ILogMessage>()), Times.Once());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustNotFailWhenRemovingNullObserver()
|
||||
{
|
||||
var sut = new Logger();
|
||||
|
||||
sut.Unsubscribe(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustSubscribeObserver()
|
||||
{
|
||||
var sut = new Logger();
|
||||
var observer = new Mock<ILogObserver>();
|
||||
var message = "Blubb";
|
||||
var messages = new List<ILogMessage>();
|
||||
|
||||
observer.Setup(o => o.Notify(It.IsAny<ILogMessage>())).Callback<ILogMessage>(m => messages.Add(m));
|
||||
|
||||
sut.Subscribe(observer.Object);
|
||||
sut.Info(message);
|
||||
sut.Warn(message);
|
||||
|
||||
observer.Verify(o => o.Notify(It.IsAny<ILogMessage>()), Times.Exactly(2));
|
||||
|
||||
Assert.IsTrue(messages.Count == 2);
|
||||
|
||||
Assert.IsTrue(messages[0].Severity == LogLevel.Info);
|
||||
Assert.IsTrue(message.Equals(messages[0].Message));
|
||||
|
||||
Assert.IsTrue(messages[1].Severity == LogLevel.Warn);
|
||||
Assert.IsTrue(message.Equals(messages[1].Message));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MustUnsubscribeObserver()
|
||||
{
|
||||
var sut = new Logger();
|
||||
var observer = new Mock<ILogObserver>();
|
||||
var message = "Blubb";
|
||||
var messages = new List<ILogMessage>();
|
||||
|
||||
observer.Setup(o => o.Notify(It.IsAny<ILogMessage>())).Callback<ILogMessage>(m => messages.Add(m));
|
||||
|
||||
sut.Subscribe(observer.Object);
|
||||
sut.Info(message);
|
||||
sut.Unsubscribe(observer.Object);
|
||||
sut.Warn(message);
|
||||
|
||||
observer.Verify(o => o.Notify(It.IsAny<ILogMessage>()), Times.Once());
|
||||
|
||||
Assert.IsTrue(messages.Count == 1);
|
||||
|
||||
Assert.IsTrue(messages[0].Severity == LogLevel.Info);
|
||||
Assert.IsTrue(message.Equals(messages[0].Message));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,28 +38,39 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Castle.Core, Version=4.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Castle.Core.4.1.0\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.7.63.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.7.63\lib\net45\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="I18n\TextTests.cs" />
|
||||
<Compile Include="Logging\LoggerTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
|
||||
<Project>{3d6fdbb6-a4af-4626-bb2b-bf329d44f9cc}</Project>
|
||||
<Name>SafeExamBrowser.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</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">
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Castle.Core" version="4.1.0" targetFramework="net452" />
|
||||
<package id="Moq" version="4.7.63" targetFramework="net452" />
|
||||
<package id="MSTest.TestAdapter" version="1.1.11" targetFramework="net452" />
|
||||
<package id="MSTest.TestFramework" version="1.1.11" targetFramework="net452" />
|
||||
</packages>
|
25
SafeExamBrowser.Core/Configuration/Settings.cs
Normal file
25
SafeExamBrowser.Core/Configuration/Settings.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.IO;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
|
||||
namespace SafeExamBrowser.Core.Configuration
|
||||
{
|
||||
public class Settings : ISettings
|
||||
{
|
||||
public string LogFolderPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SafeExamBrowser", "Logs");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,16 +8,13 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
|
||||
namespace SafeExamBrowser.Core.I18n
|
||||
{
|
||||
public class Text
|
||||
public class Text : IText
|
||||
{
|
||||
private static Text instance;
|
||||
private static readonly object @lock = new object();
|
||||
|
||||
private IDictionary<Key, string> cache = new Dictionary<Key, string>();
|
||||
private readonly IDictionary<Key, string> cache;
|
||||
|
||||
public Text(ITextResource resource)
|
||||
{
|
||||
|
@ -26,25 +23,7 @@ namespace SafeExamBrowser.Core.I18n
|
|||
throw new ArgumentNullException(nameof(resource));
|
||||
}
|
||||
|
||||
cache = resource.LoadText();
|
||||
}
|
||||
|
||||
public static Text Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
return instance ?? new Text(new NullTextResource());
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
instance = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
}
|
||||
cache = resource.LoadText() ?? new Dictionary<Key, string>();
|
||||
}
|
||||
|
||||
public string Get(Key key)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Text>
|
||||
<MessageBox_FatalErrorTitle>Fatal Error</MessageBox_FatalErrorTitle>
|
||||
<MessageBox_SingleInstance>You can only run one instance of SEB at a time.</MessageBox_SingleInstance>
|
||||
<MessageBox_SingleInstanceTitle>Startup Not Allowed</MessageBox_SingleInstanceTitle>
|
||||
</Text>
|
|
@ -11,7 +11,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
|
||||
namespace SafeExamBrowser.Core.I18n
|
||||
{
|
||||
|
|
50
SafeExamBrowser.Core/Logging/LogFileWriter.cs
Normal file
50
SafeExamBrowser.Core/Logging/LogFileWriter.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
|
||||
namespace SafeExamBrowser.Core.Logging
|
||||
{
|
||||
public class LogFileWriter : ILogObserver
|
||||
{
|
||||
private static readonly object @lock = new object();
|
||||
private readonly string filePath;
|
||||
|
||||
public LogFileWriter(ISettings settings)
|
||||
{
|
||||
var fileName = $"{DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss")}.txt";
|
||||
|
||||
if (!Directory.Exists(settings.LogFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(settings.LogFolderPath);
|
||||
}
|
||||
|
||||
filePath = Path.Combine(settings.LogFolderPath, fileName);
|
||||
}
|
||||
|
||||
public void Notify(ILogMessage message)
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
using (var stream = new StreamWriter(filePath, true, Encoding.UTF8))
|
||||
{
|
||||
var date = message.DateTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
var threadId = Thread.CurrentThread.ManagedThreadId;
|
||||
var severity = message.Severity.ToString().ToUpper();
|
||||
|
||||
stream.WriteLine($"{date} [{threadId}] - {severity}: {message.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
SafeExamBrowser.Core/Logging/LogMessage.cs
Normal file
32
SafeExamBrowser.Core/Logging/LogMessage.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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 SafeExamBrowser.Contracts.Logging;
|
||||
|
||||
namespace SafeExamBrowser.Core.Entities
|
||||
{
|
||||
public class LogMessage : ILogMessage
|
||||
{
|
||||
public DateTime DateTime { get; private set; }
|
||||
public LogLevel Severity { get; private set; }
|
||||
public string Message { get; private set; }
|
||||
|
||||
public LogMessage(DateTime dateTime, LogLevel severity, string message)
|
||||
{
|
||||
DateTime = dateTime;
|
||||
Severity = severity;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new LogMessage(DateTime, Severity, Message);
|
||||
}
|
||||
}
|
||||
}
|
85
SafeExamBrowser.Core/Logging/Logger.cs
Normal file
85
SafeExamBrowser.Core/Logging/Logger.cs
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2017 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Core.Entities;
|
||||
|
||||
namespace SafeExamBrowser.Core.Logging
|
||||
{
|
||||
public class Logger : ILogger
|
||||
{
|
||||
private static readonly object @lock = new object();
|
||||
private readonly IList<ILogMessage> log = new List<ILogMessage>();
|
||||
private readonly IList<ILogObserver> observers = new List<ILogObserver>();
|
||||
|
||||
public void Error(string message)
|
||||
{
|
||||
Log(LogLevel.Error, message);
|
||||
}
|
||||
|
||||
public void Info(string message)
|
||||
{
|
||||
Log(LogLevel.Info, message);
|
||||
}
|
||||
|
||||
public void Warn(string message)
|
||||
{
|
||||
Log(LogLevel.Warn, message);
|
||||
}
|
||||
|
||||
public IList<ILogMessage> GetLog()
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
return log.Select(m => m.Clone() as ILogMessage).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public void Subscribe(ILogObserver observer)
|
||||
{
|
||||
if (observer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(observer));
|
||||
}
|
||||
|
||||
lock (@lock)
|
||||
{
|
||||
if (!observers.Contains(observer))
|
||||
{
|
||||
observers.Add(observer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Unsubscribe(ILogObserver observer)
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
observers.Remove(observer);
|
||||
}
|
||||
}
|
||||
|
||||
private void Log(LogLevel severity, string message)
|
||||
{
|
||||
lock (@lock)
|
||||
{
|
||||
var entry = new LogMessage(DateTime.Now, severity, message);
|
||||
|
||||
log.Add(entry);
|
||||
|
||||
foreach (var observer in observers)
|
||||
{
|
||||
observer.Notify(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,18 +40,26 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Contracts\ITextResource.cs" />
|
||||
<Compile Include="Contracts\ITaskbar.cs" />
|
||||
<Compile Include="I18n\Key.cs" />
|
||||
<Compile Include="I18n\NullTextResource.cs" />
|
||||
<Compile Include="Configuration\Settings.cs" />
|
||||
<Compile Include="Logging\LogFileWriter.cs" />
|
||||
<Compile Include="Logging\LogMessage.cs" />
|
||||
<Compile Include="I18n\Text.cs" />
|
||||
<Compile Include="I18n\XmlTextResource.cs" />
|
||||
<Compile Include="Logging\Logger.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="I18n\Text.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -79,9 +79,9 @@
|
|||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
|
||||
<Project>{3d6fdbb6-a4af-4626-bb2b-bf329d44f9cc}</Project>
|
||||
<Name>SafeExamBrowser.Core</Name>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeExamBrowser.UserInterfa
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeExamBrowser.Core.UnitTests", "SafeExamBrowser.Core.UnitTests\SafeExamBrowser.Core.UnitTests.csproj", "{48B9F2A1-B87D-40F0-BEC9-399E8909860F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SafeExamBrowser.Contracts", "SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj", "{47DA5933-BEF8-4729-94E6-ABDE2DB12262}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -39,6 +41,10 @@ Global
|
|||
{48B9F2A1-B87D-40F0-BEC9-399E8909860F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48B9F2A1-B87D-40F0-BEC9-399E8909860F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{48B9F2A1-B87D-40F0-BEC9-399E8909860F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{47DA5933-BEF8-4729-94E6-ABDE2DB12262}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{47DA5933-BEF8-4729-94E6-ABDE2DB12262}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47DA5933-BEF8-4729-94E6-ABDE2DB12262}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{47DA5933-BEF8-4729-94E6-ABDE2DB12262}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Core.I18n;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
|
||||
namespace SafeExamBrowser
|
||||
{
|
||||
|
@ -27,23 +27,28 @@ namespace SafeExamBrowser
|
|||
compositionRoot.InitializeGlobalModules();
|
||||
compositionRoot.BuildObjectGraph();
|
||||
|
||||
StartApplication(compositionRoot.Taskbar);
|
||||
StartApplication(compositionRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show(e.Message + "\n\n" + e.StackTrace, Text.Instance.Get(Key.MessageBox_FatalErrorTitle));
|
||||
MessageBox.Show(e.Message + "\n\n" + e.StackTrace, "Fatal Error");
|
||||
}
|
||||
}
|
||||
|
||||
private static void StartApplication(Window taskbar)
|
||||
private static void StartApplication(CompositionRoot compositionRoot)
|
||||
{
|
||||
compositionRoot.Logger.Info("Testing the log...");
|
||||
|
||||
if (NoInstanceRunning())
|
||||
{
|
||||
new App().Run(taskbar);
|
||||
new App().Run(compositionRoot.Taskbar);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Text.Instance.Get(Key.MessageBox_SingleInstance), Text.Instance.Get(Key.MessageBox_SingleInstanceTitle));
|
||||
var message = compositionRoot.Text.Get(Key.MessageBox_SingleInstance);
|
||||
var title = compositionRoot.Text.Get(Key.MessageBox_SingleInstanceTitle);
|
||||
|
||||
MessageBox.Show(message, title);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,29 @@
|
|||
*/
|
||||
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Core.Configuration;
|
||||
using SafeExamBrowser.Core.I18n;
|
||||
using SafeExamBrowser.Core.Logging;
|
||||
using SafeExamBrowser.UserInterface;
|
||||
|
||||
namespace SafeExamBrowser
|
||||
{
|
||||
class CompositionRoot
|
||||
{
|
||||
public ILogger Logger { get; private set; }
|
||||
public ISettings Settings { get; private set; }
|
||||
public IText Text { get; private set; }
|
||||
public Window Taskbar { get; private set; }
|
||||
|
||||
public void InitializeGlobalModules()
|
||||
{
|
||||
Text.Instance = new Text(new XmlTextResource());
|
||||
Settings = new Settings();
|
||||
Logger = new Logger();
|
||||
Logger.Subscribe(new LogFileWriter(Settings));
|
||||
Text = new Text(new XmlTextResource());
|
||||
}
|
||||
|
||||
public void BuildObjectGraph()
|
||||
|
|
|
@ -13,6 +13,21 @@
|
|||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>3.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
@ -78,6 +93,10 @@
|
|||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47DA5933-BEF8-4729-94E6-ABDE2DB12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Core\SafeExamBrowser.Core.csproj">
|
||||
<Project>{3d6fdbb6-a4af-4626-bb2b-bf329d44f9cc}</Project>
|
||||
<Name>SafeExamBrowser.Core</Name>
|
||||
|
@ -87,5 +106,17 @@
|
|||
<Name>SafeExamBrowser.UserInterface</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Loading…
Reference in a new issue