Initialize CBDD solution and add a .NET-focused gitignore for generated artifacts.
This commit is contained in:
160
tests/CBDD.Tests/MaintenanceDiagnosticsAndMigrationTests.cs
Normal file
160
tests/CBDD.Tests/MaintenanceDiagnosticsAndMigrationTests.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System.IO.Compression;
|
||||
using ZB.MOM.WW.CBDD.Core.Compression;
|
||||
using ZB.MOM.WW.CBDD.Core.Storage;
|
||||
using ZB.MOM.WW.CBDD.Shared;
|
||||
|
||||
namespace ZB.MOM.WW.CBDD.Tests;
|
||||
|
||||
public class MaintenanceDiagnosticsAndMigrationTests
|
||||
{
|
||||
[Fact]
|
||||
public void DiagnosticsApis_ShouldReturnPageUsageCompressionAndFragmentationData()
|
||||
{
|
||||
var dbPath = NewDbPath();
|
||||
|
||||
try
|
||||
{
|
||||
var options = new CompressionOptions
|
||||
{
|
||||
EnableCompression = true,
|
||||
MinSizeBytes = 0,
|
||||
MinSavingsPercent = 0,
|
||||
Codec = CompressionCodec.Brotli,
|
||||
Level = CompressionLevel.Fastest
|
||||
};
|
||||
|
||||
using var db = new TestDbContext(dbPath, options);
|
||||
for (var i = 0; i < 40; i++)
|
||||
{
|
||||
db.Users.Insert(new User
|
||||
{
|
||||
Name = BuildPayload(i, 9000),
|
||||
Age = i
|
||||
});
|
||||
}
|
||||
|
||||
db.SaveChanges();
|
||||
db.ForceCheckpoint();
|
||||
|
||||
var byType = db.GetPageUsageByPageType();
|
||||
byType.Count.ShouldBeGreaterThan(0);
|
||||
byType.Any(x => x.PageType == PageType.Data && x.PageCount > 0).ShouldBeTrue();
|
||||
|
||||
var byCollection = db.GetPageUsageByCollection();
|
||||
byCollection.Any(x => x.CollectionName.Equals("users", StringComparison.OrdinalIgnoreCase)).ShouldBeTrue();
|
||||
|
||||
var compressionByCollection = db.GetCompressionRatioByCollection();
|
||||
var usersCompression = compressionByCollection.First(x => x.CollectionName.Equals("users", StringComparison.OrdinalIgnoreCase));
|
||||
usersCompression.DocumentCount.ShouldBeGreaterThan(0);
|
||||
usersCompression.BytesBeforeCompression.ShouldBeGreaterThan(0);
|
||||
usersCompression.BytesAfterCompression.ShouldBeGreaterThan(0);
|
||||
|
||||
var freeList = db.GetFreeListSummary();
|
||||
freeList.PageCount.ShouldBeGreaterThan(0u);
|
||||
|
||||
var fragmentation = db.GetFragmentationMap();
|
||||
fragmentation.Pages.Count.ShouldBeGreaterThan(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CleanupFiles(dbPath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MigrateCompression_DryRunAndApply_ShouldReturnDeterministicStatsAndPreserveData()
|
||||
{
|
||||
var dbPath = NewDbPath();
|
||||
|
||||
try
|
||||
{
|
||||
using var db = new TestDbContext(dbPath, CompressionOptions.Default);
|
||||
var ids = new List<ZB.MOM.WW.CBDD.Bson.ObjectId>();
|
||||
|
||||
for (var i = 0; i < 60; i++)
|
||||
{
|
||||
ids.Add(db.Users.Insert(new User
|
||||
{
|
||||
Name = BuildPayload(i, 12000),
|
||||
Age = i % 17
|
||||
}));
|
||||
}
|
||||
|
||||
db.SaveChanges();
|
||||
db.ForceCheckpoint();
|
||||
|
||||
var dryRun = db.MigrateCompression(new CompressionMigrationOptions
|
||||
{
|
||||
DryRun = true,
|
||||
Codec = CompressionCodec.Deflate,
|
||||
Level = CompressionLevel.Fastest,
|
||||
MinSizeBytes = 0,
|
||||
MinSavingsPercent = 0,
|
||||
IncludeCollections = ["users"]
|
||||
});
|
||||
|
||||
dryRun.DryRun.ShouldBeTrue();
|
||||
dryRun.DocumentsScanned.ShouldBeGreaterThan(0);
|
||||
dryRun.BytesBefore.ShouldBeGreaterThan(0);
|
||||
dryRun.BytesEstimatedAfter.ShouldBeGreaterThan(0);
|
||||
|
||||
var apply = db.MigrateCompression(new CompressionMigrationOptions
|
||||
{
|
||||
DryRun = false,
|
||||
Codec = CompressionCodec.Deflate,
|
||||
Level = CompressionLevel.Fastest,
|
||||
MinSizeBytes = 0,
|
||||
MinSavingsPercent = 0,
|
||||
IncludeCollections = ["users"]
|
||||
});
|
||||
|
||||
apply.DryRun.ShouldBeFalse();
|
||||
apply.DocumentsScanned.ShouldBeGreaterThan(0);
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var user = db.Users.FindById(id);
|
||||
user.ShouldNotBeNull();
|
||||
user!.Name.Length.ShouldBeGreaterThan(1000);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
CleanupFiles(dbPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildPayload(int seed, int approxLength)
|
||||
{
|
||||
var builder = new System.Text.StringBuilder(approxLength + 128);
|
||||
var i = 0;
|
||||
while (builder.Length < approxLength)
|
||||
{
|
||||
builder.Append("diag-migrate-");
|
||||
builder.Append(seed.ToString("D4"));
|
||||
builder.Append('-');
|
||||
builder.Append(i.ToString("D6"));
|
||||
builder.Append('|');
|
||||
i++;
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string NewDbPath()
|
||||
=> Path.Combine(Path.GetTempPath(), $"maint_diag_migrate_{Guid.NewGuid():N}.db");
|
||||
|
||||
private static void CleanupFiles(string dbPath)
|
||||
{
|
||||
var walPath = Path.ChangeExtension(dbPath, ".wal");
|
||||
var markerPath = $"{dbPath}.compact.state";
|
||||
var tempPath = $"{dbPath}.compact.tmp";
|
||||
var backupPath = $"{dbPath}.compact.bak";
|
||||
|
||||
if (File.Exists(dbPath)) File.Delete(dbPath);
|
||||
if (File.Exists(walPath)) File.Delete(walPath);
|
||||
if (File.Exists(markerPath)) File.Delete(markerPath);
|
||||
if (File.Exists(tempPath)) File.Delete(tempPath);
|
||||
if (File.Exists(backupPath)) File.Delete(backupPath);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user