diff --git a/Icod.TermInfo-Post-1.0-Development-Roadmap.md b/Icod.TermInfo-Post-1.0-Development-Roadmap.md index f37f130..62574c0 100644 --- a/Icod.TermInfo-Post-1.0-Development-Roadmap.md +++ b/Icod.TermInfo-Post-1.0-Development-Roadmap.md @@ -6,10 +6,10 @@ **Language:** C# 13 **Target frameworks:** `net8.0`; `net10.0` **Frozen runtime contract:** `1.0.0` -**Current release version:** `1.1.0` +**Current release version:** `1.1.1` **Next development line:** `1.2.0` -**Status:** S01-S09 complete — 1.1.0 release closure -**Current tranche:** 1.1.0 release closure +**Status:** S01-S09 complete — 1.1.1 maintenance release +**Current tranche:** 1.1.1 maintenance release **Primary objective:** Extend the terminfo ecosystem beyond runtime capability acquisition without destabilizing the frozen 1.0 runtime contract. --- diff --git a/Icod.TermInfo.Source/Icod.TermInfo.Source.csproj b/Icod.TermInfo.Source/Icod.TermInfo.Source.csproj index ab1161e..9d55108 100644 --- a/Icod.TermInfo.Source/Icod.TermInfo.Source.csproj +++ b/Icod.TermInfo.Source/Icod.TermInfo.Source.csproj @@ -12,17 +12,17 @@ Icod.TermInfo.Source Icod.TermInfo.Source Debug;Release;Staging - 1.1.0 + 1.1.1 1.0.0.0 - 1.1.0 + 1.1.1 Icod.TermInfo.Source Icod.TermInfo.Source Timothy J. Bruce Managed terminfo source-language support for Icod.TermInfo. The 1.1 line parses and resolves .ti source into the stable TerminalDescription model without enlarging the runtime Icod.TermInfo package. - 1.1.0 completes managed .ti source parsing and resolution: diagnostics and source spans, string and numeric semantics, unresolved entries, standard and extended capability classification, cancellation, use= inheritance, TerminalDescription materialization, duplicate source-identity warnings, deterministic mutation fuzzing, hostile-input bounds, and offline tic-generated compatibility fixtures. + 1.1.1 is a coordinated maintenance release of Icod.TermInfo.Source for Icod.TermInfo 1.1.1. It preserves the 1.1.0 source-language public API and semantics while retaining assembly version 1.0.0.0. README.md icon.png https://github.com/uniblab/Icod.TermInfo diff --git a/Icod.TermInfo.Source/README.md b/Icod.TermInfo.Source/README.md index f00f4ad..d9dc364 100644 --- a/Icod.TermInfo.Source/README.md +++ b/Icod.TermInfo.Source/README.md @@ -9,15 +9,17 @@ values continue to reference `Icod.TermInfo` alone. ## Install -For the 1.1.0 release: +For the 1.1.1 release: ```text -dotnet add package Icod.TermInfo.Source --version 1.1.0 +dotnet add package Icod.TermInfo.Source --version 1.1.1 ``` The package depends on the matching `Icod.TermInfo` version. -## What 1.1.0 provides +Version 1.1.1 is a maintenance release and does not change the 1.1 source-language public API or semantics. + +## What the 1.1 line provides The completed 1.1 source-language path includes: diff --git a/Icod.TermInfo.csproj b/Icod.TermInfo.csproj index 59e663a..18b9309 100644 --- a/Icod.TermInfo.csproj +++ b/Icod.TermInfo.csproj @@ -12,16 +12,16 @@ Icod.TermInfo Icod.TermInfo Debug;Release;Staging - 1.1.0 + 1.1.1 1.0.0.0 - 1.1.0 + 1.1.1 Icod.TermInfo Icod.TermInfo Timothy J. Bruce Managed, dependency-free .NET terminfo library for terminal capability metadata, compiled terminfo parsing and database discovery, ANSI/DEC/xterm and Windows profiles, parameter expansion, color semantics, and padding-aware output. - 1.1.0 publishes the completed terminfo source-language work as the optional Icod.TermInfo.Source package while preserving the frozen Icod.TermInfo runtime public contract, dependency-free runtime package, and 1.0.0.0 assembly identity throughout the 1.x line. + 1.1.1 is a maintenance release of the 1.1 line. It preserves the frozen Icod.TermInfo runtime public contract, dependency-free runtime package, and 1.0.0.0 assembly identity while coordinating package versioning with Icod.TermInfo.Source. README.md icon.png https://github.com/uniblab/Icod.TermInfo diff --git a/README.md b/README.md index 5af0135..57c1633 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,22 @@ `Icod.TermInfo` is a managed, dependency-free .NET implementation of the low-level terminal-capability model traditionally supplied by `libtinfo`. -Version 1.1.0 is the current stable package release. It preserves the frozen 1.0 runtime contract while adding the optional `Icod.TermInfo.Source` package for managed `.ti` source parsing, cancellation, `use=` inheritance, and materialization into the existing immutable `TerminalDescription` model. +Version 1.1.1 is the current maintenance release of the 1.1 line. It preserves the frozen 1.0 runtime contract and the 1.1 source-language feature set provided by the optional `Icod.TermInfo.Source` package. Both packages target `net8.0` and `net10.0`, use C# 13, contain no native ncurses/terminfo payload, and are intended to run on Windows, Linux, and macOS. ## Install -For the 1.1.0 release, runtime-only consumers use: +For the 1.1.1 release, runtime-only consumers use: ```text -dotnet add package Icod.TermInfo --version 1.1.0 +dotnet add package Icod.TermInfo --version 1.1.1 ``` Applications which need terminfo source-language support use: ```text -dotnet add package Icod.TermInfo.Source --version 1.1.0 +dotnet add package Icod.TermInfo.Source --version 1.1.1 ``` `Icod.TermInfo.Source` depends on the matching `Icod.TermInfo` package. Applications which only load compiled terminfo or consume `TerminalDescription` values continue to reference `Icod.TermInfo` alone. @@ -750,7 +750,7 @@ See `docs/RELEASING.md` for the release procedure, `Icod.TermInfo-Development-Roadmap-1.0.0.md` for the frozen runtime contract, `Icod.TermInfo-Post-1.0-Development-Roadmap.md` for the 1.1 source-language program, and `docs/1.1.0-RELEASE-AUDIT.md` for the final release gate. Tag -`v1.1.0` only on the exact `main` commit whose complete Release validation and +`v1.1.1` only on the exact `main` commit whose complete Release validation and publication succeeded; no source or package content may change between that validation and tagging. diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 0f3627c..799f3ea 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -244,6 +244,6 @@ For 1.1, use: - `docs/1.0.0-PUBLIC-API-BASELINE.txt` for the unchanged runtime API; - `docs/VERSIONING.md` and `docs/COMPATIBILITY.md` for the stable 1.x promises. -The final `v1.1.0` tag must identify the exact validated and published `main` +The final `v` tag must identify the exact validated and published `main` commit. Do not edit the audit or any other source/package content after that validation without rerunning the release gate. diff --git a/icon.png b/icon.png index 6258ecf..77249b0 100644 Binary files a/icon.png and b/icon.png differ diff --git a/tests/Icod.TermInfo.Source.Tests/src/S01ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S01ContractTests.cs index 7f69875..2b3755c 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S01ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S01ContractTests.cs @@ -3,305 +3,292 @@ namespace Icod.TermInfo.Source.Tests; -public sealed class S01ContractTests -{ - private const string DevelopmentVersion = "1.1.0"; - private const string StableAssemblyVersion = "1.0.0.0"; +public sealed class S01ContractTests { + private const string DevelopmentVersion = "1.1.1"; + private const string StableAssemblyVersion = "1.0.0.0"; - [Fact] - public void SourcePackageFoundationIsVersionedAndLayered() - { - string root = FindRepositoryRoot(); - XDocument sourceProject = - XDocument.Load( - Path.Combine( - root, - "Icod.TermInfo.Source", - "Icod.TermInfo.Source.csproj"), - LoadOptions.None); - XDocument runtimeProject = - XDocument.Load( - Path.Combine( - root, - "Icod.TermInfo.csproj"), - LoadOptions.None); + [Fact] + public void SourcePackageFoundationIsVersionedAndLayered() { + string root = FindRepositoryRoot(); + XDocument sourceProject = + XDocument.Load( + Path.Combine( + root, + "Icod.TermInfo.Source", + "Icod.TermInfo.Source.csproj" ), + LoadOptions.None ); + XDocument runtimeProject = + XDocument.Load( + Path.Combine( + root, + "Icod.TermInfo.csproj" ), + LoadOptions.None ); - Assert.Equal( - "net8.0;net10.0", - ReadRequiredProperty( - sourceProject, - "TargetFrameworks")); - Assert.Equal( - "13.0", - ReadRequiredProperty( - sourceProject, - "LangVersion")); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - sourceProject, - "Version")); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - sourceProject, - "PackageVersion")); - Assert.Equal( - StableAssemblyVersion, - ReadRequiredProperty( - sourceProject, - "AssemblyVersion")); - Assert.Equal( - "Icod.TermInfo.Source", - ReadRequiredProperty( - sourceProject, - "PackageId")); + Assert.Equal( + "net8.0;net10.0", + ReadRequiredProperty( + sourceProject, + "TargetFrameworks" ) ); + Assert.Equal( + "13.0", + ReadRequiredProperty( + sourceProject, + "LangVersion" ) ); + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + sourceProject, + "Version" ) ); + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + sourceProject, + "PackageVersion" ) ); + Assert.Equal( + StableAssemblyVersion, + ReadRequiredProperty( + sourceProject, + "AssemblyVersion" ) ); + Assert.Equal( + "Icod.TermInfo.Source", + ReadRequiredProperty( + sourceProject, + "PackageId" ) ); - XElement sourceReference = - sourceProject - .Descendants() - .Single( - element => - element.Name.LocalName - == "ProjectReference"); - Assert.Equal( - @"..\Icod.TermInfo.csproj", - sourceReference - .Attribute("Include") - ?.Value); + XElement sourceReference = + sourceProject + .Descendants() + .Single( + element => + element.Name.LocalName + == "ProjectReference" ); + Assert.Equal( + @"..\Icod.TermInfo.csproj", + sourceReference + .Attribute( "Include" ) + ?.Value ); - Assert.DoesNotContain( - runtimeProject.Descendants(), - element => - element.Name.LocalName - == "ProjectReference" - && (element.Attribute("Include")?.Value - .Contains( - "Icod.TermInfo.Source", - StringComparison.OrdinalIgnoreCase) - ?? false)); - } + Assert.DoesNotContain( + runtimeProject.Descendants(), + element => + element.Name.LocalName + == "ProjectReference" + && ( element.Attribute( "Include" )?.Value + .Contains( + "Icod.TermInfo.Source", + StringComparison.OrdinalIgnoreCase ) + ?? false ) ); + } - [Fact] - public void RuntimePackageStartsOneOneDevelopmentWithoutChangingAssemblyIdentity() - { - string root = FindRepositoryRoot(); - XDocument runtimeProject = - XDocument.Load( - Path.Combine( - root, - "Icod.TermInfo.csproj"), - LoadOptions.None); + [Fact] + public void RuntimePackageStartsOneOneDevelopmentWithoutChangingAssemblyIdentity() { + string root = FindRepositoryRoot(); + XDocument runtimeProject = + XDocument.Load( + Path.Combine( + root, + "Icod.TermInfo.csproj" ), + LoadOptions.None ); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - runtimeProject, - "Version")); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - runtimeProject, - "PackageVersion")); - Assert.Equal( - StableAssemblyVersion, - ReadRequiredProperty( - runtimeProject, - "AssemblyVersion")); - } + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + runtimeProject, + "Version" ) ); + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + runtimeProject, + "PackageVersion" ) ); + Assert.Equal( + StableAssemblyVersion, + ReadRequiredProperty( + runtimeProject, + "AssemblyVersion" ) ); + } - [Fact] - public void SourceTestsAndFreshConsumerMatchTheSupportedFrameworkMatrix() - { - string root = FindRepositoryRoot(); + [Fact] + public void SourceTestsAndFreshConsumerMatchTheSupportedFrameworkMatrix() { + string root = FindRepositoryRoot(); - Assert.Equal( - "net8.0;net10.0", - ReadProjectProperty( - root, - "tests/Icod.TermInfo.Source.Tests/Icod.TermInfo.Source.Tests.csproj", - "TargetFrameworks")); - Assert.Equal( - "net8.0;net10.0", - ReadProjectProperty( - root, - "tools/source-package-smoke/Icod.TermInfo.Source.PackageSmoke.csproj", - "TargetFrameworks")); - } + Assert.Equal( + "net8.0;net10.0", + ReadProjectProperty( + root, + "tests/Icod.TermInfo.Source.Tests/Icod.TermInfo.Source.Tests.csproj", + "TargetFrameworks" ) ); + Assert.Equal( + "net8.0;net10.0", + ReadProjectProperty( + root, + "tools/source-package-smoke/Icod.TermInfo.Source.PackageSmoke.csproj", + "TargetFrameworks" ) ); + } - [Fact] - public void SolutionAndContinuousIntegrationIncludeTheSourcePackage() - { - string root = FindRepositoryRoot(); - string solution = - File.ReadAllText( - Path.Combine( - root, - "Icod.TermInfo.sln")); - string pullRequest = - File.ReadAllText( - Path.Combine( - root, - ".github", - "workflows", - "pr-build-and-test.yaml")); - string pushMain = - File.ReadAllText( - Path.Combine( - root, - ".github", - "workflows", - "push-main.yaml")); + [Fact] + public void SolutionAndContinuousIntegrationIncludeTheSourcePackage() { + string root = FindRepositoryRoot(); + string solution = + File.ReadAllText( + Path.Combine( + root, + "Icod.TermInfo.sln" ) ); + string pullRequest = + File.ReadAllText( + Path.Combine( + root, + ".github", + "workflows", + "pr-build-and-test.yaml" ) ); + string pushMain = + File.ReadAllText( + Path.Combine( + root, + ".github", + "workflows", + "push-main.yaml" ) ); - Assert.Contains( - "Icod.TermInfo.Source", - solution); - Assert.Contains( - "Icod.TermInfo.Source.Tests", - solution); - Assert.Contains( - "dotnet pack Icod.TermInfo.Source/Icod.TermInfo.Source.csproj -c Staging", - pullRequest); - Assert.Contains( - "dotnet pack Icod.TermInfo.Source/Icod.TermInfo.Source.csproj -c Release", - pushMain); - } + Assert.Contains( + "Icod.TermInfo.Source", + solution ); + Assert.Contains( + "Icod.TermInfo.Source.Tests", + solution ); + Assert.Contains( + "dotnet pack Icod.TermInfo.Source/Icod.TermInfo.Source.csproj -c Staging", + pullRequest ); + Assert.Contains( + "dotnet pack Icod.TermInfo.Source/Icod.TermInfo.Source.csproj -c Release", + pushMain ); + } - [Fact] - public void PackageValidationCoversSourceApiParityAndFreshConsumption() - { - string root = FindRepositoryRoot(); + [Fact] + public void PackageValidationCoversSourceApiParityAndFreshConsumption() { + string root = FindRepositoryRoot(); - foreach ( - string relativePath - in new[] - { - Path.Combine( - ".github", - "scripts", - "verify-release-package.cmd"), - Path.Combine( - ".github", - "scripts", - "verify-release-package.sh"), - }) - { - string verifier = - File.ReadAllText( - Path.Combine( - root, - relativePath)); + foreach ( + string relativePath + in new[] + { + Path.Combine( + ".github", + "scripts", + "verify-release-package.cmd"), + Path.Combine( + ".github", + "scripts", + "verify-release-package.sh"), + } ) { + string verifier = + File.ReadAllText( + Path.Combine( + root, + relativePath ) ); - Assert.Contains( - "Icod.TermInfo.Source", - verifier); - Assert.Contains( - "source-package-smoke", - verifier); - Assert.Contains( - "--compare", - verifier); - Assert.Contains( - "net8.0", - verifier); - Assert.Contains( - "net10.0", - verifier); - } - } + Assert.Contains( + "Icod.TermInfo.Source", + verifier ); + Assert.Contains( + "source-package-smoke", + verifier ); + Assert.Contains( + "--compare", + verifier ); + Assert.Contains( + "net8.0", + verifier ); + Assert.Contains( + "net10.0", + verifier ); + } + } - [Fact] - public void SourceDiagnosticConventionIsRecordedBeforeParserApi() - { - string root = FindRepositoryRoot(); - string record = - File.ReadAllText( - Path.Combine( - root, - "docs", - "1.1.0-S01-SOURCE-PACKAGE-FOUNDATION.md")); + [Fact] + public void SourceDiagnosticConventionIsRecordedBeforeParserApi() { + string root = FindRepositoryRoot(); + string record = + File.ReadAllText( + Path.Combine( + root, + "docs", + "1.1.0-S01-SOURCE-PACKAGE-FOUNDATION.md" ) ); - Assert.Contains( - "TIS", - record); - Assert.True( - record.Contains( - "severity", - StringComparison.OrdinalIgnoreCase)); - Assert.True( - record.Contains( - "source location", - StringComparison.OrdinalIgnoreCase)); - Assert.True( - record.Contains( - "deterministic", - StringComparison.OrdinalIgnoreCase)); - Assert.Contains( - "S02", - record); - } + Assert.Contains( + "TIS", + record ); + Assert.True( + record.Contains( + "severity", + StringComparison.OrdinalIgnoreCase ) ); + Assert.True( + record.Contains( + "source location", + StringComparison.OrdinalIgnoreCase ) ); + Assert.True( + record.Contains( + "deterministic", + StringComparison.OrdinalIgnoreCase ) ); + Assert.Contains( + "S02", + record ); + } - private static string ReadProjectProperty( - string root, - string relativePath, - string propertyName) - { - ArgumentNullException.ThrowIfNull(root); - ArgumentNullException.ThrowIfNull(relativePath); - ArgumentNullException.ThrowIfNull(propertyName); + private static string ReadProjectProperty( + string root, + string relativePath, + string propertyName ) { + ArgumentNullException.ThrowIfNull( root ); + ArgumentNullException.ThrowIfNull( relativePath ); + ArgumentNullException.ThrowIfNull( propertyName ); - XDocument project = - XDocument.Load( - Path.Combine( - root, - relativePath.Replace( - '/', - Path.DirectorySeparatorChar)), - LoadOptions.None); + XDocument project = + XDocument.Load( + Path.Combine( + root, + relativePath.Replace( + '/', + Path.DirectorySeparatorChar ) ), + LoadOptions.None ); - return ReadRequiredProperty( - project, - propertyName); - } + return ReadRequiredProperty( + project, + propertyName ); + } - private static string ReadRequiredProperty( - XDocument project, - string propertyName) - { - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(propertyName); + private static string ReadRequiredProperty( + XDocument project, + string propertyName ) { + ArgumentNullException.ThrowIfNull( project ); + ArgumentNullException.ThrowIfNull( propertyName ); - return project - .Descendants() - .First( - element => - element.Name.LocalName - == propertyName) - .Value - .Trim(); - } + return project + .Descendants() + .First( + element => + element.Name.LocalName + == propertyName ) + .Value + .Trim(); + } - private static string FindRepositoryRoot() - { - DirectoryInfo? current = - new( - AppContext.BaseDirectory); + private static string FindRepositoryRoot() { + DirectoryInfo? current = + new( + AppContext.BaseDirectory ); - while (current is not null) - { - if (File.Exists( - Path.Combine( - current.FullName, - "Icod.TermInfo.sln"))) - { - return current.FullName; - } + while ( current is not null ) { + if ( File.Exists( + Path.Combine( + current.FullName, + "Icod.TermInfo.sln" ) ) ) { + return current.FullName; + } - current = - current.Parent; - } + current = + current.Parent; + } - throw new InvalidOperationException( - "Unable to locate the Icod.TermInfo repository root."); - } + throw new InvalidOperationException( + "Unable to locate the Icod.TermInfo repository root." ); + } } diff --git a/tests/Icod.TermInfo.Source.Tests/src/S02ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S02ContractTests.cs index 3322061..5b9a5e3 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S02ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S02ContractTests.cs @@ -7,7 +7,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S02ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Source.Tests/src/S03ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S03ContractTests.cs index a870c8b..3e8abcc 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S03ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S03ContractTests.cs @@ -7,7 +7,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S03ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Source.Tests/src/S04ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S04ContractTests.cs index 388f201..07c9fbc 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S04ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S04ContractTests.cs @@ -6,231 +6,216 @@ namespace Icod.TermInfo.Source.Tests; -public sealed class S04ContractTests -{ - private const string DevelopmentVersion = "1.1.0"; - private const string StableAssemblyVersion = "1.0.0.0"; - - [Fact] - public void SourceAndRuntimePackagesAdvanceTogetherWithoutChangingAssemblyIdentity() - { - string root = FindRepositoryRoot(); - - foreach ( - string relativePath - in new[] - { - "Icod.TermInfo.csproj", - "Icod.TermInfo.Source/Icod.TermInfo.Source.csproj", - }) - { - XDocument project = - XDocument.Load( - Path.Combine( - root, - relativePath.Replace( - '/', - Path.DirectorySeparatorChar)), - LoadOptions.None); - - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - project, - "Version")); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - project, - "PackageVersion")); - Assert.Equal( - StableAssemblyVersion, - ReadRequiredProperty( - project, - "AssemblyVersion")); - } - } - - [Fact] - public void SourcePublicSurfaceIncludesReviewedUnresolvedModelTypes() - { - Assembly assembly = - typeof(TermInfoSourceParser).Assembly; - string[] exportedTypes = - assembly - .GetExportedTypes() - .Select(type => type.FullName!) - .ToArray(); - - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceDocument", - exportedTypes - ); - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceEntry", - exportedTypes - ); - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceField", - exportedTypes - ); - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceFieldKind", - exportedTypes - ); - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceParseResult", - exportedTypes - ); - Assert.Contains( - "Icod.TermInfo.Source.TermInfoSourceParser", - exportedTypes - ); - Assert.Equal( - new Version(1, 0, 0, 0), - assembly.GetName().Version - ); - } - - [Fact] - public void UnresolvedModelDoesNotExposeTerminalDescriptionState() - { - Type[] modelTypes = - [ - typeof(TermInfoSourceDocument), - typeof(TermInfoSourceEntry), - typeof(TermInfoSourceField), - typeof(TermInfoSourceParseResult), - ]; - - Assert.DoesNotContain( - modelTypes - .SelectMany( - type => - type.GetProperties( - BindingFlags.Public - | BindingFlags.Instance)) - .SelectMany( - property => - FlattenType(property.PropertyType)), - type => type == typeof(TerminalDescription)); - } - - [Fact] - public void SourcePublicApiBaselineIncludesUnresolvedModelContract() - { - string root = FindRepositoryRoot(); - string baseline = - File.ReadAllText( - Path.Combine( - root, - "docs", - "1.1.0-SOURCE-PUBLIC-API-BASELINE.txt")); - - Assert.Contains( - "TYPE class Icod.TermInfo.Source.TermInfoSourceDocument [sealed]", - baseline); - Assert.Contains( - "TYPE class Icod.TermInfo.Source.TermInfoSourceEntry [sealed]", - baseline); - Assert.Contains( - "TYPE class Icod.TermInfo.Source.TermInfoSourceField [sealed]", - baseline); - Assert.Contains( - "TYPE enum Icod.TermInfo.Source.TermInfoSourceFieldKind [sealed]", - baseline); - Assert.Contains( - "TYPE class Icod.TermInfo.Source.TermInfoSourceParseResult [sealed]", - baseline); - Assert.Contains( - "TYPE class Icod.TermInfo.Source.TermInfoSourceParser [static]", - baseline); - } - - [Fact] - public void S04ImplementationRecordAndRoadmapLinkArePresent() - { - string root = FindRepositoryRoot(); - string recordPath = - Path.Combine( - root, - "docs", - "1.1.0-S04-UNRESOLVED-SOURCE-ENTRY-MODEL.md"); - string roadmap = - File.ReadAllText( - Path.Combine( - root, - "Icod.TermInfo-Post-1.0-Development-Roadmap.md")); - - Assert.True(File.Exists(recordPath)); - string record = - File.ReadAllText(recordPath); - Assert.Contains("1.1.0-Alpha-4", record); - Assert.Contains("TermInfoSourceDocument", record); - Assert.Contains("TermInfoSourceEntry", record); - Assert.Contains("TermInfoSourceField", record); - Assert.Contains("S05", record); - Assert.Contains( - "1.1.0-S04-UNRESOLVED-SOURCE-ENTRY-MODEL.md", - roadmap); - } - - private static IEnumerable FlattenType( - Type type) - { - ArgumentNullException.ThrowIfNull(type); - - yield return type; - if (type.IsGenericType) - { - foreach (Type argument in type.GetGenericArguments()) - { - foreach (Type nested in FlattenType(argument)) - { - yield return nested; - } - } - } - } - - private static string ReadRequiredProperty( - XDocument project, - string propertyName) - { - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(propertyName); - - return project - .Descendants() - .First( - element => - element.Name.LocalName - == propertyName) - .Value - .Trim(); - } - - private static string FindRepositoryRoot() - { - DirectoryInfo? current = - new( - AppContext.BaseDirectory); - - while (current is not null) - { - if (File.Exists( - Path.Combine( - current.FullName, - "Icod.TermInfo.sln"))) - { - return current.FullName; - } - - current = - current.Parent; - } - - throw new InvalidOperationException( - "Unable to locate the Icod.TermInfo repository root."); - } +public sealed class S04ContractTests { + private const string DevelopmentVersion = "1.1.1"; + private const string StableAssemblyVersion = "1.0.0.0"; + + [Fact] + public void SourceAndRuntimePackagesAdvanceTogetherWithoutChangingAssemblyIdentity() { + string root = FindRepositoryRoot(); + + foreach ( + string relativePath + in new[] + { + "Icod.TermInfo.csproj", + "Icod.TermInfo.Source/Icod.TermInfo.Source.csproj", + } ) { + XDocument project = + XDocument.Load( + Path.Combine( + root, + relativePath.Replace( + '/', + Path.DirectorySeparatorChar ) ), + LoadOptions.None ); + + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + project, + "Version" ) ); + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + project, + "PackageVersion" ) ); + Assert.Equal( + StableAssemblyVersion, + ReadRequiredProperty( + project, + "AssemblyVersion" ) ); + } + } + + [Fact] + public void SourcePublicSurfaceIncludesReviewedUnresolvedModelTypes() { + Assembly assembly = + typeof( TermInfoSourceParser ).Assembly; + string[] exportedTypes = + assembly + .GetExportedTypes() + .Select( type => type.FullName! ) + .ToArray(); + + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceDocument", + exportedTypes + ); + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceEntry", + exportedTypes + ); + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceField", + exportedTypes + ); + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceFieldKind", + exportedTypes + ); + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceParseResult", + exportedTypes + ); + Assert.Contains( + "Icod.TermInfo.Source.TermInfoSourceParser", + exportedTypes + ); + Assert.Equal( + new Version( 1, 0, 0, 0 ), + assembly.GetName().Version + ); + } + + [Fact] + public void UnresolvedModelDoesNotExposeTerminalDescriptionState() { + Type[] modelTypes = + [ + typeof(TermInfoSourceDocument), + typeof(TermInfoSourceEntry), + typeof(TermInfoSourceField), + typeof(TermInfoSourceParseResult), + ]; + + Assert.DoesNotContain( + modelTypes + .SelectMany( + type => + type.GetProperties( + BindingFlags.Public + | BindingFlags.Instance ) ) + .SelectMany( + property => + FlattenType( property.PropertyType ) ), + type => type == typeof( TerminalDescription ) ); + } + + [Fact] + public void SourcePublicApiBaselineIncludesUnresolvedModelContract() { + string root = FindRepositoryRoot(); + string baseline = + File.ReadAllText( + Path.Combine( + root, + "docs", + "1.1.0-SOURCE-PUBLIC-API-BASELINE.txt" ) ); + + Assert.Contains( + "TYPE class Icod.TermInfo.Source.TermInfoSourceDocument [sealed]", + baseline ); + Assert.Contains( + "TYPE class Icod.TermInfo.Source.TermInfoSourceEntry [sealed]", + baseline ); + Assert.Contains( + "TYPE class Icod.TermInfo.Source.TermInfoSourceField [sealed]", + baseline ); + Assert.Contains( + "TYPE enum Icod.TermInfo.Source.TermInfoSourceFieldKind [sealed]", + baseline ); + Assert.Contains( + "TYPE class Icod.TermInfo.Source.TermInfoSourceParseResult [sealed]", + baseline ); + Assert.Contains( + "TYPE class Icod.TermInfo.Source.TermInfoSourceParser [static]", + baseline ); + } + + [Fact] + public void S04ImplementationRecordAndRoadmapLinkArePresent() { + string root = FindRepositoryRoot(); + string recordPath = + Path.Combine( + root, + "docs", + "1.1.0-S04-UNRESOLVED-SOURCE-ENTRY-MODEL.md" ); + string roadmap = + File.ReadAllText( + Path.Combine( + root, + "Icod.TermInfo-Post-1.0-Development-Roadmap.md" ) ); + + Assert.True( File.Exists( recordPath ) ); + string record = + File.ReadAllText( recordPath ); + Assert.Contains( "1.1.0-Alpha-4", record ); + Assert.Contains( "TermInfoSourceDocument", record ); + Assert.Contains( "TermInfoSourceEntry", record ); + Assert.Contains( "TermInfoSourceField", record ); + Assert.Contains( "S05", record ); + Assert.Contains( + "1.1.0-S04-UNRESOLVED-SOURCE-ENTRY-MODEL.md", + roadmap ); + } + + private static IEnumerable FlattenType( + Type type ) { + ArgumentNullException.ThrowIfNull( type ); + + yield return type; + if ( type.IsGenericType ) { + foreach ( Type argument in type.GetGenericArguments() ) { + foreach ( Type nested in FlattenType( argument ) ) { + yield return nested; + } + } + } + } + + private static string ReadRequiredProperty( + XDocument project, + string propertyName ) { + ArgumentNullException.ThrowIfNull( project ); + ArgumentNullException.ThrowIfNull( propertyName ); + + return project + .Descendants() + .First( + element => + element.Name.LocalName + == propertyName ) + .Value + .Trim(); + } + + private static string FindRepositoryRoot() { + DirectoryInfo? current = + new( + AppContext.BaseDirectory ); + + while ( current is not null ) { + if ( File.Exists( + Path.Combine( + current.FullName, + "Icod.TermInfo.sln" ) ) ) { + return current.FullName; + } + + current = + current.Parent; + } + + throw new InvalidOperationException( + "Unable to locate the Icod.TermInfo repository root." ); + } } diff --git a/tests/Icod.TermInfo.Source.Tests/src/S05ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S05ContractTests.cs index f9c3436..3bb08bc 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S05ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S05ContractTests.cs @@ -7,7 +7,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S05ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Source.Tests/src/S06ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S06ContractTests.cs index ef916e6..c3104fe 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S06ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S06ContractTests.cs @@ -6,152 +6,143 @@ namespace Icod.TermInfo.Source.Tests; -public sealed class S06ContractTests -{ - private const string DevelopmentVersion = "1.1.0"; - private const string StableAssemblyVersion = "1.0.0.0"; - - [Fact] - public void SourceAndRuntimePackagesAdvanceTogetherWithoutChangingAssemblyIdentity() - { - string root = FindRepositoryRoot(); - - foreach ( - string relativePath - in new[] - { - "Icod.TermInfo.csproj", - "Icod.TermInfo.Source/Icod.TermInfo.Source.csproj", - }) - { - XDocument project = - XDocument.Load( - Path.Combine( - root, - relativePath.Replace( - '/', - Path.DirectorySeparatorChar)), - LoadOptions.None); - - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - project, - "Version")); - Assert.Equal( - DevelopmentVersion, - ReadRequiredProperty( - project, - "PackageVersion")); - Assert.Equal( - StableAssemblyVersion, - ReadRequiredProperty( - project, - "AssemblyVersion")); - } - } - - [Fact] - public void CancellationStateRemainsInternalSourceResolutionMachinery() - { - Assembly assembly = - typeof(TermInfoSourceParser).Assembly; - - Assert.DoesNotContain( - assembly.GetExportedTypes(), - type => - type.FullName - == "Icod.TermInfo.Source.TermInfoSourceCapabilityState"); - Assert.Contains( - assembly.GetCustomAttributes(), - attribute => - attribute.AssemblyName - == "Icod.TermInfo.Source.Tests"); - - string root = FindRepositoryRoot(); - string baseline = - File.ReadAllText( - Path.Combine( - root, - "docs", - "1.1.0-SOURCE-PUBLIC-API-BASELINE.txt")); - Assert.DoesNotContain( - "TermInfoSourceCapabilityState", - baseline); - } - - [Fact] - public void S06ImplementationRecordAndRoadmapLinkArePresent() - { - string root = FindRepositoryRoot(); - string recordPath = - Path.Combine( - root, - "docs", - "1.1.0-S06-CANCELLATION-SEMANTICS.md"); - string roadmap = - File.ReadAllText( - Path.Combine( - root, - "Icod.TermInfo-Post-1.0-Development-Roadmap.md")); - - Assert.True(File.Exists(recordPath)); - string record = - File.ReadAllText(recordPath); - Assert.Contains("1.1.0-Alpha-6", record); - Assert.Contains("capability@", record); - Assert.True( - record.Contains( - "tombstone", - StringComparison.OrdinalIgnoreCase)); - Assert.True( - record.Contains( - "rightmost", - StringComparison.OrdinalIgnoreCase)); - Assert.Contains("S07", record); - Assert.Contains( - "1.1.0-S06-CANCELLATION-SEMANTICS.md", - roadmap); - } - - private static string ReadRequiredProperty( - XDocument project, - string propertyName) - { - ArgumentNullException.ThrowIfNull(project); - ArgumentNullException.ThrowIfNull(propertyName); - - return project - .Descendants() - .First( - element => - element.Name.LocalName - == propertyName) - .Value - .Trim(); - } - - private static string FindRepositoryRoot() - { - DirectoryInfo? current = - new( - AppContext.BaseDirectory); - - while (current is not null) - { - if (File.Exists( - Path.Combine( - current.FullName, - "Icod.TermInfo.sln"))) - { - return current.FullName; - } - - current = - current.Parent; - } - - throw new InvalidOperationException( - "Unable to locate the Icod.TermInfo repository root."); - } +public sealed class S06ContractTests { + private const string DevelopmentVersion = "1.1.1"; + private const string StableAssemblyVersion = "1.0.0.0"; + + [Fact] + public void SourceAndRuntimePackagesAdvanceTogetherWithoutChangingAssemblyIdentity() { + string root = FindRepositoryRoot(); + + foreach ( + string relativePath + in new[] + { + "Icod.TermInfo.csproj", + "Icod.TermInfo.Source/Icod.TermInfo.Source.csproj", + } ) { + XDocument project = + XDocument.Load( + Path.Combine( + root, + relativePath.Replace( + '/', + Path.DirectorySeparatorChar ) ), + LoadOptions.None ); + + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + project, + "Version" ) ); + Assert.Equal( + DevelopmentVersion, + ReadRequiredProperty( + project, + "PackageVersion" ) ); + Assert.Equal( + StableAssemblyVersion, + ReadRequiredProperty( + project, + "AssemblyVersion" ) ); + } + } + + [Fact] + public void CancellationStateRemainsInternalSourceResolutionMachinery() { + Assembly assembly = + typeof( TermInfoSourceParser ).Assembly; + + Assert.DoesNotContain( + assembly.GetExportedTypes(), + type => + type.FullName + == "Icod.TermInfo.Source.TermInfoSourceCapabilityState" ); + Assert.Contains( + assembly.GetCustomAttributes(), + attribute => + attribute.AssemblyName + == "Icod.TermInfo.Source.Tests" ); + + string root = FindRepositoryRoot(); + string baseline = + File.ReadAllText( + Path.Combine( + root, + "docs", + "1.1.0-SOURCE-PUBLIC-API-BASELINE.txt" ) ); + Assert.DoesNotContain( + "TermInfoSourceCapabilityState", + baseline ); + } + + [Fact] + public void S06ImplementationRecordAndRoadmapLinkArePresent() { + string root = FindRepositoryRoot(); + string recordPath = + Path.Combine( + root, + "docs", + "1.1.0-S06-CANCELLATION-SEMANTICS.md" ); + string roadmap = + File.ReadAllText( + Path.Combine( + root, + "Icod.TermInfo-Post-1.0-Development-Roadmap.md" ) ); + + Assert.True( File.Exists( recordPath ) ); + string record = + File.ReadAllText( recordPath ); + Assert.Contains( "1.1.0-Alpha-6", record ); + Assert.Contains( "capability@", record ); + Assert.True( + record.Contains( + "tombstone", + StringComparison.OrdinalIgnoreCase ) ); + Assert.True( + record.Contains( + "rightmost", + StringComparison.OrdinalIgnoreCase ) ); + Assert.Contains( "S07", record ); + Assert.Contains( + "1.1.0-S06-CANCELLATION-SEMANTICS.md", + roadmap ); + } + + private static string ReadRequiredProperty( + XDocument project, + string propertyName ) { + ArgumentNullException.ThrowIfNull( project ); + ArgumentNullException.ThrowIfNull( propertyName ); + + return project + .Descendants() + .First( + element => + element.Name.LocalName + == propertyName ) + .Value + .Trim(); + } + + private static string FindRepositoryRoot() { + DirectoryInfo? current = + new( + AppContext.BaseDirectory ); + + while ( current is not null ) { + if ( File.Exists( + Path.Combine( + current.FullName, + "Icod.TermInfo.sln" ) ) ) { + return current.FullName; + } + + current = + current.Parent; + } + + throw new InvalidOperationException( + "Unable to locate the Icod.TermInfo repository root." ); + } } diff --git a/tests/Icod.TermInfo.Source.Tests/src/S07ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S07ContractTests.cs index a2d105d..e9c5d6a 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S07ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S07ContractTests.cs @@ -7,7 +7,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S07ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Source.Tests/src/S08ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S08ContractTests.cs index 5afa8ef..f8c8c4c 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S08ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S08ContractTests.cs @@ -7,7 +7,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S08ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Source.Tests/src/S09ContractTests.cs b/tests/Icod.TermInfo.Source.Tests/src/S09ContractTests.cs index 3e8bd78..8b46f2e 100644 --- a/tests/Icod.TermInfo.Source.Tests/src/S09ContractTests.cs +++ b/tests/Icod.TermInfo.Source.Tests/src/S09ContractTests.cs @@ -5,7 +5,7 @@ namespace Icod.TermInfo.Source.Tests; public sealed class S09ContractTests { - private const string DevelopmentVersion = "1.1.0"; + private const string DevelopmentVersion = "1.1.1"; private const string StableAssemblyVersion = "1.0.0.0"; [Fact] diff --git a/tests/Icod.TermInfo.Tests/src/T45CompletionGateTests.cs b/tests/Icod.TermInfo.Tests/src/T45CompletionGateTests.cs index dffa92f..aab751e 100644 --- a/tests/Icod.TermInfo.Tests/src/T45CompletionGateTests.cs +++ b/tests/Icod.TermInfo.Tests/src/T45CompletionGateTests.cs @@ -5,13 +5,11 @@ namespace Icod.TermInfo.Tests; -public sealed class T45CompletionGateTests -{ +public sealed class T45CompletionGateTests { [Fact] - public void AssemblyRetainsStableIdentityForOneOneRelease() - { + public void AssemblyRetainsStableIdentityForOneOneRelease() { Assembly assembly = - typeof(TerminalDescription).Assembly; + typeof( TerminalDescription ).Assembly; AssemblyName assemblyName = assembly.GetName(); string? informationalVersion = @@ -20,90 +18,87 @@ public void AssemblyRetainsStableIdentityForOneOneRelease() ?.InformationalVersion; Assert.Equal( - new Version(1, 0, 0, 0), - assemblyName.Version); + new Version( 1, 0, 0, 0 ), + assemblyName.Version ); Assert.NotNull( - informationalVersion); + informationalVersion ); string semanticVersion = informationalVersion! .Split( '+', - 2)[0]; + 2 )[ 0 ]; Assert.Equal( - "1.1.0", - semanticVersion); + "1.1.1", + semanticVersion ); } [Fact] - public void ProjectMetadataIdentifiesOneOneReleaseAndStableAssembly() - { + public void ProjectMetadataIdentifiesOneOneReleaseAndStableAssembly() { string root = FindRepositoryRoot(); XDocument project = XDocument.Load( Path.Combine( root, - "Icod.TermInfo.csproj"), - LoadOptions.None); + "Icod.TermInfo.csproj" ), + LoadOptions.None ); Assert.Equal( - "1.1.0", + "1.1.1", ReadRequiredProperty( project, - "Version")); + "Version" ) ); Assert.Equal( - "1.1.0", + "1.1.1", ReadRequiredProperty( project, - "PackageVersion")); + "PackageVersion" ) ); Assert.Equal( "1.0.0.0", ReadRequiredProperty( project, - "AssemblyVersion")); + "AssemblyVersion" ) ); Assert.Equal( "net8.0;net10.0", ReadRequiredProperty( project, - "TargetFrameworks")); + "TargetFrameworks" ) ); } [Fact] - public void FinalReadmeUsesStablePackageVersionAndPolicies() - { + public void FinalReadmeUsesStablePackageVersionAndPolicies() { string root = FindRepositoryRoot(); string readme = File.ReadAllText( Path.Combine( root, - "README.md")); + "README.md" ) ); Assert.Contains( - "dotnet add package Icod.TermInfo --version 1.1.0", - readme); + "dotnet add package Icod.TermInfo --version 1.1.1", + readme ); Assert.Contains( - "dotnet add package Icod.TermInfo.Source --version 1.1.0", - readme); + "dotnet add package Icod.TermInfo.Source --version 1.1.1", + readme ); Assert.DoesNotContain( "1.1.0-Alpha-9", - readme); + readme ); Assert.Contains( "docs/VERSIONING.md", - readme); + readme ); Assert.Contains( "docs/COMPATIBILITY.md", - readme); + readme ); Assert.Contains( "docs/1.1.0-RELEASE-AUDIT.md", - readme); + readme ); } [Fact] - public void ReleaseVerifierRetainsAllFinalCompatibilityGates() - { + public void ReleaseVerifierRetainsAllFinalCompatibilityGates() { string root = FindRepositoryRoot(); @@ -119,43 +114,41 @@ in new[] ".github", "scripts", "verify-release-package.sh"), - }) - { + } ) { string verifier = File.ReadAllText( Path.Combine( root, - relativePath)); + relativePath ) ); Assert.Contains( "--check", - verifier); + verifier ); Assert.Contains( "--compare", - verifier); + verifier ); Assert.Contains( "net8.0", - verifier); + verifier ); Assert.Contains( "net10.0", - verifier); + verifier ); Assert.Contains( "1.1.0-SOURCE-PUBLIC-API-BASELINE.txt", - verifier); + verifier ); Assert.True( verifier.Contains( "package-smoke", - StringComparison.OrdinalIgnoreCase)); + StringComparison.OrdinalIgnoreCase ) ); Assert.True( verifier.Contains( "source-package-smoke", - StringComparison.OrdinalIgnoreCase)); + StringComparison.OrdinalIgnoreCase ) ); } } [Fact] - public void OneOneReleaseAuditDefinesReleaseSignOffWithoutClaimingIt() - { + public void OneOneReleaseAuditDefinesReleaseSignOffWithoutClaimingIt() { string root = FindRepositoryRoot(); string audit = @@ -163,60 +156,56 @@ public void OneOneReleaseAuditDefinesReleaseSignOffWithoutClaimingIt() Path.Combine( root, "docs", - "1.1.0-RELEASE-AUDIT.md")); + "1.1.0-RELEASE-AUDIT.md" ) ); Assert.Contains( "Release sign-off pending", - audit); + audit ); Assert.Contains( "docs/1.0.0-PUBLIC-API-BASELINE.txt", - audit); + audit ); Assert.Contains( "docs/1.1.0-SOURCE-PUBLIC-API-BASELINE.txt", - audit); + audit ); Assert.Contains( "public-api-snapshot --check", - audit); + audit ); Assert.Contains( "verify-release-package", - audit); + audit ); Assert.Contains( "v1.1.0", - audit); + audit ); } private static string ReadRequiredProperty( XDocument project, - string name) - { + string name ) { ArgumentNullException.ThrowIfNull( - project); + project ); ArgumentNullException.ThrowIfNull( - name); + name ); return project .Descendants() .Single( element => element.Name.LocalName - == name) + == name ) .Value .Trim(); } - private static string FindRepositoryRoot() - { + private static string FindRepositoryRoot() { DirectoryInfo? current = new( - AppContext.BaseDirectory); + AppContext.BaseDirectory ); - while (current is not null) - { - if (File.Exists( + while ( current is not null ) { + if ( File.Exists( Path.Combine( current.FullName, - "Icod.TermInfo.csproj"))) - { + "Icod.TermInfo.csproj" ) ) ) { return current.FullName; } @@ -225,6 +214,6 @@ private static string FindRepositoryRoot() } throw new InvalidOperationException( - "Unable to locate the Icod.TermInfo repository root."); + "Unable to locate the Icod.TermInfo repository root." ); } }