Skip to content

Commit

Permalink
Added Unit tests to test a function. Fixed the lights not going green…
Browse files Browse the repository at this point in the history
… on multiple places
  • Loading branch information
SvenImholz committed May 22, 2024
1 parent 6577550 commit 21015e8
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 34 deletions.
6 changes: 6 additions & 0 deletions StoplichtController.sln
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoplichtController", "StoplichtController\StoplichtController.csproj", "{239EEFD5-C457-4B2C-B8BA-97B8BC611930}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StoplichtControllerTests", "StoplichtControllerTests\StoplichtControllerTests.csproj", "{E8358881-12BC-4577-977A-8F915BB738CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -12,5 +14,9 @@ Global
{239EEFD5-C457-4B2C-B8BA-97B8BC611930}.Debug|Any CPU.Build.0 = Debug|Any CPU
{239EEFD5-C457-4B2C-B8BA-97B8BC611930}.Release|Any CPU.ActiveCfg = Release|Any CPU
{239EEFD5-C457-4B2C-B8BA-97B8BC611930}.Release|Any CPU.Build.0 = Release|Any CPU
{E8358881-12BC-4577-977A-8F915BB738CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8358881-12BC-4577-977A-8F915BB738CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8358881-12BC-4577-977A-8F915BB738CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8358881-12BC-4577-977A-8F915BB738CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
11 changes: 6 additions & 5 deletions StoplichtController/Crossings/Crossing.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Text.Json.Nodes;
using StoplichtController.Crossings.Lanes;
using StoplichtController.Crossings.Lanes.Implementations;
using StoplichtController.Messages;
Expand All @@ -7,11 +6,12 @@ namespace StoplichtController.Crossings;

public class Crossing(int id)
{
public event Action<Crossing>? OnUpdateReceived;
public int Id { get; set; } = id;

public PriorityQueue<Lane, LanePriority> WaitList { get; set; } = new();
public SortedList<LanePriority, Lane> WaitList { get; set; } = new();

internal Dictionary<string, Road> Roads { get; set; } = new();
public event Action<Crossing>? OnUpdateReceived;

public void AddRoad(string roadId) { Roads.Add(roadId, new Road(roadId)); }

Expand All @@ -28,12 +28,13 @@ public void UpdateCrossing(RoadDictionary roadMessage)
{
if (!roadMessage.TryGetValue(road.Key, out var message))
continue;

road.Value.Update(message);
foreach (var lane in road.Value.Lanes.Where(
lane => lane.ShouldAddToWaitList()))
{
WaitList.Enqueue(lane, lane.GetPriority());
lane.SetPriority();
WaitList.Add(lane.GetPriority(), lane);
}
}
OnUpdateReceived?.Invoke(this);
Expand Down
8 changes: 6 additions & 2 deletions StoplichtController/Crossings/Lanes/Lane.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace StoplichtController.Crossings.Lanes;

[Serializable]
public abstract class Lane
public abstract class Lane : ICanIntersect
{
protected Lane()
{
Expand All @@ -15,9 +15,13 @@ protected Lane()
}
}
protected internal Light Light { get; set; }
public LanePriority Priority { get; private set; }

public abstract bool IntersectsWith(Lane lane);
public void Update(IUpdateMessage message) { UpdateImplementation(message); }

protected abstract bool UpdateImplementation(IUpdateMessage message);
public abstract bool ShouldAddToWaitList();
public LanePriority GetPriority() => new(this);
public LanePriority GetPriority() => Priority;
public void SetPriority() => Priority = new LanePriority(this);
}
6 changes: 3 additions & 3 deletions StoplichtController/Crossings/Lanes/LaneCrossingRoad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace StoplichtController.Crossings.Lanes;
public abstract class LaneCrossingRoad(string crossesRoad) : Lane, ICrossesRoad
{
public string CrossesRoad { get; } = crossesRoad;
public bool IntersectsWith(Lane lane) => lane is IHasPath pathLane &&
(CrossesRoad == pathLane.Path.From ||
CrossesRoad == pathLane.Path.To);
override public bool IntersectsWith(Lane lane) => lane is IHasPath other &&
(CrossesRoad == other.Path.From ||
CrossesRoad == other.Path.To);
}
23 changes: 14 additions & 9 deletions StoplichtController/Crossings/Lanes/LaneWithPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ public abstract class LaneWithPath(string from, string to) : Lane, IHasPath
{
public Path Path { get; } = new(from, to);

public bool IntersectsWith(Lane lane)
override public bool IntersectsWith(Lane lane)
{
return lane switch
switch (lane)
{
IHasPath pathLane => Path.From != pathLane.Path.From &&
Path.From == pathLane.Path.To &&
Path.To == pathLane.Path.From,
ICrossesRoad crossesRoadLane => Path.From == crossesRoadLane.CrossesRoad ||
Path.To == crossesRoadLane.CrossesRoad,
_ => false
};
case IHasPath other:
if (Path.From == other.Path.From)
return false;

return Path.From != other.Path.To || Path.To != other.Path.From;


case ICrossesRoad crossesRoadLane:
return Path.From == crossesRoadLane.CrossesRoad ||
Path.To == crossesRoadLane.CrossesRoad;
default: return true;
}
}
}
3 changes: 2 additions & 1 deletion StoplichtController/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// Global using directives
global using static System.Console;
global using static System.Console;
global using NUnit.Framework;
43 changes: 29 additions & 14 deletions StoplichtController/Policies/CarPolicy.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using StoplichtController.Crossings;
using StoplichtController.Crossings.Lanes;
using StoplichtController.Crossings.Lanes.Implementations;

namespace StoplichtController.Policies;

Expand All @@ -9,23 +11,36 @@ public class CarPolicy : Policy
if (crossing.WaitList.Count <= 0) return await base.Apply(crossing);

// Turn the light green for the lane with the highest priority and red for all other lanes
var highestPriorityLane = crossing.WaitList.Peek();
foreach (var lane in crossing.Roads.SelectMany(road => road.Value.Lanes))
var highestPriorityLane = crossing.WaitList.First().Value;

var goToGreenList = new List<Lane> { highestPriorityLane };
var waitList = crossing.WaitList.Values;

foreach (var lane in waitList)
if (goToGreenList.All(greenLane => !greenLane.IntersectsWith(lane)))
goToGreenList.Add(lane);

var greenTime = TimeSpan.FromSeconds(4);
var orangeTime = TimeSpan.FromSeconds(2);
var evacuationTime = TimeSpan.FromSeconds(5);

foreach (var lane in goToGreenList)
{
if (lane is BikeLane or PedestrianLane)
evacuationTime = TimeSpan.FromSeconds(6);
lane.Light.Green();
}

await Task.Delay(greenTime);
foreach (var lane in goToGreenList)
lane.Light.Orange();
await Task.Delay(orangeTime);
foreach (var lane in goToGreenList)
{
if (lane == highestPriorityLane)
{
lane.Light.Green();
await Task.Delay(TimeSpan.FromSeconds(4));
lane.Light.Orange();
await Task.Delay(TimeSpan.FromSeconds(1));
lane.Light.Red();
await Task.Delay(TimeSpan.FromSeconds(2));
crossing.WaitList.Dequeue();

break;
}
lane.Light.Red();
crossing.WaitList.Remove(lane.GetPriority());
}
await Task.Delay(evacuationTime);

OnPolicyApplied();

Expand Down
1 change: 1 addition & 0 deletions StoplichtController/StoplichtController.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NUnit" Version="4.1.0"/>
</ItemGroup>
</Project>
61 changes: 61 additions & 0 deletions StoplichtControllerTests/LaneWithPathTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using StoplichtController.Crossings.Lanes;
using StoplichtController.Crossings.Lanes.Implementations;

namespace StoplichtControllerTests;

public class LaneWithPathTests
{
LaneWithPath _laneWithPath;

[SetUp]
public void Setup() { _laneWithPath = new CarLane("A", "B"); }

[Test]
public void IntersectsWith_SamePath_ReturnsFalse()
{
var otherLane = new CarLane("A", "B");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.False);
}

[Test]
public void IntersectsWith_DifferentPath_ReturnsTrue()
{
var otherLane = new CarLane("B", "C");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.True);
}

[Test]
public void IntersectsWith_ReversePath_ReturnsFalse()
{
var otherLane = new CarLane("B", "A");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.False);
}

[Test]
public void IntersectsWith_CrossesRoad_From_ReturnsTrue()
{
var otherLane = new PedestrianLane("A");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.True);
}

[Test]
public void IntersectsWith_CrossesRoad_To_ReturnsTrue()
{
var otherLane = new PedestrianLane("B");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.True);
}

[Test]
public void IntersectsWith_CrossesRoad_ReturnsFalse()
{
var otherLane = new PedestrianLane("C");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.False);
}

[Test]
public void IntersectsWith_OtherLane_ReturnsTrue()
{
var otherLane = new CarLane("C", "B");
Assert.That(_laneWithPath.IntersectsWith(otherLane), Is.True);
}
}
28 changes: 28 additions & 0 deletions StoplichtControllerTests/StoplichtControllerTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="NUnit" Version="4.1.0"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\StoplichtController\StoplichtController.csproj"/>
</ItemGroup>

</Project>

0 comments on commit 21015e8

Please sign in to comment.