Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0-rc.2] - 2026-06-06

### Changed

- **License hygiene:** pinned `FluentAssertions` to **6.12.0**, the last
MIT-licensed release (7.x+ moved to a commercial Xceed license). This keeps the
published `RP2040Sharp.TestKit` package and everything it pulls in MIT-compatible.
The TestKit's custom assertions were ported back to the 6.x extension model.

## [1.0.0-rc.1] - 2026-06-06

First public release candidate. A high-performance RP2040 emulator in modern C#
Expand Down Expand Up @@ -45,5 +54,6 @@ First public release candidate. A high-performance RP2040 emulator in modern C#
- Flash programming uses C# hooks rather than the SSI XIP hardware path.
- USB host support is CDC-only (sufficient for the MicroPython REPL).

[Unreleased]: https://github.com/begeistert/RP2040Sharp/compare/v1.0.0-rc.1...HEAD
[Unreleased]: https://github.com/begeistert/RP2040Sharp/compare/v1.0.0-rc.2...HEAD
[1.0.0-rc.2]: https://github.com/begeistert/RP2040Sharp/compare/v1.0.0-rc.1...v1.0.0-rc.2
[1.0.0-rc.1]: https://github.com/begeistert/RP2040Sharp/releases/tag/v1.0.0-rc.1
15 changes: 6 additions & 9 deletions src/RP2040.TestKit/Assertions/CortexM0Assertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ namespace RP2040.TestKit.Assertions;
/// <summary>FluentAssertions extension for <see cref="CortexM0Plus"/>.</summary>
public sealed class CortexM0Assertions : ReferenceTypeAssertions<CortexM0Plus, CortexM0Assertions>
{
private readonly AssertionChain _chain;

public CortexM0Assertions(CortexM0Plus subject, AssertionChain chain) : base(subject, chain)
=> _chain = chain;
public CortexM0Assertions(CortexM0Plus subject) : base(subject) { }

protected override string Identifier => "cpu";

public AndConstraint<CortexM0Assertions> HaveRegister(int index, uint expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Registers[index] == expected)
.FailWith("Expected R{0} to be 0x{1:X8}{reason}, but found 0x{2:X8}.",
index, expected, Subject.Registers[index]);
Expand All @@ -28,7 +25,7 @@ public AndConstraint<CortexM0Assertions> HaveRegister(int index, uint expected,
public AndConstraint<CortexM0Assertions> HavePC(uint expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Registers.PC == expected)
.FailWith("Expected PC to be 0x{0:X8}{reason}, but found 0x{1:X8}.",
expected, Subject.Registers.PC);
Expand All @@ -38,7 +35,7 @@ public AndConstraint<CortexM0Assertions> HavePC(uint expected,
public AndConstraint<CortexM0Assertions> HaveSP(uint expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Registers.SP == expected)
.FailWith("Expected SP to be 0x{0:X8}{reason}, but found 0x{1:X8}.",
expected, Subject.Registers.SP);
Expand All @@ -48,7 +45,7 @@ public AndConstraint<CortexM0Assertions> HaveSP(uint expected,
public AndConstraint<CortexM0Assertions> HaveCycles(long expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Cycles == expected)
.FailWith("Expected Cycles to be {0}{reason}, but found {1}.",
expected, Subject.Cycles);
Expand All @@ -74,7 +71,7 @@ public AndConstraint<CortexM0Assertions> HaveOverflowFlag(bool expected,
private AndConstraint<CortexM0Assertions> HaveFlag(string name, bool actual, bool expected,
string because, object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(actual == expected)
.FailWith("Expected flag {0} to be {1}{reason}, but found {2}.", name, expected, actual);
return new AndConstraint<CortexM0Assertions>(this);
Expand Down
15 changes: 6 additions & 9 deletions src/RP2040.TestKit/Assertions/GpioAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ namespace RP2040.TestKit.Assertions;
/// <summary>FluentAssertions extension for <see cref="GpioPin"/>.</summary>
public sealed class GpioAssertions : ReferenceTypeAssertions<GpioPin, GpioAssertions>
{
private readonly AssertionChain _chain;

public GpioAssertions(GpioPin subject, AssertionChain chain) : base(subject, chain)
=> _chain = chain;
public GpioAssertions(GpioPin subject) : base(subject) { }

protected override string Identifier => "pin";

public AndConstraint<GpioAssertions> BeHigh(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.DigitalValue)
.FailWith("Expected GPIO pin to be HIGH{reason}, but it was LOW.");
return new AndConstraint<GpioAssertions>(this);
Expand All @@ -27,7 +24,7 @@ public AndConstraint<GpioAssertions> BeHigh(
public AndConstraint<GpioAssertions> BeLow(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(!Subject.DigitalValue)
.FailWith("Expected GPIO pin to be LOW{reason}, but it was HIGH.");
return new AndConstraint<GpioAssertions>(this);
Expand All @@ -36,7 +33,7 @@ public AndConstraint<GpioAssertions> BeLow(
public AndConstraint<GpioAssertions> BeOutput(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.IsOutput)
.FailWith("Expected GPIO pin to be configured as OUTPUT{reason}, but it was INPUT.");
return new AndConstraint<GpioAssertions>(this);
Expand All @@ -50,7 +47,7 @@ public AndConstraint<GpioAssertions> BeOutput(
public AndConstraint<GpioAssertions> BePioOutput(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.IsPioOutput)
.FailWith("Expected GPIO pin to be assigned to a PIO state machine (FUNCSEL=6 or 7){reason}, but it was not.");
return new AndConstraint<GpioAssertions>(this);
Expand All @@ -59,7 +56,7 @@ public AndConstraint<GpioAssertions> BePioOutput(
public AndConstraint<GpioAssertions> BeInput(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(!Subject.IsOutput)
.FailWith("Expected GPIO pin to be configured as INPUT{reason}, but it was OUTPUT.");
return new AndConstraint<GpioAssertions>(this);
Expand Down
19 changes: 8 additions & 11 deletions src/RP2040.TestKit/Assertions/UartProbeAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ namespace RP2040.TestKit.Assertions;
/// <summary>FluentAssertions extension for <see cref="UartProbe"/>.</summary>
public sealed class UartProbeAssertions : ReferenceTypeAssertions<UartProbe, UartProbeAssertions>
{
private readonly AssertionChain _chain;

public UartProbeAssertions(UartProbe subject, AssertionChain chain) : base(subject, chain)
=> _chain = chain;
public UartProbeAssertions(UartProbe subject) : base(subject) { }

protected override string Identifier => "uart";

public AndConstraint<UartProbeAssertions> Contain(string expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Text.Contains(expected))
.FailWith("Expected UART output to contain {0}{reason}, but found {1}.",
expected, Subject.Text);
Expand All @@ -28,7 +25,7 @@ public AndConstraint<UartProbeAssertions> Contain(string expected,
public AndConstraint<UartProbeAssertions> NotContain(string expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(!Subject.Text.Contains(expected))
.FailWith("Expected UART output not to contain {0}{reason}, but found {1}.",
expected, Subject.Text);
Expand All @@ -38,7 +35,7 @@ public AndConstraint<UartProbeAssertions> NotContain(string expected,
public AndConstraint<UartProbeAssertions> StartWith(string expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Text.StartsWith(expected, StringComparison.Ordinal))
.FailWith("Expected UART output to start with {0}{reason}, but found {1}.",
expected, Subject.Text);
Expand All @@ -48,7 +45,7 @@ public AndConstraint<UartProbeAssertions> StartWith(string expected,
public AndConstraint<UartProbeAssertions> BeEmpty(
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.ByteCount == 0)
.FailWith("Expected UART to have no output{reason}, but found {0} bytes.", Subject.ByteCount);
return new AndConstraint<UartProbeAssertions>(this);
Expand All @@ -57,7 +54,7 @@ public AndConstraint<UartProbeAssertions> BeEmpty(
public AndConstraint<UartProbeAssertions> HaveByteCount(int expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.ByteCount == expected)
.FailWith("Expected UART to have {0} bytes{reason}, but found {1}.",
expected, Subject.ByteCount);
Expand All @@ -67,7 +64,7 @@ public AndConstraint<UartProbeAssertions> HaveByteCount(int expected,
public AndConstraint<UartProbeAssertions> ContainLine(string expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Lines.Contains(expected))
.FailWith("Expected UART output to contain line {0}{reason}.", expected);
return new AndConstraint<UartProbeAssertions>(this);
Expand All @@ -76,7 +73,7 @@ public AndConstraint<UartProbeAssertions> ContainLine(string expected,
public AndConstraint<UartProbeAssertions> HaveLineCount(int expected,
string because = "", params object[] becauseArgs)
{
_chain.BecauseOf(because, becauseArgs)
Execute.Assertion.BecauseOf(because, becauseArgs)
.ForCondition(Subject.Lines.Count == expected)
.FailWith("Expected UART output to have {0} lines{reason}, but found {1}.",
expected, Subject.Lines.Count);
Expand Down
10 changes: 3 additions & 7 deletions src/RP2040.TestKit/Extensions/AssertionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using FluentAssertions.Execution;
using RP2040.Core.Cpu;
using RP2040.Peripherals.Gpio;
using RP2040.TestKit.Assertions;
Expand All @@ -11,12 +10,9 @@ namespace RP2040.TestKit.Extensions;
/// </summary>
public static class AssertionExtensions
{
public static CortexM0Assertions Should(this CortexM0Plus cpu)
=> new(cpu, AssertionChain.GetOrCreate());
public static CortexM0Assertions Should(this CortexM0Plus cpu) => new(cpu);

public static UartProbeAssertions Should(this UartProbe probe)
=> new(probe, AssertionChain.GetOrCreate());
public static UartProbeAssertions Should(this UartProbe probe) => new(probe);

public static GpioAssertions Should(this GpioPin pin)
=> new(pin, AssertionChain.GetOrCreate());
public static GpioAssertions Should(this GpioPin pin) => new(pin);
}
3 changes: 2 additions & 1 deletion src/RP2040.TestKit/RP2040.TestKit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ProjectReference Include="..\RP2040Sharp\RP2040Sharp.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<!-- 6.12.0 is the last MIT-licensed release; 7.x+ are under a commercial license. -->
<PackageReference Include="FluentAssertions" Version="6.12.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down
2 changes: 1 addition & 1 deletion tests/RP2040Sharp.Tests/RP2040Sharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
Expand Down
Loading