// ----------------------------------------------------------------------------- // DeprecationWarningTests.cs // Sprint: SPRINT_20260118_014_CLI_evidence_remaining_consolidation (CLI-E-009) // Description: Tests verifying that deprecated command paths produce appropriate // deprecation warnings to guide users toward canonical paths. // ----------------------------------------------------------------------------- using System; using System.IO; using Xunit; using StellaOps.Cli.Infrastructure; namespace StellaOps.Cli.Tests.Integration; /// /// Tests verifying deprecation warnings are properly generated for old command paths. /// Ensures users are guided toward canonical command paths with clear messaging. /// [Trait("Category", "Integration")] [Trait("Sprint", "SPRINT_20260118_014_CLI_evidence_remaining_consolidation")] public class DeprecationWarningTests { #region Warning Message Format Tests [Theory] [InlineData("evidenceholds list", "evidence holds list")] [InlineData("reachgraph list", "reachability graph list")] [InlineData("sbomer compose", "sbom compose")] [InlineData("keys list", "crypto keys list")] [InlineData("doctor run", "admin doctor run")] [InlineData("binary diff", "tools binary diff")] [InlineData("gate evaluate", "release gate evaluate")] [InlineData("vexgatescan", "vex gate-scan")] public void DeprecatedPath_ShouldGenerateWarningWithCanonicalPath(string oldPath, string newPath) { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var warning = router.GetDeprecationWarning(oldPath); // Assert Assert.NotNull(warning); Assert.Contains(newPath, warning); Assert.Contains("deprecated", warning, StringComparison.OrdinalIgnoreCase); } [Theory] [InlineData("evidenceholds list")] [InlineData("reachgraph list")] [InlineData("sbomer compose")] [InlineData("keys list")] [InlineData("doctor run")] public void DeprecatedPath_ShouldIncludeRemovalVersion(string oldPath) { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var warning = router.GetDeprecationWarning(oldPath); // Assert Assert.NotNull(warning); Assert.Contains("3.0", warning); } [Theory] [InlineData("evidenceholds list", "Evidence commands consolidated")] [InlineData("reachgraph list", "Reachability graph consolidated")] [InlineData("sbomer compose", "SBOM commands consolidated")] [InlineData("keys list", "Key management consolidated under crypto")] [InlineData("doctor run", "Doctor consolidated under admin")] [InlineData("binary diff", "Utility commands consolidated under tools")] [InlineData("gate evaluate", "Gate evaluation consolidated under release")] [InlineData("vexgatescan", "VEX gate scan consolidated")] public void DeprecatedPath_ShouldIncludeReasonForMove(string oldPath, string expectedReason) { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var reason = router.GetDeprecationReason(oldPath); // Assert Assert.NotNull(reason); Assert.Contains(expectedReason, reason, StringComparison.OrdinalIgnoreCase); } #endregion #region Warning Output Tests [Fact] public void DeprecatedPath_ShouldWriteWarningToStderr() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); var originalError = Console.Error; using var errorWriter = new StringWriter(); Console.SetError(errorWriter); try { // Act router.EmitDeprecationWarningIfNeeded("evidenceholds list"); var output = errorWriter.ToString(); // Assert Assert.Contains("warning", output, StringComparison.OrdinalIgnoreCase); Assert.Contains("evidence holds list", output); } finally { Console.SetError(originalError); } } [Fact] public void NonDeprecatedPath_ShouldNotWriteWarning() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); var originalError = Console.Error; using var errorWriter = new StringWriter(); Console.SetError(errorWriter); try { // Act router.EmitDeprecationWarningIfNeeded("evidence holds list"); var output = errorWriter.ToString(); // Assert Assert.Empty(output); } finally { Console.SetError(originalError); } } #endregion #region Warning Count Tests [Fact] public void AllDeprecatedPaths_ShouldHaveWarnings() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); var deprecatedPaths = router.GetAllDeprecatedPaths(); // Act & Assert foreach (var path in deprecatedPaths) { var warning = router.GetDeprecationWarning(path); Assert.NotNull(warning); Assert.NotEmpty(warning); } } [Fact] public void DeprecatedPathCount_ShouldMatchExpected() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var deprecatedPaths = router.GetAllDeprecatedPaths(); // Assert - Sprint 014 adds significant number of deprecated paths // Sprints 011-014 combined should have 45+ deprecated paths Assert.True(deprecatedPaths.Count >= 45, $"Expected at least 45 deprecated paths, but found {deprecatedPaths.Count}"); } #endregion #region Warning Consistency Tests [Theory] [InlineData("evidenceholds list", "evidence holds list")] [InlineData("EVIDENCEHOLDS LIST", "evidence holds list")] [InlineData("EvidenceHolds List", "evidence holds list")] public void DeprecatedPath_ShouldBeCaseInsensitive(string oldPath, string expectedNewPath) { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var resolved = router.ResolveCanonicalPath(oldPath); // Assert Assert.Equal(expectedNewPath, resolved); } [Theory] [InlineData("evidenceholds list", "evidence holds list")] [InlineData(" evidenceholds list ", "evidence holds list")] public void DeprecatedPath_ShouldHandleExtraWhitespace(string oldPath, string expectedNewPath) { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act var resolved = router.ResolveCanonicalPath(oldPath); // Assert Assert.Equal(expectedNewPath, resolved); } #endregion #region Warning Suppression Tests [Fact] public void DeprecationWarning_ShouldRespectSuppressFlag() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); // Act router.SuppressWarnings = true; var originalError = Console.Error; using var errorWriter = new StringWriter(); Console.SetError(errorWriter); try { router.EmitDeprecationWarningIfNeeded("evidenceholds list"); var output = errorWriter.ToString(); // Assert Assert.Empty(output); } finally { Console.SetError(originalError); router.SuppressWarnings = false; } } [Fact] public void DeprecationWarning_ShouldRespectEnvironmentVariable() { // Arrange var router = CommandRouter.LoadFromEmbeddedResource(); var originalValue = Environment.GetEnvironmentVariable("STELLA_SUPPRESS_DEPRECATION_WARNINGS"); try { // Act Environment.SetEnvironmentVariable("STELLA_SUPPRESS_DEPRECATION_WARNINGS", "1"); var originalError = Console.Error; using var errorWriter = new StringWriter(); Console.SetError(errorWriter); Console.SetError(errorWriter); router.EmitDeprecationWarningIfNeeded("evidenceholds list"); Console.SetError(originalError); var output = errorWriter.ToString(); // Assert Assert.Empty(output); } finally { Environment.SetEnvironmentVariable("STELLA_SUPPRESS_DEPRECATION_WARNINGS", originalValue); } } #endregion }