Later slices did not touch 56-57 paths. Add remaining projects.md graph bans and document Simulation's direct Schedule reference. Co-authored-by: Cursor <cursoragent@cursor.com>
165 lines
6.3 KiB
C#
165 lines
6.3 KiB
C#
using HSchool.Ai;
|
|
using HSchool.Content;
|
|
using HSchool.People;
|
|
using HSchool.Protocol;
|
|
using HSchool.Schedule;
|
|
using HSchool.Simulation;
|
|
|
|
namespace HSchool.Architecture.Tests;
|
|
|
|
public class LayerBoundaryTests
|
|
{
|
|
private static readonly string[] LibraryFolders =
|
|
[
|
|
"HSchool.Protocol",
|
|
"HSchool.Content",
|
|
"HSchool.People",
|
|
"HSchool.Schedule",
|
|
"HSchool.Ai",
|
|
"HSchool.Simulation"
|
|
];
|
|
|
|
private static readonly string[] OldTestProjects =
|
|
[
|
|
"HSchool.People.Tests",
|
|
"HSchool.Ai.Tests",
|
|
"HSchool.Schedule.Tests",
|
|
"HSchool.Simulation.Tests"
|
|
];
|
|
|
|
[Fact]
|
|
public void Protocol_DoesNotReferenceArchAspNetSocketsContentOrSimulation()
|
|
{
|
|
var names = References(typeof(ProtocolCodec));
|
|
AssertNoArchAspNetOrSockets(names);
|
|
Assert.DoesNotContain("HSchool.Content", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.People", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Schedule", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Ai", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Simulation", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void Content_DoesNotReferenceArchAspNetSocketsProtocolPeopleScheduleAiOrSimulation()
|
|
{
|
|
var names = References(typeof(MapLayout));
|
|
AssertNoArchAspNetOrSockets(names);
|
|
Assert.DoesNotContain("HSchool.Protocol", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.People", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Schedule", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Ai", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Simulation", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(typeof(RosterGenerator))]
|
|
[InlineData(typeof(TimetablePlanner))]
|
|
[InlineData(typeof(WalkGraph))]
|
|
public void PeopleScheduleAi_DoNotReferenceArchAspNetOrSockets(Type marker)
|
|
{
|
|
var names = References(marker);
|
|
AssertNoArchAspNetOrSockets(names);
|
|
Assert.DoesNotContain("HSchool.Protocol", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Simulation", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void People_DoesNotReferenceScheduleOrAi()
|
|
{
|
|
var names = References(typeof(RosterGenerator));
|
|
Assert.DoesNotContain("HSchool.Schedule", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Ai", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void Schedule_DoesNotReferencePeopleOrAi()
|
|
{
|
|
var names = References(typeof(TimetablePlanner));
|
|
Assert.DoesNotContain("HSchool.People", names, StringComparer.Ordinal);
|
|
Assert.DoesNotContain("HSchool.Ai", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void Simulation_DoesNotReferenceAspNetSocketsOrProtocol()
|
|
{
|
|
var names = References(typeof(School));
|
|
Assert.DoesNotContain(names, name => name.Contains("AspNet", StringComparison.OrdinalIgnoreCase));
|
|
Assert.DoesNotContain(names, name => name.Contains("Sockets", StringComparison.OrdinalIgnoreCase));
|
|
Assert.DoesNotContain("HSchool.Protocol", names, StringComparer.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void SixLibrarySources_DoNotUseWallClock()
|
|
{
|
|
foreach (var folder in LibraryFolders)
|
|
{
|
|
var root = Path.Combine(RepoRoot(), "src", folder);
|
|
Assert.True(Directory.Exists(root), root);
|
|
foreach (var path in SourceFiles(root))
|
|
{
|
|
var text = File.ReadAllText(path);
|
|
Assert.DoesNotContain("DateTime.Now", text, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("DateTime.UtcNow", text, StringComparison.Ordinal);
|
|
// Unused `using System.Net.Http` never becomes a referenced assembly.
|
|
Assert.DoesNotContain("System.Net.Http", text, StringComparison.Ordinal);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void ArchitectureTests_DoNotReferenceHostOrNetArchTest()
|
|
{
|
|
var csproj = File.ReadAllText(
|
|
Path.Combine(RepoRoot(), "tests", "HSchool.Architecture.Tests", "HSchool.Architecture.Tests.csproj"));
|
|
Assert.DoesNotContain("HSchool.Server", csproj, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("HSchool.AppHost", csproj, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("NetArchTest", csproj, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void PeopleAiScheduleSimulationTests_NoLongerCarryLayerBans()
|
|
{
|
|
foreach (var project in OldTestProjects)
|
|
{
|
|
var root = Path.Combine(RepoRoot(), "tests", project);
|
|
Assert.True(Directory.Exists(root), root);
|
|
foreach (var path in SourceFiles(root))
|
|
{
|
|
var text = File.ReadAllText(path);
|
|
Assert.DoesNotContain("Assembly_DoesNotReference", text, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("Sources_DoNotUseWallClock", text, StringComparison.Ordinal);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static IEnumerable<string> SourceFiles(string root) =>
|
|
Directory.EnumerateFiles(root, "*.cs", SearchOption.AllDirectories)
|
|
.Where(path => path.Split(Path.DirectorySeparatorChar).All(part => part is not ("bin" or "obj")));
|
|
|
|
private static string[] References(Type marker) =>
|
|
[.. marker.Assembly.GetReferencedAssemblies().Select(assembly => assembly.Name!)];
|
|
|
|
private static void AssertNoArchAspNetOrSockets(IEnumerable<string> names)
|
|
{
|
|
Assert.DoesNotContain(names, name => name.StartsWith("Arch", StringComparison.OrdinalIgnoreCase));
|
|
Assert.DoesNotContain(names, name => name.Contains("AspNet", StringComparison.OrdinalIgnoreCase));
|
|
Assert.DoesNotContain(names, name => name.Contains("Sockets", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
private static string RepoRoot()
|
|
{
|
|
var dir = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (dir is not null && !File.Exists(Path.Combine(dir.FullName, "h-school.sln")))
|
|
{
|
|
dir = dir.Parent;
|
|
}
|
|
|
|
if (dir is null)
|
|
{
|
|
throw new InvalidOperationException("Could not find h-school.sln from the test output directory.");
|
|
}
|
|
|
|
return dir.FullName;
|
|
}
|
|
}
|