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
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ below exist because ordinary review does not catch it.
| `PackagingConventionTests` | Every package ships its own README as `PackageReadmeFile`; `.targets` ship to both `build/` and `buildTransitive/`, reference a real `IDesignTimeServices` in their own assembly, and set `ForProvider` on satellites but not on core. |
| `ClaudeMdConsistencyTests` | This file. Prose cannot be asserted, so it checks the falsifiable parts: cited paths and file names exist, annotation keys under a prefix this repo owns are declared somewhere, `Type.Member` references resolve, and the stated size of the Npgsql whitelist matches it. Those are what a rename rots silently — and the count claim had already gone stale by two. |
| `BuilderApiParityTests` | Every key in a satellite's annotation whitelist is reachable from a builder method. `SqlServer:DataCompression` sat whitelisted with no API for a full release; this catches that class of drift by invoking every builder extension and diffing the keys it sets. |
| `SecurityPolicyConsistencyTests` | SECURITY.md's supported-versions table names the minor being shipped, and its `< x.y` row meets it. The table is prose a version bump forgets — the sibling repository shipped 6.2.0 with the table still saying 6.1.x. |

**`test/consumer-smoke-test.sh`** is the only check that exercises *delivery* rather than code. Every
other layer is verified in isolation and in-process; this one packs the nupkgs, restores them into a
Expand Down
69 changes: 69 additions & 0 deletions test/EFCore.ComplexIndexes.Tests/SecurityPolicyConsistencyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace EFCore.ComplexIndexes.Tests;

/// <summary>
/// SECURITY.md promises fixes for "the latest released minor version" and tabulates which line that
/// is. The table is prose: nothing ties it to <c>Directory.Build.props</c>, so a release that bumps
/// the version and forgets the table leaves the policy pointing a reporter at a line that no longer
/// receives fixes. A supported-versions table that is wrong is worse than none — it reads as a
/// considered statement — and it is exactly the kind of line a version bump forgets.
/// </summary>
[TestClass]
public class SecurityPolicyConsistencyTests
{
private static string SecurityPolicy => Path.Combine(RepositoryLayout.Root, "SECURITY.md");

// "| 5.0.x | ✅ |" — the one line that receives fixes.
private static readonly Regex SupportedRow =
new(@"^\|\s*(\d+)\.(\d+)\.x\s*\|\s*✅\s*\|", RegexOptions.Multiline | RegexOptions.Compiled);

// "| < 5.0 | ❌ |" — everything before it.
private static readonly Regex UnsupportedRow =
new(@"^\|\s*<\s*(\d+)\.(\d+)\s*\|\s*❌\s*\|", RegexOptions.Multiline | RegexOptions.Compiled);

private static Version PackageVersion =>
Version.Parse(XDocument.Load(RepositoryLayout.BuildProps)
.Descendants("Version")
.Single()
.Value);

[TestMethod(DisplayName = "SECURITY.md's supported-versions table names the minor being shipped")]
public void Supported_versions_table_names_the_shipped_minor()
{
var text = File.ReadAllText(SecurityPolicy);
var shipped = PackageVersion;
var expected = $"{shipped.Major}.{shipped.Minor}";

var supported = SupportedRow.Matches(text);

Assert.HasCount(
1, supported,
"SECURITY.md should have exactly one '| x.y.x | ✅ |' row — the policy is that fixes land "
+ "on the latest released minor only, so there is one supported line to name.");

var supportedLine = $"{supported[0].Groups[1].Value}.{supported[0].Groups[2].Value}";

Assert.AreEqual(
expected, supportedLine,
$"SECURITY.md lists {supportedLine}.x as the supported line, but Directory.Build.props ships "
+ $"{shipped}. The table is part of the version bump: a reporter reads it to decide whether "
+ "their version still receives fixes.");

var unsupported = UnsupportedRow.Match(text);

Assert.IsTrue(
unsupported.Success,
"SECURITY.md should have a '| < x.y | ❌ |' row saying that everything before the supported "
+ "line is unmaintained.");

var unsupportedBelow = $"{unsupported.Groups[1].Value}.{unsupported.Groups[2].Value}";

Assert.AreEqual(
expected, unsupportedBelow,
$"SECURITY.md says versions below {unsupportedBelow} are unsupported, but the supported line "
+ $"is {expected}.x — the two rows should meet at the same minor, or a range is left "
+ "described by neither.");
}
}
Loading