Skip to content

Commit 94568be

Browse files
rducomNatMarchand
authored andcommitted
chore: upgrade to .NET 10 and add unit tests
- Upgrade from .NET 8 to .NET 10 - Update all NuGet packages to latest versions (.NET 10.0.0, xunit 2.9.3) - Add 29 new unit and integration tests - Fix CA2022 warning in IntegrationTests - Add macOS support for local development (NullStateCollector) - Update GitHub Actions workflow to .NET 10 - Update README to reflect .NET 10
1 parent 2d988ea commit 94568be

15 files changed

Lines changed: 785 additions & 105 deletions

.github/workflows/dotnetcore.yml

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ jobs:
1717
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
1818
- run: git fetch --prune --unshallow
1919

20-
- name: Setup .NET Core 8
20+
- name: Setup .NET 10
2121
uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5
2222
with:
23-
dotnet-version: '8.0.x'
23+
dotnet-version: '10.0.x'
2424

2525
- name: Install dependencies
2626
run: dotnet restore
@@ -34,19 +34,8 @@ jobs:
3434
id: gitversion # step id used as reference for output values
3535
uses: gittools/actions/gitversion/execute@51d325634925d7d9ce0a7efc2c586c0bc2b9eee6 # v3.2.1
3636

37-
# - name: Setup SonarScanner
38-
# run: dotnet tool install --tool-path artifacts dotnet-sonarscanner
39-
40-
# - name: SonarScanner begin
41-
# run: artifacts/dotnet-sonarscanner begin /k:"Haproxy.AgentCheck" /o:"lucca" /d:sonar.login=${{ secrets.SONAR_TOKEN }} /d:sonar.host.url="https://sonarcloud.io/" /d:sonar.cs.opencover.reportsPaths="./coverage.opencover.xml"
42-
4337
- name: Test
44-
run: dotnet test --no-restore --verbosity minimal /p:CollectCoverage=true /p:CoverletOutput=../ /p:CoverletOutputFormat=opencover --logger:"console;verbosity=detailed"
45-
46-
# - name: SonarScanner end
47-
# run: artifacts/dotnet-sonarscanner end /d:sonar.login=${{ secrets.SONAR_TOKEN }}
48-
# env:
49-
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38+
run: dotnet test --solution Haproxy.AgentCheck.sln --coverage --report-github
5039

5140
- name: Publish win-x64
5241
run: |

Directory.Packages.props

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,22 @@
44
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
55
</PropertyGroup>
66
<ItemGroup>
7-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.22" />
7+
<PackageVersion Include="GitHubActionsTestLogger" Version="3.0.1" />
8+
<PackageVersion Include="Microsoft.CodeCoverage" Version="18.0.1" />
89
<PackageVersion Include="Microsoft.Diagnostics.NETCore.Client" Version="0.2.652701" />
910
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.28" />
10-
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="9.10.0" />
11-
<PackageVersion Include="Microsoft.Extensions.Hosting.Systemd" Version="9.0.11" />
12-
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.11" />
13-
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
11+
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.1.0" />
1412
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.14.0" />
1513
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.14.0" />
1614
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.14.0" />
17-
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.11" />
18-
<PackageVersion Include="System.IO.Pipelines" Version="9.0.11" />
19-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
20-
<PackageVersion Include="coverlet.msbuild" Version="6.0.4">
21-
<PrivateAssets>all</PrivateAssets>
22-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
23-
</PackageVersion>
24-
<PackageVersion Include="xunit" Version="2.9.3" />
25-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5">
26-
<PrivateAssets>all</PrivateAssets>
27-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
28-
</PackageVersion>
15+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
16+
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="10.0.0" />
17+
<PackageVersion Include="Microsoft.Extensions.Hosting.Systemd" Version="10.0.0" />
18+
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.0" />
19+
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.0" />
20+
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.1" />
2921
</ItemGroup>
3022
<ItemGroup>
3123
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="10.16.0.128591" />
3224
</ItemGroup>
33-
</Project>
25+
</Project>
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using Lucca.Infra.Haproxy.AgentCheck.Config;
2+
using Lucca.Infra.Haproxy.AgentCheck.Metrics;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Xunit;
5+
6+
namespace Lucca.Infra.Haproxy.AgentCheck.Tests;
7+
8+
public class CountersStateTests(ITestOutputHelper testOutputHelper)
9+
{
10+
[Fact]
11+
public void UpdateState_WithCounterValue_UpdatesWeight()
12+
{
13+
var serviceProvider = CreateServiceProvider(
14+
new RuleConfig
15+
{
16+
Name = "custom-counter",
17+
Source = RuleSource.Counters,
18+
Weight = new WeightRule
19+
{
20+
SystemResponse = SystemResponse.Linear,
21+
MinValue = 0,
22+
MaxValue = 100,
23+
MinWeight = 0,
24+
MaxWeight = 100
25+
}
26+
});
27+
28+
var sut = serviceProvider.GetRequiredService<State>();
29+
sut.UpdateState(new CountersState
30+
{
31+
Values = new Dictionary<string, double> { ["custom-counter"] = 50 }
32+
});
33+
34+
Assert.True(sut.IsUp);
35+
Assert.Equal(50, sut.Weight, 0.01);
36+
}
37+
38+
[Fact]
39+
public void UpdateState_WithCounterAboveThreshold_BreaksCircuit()
40+
{
41+
var serviceProvider = CreateServiceProvider(
42+
new RuleConfig
43+
{
44+
Name = "error-rate",
45+
Source = RuleSource.Counters,
46+
Failure = new FailureRule
47+
{
48+
EnterThreshold = 10,
49+
LeaveThreshold = 5
50+
}
51+
});
52+
53+
var sut = serviceProvider.GetRequiredService<State>();
54+
sut.UpdateState(new CountersState
55+
{
56+
Values = new Dictionary<string, double> { ["error-rate"] = 15 }
57+
});
58+
59+
Assert.False(sut.IsUp);
60+
Assert.Contains("Counters/error-rate", sut.BrokenCircuitsBreakers);
61+
}
62+
63+
[Fact]
64+
public void UpdateState_WhenCounterRemoved_RemovesBrokenCircuit()
65+
{
66+
var serviceProvider = CreateServiceProvider(
67+
new RuleConfig
68+
{
69+
Name = "temp-counter",
70+
Source = RuleSource.Counters,
71+
Failure = new FailureRule
72+
{
73+
EnterThreshold = 10,
74+
LeaveThreshold = 5
75+
}
76+
});
77+
78+
var sut = serviceProvider.GetRequiredService<State>();
79+
80+
// First update with counter above threshold
81+
sut.UpdateState(new CountersState
82+
{
83+
Values = new Dictionary<string, double> { ["temp-counter"] = 15 }
84+
});
85+
Assert.Contains("Counters/temp-counter", sut.BrokenCircuitsBreakers);
86+
87+
// Second update without the counter
88+
sut.UpdateState(new CountersState
89+
{
90+
Values = new Dictionary<string, double>()
91+
});
92+
93+
Assert.DoesNotContain("Counters/temp-counter", sut.BrokenCircuitsBreakers);
94+
}
95+
96+
[Fact]
97+
public void UpdateState_WithMultipleCounters_UsesLowestWeight()
98+
{
99+
var serviceProvider = CreateServiceProvider(
100+
new RuleConfig
101+
{
102+
Name = "counter1",
103+
Source = RuleSource.Counters,
104+
Weight = new WeightRule
105+
{
106+
SystemResponse = SystemResponse.Linear,
107+
MinValue = 0,
108+
MaxValue = 100,
109+
MinWeight = 0,
110+
MaxWeight = 100
111+
}
112+
},
113+
new RuleConfig
114+
{
115+
Name = "counter2",
116+
Source = RuleSource.Counters,
117+
Weight = new WeightRule
118+
{
119+
SystemResponse = SystemResponse.Linear,
120+
MinValue = 0,
121+
MaxValue = 100,
122+
MinWeight = 0,
123+
MaxWeight = 100
124+
}
125+
});
126+
127+
var sut = serviceProvider.GetRequiredService<State>();
128+
sut.UpdateState(new CountersState
129+
{
130+
Values = new Dictionary<string, double>
131+
{
132+
["counter1"] = 20, // Weight would be 80
133+
["counter2"] = 90 // Weight would be 10
134+
}
135+
});
136+
137+
Assert.True(sut.IsUp);
138+
Assert.Equal(10, sut.Weight, 0.01);
139+
}
140+
141+
[Fact]
142+
public void UpdateState_CombineSystemAndCounters_UsesLowestWeight()
143+
{
144+
var serviceProvider = CreateServiceProvider(
145+
new RuleConfig
146+
{
147+
Name = "CPU",
148+
Source = RuleSource.System,
149+
Weight = new WeightRule
150+
{
151+
SystemResponse = SystemResponse.Linear,
152+
MinValue = 0,
153+
MaxValue = 100,
154+
MinWeight = 0,
155+
MaxWeight = 100
156+
}
157+
},
158+
new RuleConfig
159+
{
160+
Name = "custom-metric",
161+
Source = RuleSource.Counters,
162+
Weight = new WeightRule
163+
{
164+
SystemResponse = SystemResponse.Linear,
165+
MinValue = 0,
166+
MaxValue = 100,
167+
MinWeight = 0,
168+
MaxWeight = 100
169+
}
170+
});
171+
172+
var sut = serviceProvider.GetRequiredService<State>();
173+
174+
// CPU at 30% -> weight 70
175+
sut.UpdateState(new SystemState { CpuPercent = 30 });
176+
177+
// Custom metric at 80 -> weight 20
178+
sut.UpdateState(new CountersState
179+
{
180+
Values = new Dictionary<string, double> { ["custom-metric"] = 80 }
181+
});
182+
183+
Assert.True(sut.IsUp);
184+
Assert.Equal(20, sut.Weight, 0.01);
185+
}
186+
187+
private IServiceProvider CreateServiceProvider(params RuleConfig[] rules)
188+
{
189+
return new ServiceCollection()
190+
.AddOptions()
191+
.Configure<RulesConfig>(o => o.AddRange(rules))
192+
.AddFakeLogging(o => o.OutputSink = testOutputHelper.WriteLine)
193+
.AddSingleton<TestTimeProvider>()
194+
.AddSingleton<TimeProvider>(p => p.GetRequiredService<TestTimeProvider>())
195+
.AddSingleton<State>()
196+
.BuildServiceProvider();
197+
}
198+
}

Haproxy.AgentCheck.Tests/Haproxy.AgentCheck.Tests.csproj

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<OutputType>Exe</OutputType>
56
</PropertyGroup>
67

78
<ItemGroup>
9+
<PackageReference Include="GitHubActionsTestLogger" />
810
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
911
<PackageReference Include="Microsoft.Extensions.Diagnostics.Testing" />
10-
<PackageReference Include="Microsoft.NET.Test.Sdk" />
11-
<PackageReference Include="coverlet.msbuild">
12-
<PrivateAssets>all</PrivateAssets>
13-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
14-
</PackageReference>
15-
<PackageReference Include="xunit" />
16-
<PackageReference Include="xunit.runner.visualstudio">
17-
<PrivateAssets>all</PrivateAssets>
18-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19-
</PackageReference>
12+
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" />
13+
<PackageReference Include="xunit.v3.mtp-v2" />
2014
</ItemGroup>
2115

2216
<ItemGroup>

0 commit comments

Comments
 (0)