Skip to content

Commit

Permalink
Merge branch 'memleak'
Browse files Browse the repository at this point in the history
  • Loading branch information
dogguts committed Dec 27, 2019
2 parents 51516fc + 26a96ea commit b98641b
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion assemblyInfo.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<AssemblyVersion>1.0.1.0</AssemblyVersion>
<AssemblyVersion>1.0.2.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<RequireLicenseAcceptance>false</RequireLicenseAcceptance>
<Product>Aeon</Product>
Expand Down
2 changes: 1 addition & 1 deletion nupkgs.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VersionPrefix>1.0.1</VersionPrefix>
<VersionPrefix>1.0.2</VersionPrefix>
<!-- <VersionSuffix>preview2</VersionSuffix> -->
<PackageVersion>$(VersionPrefix)</PackageVersion> <!-- -$(VersionSuffix) -->
<IncludeSymbols>true</IncludeSymbols>
Expand Down
23 changes: 7 additions & 16 deletions src/Aeon.Core.Repository/Repository`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,8 @@ public async Task<T> GetAsync(IRepositoryInclude<T> includes, params object[] ke

// if (keyProperties.Count != keyValues.Length) TODO: throw exception

// (p) =>
var entityParameter = Expression.Parameter(typeof(T), "p");

//var keyValuesConstant = Expression.Constant(keyValues);
var entityParameter = Expression.Parameter(typeof(T), "p");

BinaryExpression predicate = null;

Expand All @@ -87,19 +85,12 @@ public async Task<T> GetAsync(IRepositoryInclude<T> includes, params object[] ke


var leftExpr = Expression.Property(entityParameter, property.Name);
/*
var leftExpr = Expression.Call(
PropertyMethod.MakeGenericMethod(property.ClrType),
entityParameter,
Expression.Constant(property.Name, typeof(string)));
*/

var rightExpr = Expression.Convert(Expression.Constant(keyValues[i]), property.ClrType);

var equalsExpression =
Expression.Equal(
leftExpr,
rightExpr);

object keyValuePart = keyValues[i];
Expression<Func<object>> closure = () => keyValuePart;
var rightExpr = Expression.Convert(closure.Body, leftExpr.Type);

var equalsExpression = Expression.Equal(leftExpr, rightExpr);

predicate = predicate == null ? equalsExpression : Expression.AndAlso(predicate, equalsExpression);
}
Expand Down
61 changes: 61 additions & 0 deletions tests/Repository.Test.Integration/Remedies/Remedy4.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Linq;
using Aeon.Core.Repository.Infrastructure;
using Model = Chinook.Repository.Model;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
using Aeon.Core.Repository;
using System.ComponentModel;
using System.Reflection;
using System.Collections;

namespace Chinook.Repository.Integration.Tests.Remedies {
/// <summary>
/// https://github.com/dogguts/aeon/issues/4
/// </summary>
public class TestRemedy4 : IClassFixture<Remedy4Setup> {

private readonly IRepository<Model.MediaType> _mediaTypeRepository;
private readonly ServiceProvider _serviceProvider;
public TestRemedy4(Remedy4Setup serviceSetup) {
_serviceProvider = serviceSetup.ServiceProvider;
_mediaTypeRepository = _serviceProvider.GetRequiredService<IRepository<Model.MediaType>>();
}

private static int MemoryCacheEntryCount(ServiceProvider _serviceProvider) {
var compiledQueryCache = (Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache)_serviceProvider.GetRequiredService<Microsoft.EntityFrameworkCore.Query.Internal.ICompiledQueryCache>();
var memoryCacheFieldInfo = compiledQueryCache.GetType().GetField("_memoryCache", BindingFlags.Instance | BindingFlags.NonPublic);
var memoryCache = (Microsoft.Extensions.Caching.Memory.MemoryCache)memoryCacheFieldInfo.GetValue(compiledQueryCache);
Console.WriteLine($"Cached #{memoryCache.Count}");
return memoryCache.Count;
}

private static int? InitialCacheEntryCount = null;

/// <summary>
/// Subsequent queries with different parameters should only get cached once
/// </summary>
[Theory]
[InlineData(1, "MP3")]
[InlineData(2, "OGG")]
[InlineData(3, "FLAC")]
[InlineData(4, "OPUS")]
[InlineData(5, "VOC")]
public void Get(long id, string expectedMediaType) {
if (!InitialCacheEntryCount.HasValue) {
//get initial cache count
InitialCacheEntryCount = MemoryCacheEntryCount(_serviceProvider);
}

var mediaType = _mediaTypeRepository.Get(id);
Assert.Equal(expectedMediaType, mediaType.Name);

var currentCacheEntryCount = MemoryCacheEntryCount(_serviceProvider);
// the querycache should only grow with max. 2 entries over all the test data in this specific test.
// +2 = 1(query .Count) +1(query)
Assert.InRange(currentCacheEntryCount, InitialCacheEntryCount.Value, InitialCacheEntryCount.Value + 2);

}

}
}
66 changes: 66 additions & 0 deletions tests/Repository.Test.Integration/Remedies/Remedy4Setup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using Aeon.Core.Repository;
using Aeon.Core.Repository.Infrastructure;
using Chinook.Repository;
using Chinook.Repository.Model;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;

namespace Chinook.Repository.Integration.Tests.Remedies {

public class Remedy4Setup {

public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {
new ConsoleLoggerProvider((category, level) => level == LogLevel.Warning, true) /* level == LogLevel.Information */
});

private SqliteConnection connection;

public ServiceProvider ServiceProvider { get; private set; }

// public static MemoryCache MemoryCache = new MemoryCache(new MemoryCacheOptions());

public Remedy4Setup() {

var services = new ServiceCollection();

services.AddEntityFrameworkSqlite();

connection = new SqliteConnection("DataSource=:memory:");
connection.Open();




services.AddDbContext<Chinook.Repository.ChinookDbContext>(opt => opt.UseSqlite(connection)
// .UseMemoryCache(MemoryCache)
.EnableSensitiveDataLogging()
.UseLoggerFactory(MyLoggerFactory));

services.AddScoped<IRepository<Model.MediaType>, Repository<Model.MediaType, ChinookDbContext>>();

ServiceProvider = services.BuildServiceProvider();
var dbContext = ServiceProvider.GetService<Chinook.Repository.ChinookDbContext>();
dbContext.Database.EnsureCreated();

//Add some predefined records
dbContext.MediaType.AddRange(new Model.MediaType() { Name = "MP3" },
new Model.MediaType() { Name = "OGG" },
new Model.MediaType() { Name = "FLAC" },
new Model.MediaType() { Name = "OPUS" },
new Model.MediaType() { Name = "VOC" });

dbContext.SaveChanges();
}

public void Dispose() {
connection.Close();
}

}
}

0 comments on commit b98641b

Please sign in to comment.