Put layer and wall-clock bans in one test project so Content and Protocol fail the same way as People.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -141,6 +141,8 @@ only resolved a status line. Solution-wide is CI.
|
|||||||
same route and commute; the suite does not boot a host, and it does not reference Arch.
|
same route and commute; the suite does not boot a host, and it does not reference Arch.
|
||||||
- Catalog, inheritance, patches and map validation belong in `tests/HSchool.Content.Tests`.
|
- Catalog, inheritance, patches and map validation belong in `tests/HSchool.Content.Tests`.
|
||||||
Feed the loader documents, not disk paths.
|
Feed the loader documents, not disk paths.
|
||||||
|
- Layer bans (Arch, ASP.NET, sockets, wall-clock) belong in `tests/HSchool.Architecture.Tests`.
|
||||||
|
They do not boot a host.
|
||||||
- Protocol changes need a round-trip test **and** a byte-layout assertion on both sides.
|
- Protocol changes need a round-trip test **and** a byte-layout assertion on both sides.
|
||||||
- Server wiring, endpoints and the WebSocket belong in `tests/HSchool.AppHost.Tests`. That suite
|
- Server wiring, endpoints and the WebSocket belong in `tests/HSchool.AppHost.Tests`. That suite
|
||||||
shares one AppHost across all tests (`AppHostFixture`) — keep it that way, booting per test costs
|
shares one AppHost across all tests (`AppHostFixture`) — keep it that way, booting per test costs
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ in-game calendars, a TypeScript client that renders the menus, and .NET Aspire t
|
|||||||
for local runs and integration tests.
|
for local runs and integration tests.
|
||||||
|
|
||||||
What exists today is the shell around a game: a main menu of schools, a creation form, and a
|
What exists today is the shell around a game: a main menu of schools, a creation form, and a
|
||||||
school screen with a running game clock. The school itself is still empty.
|
school screen with a running game clock. People already walk, dress, take lessons and talk.
|
||||||
|
|
||||||
## Stack
|
## Stack
|
||||||
|
|
||||||
@@ -65,7 +65,8 @@ Do **not** add port 5180 or the Aspire dashboard to `tailscale serve`.
|
|||||||
ticking live. Deleting one asks for confirmation first. The footer switches the UI between
|
ticking live. Deleting one asks for confirmation first. The footer switches the UI between
|
||||||
Russian and English; the choice is remembered in the browser.
|
Russian and English; the choice is remembered in the browser.
|
||||||
- **Create a school** — type a name or roll a random one, pick a start date (3 April 2012, 06:00
|
- **Create a school** — type a name or roll a random one, pick a start date (3 April 2012, 06:00
|
||||||
by default). At six schools the create button is disabled and says why.
|
by default). When the player has filled their school slots the create button is disabled and
|
||||||
|
says why.
|
||||||
- **Inside a school** — the date, time and weekday of the game calendar, play/pause and the
|
- **Inside a school** — the date, time and weekday of the game calendar, play/pause and the
|
||||||
×½ ×1 ×2 ×5 ×10 speed buttons, plus a way back to the menu.
|
×½ ×1 ×2 ×5 ×10 speed buttons, plus a way back to the menu.
|
||||||
|
|
||||||
@@ -94,6 +95,8 @@ which matches the server's launch profile.
|
|||||||
dotnet test
|
dotnet test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `tests/HSchool.Architecture.Tests` — layer bans (Arch, ASP.NET, sockets, wall-clock) for
|
||||||
|
Protocol through Simulation. No host.
|
||||||
- `tests/HSchool.Protocol.Tests` — wire-format round-trips and byte layouts.
|
- `tests/HSchool.Protocol.Tests` — wire-format round-trips and byte layouts.
|
||||||
- `tests/HSchool.Content.Tests` — JSONC catalog, inheritance, patches, map connectivity. No host.
|
- `tests/HSchool.Content.Tests` — JSONC catalog, inheritance, patches, map connectivity. No host.
|
||||||
- `tests/HSchool.Simulation.Tests` — the game clock, school load/create, and the school registry, no host involved.
|
- `tests/HSchool.Simulation.Tests` — the game clock, school load/create, and the school registry, no host involved.
|
||||||
@@ -133,7 +136,7 @@ Simulation tunables live under the `Simulation` section of
|
|||||||
| Key | Default | Meaning |
|
| Key | Default | Meaning |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `TickRate` | 20 | fixed simulation steps per second |
|
| `TickRate` | 20 | fixed simulation steps per second |
|
||||||
| `MaxSchools` | 6 | how many schools may exist at once |
|
| `MaxSchools` | 2 | how many schools each player may own |
|
||||||
| `GameMinutesPerRealSecond` | 1 | game minutes per real second at ×1 |
|
| `GameMinutesPerRealSecond` | 1 | game minutes per real second at ×1 |
|
||||||
| `DefaultStartDate` | `2012-03-31T06:00:00` | prefilled start of a new school |
|
| `DefaultStartDate` | `2012-03-31T06:00:00` | prefilled start of a new school |
|
||||||
| `SavesDirectory` | `saves` | per-school JSON files |
|
| `SavesDirectory` | `saves` | per-school JSON files |
|
||||||
|
|||||||
@@ -11,24 +11,24 @@
|
|||||||
|
|
||||||
## Задачи
|
## Задачи
|
||||||
|
|
||||||
- [ ] Проект `tests/HSchool.Architecture.Tests` в solution, `IsTestProject`, без AppHost и без
|
- [x] Проект `tests/HSchool.Architecture.Tests` в solution, `IsTestProject`, без AppHost и без
|
||||||
нового NuGet. Ссылки на Protocol, Content, People, Schedule, Ai, Simulation
|
нового NuGet. Ссылки на Protocol, Content, People, Schedule, Ai, Simulation
|
||||||
- [ ] Тесты ссылок: каждая библиотека из таблицы в [`craft.md`](../../design/10-craft/craft.md) — этап A
|
- [x] Тесты ссылок: каждая библиотека из таблицы в [`craft.md`](../../design/10-craft/craft.md) — этап A
|
||||||
- [ ] Тесты исходников: в `src/HSchool.{Protocol,Content,People,Schedule,Ai,Simulation}` нет
|
- [x] Тесты исходников: в `src/HSchool.{Protocol,Content,People,Schedule,Ai,Simulation}` нет
|
||||||
`DateTime.Now` / `DateTime.UtcNow`
|
`DateTime.Now` / `DateTime.UtcNow`
|
||||||
- [ ] Удалить копипасты `Assembly_DoesNotReference*` и `Sources_DoNotUseWallClock` из People,
|
- [x] Удалить копипасты `Assembly_DoesNotReference*` и `Sources_DoNotUseWallClock` из People,
|
||||||
Ai, Schedule, Simulation (остальные факты тех файлов не трогать)
|
Ai, Schedule, Simulation (остальные факты тех файлов не трогать)
|
||||||
- [ ] Testing policy в `AGENTS.md`: слои — `HSchool.Architecture.Tests`, не хост
|
- [x] Testing policy в `AGENTS.md`: слои — `HSchool.Architecture.Tests`, не хост
|
||||||
- [ ] README: школа не «ещё пустая»; потолок create — слоты игрока, не «шесть»
|
- [x] README: школа не «ещё пустая»; потолок create — слоты игрока, не «шесть»
|
||||||
|
|
||||||
## Тесты, без которых фаза не закрыта
|
## Тесты, без которых фаза не закрыта
|
||||||
|
|
||||||
- [ ] Protocol не ссылается на Arch, ASP.NET, Sockets, Content, Simulation
|
- [x] Protocol не ссылается на Arch, ASP.NET, Sockets, Content, Simulation
|
||||||
- [ ] Content не ссылается на Arch, ASP.NET, Sockets, Protocol, Simulation
|
- [x] Content не ссылается на Arch, ASP.NET, Sockets, Protocol, Simulation
|
||||||
- [ ] People, Schedule, Ai не ссылаются на Arch, ASP.NET, Sockets
|
- [x] People, Schedule, Ai не ссылаются на Arch, ASP.NET, Sockets
|
||||||
- [ ] Simulation не ссылается на ASP.NET и Sockets (Arch — можно)
|
- [x] Simulation не ссылается на ASP.NET и Sockets (Arch — можно)
|
||||||
- [ ] Исходники шести библиотек выше не содержат `DateTime.Now` / `DateTime.UtcNow`
|
- [x] Исходники шести библиотек выше не содержат `DateTime.Now` / `DateTime.UtcNow`
|
||||||
- [ ] В People/Ai/Schedule/Simulation.Tests больше нет этих двух фактов
|
- [x] В People/Ai/Schedule/Simulation.Tests больше нет этих двух фактов
|
||||||
|
|
||||||
## Критерий готовности
|
## Критерий готовности
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSchool.Ai.Tests", "tests\H
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSchool.Server.Tests", "tests\HSchool.Server.Tests\HSchool.Server.Tests.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSchool.Server.Tests", "tests\HSchool.Server.Tests\HSchool.Server.Tests.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSchool.Architecture.Tests", "tests\HSchool.Architecture.Tests\HSchool.Architecture.Tests.csproj", "{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -255,6 +257,18 @@ Global
|
|||||||
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.Build.0 = Release|Any CPU
|
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.ActiveCfg = Release|Any CPU
|
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.Build.0 = Release|Any CPU
|
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -277,6 +291,7 @@ Global
|
|||||||
{C21FB23F-F131-4651-8236-4F3E076B40BF} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
{C21FB23F-F131-4651-8236-4F3E076B40BF} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||||
{C355307C-D7D3-48C7-9615-CB5FBCF83D49} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
{C355307C-D7D3-48C7-9615-CB5FBCF83D49} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{75B7B736-9775-4F3E-B39B-29A3FAF1CCBB} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DD14EF4D-167E-4AC7-953A-AF606CC34829}
|
SolutionGuid = {DD14EF4D-167E-4AC7-953A-AF606CC34829}
|
||||||
|
|||||||
@@ -188,27 +188,6 @@ public class WalkingTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Assembly_DoesNotReferenceArchAspNetOrSockets()
|
|
||||||
{
|
|
||||||
var names = typeof(WalkGraph).Assembly.GetReferencedAssemblies().Select(assembly => assembly.Name!);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Sources_DoNotUseWallClock()
|
|
||||||
{
|
|
||||||
var root = Path.Combine(Fixtures.RepoRoot(), "src", "HSchool.Ai");
|
|
||||||
foreach (var path in Directory.EnumerateFiles(root, "*.cs"))
|
|
||||||
{
|
|
||||||
var text = File.ReadAllText(path);
|
|
||||||
Assert.DoesNotContain("DateTime.Now", text, StringComparison.Ordinal);
|
|
||||||
Assert.DoesNotContain("DateTime.UtcNow", text, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static (DayPlan Clear, DayPlan Weather, int Extra) PlansWithExtra(Func<DefCatalog, int> extraOf)
|
private static (DayPlan Clear, DayPlan Weather, int Extra) PlansWithExtra(Func<DefCatalog, int> extraOf)
|
||||||
{
|
{
|
||||||
var (catalog, map) = Fixtures.Vanilla();
|
var (catalog, map) = Fixtures.Vanilla();
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<RootNamespace>HSchool.Architecture.Tests</RootNamespace>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
|
<PackageReference Include="xunit.v3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.Ai\HSchool.Ai.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.Content\HSchool.Content.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.People\HSchool.People.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.Protocol\HSchool.Protocol.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.Schedule\HSchool.Schedule.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\HSchool.Simulation\HSchool.Simulation.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
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_DoesNotReferenceArchAspNetSocketsProtocolOrSimulation()
|
||||||
|
{
|
||||||
|
var names = References(typeof(MapLayout));
|
||||||
|
AssertNoArchAspNetOrSockets(names);
|
||||||
|
Assert.DoesNotContain("HSchool.Protocol", 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)
|
||||||
|
{
|
||||||
|
AssertNoArchAspNetOrSockets(References(marker));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Simulation_DoesNotReferenceAspNetOrSockets()
|
||||||
|
{
|
||||||
|
var names = References(typeof(School));
|
||||||
|
Assert.DoesNotContain(names, name => name.Contains("AspNet", StringComparison.OrdinalIgnoreCase));
|
||||||
|
Assert.DoesNotContain(names, name => name.Contains("Sockets", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
[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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -143,27 +143,6 @@ public class RosterGeneratorTests
|
|||||||
Assert.False(RosterFit.Matches(loaded, SchoolDemand.From(Fixtures.Catalog(), Fixtures.Classrooms(2))));
|
Assert.False(RosterFit.Matches(loaded, SchoolDemand.From(Fixtures.Catalog(), Fixtures.Classrooms(2))));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Assembly_DoesNotReferenceArchAspNetOrSockets()
|
|
||||||
{
|
|
||||||
var names = typeof(RosterGenerator).Assembly.GetReferencedAssemblies().Select(assembly => assembly.Name!);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Sources_DoNotUseWallClock()
|
|
||||||
{
|
|
||||||
var root = Path.Combine(Fixtures.RepoRoot(), "src", "HSchool.People");
|
|
||||||
foreach (var path in Directory.EnumerateFiles(root, "*.cs"))
|
|
||||||
{
|
|
||||||
var text = File.ReadAllText(path);
|
|
||||||
Assert.DoesNotContain("DateTime.Now", text, StringComparison.Ordinal);
|
|
||||||
Assert.DoesNotContain("DateTime.UtcNow", text, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AssertFilled(Roster roster, int classrooms)
|
private static void AssertFilled(Roster roster, int classrooms)
|
||||||
{
|
{
|
||||||
Assert.Equal(classrooms, roster.Classes.Count);
|
Assert.Equal(classrooms, roster.Classes.Count);
|
||||||
|
|||||||
@@ -125,27 +125,6 @@ public class TimetablePlannerTests
|
|||||||
Assert.Equal(Snapshot(a), Snapshot(b));
|
Assert.Equal(Snapshot(a), Snapshot(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Assembly_DoesNotReferenceArchAspNetOrSockets()
|
|
||||||
{
|
|
||||||
var names = typeof(TimetablePlanner).Assembly.GetReferencedAssemblies().Select(assembly => assembly.Name!);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Sources_DoNotUseWallClock()
|
|
||||||
{
|
|
||||||
var root = Path.Combine(Fixtures.RepoRoot(), "src", "HSchool.Schedule");
|
|
||||||
foreach (var path in Directory.EnumerateFiles(root, "*.cs"))
|
|
||||||
{
|
|
||||||
var text = File.ReadAllText(path);
|
|
||||||
Assert.DoesNotContain("DateTime.Now", text, StringComparison.Ordinal);
|
|
||||||
Assert.DoesNotContain("DateTime.UtcNow", text, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The four bans alone allowed a legal but unusable week. Taking the first free slot day by
|
/// The four bans alone allowed a legal but unusable week. Taking the first free slot day by
|
||||||
/// day gave a full school 77 lessons on Monday and 16 on Friday, with three foreign-language
|
/// day gave a full school 77 lessons on Monday and 16 on Friday, with three foreign-language
|
||||||
|
|||||||
@@ -274,14 +274,6 @@ public class PresenceTests
|
|||||||
"stale day plans after an assign that did not change headcount left the campus empty");
|
"stale day plans after an assign that did not change headcount left the campus empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Simulation_DoesNotReferenceSockets()
|
|
||||||
{
|
|
||||||
var names = typeof(School).Assembly.GetReferencedAssemblies().Select(assembly => assembly.Name!);
|
|
||||||
Assert.DoesNotContain(names, name => name.Contains("Sockets", StringComparison.OrdinalIgnoreCase));
|
|
||||||
Assert.DoesNotContain(names, name => name.Contains("AspNet", StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static School UnstaffedDuringLessonThree()
|
private static School UnstaffedDuringLessonThree()
|
||||||
{
|
{
|
||||||
var start = new DateTime(2012, 4, 3, 10, 20, 0, DateTimeKind.Utc);
|
var start = new DateTime(2012, 4, 3, 10, 20, 0, DateTimeKind.Utc);
|
||||||
|
|||||||
Reference in New Issue
Block a user