Skip to content

Commit

Permalink
Autentification (#26)
Browse files Browse the repository at this point in the history
* Dahua Client support
* HTTPS improvements (add roles)
* Minor improvements
* ArchiveJob -> FilesCollectorJob
  • Loading branch information
vov4uk committed Jan 29, 2024
1 parent da019de commit 3036bf4
Show file tree
Hide file tree
Showing 100 changed files with 1,372 additions and 479 deletions.
4 changes: 0 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# NOTE: Requires **VS2019 16.3** or later

# Rules for Hik.Client
# Description: Code analysis rules for Hik.Client.csproj.

# Code files
[*.{cs,vb}]
Expand Down
357 changes: 357 additions & 0 deletions Tests/Hik.Client.Tests/DahuaVideoClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,357 @@
namespace Hik.Client.Tests
{
using AutoFixture;
using AutoMapper;
using Dahua.Api.Abstractions;
using Dahua.Api.Data;
using Hik.Client.Client;
using Hik.Client.Infrastructure;
using Hik.DTO.Config;
using Hik.DTO.Contracts;
using Hik.Helpers.Abstraction;
using Moq;
using Serilog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

public class DahuaVideoClientTests
{
private readonly Mock<IDahuaSDK> sdkMock;
private readonly Mock<IDahuaApi> apiMock;
private readonly Mock<IVideoService> videoServiceMock;
private readonly Mock<IConfigService> configServiceMock;
private readonly Mock<IFilesHelper> filesMock;
private readonly Mock<IDirectoryHelper> dirMock;
private readonly Mock<ILogger> loggerMock;
private readonly Fixture fixture;
private readonly IMapper mapper;

public DahuaVideoClientTests()
{
this.videoServiceMock = new (MockBehavior.Strict);
this.configServiceMock = new (MockBehavior.Strict);
this.loggerMock = new ();
this.sdkMock = new (MockBehavior.Strict);
this.apiMock = new(MockBehavior.Strict);
this.apiMock.SetupGet(x => x.VideoService)
.Returns(this.videoServiceMock.Object);
this.apiMock.SetupGet(x => x.ConfigService)
.Returns(this.configServiceMock.Object);

this.filesMock = new(MockBehavior.Strict);
this.dirMock = new(MockBehavior.Strict);
this.fixture = new();
Action<IMapperConfigurationExpression> configureAutoMapper = x =>
{
x.AddProfile<HikConsoleProfile>();
};

var mapperConfig = new MapperConfiguration(configureAutoMapper);
this.mapper = mapperConfig.CreateMapper();
}

[Fact]
public void Constructor_PutEmptyConfig_ThrowsException()
{
Assert.Throws<ArgumentNullException>(() => new DahuaVideoClient(null, this.sdkMock.Object, this.filesMock.Object, this.dirMock.Object, this.mapper, this.loggerMock.Object));
}

#region InitializeClient
[Fact]
public void InitializeClient_CallInitializeClient_ClientInitialized()
{
this.filesMock.Setup(x => x.CombinePath(It.IsAny<string[]>()))
.Returns(string.Empty);
this.dirMock.Setup(x => x.CreateDirIfNotExist(It.IsAny<string>()));
this.sdkMock.Setup(x => x.Initialize());

this.GetClient().InitializeClient();

this.sdkMock.Verify(x => x.Initialize(), Times.Once);
}

#endregion InitializeClient

#region Login
[Fact]
public void Login_CallLogin_LoginSuccessfully()
{
this.SetupLogin();
var client = this.GetClient();
bool loginResult = client.Login();

this.sdkMock.Verify(x => x.Login(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
Assert.True(loginResult);
}



[Fact]
public void Login_CallLoginTwice_LoginOnce()
{
this.SetupLogin();

var client = this.GetClient();
var first = client.Login();
var second = client.Login();

Assert.True(first);
Assert.False(second);
this.sdkMock.Verify(x => x.Login(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}

#endregion Login

#region Dispose
[Fact]
public void Dispose_CallLogin_LogoutSuccess()
{
this.SetupLogin();

this.apiMock.Setup(x => x.Logout());
this.sdkMock.Setup(x => x.Cleanup());

bool loginResult = false;
using (var client = this.GetClient())
{
loginResult = client.Login();
}

Assert.True(loginResult);
this.sdkMock.Verify(x => x.Login(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
this.apiMock.Verify(x => x.Logout(), Times.Once);
this.sdkMock.Verify(x => x.Cleanup(), Times.Once);
}

[Fact]
public void Dispose_DoNotLogin_LogoutNotCall()
{
this.sdkMock.Setup(x => x.Cleanup()).Verifiable();
using (var client = this.GetClient())
{
// Do nothing
}

this.sdkMock.Verify();
this.apiMock.Verify(x => x.Logout(), Times.Never);
}

#endregion Dispose

#region GetFilesListAsync
[Fact]
public async Task GetFilesListAsync_CallWithValidParameters_ReturnMappedFiles()
{
DateTime start = default(DateTime);
DateTime end = start.AddSeconds(1);
var remoteFile = fixture.Create<RemoteFile>();

this.SetupLogin();
this.videoServiceMock.Setup(x => x.FindFiles(It.IsAny<DateTime>(), It.IsAny<DateTime>()))
.Returns(new List<RemoteFile>() { remoteFile });

var client = this.GetClient();
client.Login();
var mediaFiles = await client.GetFilesListAsync(start, end);

this.videoServiceMock.Verify(x => x.FindFiles(It.IsAny<DateTime>(), It.IsAny<DateTime>()), Times.Once);
Assert.Single(mediaFiles);
var firstFile = mediaFiles.First();
Assert.Equal(remoteFile.Name, firstFile.Name);
Assert.Equal(remoteFile.Date, firstFile.Date);
Assert.Equal(remoteFile.Duration, firstFile.Duration);
Assert.Equal(remoteFile.Size, firstFile.Size);
}

[Fact]
public async Task GetFilesListAsync_CallWithInvalidParameters_ThrowsException()
{
var client = this.GetClient();

await Assert.ThrowsAsync<ArgumentException>(async () =>
{
var date = new DateTime(1970, 1, 1);
await client.GetFilesListAsync(date, date);
});
}

#endregion GetFilesListAsync

#region DownloadFileAsync

[Theory]
[InlineData(1991, 05, 31, 60, "video", "C:\\1991-05\\31\\00\\19910531_000000_000100.mp4")]
[InlineData(2020, 12, 31, 3600, "ch000000001", "C:\\2020-12\\31\\00\\20201231_000000_010000.mp4")]
public async Task DownloadFileAsync_CallDownload_ProperFilesStored(int y, int m, int d, int duration, string name, string fileName)
{
var cameraConfig = new CameraConfig { ClientType = ClientType.HikVisionVideo, DestinationFolder = "C:\\", Camera = new DTO.Config.DeviceConfig() };

long downloadHandler = 1;
this.SetupLogin();
MediaFileDto remoteFile = new MediaFileDto { Date = new DateTime(y, m, d), Duration = duration, Name = name };

var tempName = fileName + ".tmp";
var targetName = fileName;

this.filesMock.Setup(x => x.CombinePath(It.IsAny<string[]>()))
.Returns((string[] arg) => Path.Combine(arg));
this.dirMock.Setup(x => x.CreateDirIfNotExist(It.IsAny<string>()));
this.filesMock.Setup(x => x.FileSize(targetName))
.Returns(1);
this.filesMock.Setup(x => x.RenameFile(tempName + ".mp4", targetName));
this.filesMock.Setup(x => x.FileExists(targetName))
.Returns(false);
this.filesMock.Setup(x => x.GetTempFileName())
.Returns(tempName);

this.videoServiceMock.Setup(x => x.StartDownloadFile(It.IsAny<IRemoteFile>(), tempName + ".mp4"))
.Returns(downloadHandler);
this.videoServiceMock.Setup(x => x.GetDownloadPosition(It.IsAny<long>()))
.Returns((false,1,1));
this.videoServiceMock.Setup(x => x.StopDownloadFile(It.IsAny<long>()))
.Returns(true);

var client = new DahuaVideoClient(cameraConfig, this.sdkMock.Object, this.filesMock.Object, this.dirMock.Object, this.mapper, loggerMock.Object);
client.Login();
var isDownloaded = await client.DownloadFileAsync(remoteFile, CancellationToken.None);

Assert.True(isDownloaded);
this.filesMock.Verify(x => x.CombinePath(It.IsAny<string[]>()), Times.Exactly(2));
this.dirMock.Verify(x => x.CreateDirIfNotExist(It.IsAny<string>()), Times.Once);
this.filesMock.Verify(x => x.FileExists(targetName), Times.Once);
this.filesMock.Verify(x => x.GetTempFileName(), Times.Once);
this.filesMock.Verify(x => x.RenameFile(tempName + ".mp4", targetName), Times.Once);
this.videoServiceMock.Verify(x => x.StartDownloadFile(It.IsAny<IRemoteFile>(), tempName + ".mp4"), Times.Once);
}

[Fact]
public async Task DownloadFileAsync_FileAlreadyExist_ReturnFalse()
{
this.filesMock.Setup(x => x.CombinePath(It.IsAny<string[]>()))
.Returns(string.Empty);
this.dirMock.Setup(x => x.CreateDirIfNotExist(It.IsAny<string>()));
this.filesMock.Setup(x => x.FileExists(It.IsAny<string>()))
.Returns(true);
this.filesMock.Setup(x => x.GetTempFileName())
.Returns(string.Empty);

var client = this.GetClient();
var isDownloaded = await client.DownloadFileAsync(this.fixture.Create<MediaFileDto>(), CancellationToken.None);

Assert.False(isDownloaded);
}

[Fact]
public async Task DownloadFileAsync_AbnormalProgress_StopDownloadFile()
{
long downloadHandler = 1;
this.SetupLogin();

this.SetupFilesMockForDownload();

this.filesMock.Setup(x => x.FileExists(It.IsAny<string>()))
.Returns(false);
this.filesMock.Setup(x => x.GetTempFileName())
.Returns(string.Empty);
this.videoServiceMock
.Setup(x => x.StartDownloadFile(It.IsAny<IRemoteFile>(), It.IsAny<string>()))
.Returns(downloadHandler);
this.videoServiceMock.Setup(x => x.StopDownloadFile(downloadHandler))
.Returns(true);
this.videoServiceMock.Setup(x => x.GetDownloadPosition(It.IsAny<long>()))
.Returns((false,0,0));
this.apiMock.Setup(x => x.Logout());
this.sdkMock.Setup(x => x.Cleanup());

DahuaVideoClient client = null;
using (client = this.GetClient())
{
client.Login();
await client.DownloadFileAsync(this.fixture.Create<MediaFileDto>(), CancellationToken.None);
}

this.videoServiceMock.Verify(x => x.StopDownloadFile(downloadHandler), Times.Once);
this.apiMock.Verify(x => x.Logout(), Times.Once);
this.sdkMock.Verify(x => x.Cleanup(), Times.Once);
}

#endregion DownloadFileAsync

#region ForceExit
[Fact]
public void ForceExit_FilesNotDownloading_DoNotDeleteFile()
{
this.SetupLogin();

this.apiMock.Setup(x => x.Logout());
this.sdkMock.Setup(x => x.Cleanup());

var client = this.GetClient();
client.Login();
client.ForceExit();

this.apiMock.Verify(x => x.Logout(), Times.Once);
this.sdkMock.Verify(x => x.Cleanup(), Times.Once);
}

[Fact]
public async Task ForceExit_FileIsDownloading_DoStop()
{
long downloadHandler = 1;
var client = this.GetClient();
this.SetupLogin();
this.SetupFilesMockForDownload();

this.videoServiceMock
.Setup(x => x.StartDownloadFile(It.IsAny<IRemoteFile>(), It.IsAny<string>()))
.Returns(downloadHandler);
this.videoServiceMock.Setup(x => x.StopDownloadFile(downloadHandler))
.Returns(true);
this.videoServiceMock.Setup(x => x.GetDownloadPosition(It.IsAny<long>()))
.Callback(client.ForceExit)
.Returns((true, 1, 10));
this.apiMock.Setup(x => x.Logout());
this.sdkMock.Setup(x => x.Cleanup());
this.filesMock.Setup(x => x.GetTempFileName())
.Returns(string.Empty);


client.Login();
var isDownloadingStarted = await client.DownloadFileAsync(this.fixture.Create<MediaFileDto>(), CancellationToken.None);

this.apiMock.Verify(x => x.Logout(), Times.Once);
this.sdkMock.Verify(x => x.Cleanup(), Times.Once);

Assert.True(isDownloadingStarted);
this.videoServiceMock.Verify(x => x.StopDownloadFile(downloadHandler), Times.Once);
}

#endregion ForceExit

private void SetupLogin()
{
this.sdkMock.Setup(x => x.Login(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(apiMock.Object);
}

private void SetupFilesMockForDownload()
{
this.filesMock.Setup(x => x.CombinePath(It.IsAny<string[]>()))
.Returns(string.Empty);
this.dirMock.Setup(x => x.CreateDirIfNotExist(It.IsAny<string>()));
this.filesMock.Setup(x => x.FileSize(It.IsAny<string>()))
.Returns(1);
this.filesMock.Setup(x => x.RenameFile(It.IsAny<string>(), It.IsAny<string>()));
this.filesMock.Setup(x => x.FileExists(It.IsAny<string>()))
.Returns(false);
}

private DahuaVideoClient GetClient() =>
new DahuaVideoClient(this.fixture.Create<CameraConfig>(), this.sdkMock.Object, this.filesMock.Object, this.dirMock.Object, this.mapper, loggerMock.Object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void GetNextBatch_Initialized_ReturnsFilesList()
}

[Fact]
public void GetNextBatch_NoExtention_ReturnsAllFiles()
public void GetNextBatch_NoExtension_ReturnsAllFiles()
{
dirMock.Setup(x => x.EnumerateAllDirectories(folder1))
.Returns(new List<string>() { subFolder1 })
Expand Down
4 changes: 2 additions & 2 deletions Tests/Hik.Client.Tests/FtpDownloaderClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void InitializeClient_CallInitializeClient_ClientInitialized()
}

[Fact]
public async Task GetFilesListAsync_CallWithValidParameters_ReturnMapppedFiles()
public async Task GetFilesListAsync_CallWithValidParameters_ReturnMappedFiles()
{
ftpMock.Setup(x => x.GetListing("/CameraName", default)).ReturnsAsync(new FtpListItem[]
{
Expand Down Expand Up @@ -104,7 +104,7 @@ public async Task DownloadFileAsync_RemoteFileNotExist_ReturnFalse()
}

[Fact]
public async Task DownloadFileAsync_SizeMistmatch_DownloadFalse()
public async Task DownloadFileAsync_SizeMismatch_DownloadFalse()
{
string randomName = "RandomName";

Expand Down
Loading

0 comments on commit 3036bf4

Please sign in to comment.