Skip to content

Commit

Permalink
Fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianKuesters committed Sep 22, 2022
1 parent 6c2e5fa commit 0f89be9
Show file tree
Hide file tree
Showing 28 changed files with 493 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using Wemogy.Infrastructure.Database.Core.Abstractions;
using Wemogy.Infrastructure.Database.Core.Attributes;
using Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.DatabaseRepositories;

[RepositoryOptions(enableSoftDelete: true)]
public interface IAnimalRepository : IDatabaseRepository<Animal, Guid, string>
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
namespace Wemogy.Infrastructure.Database.Core.UnitTests.DatabaseRepositories;

[RepositoryOptions(enableSoftDelete: true)]
// [RepositoryReadFilter(typeof(GeneralUserReadFilter))]
// [RepositoryPropertyFilter(typeof(GeneralUserPropertyFilter))]
[RepositoryReadFilter(typeof(GeneralUserReadFilter))]
[RepositoryPropertyFilter(typeof(GeneralUserPropertyFilter))]
public interface IUserRepository : IDatabaseRepository<User>
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using Bogus;
using Wemogy.Core.Extensions;
using Wemogy.Infrastructure.Database.Core.Abstractions;
using Wemogy.Infrastructure.Database.Core.Attributes;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;

public class Animal : EntityBase<string>
{
[PartitionKey]
public Guid TenantId { get; set; }

public string Firstname { get; set; }

public string Lastname { get; set; }

public string PrivateNote { get; set; }

public Animal()
: base(Guid.NewGuid().ToString())
{
TenantId = Guid.Empty;
Firstname = string.Empty;
Lastname = string.Empty;
PrivateNote = string.Empty;
}

public static Faker<Animal> Faker
{
get
{
return new Faker<Animal>()
.RuleFor(x => x.CreatedAt, f => f.Date.Past().Clone())
.RuleFor(x => x.UpdatedAt, f => f.Date.Past().Clone())
.RuleFor(x => x.TenantId, f => f.Random.Guid())
.RuleFor(x => x.Firstname, f => f.Name.FirstName())
.RuleFor(x => x.Lastname, f => f.Name.LastName());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Threading.Tasks;
using FluentAssertions;
using Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;
using Xunit;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories.AnimalEntity;

public abstract partial class ComposedPrimaryKeyDatabaseRepositoryTestBase
{
[Fact]
public async Task GetAsync_ShouldRespectComposedKey()
{
// Arrange
var animal = Animal.Faker.Generate();
var prefix = "tenantA";
SetPrefixContext(prefix);
await AnimalRepository.CreateAsync(animal);

// Act
var animalFromDb = await AnimalRepository.GetAsync(
animal.Id,
animal.TenantId);

// Assert
animalFromDb.Should().BeEquivalentTo(animal);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Wemogy.Infrastructure.Database.Core.Factories;
using Wemogy.Infrastructure.Database.Core.UnitTests.DatabaseRepositories;
using Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.TestingData.Models;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories.AnimalEntity;

public abstract partial class ComposedPrimaryKeyDatabaseRepositoryTestBase : IDisposable
{
private readonly IServiceCollection _serviceCollection;
private IAnimalRepository AnimalRepository => _serviceCollection.BuildServiceProvider().GetRequiredService<IAnimalRepository>();

protected ComposedPrimaryKeyDatabaseRepositoryTestBase(Action<IServiceCollection> addRepositoryAction)
{
_serviceCollection = new ServiceCollection();
_serviceCollection.AddScoped<StringPrefixComposedPrimaryKeyBuilder>();
addRepositoryAction(_serviceCollection);
DatabaseRepositoryFactoryFactory.DatabaseClientProxy = null;
}

public void Dispose()
{
// Cleanup
// AnimalRepository.DeleteAsync(x => true).Wait();
}

private void SetPrefixContext(string prefix)
{
_serviceCollection.AddSingleton(new PrefixContext(prefix));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;
using Xunit;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories;
namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories.UserEntity;

public abstract partial class ComposedPrimaryKeyDatabaseRepositoryTestBase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
using Wemogy.Infrastructure.Database.Core.UnitTests.DatabaseRepositories;
using Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.TestingData.Models;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories;
namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.Repositories.UserEntity;

public abstract partial class ComposedPrimaryKeyDatabaseRepositoryTestBase : IDisposable
{
private readonly IServiceCollection _serviceCollection;
protected IUserRepository UserRepository => _serviceCollection.BuildServiceProvider().GetRequiredService<IUserRepository>();
private IUserRepository UserRepository => _serviceCollection.BuildServiceProvider().GetRequiredService<IUserRepository>();

protected ComposedPrimaryKeyDatabaseRepositoryTestBase(Action<IServiceCollection> addRepositoryAction)
{
Expand All @@ -22,10 +22,10 @@ protected ComposedPrimaryKeyDatabaseRepositoryTestBase(Action<IServiceCollection
public void Dispose()
{
// Cleanup
// UserRepository.DeleteAsync(x => true).Wait();
UserRepository.DeleteAsync(x => true).Wait();
}

protected void SetPrefixContext(string prefix)
private void SetPrefixContext(string prefix)
{
_serviceCollection.AddSingleton(new PrefixContext(prefix));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public PrefixComposedPrimaryKeyBuilder(PrefixContext prefixContext)
_prefixContext = prefixContext;
}

public string GetComposedPrimaryKeyPrefix()
{
return $"{_prefixContext.Prefix}_";
}

public string BuildComposedPrimaryKey(Guid id)
{
return $"{_prefixContext.Prefix}_{id}";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using Wemogy.Core.Extensions;
using Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.Abstractions;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Plugins.ComposedPrimaryKey.TestingData.Models;

public class StringPrefixComposedPrimaryKeyBuilder : IComposedPrimaryKeyBuilder<string>
{
private readonly PrefixContext _prefixContext;

public StringPrefixComposedPrimaryKeyBuilder(PrefixContext prefixContext)
{
_prefixContext = prefixContext;
}

public string GetComposedPrimaryKeyPrefix()
{
return $"{_prefixContext.Prefix}_";
}

public string BuildComposedPrimaryKey(string id)
{
return $"{_prefixContext.Prefix}_{id}";
}

public string ExtractIdFromComposedPrimaryKey(string composedPrimaryKey)
{
return composedPrimaryKey.SplitOnFirstOccurrence("_")[1];
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using FluentAssertions;
using Wemogy.Core.Errors.Exceptions;
using Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;
using Xunit;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using FluentAssertions;
using Wemogy.Core.DynamicProxies;
using Wemogy.Core.DynamicProxies.Enums;
using Wemogy.Core.DynamicProxies.Extensions;
using Wemogy.Core.Errors;
using Wemogy.Core.Errors.Exceptions;
using Wemogy.Infrastructure.Database.Core.Abstractions;
Expand All @@ -21,7 +20,6 @@ public async Task UpdateAsync_ShouldRetryAutomatically()
// Arrange
await ResetAsync();
var user = User.Faker.Generate();
await UserRepository.CreateAsync(user);

var flakyProxy = new FlakyProxy(
2,
Expand All @@ -30,6 +28,7 @@ public async Task UpdateAsync_ShouldRetryAutomatically()
.OnlyForMethodsWithName(nameof(IDatabaseClient<User, Guid, Guid>.ReplaceAsync));
DatabaseRepositoryFactoryFactory.DatabaseClientProxy = flakyProxy;
var flakyUserRepository = UserRepositoryFactory();
await flakyUserRepository.CreateAsync(user);

void UpdateAction(User u)
{
Expand All @@ -53,7 +52,6 @@ public async Task UpdateAsync_ShouldRetryOnlyMaxAttempts()
// Arrange
await ResetAsync();
var user = User.Faker.Generate();
await UserRepository.CreateAsync(user);

var flakyProxy = new FlakyProxy(
100,
Expand All @@ -62,6 +60,7 @@ public async Task UpdateAsync_ShouldRetryOnlyMaxAttempts()
.OnlyForMethodsWithName(nameof(IDatabaseClient<User, Guid, Guid>.ReplaceAsync));
DatabaseRepositoryFactoryFactory.DatabaseClientProxy = flakyProxy;
var flakyUserRepository = UserRepositoryFactory();
await flakyUserRepository.CreateAsync(user);

void UpdateAction(User u)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using System.Threading.Tasks;
using FluentAssertions;
using Wemogy.Infrastructure.Database.Core.Factories;
using Wemogy.Infrastructure.Database.Core.UnitTests.DatabaseRepositories;
using Wemogy.Infrastructure.Database.Core.UnitTests.Fakes.Entities;
using Xunit;

namespace Wemogy.Infrastructure.Database.Core.UnitTests.Repositories;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ImpromptuInterface;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -14,6 +15,7 @@
using Wemogy.Infrastructure.Database.Core.Models;
using Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.Abstractions;
using Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.Delegates;
using Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.ReadFilters;
using Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.Repositories;

namespace Wemogy.Infrastructure.Database.Core.Factories;
Expand Down Expand Up @@ -44,20 +46,30 @@ public ComposedPrimaryKeyDatabaseRepositoryFactoryDelegate<TDatabaseRepository>
internalEntityType,
typeof(TComposedPrimaryKeyBuilder));

// ToDo: wrap
var getReadFiltersGenericMethod = typeof(DatabaseRepositoryFactoryFactory)
.GetGenericMethod(
nameof(GetReadFilters),
databaseRepositoryTypeMetadata.EntityType,
databaseRepositoryTypeMetadata.IdType);
var getWrappedReadFiltersGenericMethod = typeof(DatabaseRepositoryFactoryFactory)
.GetGenericMethod(
nameof(GetWrappedReadFilters),
internalEntityType,
typeof(string));
databaseRepositoryTypeMetadata.EntityType,
databaseRepositoryTypeMetadata.IdType);
var repositoryReadFilterAttribute = databaseRepositoryType.GetCustomAttribute<RepositoryReadFilterAttribute>();

// ToDo: wrap
var getPropertyFiltersGenericMethod = typeof(DatabaseRepositoryFactoryFactory)
.GetGenericMethod(
nameof(GetPropertyFilters),
databaseRepositoryTypeMetadata.EntityType,
databaseRepositoryTypeMetadata.IdType);
var getWrappedPropertyFiltersGenericMethod = typeof(DatabaseRepositoryFactoryFactory)
.GetGenericMethod(
nameof(GetWrappedPropertyFilters),
internalEntityType,
typeof(string));
databaseRepositoryTypeMetadata.EntityType,
databaseRepositoryTypeMetadata.IdType);
var repositoryPropertyFilterAttribute =
databaseRepositoryType.GetCustomAttribute<RepositoryPropertyFilterAttribute>();

Expand Down Expand Up @@ -92,18 +104,27 @@ public ComposedPrimaryKeyDatabaseRepositoryFactoryDelegate<TDatabaseRepository>

return serviceProvider =>
{
var composedPrimaryKeyBuilder = serviceProvider.GetRequiredService<TComposedPrimaryKeyBuilder>();
var readFilters = getReadFiltersGenericMethod.Invoke(
this,
new object[] { serviceProvider, repositoryReadFilterAttribute });
var internalReadFilters = getWrappedReadFiltersGenericMethod.Invoke(
this,
new object[] { readFilters, composedPrimaryKeyBuilder.GetComposedPrimaryKeyPrefix() });
var propertyFilters = getPropertyFiltersGenericMethod.Invoke(
this,
new object[] { serviceProvider, repositoryPropertyFilterAttribute });
var composedPrimaryKeyBuilder = serviceProvider.GetRequiredService<TComposedPrimaryKeyBuilder>();
var internalPropertyFilters = getWrappedPropertyFiltersGenericMethod.Invoke(
this,
new object[] { propertyFilters });
var databaseRepository = createComposedPrimaryKeyDatabaseRepositoryGenericMethod.Invoke(
this,
new[]
{
databaseClientInstance, databaseRepositoryOptions, readFilters, propertyFilters,
databaseClientInstance,
databaseRepositoryOptions,
internalReadFilters,
internalPropertyFilters,
composedPrimaryKeyBuilder
});
return retryProxy.Wrap<TDatabaseRepository>(databaseRepository.ActLike<TDatabaseRepository>());
Expand Down Expand Up @@ -134,6 +155,39 @@ public ComposedPrimaryKeyDatabaseRepositoryFactoryDelegate<TDatabaseRepository>
composedPrimaryKeyBuilder);
}

private List<IDatabaseRepositoryReadFilter<TInternalEntity>> GetWrappedReadFilters<TInternalEntity, TEntity, TId>(
List<IDatabaseRepositoryReadFilter<TEntity>> readFilters,
string prefix)
where TEntity : class, IEntityBase<TId>
where TId : IEquatable<TId>
{
var internalReadFilters = readFilters
.Select(
x => new ComposedPrimaryKeyReadFilterWrapper<TInternalEntity, TEntity>(x, prefix) as IDatabaseRepositoryReadFilter<TInternalEntity>)
.ToList();
return internalReadFilters;
}

private List<IDatabaseRepositoryPropertyFilter<TInternalEntity>> GetWrappedPropertyFilters<TInternalEntity, TEntity, TId>(
List<IDatabaseRepositoryPropertyFilter<TEntity>> propertyFilters)
where TEntity : class, IEntityBase<TId>
where TId : IEquatable<TId>
where TInternalEntity : IEntityBase<string>
{
var composedPrimaryKeyPropertyFilterWrapper = new ComposedPrimaryKeyPropertyFilterWrapper<TInternalEntity, TEntity, TId>(
propertyFilters);

if (composedPrimaryKeyPropertyFilterWrapper.IsEmpty)
{
return new List<IDatabaseRepositoryPropertyFilter<TInternalEntity>>();
}

return new List<IDatabaseRepositoryPropertyFilter<TInternalEntity>>
{
composedPrimaryKeyPropertyFilterWrapper
};
}

private Type GetInternalEntityType(Type entityType, Type idType)
{
if (idType == typeof(string))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ namespace Wemogy.Infrastructure.Database.Core.Plugins.ComposedPrimaryKey.Abstrac

public interface IComposedPrimaryKeyBuilder
{
string GetComposedPrimaryKeyPrefix();
}
Loading

0 comments on commit 0f89be9

Please sign in to comment.