Reformat / cleanup
This commit is contained in:
@@ -1,33 +1,29 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
using System.Collections.Concurrent;
|
||||
using ZB.MOM.WW.CBDD.Bson;
|
||||
using ZB.MOM.WW.CBDD.Bson.Schema;
|
||||
using ZB.MOM.WW.CBDD.Core.Storage;
|
||||
using ZB.MOM.WW.CBDD.Core.Collections;
|
||||
using ZB.MOM.WW.CBDD.Core.Indexing;
|
||||
using ZB.MOM.WW.CBDD.Shared.TestDbContext_TestDbContext_Mappers;
|
||||
using ZB.MOM.WW.CBDD.Core.Storage;
|
||||
using ZB.MOM.WW.CBDD.Shared;
|
||||
using ZB.MOM.WW.CBDD.Shared.TestDbContext_TestDbContext_Mappers;
|
||||
|
||||
namespace ZB.MOM.WW.CBDD.Tests;
|
||||
|
||||
public class SchemaPersistenceTests : IDisposable
|
||||
{
|
||||
private readonly TestDbContext _db;
|
||||
private readonly string _dbPath;
|
||||
private readonly Shared.TestDbContext _db;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchemaPersistenceTests"/> class.
|
||||
/// Initializes a new instance of the <see cref="SchemaPersistenceTests" /> class.
|
||||
/// </summary>
|
||||
public SchemaPersistenceTests()
|
||||
{
|
||||
_dbPath = Path.Combine(Path.GetTempPath(), $"schema_test_{Guid.NewGuid()}.db");
|
||||
_db = new Shared.TestDbContext(_dbPath);
|
||||
_db = new TestDbContext(_dbPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes test resources and removes temporary files.
|
||||
/// Disposes test resources and removes temporary files.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
@@ -36,7 +32,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies BSON schema serialization and deserialization round-trips correctly.
|
||||
/// Verifies BSON schema serialization and deserialization round-trips correctly.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BsonSchema_Serialization_RoundTrip()
|
||||
@@ -65,12 +61,16 @@ public class SchemaPersistenceTests : IDisposable
|
||||
};
|
||||
|
||||
var buffer = new byte[1024];
|
||||
var keyMap = new System.Collections.Concurrent.ConcurrentDictionary<string, ushort>(StringComparer.OrdinalIgnoreCase);
|
||||
var keys = new System.Collections.Concurrent.ConcurrentDictionary<ushort, string>();
|
||||
var keyMap = new ConcurrentDictionary<string, ushort>(StringComparer.OrdinalIgnoreCase);
|
||||
var keys = new ConcurrentDictionary<ushort, string>();
|
||||
|
||||
// Manual registration for schema keys
|
||||
ushort id = 1;
|
||||
foreach (var k in new[] { "person", "id", "name", "age", "address", "city", "fields", "title", "type", "isnullable", "nestedschema", "t", "v", "f", "n", "b", "s", "a", "_v", "0", "1", "2", "3", "4", "5" })
|
||||
foreach (string k in new[]
|
||||
{
|
||||
"person", "id", "name", "age", "address", "city", "fields", "title", "type", "isnullable",
|
||||
"nestedschema", "t", "v", "f", "n", "b", "s", "a", "_v", "0", "1", "2", "3", "4", "5"
|
||||
})
|
||||
{
|
||||
keyMap[k] = id;
|
||||
keys[id] = k;
|
||||
@@ -91,7 +91,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies collection metadata is persisted and reloaded correctly.
|
||||
/// Verifies collection metadata is persisted and reloaded correctly.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void StorageEngine_Collections_Metadata_Persistence()
|
||||
@@ -102,7 +102,8 @@ public class SchemaPersistenceTests : IDisposable
|
||||
PrimaryRootPageId = 10,
|
||||
SchemaRootPageId = 20
|
||||
};
|
||||
meta.Indexes.Add(new IndexMetadata { Name = "age", IsUnique = false, Type = IndexType.BTree, PropertyPaths = ["Age"] });
|
||||
meta.Indexes.Add(new IndexMetadata
|
||||
{ Name = "age", IsUnique = false, Type = IndexType.BTree, PropertyPaths = ["Age"] });
|
||||
|
||||
_db.Storage.SaveCollectionMetadata(meta);
|
||||
|
||||
@@ -116,38 +117,48 @@ public class SchemaPersistenceTests : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies schema versioning appends new schema versions correctly.
|
||||
/// Verifies schema versioning appends new schema versions correctly.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void StorageEngine_Schema_Versioning()
|
||||
{
|
||||
var schema1 = new BsonSchema { Title = "V1", Fields = { new BsonField { Name = "f1", Type = BsonType.String } } };
|
||||
var schema2 = new BsonSchema { Title = "V2", Fields = { new BsonField { Name = "f1", Type = BsonType.String }, new BsonField { Name = "f2", Type = BsonType.Int32 } } };
|
||||
var schema1 = new BsonSchema
|
||||
{ Title = "V1", Fields = { new BsonField { Name = "f1", Type = BsonType.String } } };
|
||||
var schema2 = new BsonSchema
|
||||
{
|
||||
Title = "V2",
|
||||
Fields =
|
||||
{
|
||||
new BsonField { Name = "f1", Type = BsonType.String },
|
||||
new BsonField { Name = "f2", Type = BsonType.Int32 }
|
||||
}
|
||||
};
|
||||
|
||||
var rootId = _db.Storage.AppendSchema(0, schema1);
|
||||
uint rootId = _db.Storage.AppendSchema(0, schema1);
|
||||
rootId.ShouldNotBe(0u);
|
||||
|
||||
var schemas = _db.Storage.GetSchemas(rootId);
|
||||
schemas.Count().ShouldBe(1);
|
||||
schemas[0].Title.ShouldBe("V1");
|
||||
|
||||
var updatedRoot = _db.Storage.AppendSchema(rootId, schema2);
|
||||
uint updatedRoot = _db.Storage.AppendSchema(rootId, schema2);
|
||||
updatedRoot.ShouldBe(rootId);
|
||||
|
||||
schemas = _db.Storage.GetSchemas(rootId);
|
||||
schemas.Count.ShouldBe(2, $"Expected 2 schemas but found {schemas.Count}. Titles: {(schemas.Count > 0 ? string.Join(", ", schemas.Select(s => s.Title)) : "None")}");
|
||||
schemas.Count.ShouldBe(2,
|
||||
$"Expected 2 schemas but found {schemas.Count}. Titles: {(schemas.Count > 0 ? string.Join(", ", schemas.Select(s => s.Title)) : "None")}");
|
||||
schemas[0].Title.ShouldBe("V1");
|
||||
schemas[1].Title.ShouldBe("V2");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies collection startup integrates schema versioning behavior.
|
||||
/// Verifies collection startup integrates schema versioning behavior.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DocumentCollection_Integrates_Schema_Versioning_On_Startup()
|
||||
{
|
||||
// Use a dedicated database for this test to avoid schema pollution from _db
|
||||
var testDbPath = Path.Combine(Path.GetTempPath(), $"schema_versioning_test_{Guid.NewGuid()}.db");
|
||||
string testDbPath = Path.Combine(Path.GetTempPath(), $"schema_versioning_test_{Guid.NewGuid()}.db");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -155,7 +166,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
var schema1 = mapper1.GetSchema();
|
||||
|
||||
// 1. First startup - create DB and initialize Person collection
|
||||
using (var db1 = new Shared.TestDbContext(testDbPath))
|
||||
using (var db1 = new TestDbContext(testDbPath))
|
||||
{
|
||||
// Access only People collection to avoid initializing others
|
||||
var coll = db1.People;
|
||||
@@ -171,7 +182,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
}
|
||||
|
||||
// 2. Restart with SAME schema (should NOT append)
|
||||
using (var db2 = new Shared.TestDbContext(testDbPath))
|
||||
using (var db2 = new TestDbContext(testDbPath))
|
||||
{
|
||||
var coll = db2.People;
|
||||
var meta = db2.Storage.GetCollectionMetadata("people_collection");
|
||||
@@ -186,7 +197,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
// Since we can't change the actual Person class at runtime, this test verifies
|
||||
// that the same schema doesn't get re-appended.
|
||||
// A real-world scenario would involve deploying a new mapper version.
|
||||
using (var db3 = new Shared.TestDbContext(testDbPath))
|
||||
using (var db3 = new TestDbContext(testDbPath))
|
||||
{
|
||||
var coll = db3.People;
|
||||
var meta = db3.Storage.GetCollectionMetadata("people_collection");
|
||||
@@ -205,7 +216,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies persisted documents include the schema version field.
|
||||
/// Verifies persisted documents include the schema version field.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Document_Contains_Schema_Version_Field()
|
||||
@@ -214,7 +225,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
using (var coll = _db.People)
|
||||
{
|
||||
var person = new Person { Name = "John" };
|
||||
var id = coll.Insert(person);
|
||||
int id = coll.Insert(person);
|
||||
_db.SaveChanges();
|
||||
|
||||
coll.Count().ShouldBe(1);
|
||||
@@ -232,7 +243,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
// Read raw bytes from page
|
||||
var pageBuffer = new byte[_db.Storage.PageSize];
|
||||
_db.Storage.ReadPage(location.PageId, 0, pageBuffer);
|
||||
var slotOffset = SlottedPageHeader.Size + (location.SlotIndex * SlotEntry.Size);
|
||||
int slotOffset = SlottedPageHeader.Size + location.SlotIndex * SlotEntry.Size;
|
||||
var slot = SlotEntry.ReadFrom(pageBuffer.AsSpan(slotOffset));
|
||||
var docData = pageBuffer.AsSpan(slot.Offset, slot.Length);
|
||||
|
||||
@@ -241,7 +252,7 @@ public class SchemaPersistenceTests : IDisposable
|
||||
|
||||
// Look for _v (BsonType.Int32 + 2-byte ID)
|
||||
ushort vId = _db.Storage.GetKeyMap()["_v"];
|
||||
string vIdHex = vId.ToString("X4");
|
||||
var vIdHex = vId.ToString("X4");
|
||||
// Reverse endian for hex string check (ushort is LE)
|
||||
string vIdHexLE = vIdHex.Substring(2, 2) + vIdHex.Substring(0, 2);
|
||||
string pattern = "10" + vIdHexLE;
|
||||
@@ -255,4 +266,4 @@ public class SchemaPersistenceTests : IDisposable
|
||||
valueHex.ShouldBe("01000000");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user