Reformat / cleanup
This commit is contained in:
@@ -16,12 +16,12 @@ public class ArchitectureFitnessTests
|
||||
private const string FacadeProject = "src/CBDD/ZB.MOM.WW.CBDD.csproj";
|
||||
|
||||
/// <summary>
|
||||
/// Executes Solution_DependencyGraph_ShouldRemainAcyclic_AndFollowLayerDirection.
|
||||
/// Executes Solution_DependencyGraph_ShouldRemainAcyclic_AndFollowLayerDirection.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Solution_DependencyGraph_ShouldRemainAcyclic_AndFollowLayerDirection()
|
||||
{
|
||||
var repoRoot = FindRepositoryRoot();
|
||||
string repoRoot = FindRepositoryRoot();
|
||||
var projectGraph = LoadSolutionProjectGraph(repoRoot);
|
||||
|
||||
// Explicit layer rules
|
||||
@@ -30,28 +30,27 @@ public class ArchitectureFitnessTests
|
||||
projectGraph[CoreProject].ShouldBe(new[] { BsonProject });
|
||||
projectGraph[FacadeProject]
|
||||
.OrderBy(v => v, StringComparer.Ordinal)
|
||||
.ShouldBe(new[] { BsonProject, CoreProject, SourceGeneratorsProject }.OrderBy(v => v, StringComparer.Ordinal));
|
||||
.ShouldBe(new[] { BsonProject, CoreProject, SourceGeneratorsProject }.OrderBy(v => v,
|
||||
StringComparer.Ordinal));
|
||||
|
||||
// Source projects should not depend on tests.
|
||||
foreach (var kvp in projectGraph.Where(p => p.Key.StartsWith("src/", StringComparison.Ordinal)))
|
||||
{
|
||||
kvp.Value.Any(dep => dep.StartsWith("tests/", StringComparison.Ordinal))
|
||||
.ShouldBeFalse($"{kvp.Key} must not reference test projects.");
|
||||
}
|
||||
|
||||
HasCycle(projectGraph)
|
||||
.ShouldBeFalse("Project references must remain acyclic.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes HighLevelCollectionApi_ShouldNotExpandRawBsonReaderWriterSurface.
|
||||
/// Executes HighLevelCollectionApi_ShouldNotExpandRawBsonReaderWriterSurface.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void HighLevelCollectionApi_ShouldNotExpandRawBsonReaderWriterSurface()
|
||||
{
|
||||
var lowLevelTypes = new[] { typeof(BsonSpanReader), typeof(BsonSpanWriter) };
|
||||
|
||||
var collectionOffenders = typeof(DocumentCollection<,>)
|
||||
string[] collectionOffenders = typeof(DocumentCollection<,>)
|
||||
.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
.Where(m => lowLevelTypes.Any(t => MethodUsesType(m, t)))
|
||||
.Select(m => m.Name)
|
||||
@@ -61,7 +60,7 @@ public class ArchitectureFitnessTests
|
||||
|
||||
collectionOffenders.ShouldBeEmpty();
|
||||
|
||||
var dbContextOffenders = typeof(DocumentDbContext)
|
||||
string[] dbContextOffenders = typeof(DocumentDbContext)
|
||||
.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
.Where(m => lowLevelTypes.Any(t => MethodUsesType(m, t)))
|
||||
.Select(m => m.Name)
|
||||
@@ -72,7 +71,7 @@ public class ArchitectureFitnessTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes CollectionAndIndexOrchestration_ShouldUseStoragePortInternally.
|
||||
/// Executes CollectionAndIndexOrchestration_ShouldUseStoragePortInternally.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void CollectionAndIndexOrchestration_ShouldUseStoragePortInternally()
|
||||
@@ -84,22 +83,23 @@ public class ArchitectureFitnessTests
|
||||
typeof(BTreeIndex),
|
||||
typeof(CollectionIndexManager<,>),
|
||||
typeof(CollectionSecondaryIndex<,>),
|
||||
typeof(VectorSearchIndex),
|
||||
typeof(VectorSearchIndex)
|
||||
};
|
||||
|
||||
var fieldOffenders = targetTypes
|
||||
string[] fieldOffenders = targetTypes
|
||||
.SelectMany(t => t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(f => f.FieldType == typeof(StorageEngine))
|
||||
.Select(f => $"{t.Name}.{f.Name}"))
|
||||
.OrderBy(v => v)
|
||||
.ToArray();
|
||||
|
||||
fieldOffenders.ShouldBeEmpty("Collection/index orchestration should hold IStorageEngine instead of concrete StorageEngine.");
|
||||
fieldOffenders.ShouldBeEmpty(
|
||||
"Collection/index orchestration should hold IStorageEngine instead of concrete StorageEngine.");
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<string>> LoadSolutionProjectGraph(string repoRoot)
|
||||
{
|
||||
var solutionPath = Path.Combine(repoRoot, "CBDD.slnx");
|
||||
string solutionPath = Path.Combine(repoRoot, "CBDD.slnx");
|
||||
var solutionDoc = XDocument.Load(solutionPath);
|
||||
|
||||
var projects = solutionDoc
|
||||
@@ -115,11 +115,11 @@ public class ArchitectureFitnessTests
|
||||
_ => new List<string>(),
|
||||
StringComparer.Ordinal);
|
||||
|
||||
foreach (var project in projects)
|
||||
foreach (string project in projects)
|
||||
{
|
||||
var projectFile = Path.Combine(repoRoot, project);
|
||||
string projectFile = Path.Combine(repoRoot, project);
|
||||
var projectDoc = XDocument.Load(projectFile);
|
||||
var projectDir = Path.GetDirectoryName(projectFile)!;
|
||||
string projectDir = Path.GetDirectoryName(projectFile)!;
|
||||
|
||||
var refs = projectDoc
|
||||
.Descendants()
|
||||
@@ -127,7 +127,8 @@ public class ArchitectureFitnessTests
|
||||
.Select(e => e.Attribute("Include")?.Value)
|
||||
.Where(v => !string.IsNullOrWhiteSpace(v))
|
||||
.Select(v => v!.Replace('\\', '/'))
|
||||
.Select(v => NormalizePath(Path.GetRelativePath(repoRoot, Path.GetFullPath(Path.Combine(projectDir, v)))))
|
||||
.Select(v =>
|
||||
NormalizePath(Path.GetRelativePath(repoRoot, Path.GetFullPath(Path.Combine(projectDir, v)))))
|
||||
.Where(projects.Contains)
|
||||
.Distinct(StringComparer.Ordinal)
|
||||
.OrderBy(v => v, StringComparer.Ordinal)
|
||||
@@ -143,30 +144,20 @@ public class ArchitectureFitnessTests
|
||||
{
|
||||
var state = graph.Keys.ToDictionary(k => k, _ => 0, StringComparer.Ordinal);
|
||||
|
||||
foreach (var node in graph.Keys)
|
||||
{
|
||||
foreach (string node in graph.Keys)
|
||||
if (state[node] == 0 && Visit(node))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
bool Visit(string node)
|
||||
{
|
||||
state[node] = 1; // visiting
|
||||
foreach (var dep in graph[node])
|
||||
foreach (string dep in graph[node])
|
||||
{
|
||||
if (state[dep] == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (state[dep] == 1) return true;
|
||||
|
||||
if (state[dep] == 0 && Visit(dep))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (state[dep] == 0 && Visit(dep)) return true;
|
||||
}
|
||||
|
||||
state[node] = 2; // visited
|
||||
@@ -176,30 +167,19 @@ public class ArchitectureFitnessTests
|
||||
|
||||
private static bool MethodUsesType(MethodInfo method, Type forbidden)
|
||||
{
|
||||
if (TypeContains(method.ReturnType, forbidden))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (TypeContains(method.ReturnType, forbidden)) return true;
|
||||
|
||||
return method.GetParameters().Any(p => TypeContains(p.ParameterType, forbidden));
|
||||
}
|
||||
|
||||
private static bool TypeContains(Type inspected, Type forbidden)
|
||||
{
|
||||
if (inspected == forbidden)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (inspected == forbidden) return true;
|
||||
|
||||
if (inspected.HasElementType && inspected.GetElementType() is { } elementType && TypeContains(elementType, forbidden))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (inspected.HasElementType && inspected.GetElementType() is { } elementType &&
|
||||
TypeContains(elementType, forbidden)) return true;
|
||||
|
||||
if (!inspected.IsGenericType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!inspected.IsGenericType) return false;
|
||||
|
||||
return inspected.GetGenericArguments().Any(t => TypeContains(t, forbidden));
|
||||
}
|
||||
@@ -209,11 +189,8 @@ public class ArchitectureFitnessTests
|
||||
var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (current != null)
|
||||
{
|
||||
var solutionPath = Path.Combine(current.FullName, "CBDD.slnx");
|
||||
if (File.Exists(solutionPath))
|
||||
{
|
||||
return current.FullName;
|
||||
}
|
||||
string solutionPath = Path.Combine(current.FullName, "CBDD.slnx");
|
||||
if (File.Exists(solutionPath)) return current.FullName;
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
@@ -222,5 +199,7 @@ public class ArchitectureFitnessTests
|
||||
}
|
||||
|
||||
private static string NormalizePath(string path)
|
||||
=> path.Replace('\\', '/');
|
||||
}
|
||||
{
|
||||
return path.Replace('\\', '/');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user