513fa1aa16
Comment/XML-doc changes only: - add summaries to ~10k test methods, fixtures, fakes and helpers (+ <param> on theories, <returns> on async Task methods, <inheritdoc/> on interface implementations the checker can resolve) - strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N, #NN, Component-0NN) from comments, keeping the explanatory text; reword false positives in comments only - real docs on fakes implementing BCL/library interfaces (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime) - reword the last 5 src/ false positives (CWE-1236, failures-1, year-0001, M365) Only non-comment edits: four one-line nested classes split across lines so members can carry docs. Build 0 errors / 0 warnings.
130 lines
5.6 KiB
C#
130 lines
5.6 KiB
C#
using Microsoft.AspNetCore.DataProtection;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment;
|
|
using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests;
|
|
|
|
/// <summary>
|
|
/// Test DbContext that adapts SQL Server-specific features for SQLite:
|
|
/// - Maps DateTimeOffset to sortable ISO 8601 strings (SQLite has no native DateTimeOffset ORDER BY)
|
|
/// - Replaces SQL Server RowVersion with a nullable byte[] column (SQLite can't auto-generate rowversion)
|
|
///
|
|
/// Constructed with an explicit ephemeral Data Protection provider so secret-bearing
|
|
/// columns are write-capable in tests. The schema-only no-provider constructor would
|
|
/// throw on a secret-column write; passing a provider here
|
|
/// makes the test fixture's intent explicit at the call site.
|
|
/// </summary>
|
|
public class SqliteTestDbContext : ScadaBridgeDbContext
|
|
{
|
|
/// <summary>Initializes the context with the given SQLite options and an ephemeral data protection provider.</summary>
|
|
/// <param name="options">The EF options configured for the SQLite provider.</param>
|
|
public SqliteTestDbContext(DbContextOptions<ScadaBridgeDbContext> options)
|
|
: base(options, new EphemeralDataProtectionProvider())
|
|
{
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
// SQLite cannot auto-generate SQL Server rowversion values.
|
|
// Replace with a nullable byte[] column so inserts don't fail with NOT NULL constraint.
|
|
modelBuilder.Entity<DeploymentRecord>(builder =>
|
|
{
|
|
builder.Property(d => d.RowVersion)
|
|
.IsRequired(false)
|
|
.IsConcurrencyToken(false)
|
|
.ValueGeneratedNever();
|
|
});
|
|
|
|
// Note: the central dbo.AuditLog persisted computed columns
|
|
// (JSON_VALUE-based) are neutralized for non-SQL-Server providers inside
|
|
// ScadaBridgeDbContext.OnModelCreating itself, so every SQLite test context —
|
|
// including ones that construct ScadaBridgeDbContext directly rather than via
|
|
// this helper — gets the strip. Nothing to do here.
|
|
|
|
// Convert DateTimeOffset to ISO 8601 string for SQLite so ORDER BY works
|
|
var converter = new ValueConverter<DateTimeOffset, string>(
|
|
v => v.UtcDateTime.ToString("o"),
|
|
v => DateTimeOffset.Parse(v));
|
|
|
|
var nullableConverter = new ValueConverter<DateTimeOffset?, string?>(
|
|
v => v.HasValue ? v.Value.UtcDateTime.ToString("o") : null,
|
|
v => v != null ? DateTimeOffset.Parse(v) : null);
|
|
|
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
|
{
|
|
foreach (var property in entityType.GetProperties())
|
|
{
|
|
if (property.ClrType == typeof(DateTimeOffset))
|
|
{
|
|
property.SetValueConverter(converter);
|
|
property.SetColumnType("TEXT");
|
|
}
|
|
else if (property.ClrType == typeof(DateTimeOffset?))
|
|
{
|
|
property.SetValueConverter(nullableConverter);
|
|
property.SetColumnType("TEXT");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class SqliteTestHelper
|
|
{
|
|
/// <summary>Creates a context backed by a fresh in-memory SQLite database with the schema created.</summary>
|
|
/// <returns>The open in-memory test context.</returns>
|
|
public static ScadaBridgeDbContext CreateInMemoryContext()
|
|
{
|
|
var options = new DbContextOptionsBuilder<ScadaBridgeDbContext>()
|
|
.UseSqlite("DataSource=:memory:")
|
|
.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
|
|
.Options;
|
|
|
|
var context = new SqliteTestDbContext(options);
|
|
context.Database.OpenConnection();
|
|
context.Database.EnsureCreated();
|
|
return context;
|
|
}
|
|
|
|
/// <summary>
|
|
/// In-memory SQLite context with EF command interceptors attached — lets a
|
|
/// test observe the actual SQL a repository emits (e.g. count DELETE statements
|
|
/// issued by a batched purge).
|
|
/// </summary>
|
|
/// <param name="interceptors">The EF interceptors to attach to the context.</param>
|
|
/// <returns>The open in-memory test context with the interceptors attached.</returns>
|
|
public static ScadaBridgeDbContext CreateInMemoryContext(params IInterceptor[] interceptors)
|
|
{
|
|
var options = new DbContextOptionsBuilder<ScadaBridgeDbContext>()
|
|
.UseSqlite("DataSource=:memory:")
|
|
.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
|
|
.AddInterceptors(interceptors)
|
|
.Options;
|
|
|
|
var context = new SqliteTestDbContext(options);
|
|
context.Database.OpenConnection();
|
|
context.Database.EnsureCreated();
|
|
return context;
|
|
}
|
|
|
|
/// <summary>Creates a context backed by a SQLite database file.</summary>
|
|
/// <param name="dbPath">The path of the SQLite database file.</param>
|
|
/// <returns>The file-backed test context.</returns>
|
|
public static ScadaBridgeDbContext CreateFileContext(string dbPath)
|
|
{
|
|
var options = new DbContextOptionsBuilder<ScadaBridgeDbContext>()
|
|
.UseSqlite($"DataSource={dbPath}")
|
|
.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
|
|
.Options;
|
|
|
|
var context = new SqliteTestDbContext(options);
|
|
return context;
|
|
}
|
|
}
|