428 lines
13 KiB
C#
428 lines
13 KiB
C#
using DD.Persistence.Client;
|
||
using DD.Persistence.Client.Clients;
|
||
using DD.Persistence.Client.Clients.Interfaces;
|
||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||
using DD.Persistence.Database.Entity;
|
||
using DD.Persistence.Models;
|
||
using Microsoft.Extensions.Caching.Memory;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Microsoft.Extensions.Logging;
|
||
using System.Text.Json;
|
||
using Xunit;
|
||
|
||
namespace DD.Persistence.IntegrationTests.Controllers;
|
||
public class TimestampedValuesControllerTest : BaseIntegrationTest
|
||
{
|
||
private readonly ITimestampedValuesClient timestampedValuesClient;
|
||
private readonly IMemoryCache memoryCache;
|
||
private IEnumerable<Guid> discriminatorIds = [];
|
||
|
||
public TimestampedValuesControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||
{
|
||
var refitClientFactory = scope.ServiceProvider
|
||
.GetRequiredService<IRefitClientFactory<IRefitTimestampedValuesClient>>();
|
||
var logger = scope.ServiceProvider.GetRequiredService<ILogger<TimestampedValuesClient>>();
|
||
|
||
timestampedValuesClient = scope.ServiceProvider
|
||
.GetRequiredService<ITimestampedValuesClient>();
|
||
memoryCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
|
||
}
|
||
|
||
[Fact]
|
||
public async Task AddRange_returns_success()
|
||
{
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
await AddRange(discriminatorId);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task Get_returns_BadRequest()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var firstDiscriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(firstDiscriminatorId);
|
||
|
||
var secondDiscriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(secondDiscriminatorId);
|
||
|
||
try
|
||
{
|
||
//act
|
||
var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId], null, null, null, 0, 1, CancellationToken.None);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var expectedMessage = $"На сервере произошла ошибка, в результате которой он не может успешно обработать запрос";
|
||
|
||
//assert
|
||
Assert.Equal(expectedMessage, ex.Message);
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public async Task Get_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var firstDiscriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(firstDiscriminatorId);
|
||
|
||
var secondDiscriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(secondDiscriminatorId);
|
||
|
||
var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1);
|
||
var columnNames = new List<string>() { "A", "C" };
|
||
var skip = 0;
|
||
var take = 6; // Ровно столько значений будет удовлетворять фильтру (\"A\">3) (для одного дискриминатора)
|
||
|
||
var customFilter = "(\"A\">3)";
|
||
|
||
var dtos = (await AddRange(firstDiscriminatorId)).ToList();
|
||
dtos.AddRange(await AddRange(secondDiscriminatorId));
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.Get([firstDiscriminatorId, secondDiscriminatorId],
|
||
timestampBegin, customFilter, columnNames, skip, take, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
Assert.NotEmpty(response);
|
||
|
||
var expectedCount = take * 2;
|
||
var actualCount = response.Count();
|
||
Assert.Equal(expectedCount, actualCount);
|
||
|
||
var actualColumnNames = response.SelectMany(e => e.Values.Keys).Distinct().ToList();
|
||
Assert.Equal(columnNames, actualColumnNames);
|
||
|
||
var expectedValueKind = JsonValueKind.Number;
|
||
var actualValueKind = ((JsonElement)response.First().Values["A"]).ValueKind;
|
||
Assert.Equal(expectedValueKind, actualValueKind);
|
||
|
||
expectedValueKind = JsonValueKind.String;
|
||
actualValueKind = ((JsonElement)response.First().Values["C"]).ValueKind;
|
||
Assert.Equal(expectedValueKind, actualValueKind);
|
||
}
|
||
|
||
|
||
[Fact]
|
||
public async Task GetGtDate_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var timestampBegin = DateTimeOffset.UtcNow.AddDays(-1);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetGtDate(discriminatorId, timestampBegin, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.Null(response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetGtDate_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var dtos = await AddRange(discriminatorId);
|
||
var timestampBegin = DateTimeOffset.UtcNow.AddSeconds(-5);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetGtDate(discriminatorId, timestampBegin, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
Assert.NotEmpty(response);
|
||
|
||
var expectedCount = dtos.Count(dto => dto.Timestamp.ToUniversalTime() > timestampBegin);
|
||
var actualCount = response.Count();
|
||
Assert.Equal(expectedCount, actualCount);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFirst_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var take = 1;
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetFirst(discriminatorId, take, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.Null(response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFirst_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var dtos = await AddRange(discriminatorId);
|
||
var take = 1;
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetFirst(discriminatorId, take, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
Assert.NotEmpty(response);
|
||
|
||
var expectedTimestampString = dtos
|
||
.OrderBy(dto => dto.Timestamp)
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
var actualTimestampString = response
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
Assert.Equal(expectedTimestampString, actualTimestampString);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetLast_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var take = 1;
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetLast(discriminatorId, take, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.Null(response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetLast_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var dtos = await AddRange(discriminatorId);
|
||
var take = 1;
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetLast(discriminatorId, take, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
Assert.NotEmpty(response);
|
||
|
||
var expectedTimestampString = dtos
|
||
.OrderByDescending(dto => dto.Timestamp)
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
var actualTimestampString = response
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
Assert.Equal(expectedTimestampString, actualTimestampString);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetResampledData_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var timestampBegin = DateTimeOffset.UtcNow;
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetResampledData(discriminatorId, timestampBegin);
|
||
|
||
//assert
|
||
Assert.Null(response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetResampledData_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var count = 2048;
|
||
var timestampBegin = DateTimeOffset.UtcNow;
|
||
var dtos = await AddRange(discriminatorId, count);
|
||
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetResampledData(discriminatorId, timestampBegin, count);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
Assert.NotEmpty(response);
|
||
|
||
var expectedCount = count / 2;
|
||
var actualCount = response.Count();
|
||
Assert.Equal(expectedCount, actualCount);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task Count_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.Count(discriminatorId, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.Equal(0, response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task Count_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var dtos = await AddRange(discriminatorId);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.Count(discriminatorId, CancellationToken.None);
|
||
|
||
//assert
|
||
var expectedCount = dtos.Count();
|
||
Assert.Equal(expectedCount, response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetDatesRange_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetDatesRange(discriminatorId, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.Null(response);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetDatesRange_AfterSave_returns_success()
|
||
{
|
||
//arrange
|
||
Cleanup();
|
||
|
||
var discriminatorId = Guid.NewGuid();
|
||
discriminatorIds.Append(discriminatorId);
|
||
|
||
var dtos = await AddRange(discriminatorId);
|
||
|
||
//act
|
||
var response = await timestampedValuesClient.GetDatesRange(discriminatorId, CancellationToken.None);
|
||
|
||
//assert
|
||
Assert.NotNull(response);
|
||
|
||
var expectedDateFromString = dtos
|
||
.OrderBy(dto => dto.Timestamp)
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
var actualDateFromString = response.From
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
Assert.Equal(expectedDateFromString, actualDateFromString);
|
||
|
||
var expectedDateToString = dtos
|
||
.OrderByDescending(dto => dto.Timestamp)
|
||
.First().Timestamp
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
var actualDateToString = response.To
|
||
.ToUniversalTime()
|
||
.ToString();
|
||
Assert.Equal(expectedDateToString, actualDateToString);
|
||
}
|
||
|
||
private async Task<IEnumerable<TimestampedValuesDto>> AddRange(Guid discriminatorId, int countToCreate = 10)
|
||
{
|
||
// arrange
|
||
IEnumerable<TimestampedValuesDto> generatedDtos = Generate(countToCreate, DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(7)));
|
||
|
||
// act
|
||
var response = await timestampedValuesClient.AddRange(discriminatorId, generatedDtos, CancellationToken.None);
|
||
|
||
// assert
|
||
//Assert.Equal(generatedDtos.Count(), response);
|
||
|
||
return generatedDtos;
|
||
}
|
||
|
||
private static IEnumerable<TimestampedValuesDto> Generate(int countToCreate, DateTimeOffset from)
|
||
{
|
||
var result = new List<TimestampedValuesDto>();
|
||
for (int i = 0; i < countToCreate; i++)
|
||
{
|
||
var values = new Dictionary<string, object>()
|
||
{
|
||
{ "A", i },
|
||
{ "B", i * 1.1 },
|
||
{ "C", $"Any{i}" },
|
||
{ "D", DateTimeOffset.Now },
|
||
};
|
||
|
||
yield return new TimestampedValuesDto()
|
||
{
|
||
Timestamp = from.AddSeconds(i),
|
||
Values = values
|
||
};
|
||
}
|
||
}
|
||
|
||
private void Cleanup()
|
||
{
|
||
foreach (var item in discriminatorIds)
|
||
{
|
||
memoryCache.Remove(item);
|
||
}
|
||
discriminatorIds = [];
|
||
dbContext.CleanupDbSet<TimestampedValues>();
|
||
dbContext.CleanupDbSet<SchemeProperty>();
|
||
}
|
||
}
|