Skip to content

Commit

Permalink
reformat rangetest && add test && add parameter for faster tests && n…
Browse files Browse the repository at this point in the history
…ullable for import to avoid sonar issues
  • Loading branch information
qdraw committed Oct 26, 2024
1 parent cf1341a commit 71e1b23
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 126 deletions.
2 changes: 1 addition & 1 deletion starsky/starsky.feature.import/Services/Import.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class Import : IImport
private readonly IImportQuery? _importQuery;
private readonly IWebLogger _logger;

private readonly IMemoryCache _memoryCache;
private readonly IMemoryCache? _memoryCache;
private readonly IMetaExifThumbnailService _metaExifThumbnailService;
private readonly IQuery _query;

Expand Down
8 changes: 5 additions & 3 deletions starsky/starsky.foundation.database/Import/ImportQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ public async Task<List<ImportIndexItem>> AddRangeAsync(
return importIndexItemList;
}

public async Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem)
public async Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem,
int maxAttemptCount = 3)
{
async Task<bool> LocalRemoveDefaultQuery()
{
Expand Down Expand Up @@ -144,7 +145,7 @@ async Task LocalRemoveQuery(ApplicationDbContext context)
{
// Files that are locked
await RetryHelper.DoAsync(LocalRemoveDefaultQuery,
TimeSpan.FromSeconds(2), 4);
TimeSpan.FromSeconds(2), maxAttemptCount);
}
catch ( ObjectDisposedException )
{
Expand All @@ -161,7 +162,8 @@ await RetryHelper.DoAsync(LocalRemoveDefaultQuery,
exception.Message);
try
{
await RetryHelper.DoAsync(LocalRemoveDefaultQuery, TimeSpan.FromSeconds(2), 2);
await RetryHelper.DoAsync(LocalRemoveDefaultQuery, TimeSpan.FromSeconds(2),
maxAttemptCount);
}
catch ( AggregateException )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public interface IImportQuery
Task<bool> AddAsync(ImportIndexItem updateStatusContent, bool writeConsole = true);
List<ImportIndexItem> History();
Task<List<ImportIndexItem>> AddRangeAsync(List<ImportIndexItem> importIndexItemList);
Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem);
Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem, int maxAttemptCount = 3);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public sealed class ThumbnailQueryFactory

public ThumbnailQueryFactory(SetupDatabaseTypes? setupDatabaseTypes,
IServiceScopeFactory? serviceScopeFactory, IThumbnailQuery? thumbnailQuery,
IWebLogger logger, IMemoryCache memoryCache)
IWebLogger logger, IMemoryCache? memoryCache)
{
_setupDatabaseTypes = setupDatabaseTypes;
_serviceScopeFactory = serviceScopeFactory;
Expand Down
3 changes: 2 additions & 1 deletion starsky/starskytest/FakeMocks/FakeIImportQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public async Task<List<ImportIndexItem>> AddRangeAsync(
return importIndexItemList;
}

public async Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem)
public async Task<ImportIndexItem> RemoveItemAsync(ImportIndexItem importIndexItem,
int maxAttemptCount = 3)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -249,4 +250,53 @@ public async Task ImportQuery_RemoveAsync_Disposed()

Assert.AreEqual(0, queryFromDb.Count);
}

[TestMethod]
public async Task RemoveItemAsync_DbUpdateConcurrencyException()
{
var addedItems = new List<ImportIndexItem>
{
new() { FileHash = "RemoveAsync_Disposed__1" }
};

var serviceScopeFactory = CreateNewScope();
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase("MovieListDatabase")
.Options;
var dbContext = new ConcurrencyExceptionApplicationDbContext(options);

var webLogger = new FakeIWebLogger();
var importQuery = new ImportQuery(serviceScopeFactory, new FakeConsoleWrapper(),
webLogger, dbContext);

await importQuery.RemoveItemAsync(addedItems[0], 1);

Assert.IsTrue(webLogger.TrackedInformation[0].Item2?.StartsWith(
"Import [RemoveItemAsync] catch-ed " +
"DbUpdateConcurrencyException (retry)"));
Assert.IsTrue(webLogger.TrackedInformation[1].Item2?
.StartsWith("Import [RemoveItemAsync] catch-ed " +
"AggregateException (ignored after retry)"));
}

private class ConcurrencyExceptionApplicationDbContext : ApplicationDbContext
{
public ConcurrencyExceptionApplicationDbContext(DbContextOptions options) : base(options)
{
}

public override DbSet<FileIndexItem> FileIndex
{
get => throw new DbUpdateConcurrencyException();
set
{
// do nothing
}
}

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
throw new DbUpdateConcurrencyException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,139 +13,140 @@
using starskytest.FakeMocks;

// ReSharper disable once IdentifierTypo
namespace starskytest.starsky.foundation.database.QueryTest
namespace starskytest.starsky.foundation.database.QueryTest;

/// <summary>
/// AddRangeAsyncTest
/// </summary>
[TestClass]
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
public class QueryAddRangeTest
{

/// <summary>
/// AddRangeAsyncTest
/// </summary>
[TestClass]
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeEvident")]
public class QueryAddRangeTest
private static IServiceScopeFactory CreateNewScope()
{
var services = new ServiceCollection();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase(nameof(QueryAddRangeTest)));
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<IServiceScopeFactory>();
}

[TestMethod]
public async Task AddRangeAsync()
{
private static IServiceScopeFactory CreateNewScope()
var expectedResult = new List<FileIndexItem>
{
var services = new ServiceCollection();
services.AddDbContext<ApplicationDbContext>(options => options.UseInMemoryDatabase(nameof(QueryAddRangeTest)));
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<IServiceScopeFactory>();
}

[TestMethod]
public async Task AddRangeAsync()
new FileIndexItem { FileHash = "TEST4" }, new FileIndexItem { FileHash = "TEST5" }
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

var query = new Query(dbContext,
new AppSettings { AddMemoryCache = false, Verbose = true },
serviceScopeFactory, new FakeIWebLogger(), new FakeMemoryCache()
);
await query.AddRangeAsync(expectedResult);

var queryFromDb = dbContext.FileIndex
.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();
Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash,
queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}

[TestMethod]
public async Task AddRangeAsync_Disposed()
{
var expectedResult = new List<FileIndexItem>
{
var expectedResult = new List<FileIndexItem>
{
new FileIndexItem {FileHash = "TEST4"},
new FileIndexItem {FileHash = "TEST5"}
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

var query = new Query(dbContext,
new AppSettings { AddMemoryCache = false, Verbose = true },
serviceScopeFactory, new FakeIWebLogger(), new FakeMemoryCache()
);
await query.AddRangeAsync(expectedResult);

var queryFromDb = dbContext.FileIndex.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();
Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash, queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}

[TestMethod]
public async Task AddRangeAsync_Disposed()
new FileIndexItem { FileHash = "TEST4" }, new FileIndexItem { FileHash = "TEST5" }
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContextDisposed = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

// Dispose here
await dbContextDisposed.DisposeAsync();

await new Query(dbContextDisposed,
new AppSettings { AddMemoryCache = false }, serviceScopeFactory, new FakeIWebLogger(),
new FakeMemoryCache()).AddRangeAsync(expectedResult);

var context = new InjectServiceScope(serviceScopeFactory).Context();
var queryFromDb = context.FileIndex
.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();

Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash,
queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}

[TestMethod]
public async Task AddRange()
{
var expectedResult = new List<FileIndexItem>
{
var expectedResult = new List<FileIndexItem>
{
new FileIndexItem {FileHash = "TEST4"},
new FileIndexItem {FileHash = "TEST5"}
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContextDisposed = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

// Dispose here
await dbContextDisposed.DisposeAsync();

await new Query(dbContextDisposed,
new AppSettings {
AddMemoryCache = false
}, serviceScopeFactory, new FakeIWebLogger(), new FakeMemoryCache()).AddRangeAsync(expectedResult);

var context = new InjectServiceScope(serviceScopeFactory).Context();
var queryFromDb = context.FileIndex.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();

Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash, queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}
new FileIndexItem { FileHash = "TEST4" }, new FileIndexItem { FileHash = "TEST5" }
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

await new Query(dbContext,
new AppSettings { AddMemoryCache = false }, serviceScopeFactory, new FakeIWebLogger(),
new FakeMemoryCache()).AddRangeAsync(expectedResult);

var queryFromDb = dbContext.FileIndex
.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();
Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash,
queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}

[TestMethod]
public async Task AddRange()
[TestMethod]
public async Task AddRangeAsync_DbUpdateConcurrencyException()
{
var expectedResult = new List<FileIndexItem>
{
var expectedResult = new List<FileIndexItem>
{
new FileIndexItem {FileHash = "TEST4"},
new FileIndexItem {FileHash = "TEST5"}
};

var serviceScopeFactory = CreateNewScope();
var scope = serviceScopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

await new Query(dbContext,
new AppSettings {
AddMemoryCache = false
}, serviceScopeFactory, new FakeIWebLogger(), new FakeMemoryCache()).AddRangeAsync(expectedResult);

var queryFromDb = dbContext.FileIndex.Where(p => p.FileHash == "TEST4" || p.FileHash == "TEST5").ToList();
Assert.AreEqual(expectedResult.FirstOrDefault()?.FileHash, queryFromDb.FirstOrDefault()?.FileHash);
Assert.AreEqual(expectedResult[1].FileHash, queryFromDb[1].FileHash);
}
new FileIndexItem { FileHash = "TEST4" }, new FileIndexItem { FileHash = "TEST5" }
};
var serviceScopeFactory = CreateNewScope();
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase("MovieListDatabase")
.Options;
var dbContext = new ConcurrencyExceptionApplicationDbContext(options);

var webLogger = new FakeIWebLogger();
await new Query(dbContext,
new AppSettings { AddMemoryCache = false }, serviceScopeFactory, webLogger,
new FakeMemoryCache()).AddRangeAsync(expectedResult);

private class ConException : ApplicationDbContext
Assert.AreEqual("[AddRangeAsync] save failed after DbUpdateConcurrencyException",
webLogger.TrackedExceptions[0].Item2);
}

private class ConcurrencyExceptionApplicationDbContext : ApplicationDbContext
{
public ConcurrencyExceptionApplicationDbContext(DbContextOptions options) : base(options)
{
public ConException(DbContextOptions options) : base(options)
{
}
}

public override DbSet<FileIndexItem> FileIndex
public override DbSet<FileIndexItem> FileIndex
{
get => throw new DbUpdateConcurrencyException();
set
{
get => throw new DbUpdateConcurrencyException();
set
{
// do nothing
}
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) {
throw new DbUpdateConcurrencyException();
// do nothing
}
}

[TestMethod]
public async Task AddRangeAsync_DbUpdateConcurrencyException()

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
var expectedResult = new List<FileIndexItem>
{
new FileIndexItem {FileHash = "TEST4"},
new FileIndexItem {FileHash = "TEST5"}
};
var serviceScopeFactory = CreateNewScope();
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "MovieListDatabase")
.Options;
var dbContext = new ConException(options);

var webLogger = new FakeIWebLogger();
await new Query(dbContext,
new AppSettings {
AddMemoryCache = false
}, serviceScopeFactory, webLogger, new FakeMemoryCache()).AddRangeAsync(expectedResult);

Assert.AreEqual("[AddRangeAsync] save failed after DbUpdateConcurrencyException",webLogger.TrackedExceptions[0].Item2);
throw new DbUpdateConcurrencyException();
}
}
}

0 comments on commit 71e1b23

Please sign in to comment.