diff --git a/SVSim.Bootstrap/Importers/ReferenceDataImporter.cs b/SVSim.Bootstrap/Importers/ReferenceDataImporter.cs
index a65fe81..a7a8002 100644
--- a/SVSim.Bootstrap/Importers/ReferenceDataImporter.cs
+++ b/SVSim.Bootstrap/Importers/ReferenceDataImporter.cs
@@ -15,14 +15,30 @@ namespace SVSim.Bootstrap.Importers;
///
public class ReferenceDataImporter
{
+ private readonly TextWriter _out;
+ private readonly TextWriter _err;
+
+ public ReferenceDataImporter() : this(Console.Out, Console.Error) { }
+
+ ///
+ /// Pass for both to silence progress banners (tests
+ /// instantiate this importer ~500 times per run; the captured stdout otherwise OOMs
+ /// the NUnit trx serializer).
+ ///
+ public ReferenceDataImporter(TextWriter output, TextWriter error)
+ {
+ _out = output;
+ _err = error;
+ }
+
public async Task ImportAllAsync(SVSimDbContext context, string dataDir)
{
if (!Directory.Exists(dataDir))
{
- Console.Error.WriteLine($"[ReferenceDataImporter] Data dir missing: {dataDir}");
+ _err.WriteLine($"[ReferenceDataImporter] Data dir missing: {dataDir}");
return;
}
- Console.WriteLine($"[ReferenceDataImporter] Reading CSVs from {dataDir}...");
+ _out.WriteLine($"[ReferenceDataImporter] Reading CSVs from {dataDir}...");
await ImportClasses(context, dataDir);
await ImportLeaderSkins(context, dataDir);
@@ -34,10 +50,10 @@ public class ReferenceDataImporter
await ImportRankInfo(context, dataDir);
await ImportClassExp(context, dataDir);
- Console.WriteLine("[ReferenceDataImporter] Done.");
+ _out.WriteLine("[ReferenceDataImporter] Done.");
}
- private static async Task ImportClasses(SVSimDbContext ctx, string dir)
+ private async Task ImportClasses(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "classes.csv");
var existing = await ctx.Classes.ToDictionaryAsync(c => c.Id);
@@ -51,10 +67,10 @@ public class ReferenceDataImporter
else { ctx.Classes.Add(r); created++; }
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] Classes: +{created} / ~{updated}");
+ _out.WriteLine($"[ReferenceDataImporter] Classes: +{created} / ~{updated}");
}
- private static async Task ImportLeaderSkins(SVSimDbContext ctx, string dir)
+ private async Task ImportLeaderSkins(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "leaderskins.csv");
// CSV writes class_chara_id=0 for neutral/unassigned; the FK column is nullable.
@@ -74,10 +90,10 @@ public class ReferenceDataImporter
else { ctx.LeaderSkins.Add(r); created++; }
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] LeaderSkins: +{created} / ~{updated}");
+ _out.WriteLine($"[ReferenceDataImporter] LeaderSkins: +{created} / ~{updated}");
}
- private static async Task ImportSleeves(SVSimDbContext ctx, string dir)
+ private async Task ImportSleeves(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "sleeves.csv");
var existing = (await ctx.Sleeves.ToListAsync()).ToHashSet();
@@ -88,10 +104,10 @@ public class ReferenceDataImporter
ctx.Sleeves.Add(r); created++;
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] Sleeves: +{created}");
+ _out.WriteLine($"[ReferenceDataImporter] Sleeves: +{created}");
}
- private static async Task ImportEmblems(SVSimDbContext ctx, string dir)
+ private async Task ImportEmblems(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "emblems.csv");
var existing = (await ctx.Emblems.Select(e => e.Id).ToListAsync()).ToHashSet();
@@ -102,10 +118,10 @@ public class ReferenceDataImporter
ctx.Emblems.Add(r); created++;
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] Emblems: +{created}");
+ _out.WriteLine($"[ReferenceDataImporter] Emblems: +{created}");
}
- private static async Task ImportDegrees(SVSimDbContext ctx, string dir)
+ private async Task ImportDegrees(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "degrees.csv");
var existing = (await ctx.Degrees.Select(e => e.Id).ToListAsync()).ToHashSet();
@@ -116,10 +132,10 @@ public class ReferenceDataImporter
ctx.Degrees.Add(r); created++;
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] Degrees: +{created}");
+ _out.WriteLine($"[ReferenceDataImporter] Degrees: +{created}");
}
- private static async Task ImportBattlefields(SVSimDbContext ctx, string dir)
+ private async Task ImportBattlefields(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "battlefields.csv");
var existing = await ctx.Battlefields.ToDictionaryAsync(b => b.Id);
@@ -133,10 +149,10 @@ public class ReferenceDataImporter
else { ctx.Battlefields.Add(r); created++; }
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] Battlefields: +{created} / ~{updated}");
+ _out.WriteLine($"[ReferenceDataImporter] Battlefields: +{created} / ~{updated}");
}
- private static async Task ImportMyPageBackgrounds(SVSimDbContext ctx, string dir)
+ private async Task ImportMyPageBackgrounds(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "mypagebackgrounds.csv");
var existing = (await ctx.MyPageBackgrounds.Select(e => e.Id).ToListAsync()).ToHashSet();
@@ -147,10 +163,10 @@ public class ReferenceDataImporter
ctx.MyPageBackgrounds.Add(r); created++;
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] MyPageBackgrounds: +{created}");
+ _out.WriteLine($"[ReferenceDataImporter] MyPageBackgrounds: +{created}");
}
- private static async Task ImportRankInfo(SVSimDbContext ctx, string dir)
+ private async Task ImportRankInfo(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "ranks.csv");
var existing = await ctx.RankInfo.ToDictionaryAsync(r => r.Id);
@@ -164,7 +180,7 @@ public class ReferenceDataImporter
else { ctx.RankInfo.Add(r); created++; }
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] RankInfo: +{created} / ~{updated}");
+ _out.WriteLine($"[ReferenceDataImporter] RankInfo: +{created} / ~{updated}");
}
private static bool ApplyRankUpdates(RankInfoEntry e, RankInfoEntry r)
@@ -189,7 +205,7 @@ public class ReferenceDataImporter
return changed;
}
- private static async Task ImportClassExp(SVSimDbContext ctx, string dir)
+ private async Task ImportClassExp(SVSimDbContext ctx, string dir)
{
var rows = ReadCsv(dir, "classexp.csv");
var existing = await ctx.ClassExpCurve.ToDictionaryAsync(c => c.Id);
@@ -203,15 +219,15 @@ public class ReferenceDataImporter
else { ctx.ClassExpCurve.Add(r); created++; }
}
await ctx.SaveChangesAsync();
- Console.WriteLine($"[ReferenceDataImporter] ClassExp: +{created} / ~{updated}");
+ _out.WriteLine($"[ReferenceDataImporter] ClassExp: +{created} / ~{updated}");
}
- private static List ReadCsv(string dir, string fileName) where TMap : ClassMap, new()
+ private List ReadCsv(string dir, string fileName) where TMap : ClassMap, new()
{
string path = Path.Combine(dir, fileName);
if (!File.Exists(path))
{
- Console.Error.WriteLine($"[ReferenceDataImporter] Missing CSV: {path}");
+ _err.WriteLine($"[ReferenceDataImporter] Missing CSV: {path}");
return new List();
}
using var reader = new StreamReader(path);
diff --git a/SVSim.EmulatedEntrypoint/Program.cs b/SVSim.EmulatedEntrypoint/Program.cs
index 2a41a49..0ef2d65 100644
--- a/SVSim.EmulatedEntrypoint/Program.cs
+++ b/SVSim.EmulatedEntrypoint/Program.cs
@@ -151,7 +151,13 @@ public class Program
}
}
- app.UseHttpLogging();
+ // HttpLogging captures full request/response per call. In Testing it pipes ~3 GB of
+ // stdout into NUnit's per-test result capture across the suite, which OOMs the trx
+ // serializer. Production keeps it on.
+ if (!app.Environment.IsEnvironment("Testing"))
+ {
+ app.UseHttpLogging();
+ }
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
diff --git a/SVSim.EmulatedEntrypoint/appsettings.Testing.json b/SVSim.EmulatedEntrypoint/appsettings.Testing.json
new file mode 100644
index 0000000..0a42f07
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/appsettings.Testing.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Warning",
+ "Microsoft.AspNetCore": "Warning",
+ "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Warning",
+ "Microsoft.EntityFrameworkCore": "Warning"
+ }
+ }
+}
diff --git a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs
index 83b2fea..731a65f 100644
--- a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs
+++ b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs
@@ -78,7 +78,8 @@ internal sealed class SVSimTestFactory : WebApplicationFactory
// production uses so tests exercise the same code path. CardCosmeticRewards skipped —
// FK to Cards would reject every row against the minimal 3-card test seed below.
var dataDir = Path.Combine(AppContext.BaseDirectory, "Data");
- new ReferenceDataImporter().ImportAllAsync(db, dataDir).GetAwaiter().GetResult();
+ new ReferenceDataImporter(TextWriter.Null, TextWriter.Null)
+ .ImportAllAsync(db, dataDir).GetAwaiter().GetResult();
// Seed a minimal card set so card-pool tests can resolve a non-empty pool without
// requiring the full CardImporter tool or a cards.json file. The set is marked