using System.Xml.Linq; namespace MeetingAssistant.Tests; // These are synthetic verifier fixtures, not execution evidence from a Windows host. public sealed class PlatformTestVerificationTests { private const string Guard = "MeetingAssistant.Tests.TestTargetCompositionTests.TestAndApplicationTargetsUseMatchingComposition"; private const string UserEnvironment = "MeetingAssistant.Tests.AzureSpeechStreamingTranscriptionProviderTests.ResolveKeyFallsBackToUserEnvironment"; private const string Glyphs = "MeetingAssistant.Tests.TaskbarIconTests.TaskbarIconGlyphsAreVisuallyCentered"; private static readonly XNamespace Trx = "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"; private static readonly string[] OutlookCases = [ "MeetingAssistant.Tests.OutlookClassicMeetingMetadataProviderTests.ExtractAgendaStopsBeforeTeamsJoinInformation", "MeetingAssistant.Tests.OutlookClassicMeetingMetadataProviderTests.NormalizeAttendeesDeduplicatesOrganizerAndRecipientEmail", "MeetingAssistant.Tests.OutlookClassicMeetingMetadataProviderTests.SubjectIndicatesCancellationRecognizesOutlookCanceledPrefixes(subject: \"Canceled: Project sync\")", "MeetingAssistant.Tests.OutlookClassicMeetingMetadataProviderTests.SubjectIndicatesCancellationRecognizesOutlookCanceledPrefixes(subject: \"Cancelled: Project sync\")", "MeetingAssistant.Tests.OutlookClassicMeetingMetadataProviderTests.SubjectIndicatesCancellationRecognizesOutlookCanceledPrefixes(subject: \"Abgesagt: Project sync\")" ]; private static readonly string[] WindowsCropCases = [ "MeetingAssistant.Tests.WindowsScreenshotImageCropperTests.WindowsCropUsesOcrPixelCoordinates", "MeetingAssistant.Tests.WindowsScreenshotImageCropperTests.WindowsCropPreservesExpectedPixelsAtNonzeroOrigin", "MeetingAssistant.Tests.WindowsScreenshotImageCropperTests.WindowsCropRejectsInvalidBounds" ]; [Fact] public void RejectsEmptyExecutionRecordsInsteadOfAcceptingSummaryCounts() { var trx = XDocument.Parse(""" """); var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", "MeetingAssistant.Tests.Example.Passes", trx)); Assert.Contains("execution records", failure.Message); } [Fact] public void DerivesCurrentTotalsFromExecutionRecords() { var (discovery, trx) = PortableFixture(); var result = PlatformTestVerification.Verify("portable", discovery, trx); Assert.Equal(3, result.Total); Assert.Equal(1, result.Passed); Assert.Equal(2, result.Skipped); Assert.Contains("Totals: 3 discovered, 3 results, 1 passed, 2 skipped, 0 failed.", result.Lines); Assert.Contains("Windows crop cases: excluded from portable target (3 Windows-only native cases).", result.Lines); } [Theory] [InlineData("Passed", "")] [InlineData("Passed", "platform-assurance: target=windows; host=linux")] [InlineData("Passed", "platform-assurance: target=portable; host=unknown")] [InlineData("NotExecuted", "platform-assurance: target=portable; host=linux")] [InlineData("Passed", "platform-assurance: target=portable; host=linux\nplatform-assurance: target=portable; host=windows")] public void RequiresMatchingPassedCompositionGuard(string outcome, string marker) { var (discovery, trx) = PortableFixture(); var guard = trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard); guard.SetAttributeValue("outcome", outcome); guard.Descendants(Trx + "StdOut").Single().Value = marker; var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); Assert.Contains("composition guard", failure.Message); } [Theory] [InlineData(UserEnvironment, "linux", "Passed", "")] [InlineData(Glyphs, "macos", "Passed", "")] [InlineData(UserEnvironment, "linux", "NotExecuted", "")] [InlineData(Glyphs, "macos", "NotExecuted", "No explanation")] [InlineData(UserEnvironment, "windows", "NotExecuted", "Requires Windows per-user environment variables.")] [InlineData(Glyphs, "windows", "NotExecuted", "Requires Windows rendering.")] public void RequiresCompatibleExecutionOrReasonedWindowsSkip(string name, string host, string outcome, string reason) { var (discovery, trx) = PortableFixture(); var guard = trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard); guard.Descendants(Trx + "StdOut").Single().Value = $"platform-assurance: target=portable; host={host}"; if (host == "windows") { foreach (var runtimeTest in trx.Descendants(Trx + "UnitTestResult").Where(record => (string?)record.Attribute("testName") != Guard)) { runtimeTest.SetAttributeValue("outcome", "Passed"); } } var record = trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == name); record.SetAttributeValue("outcome", outcome); record.Descendants(Trx + "StdOut").Single().Value = reason; var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); Assert.Contains(name, failure.Message); } [Fact] public void ReportsWindowsSkipNamesAndReasonsFromTrxErrorInfo() { var (discovery, trx) = PortableFixture(); foreach (var record in trx.Descendants(Trx + "UnitTestResult").Where(record => (string?)record.Attribute("outcome") == "NotExecuted")) { var output = record.Element(Trx + "Output")!; var reason = output.Element(Trx + "StdOut")!.Value; output.ReplaceNodes(new XElement(Trx + "ErrorInfo", new XElement(Trx + "Message", reason))); } var result = PlatformTestVerification.Verify("portable", discovery, trx); Assert.Contains($"Skipped: {UserEnvironment} — Requires Windows per-user environment variables; run on Windows.", result.Lines); Assert.Contains($"Skipped: {Glyphs} — Requires Windows System.Drawing bitmap rendering; run on Windows.", result.Lines); } [Fact] public void WindowsEvidenceNamesAllPassedOutlookAndNativeCropCases() { var (discovery, trx) = WindowsFixture(); var result = PlatformTestVerification.Verify("windows", discovery, trx); Assert.Equal(11, result.Total); Assert.Equal(11, result.Passed); Assert.Equal(0, result.Skipped); foreach (var name in OutlookCases) { Assert.Contains($"Passed: {name}", result.Lines); } foreach (var name in WindowsCropCases) { Assert.Contains($"Passed: {name}", result.Lines); } Assert.Contains("Test artifacts only; full Windows resource/PRI builds and native operational acceptance require separate evidence.", result.Lines); } [Theory] [InlineData(0, "both")] [InlineData(1, "both")] [InlineData(2, "both")] [InlineData(0, "discovery")] [InlineData(1, "discovery")] [InlineData(2, "discovery")] [InlineData(0, "execution")] [InlineData(1, "execution")] [InlineData(2, "execution")] public void RequiresDiscoveryAndExecutionOfEachNativeWindowsCropCase(int missingCase, string missingArtifact) { var (discovery, trx) = WindowsFixture(); var name = WindowsCropCases[missingCase]; if (missingArtifact is "discovery" or "both") { discovery = discovery.Replace(name, "", StringComparison.Ordinal); } if (missingArtifact is "execution" or "both") { trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == name).Remove(); var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("total", 10); counters.SetAttributeValue("executed", 10); counters.SetAttributeValue("passed", 10); } var failure = Assert.Throws(() => PlatformTestVerification.Verify("windows", discovery, trx)); Assert.Contains(name, failure.Message); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(2)] public void ReasonedWindowsCropSkipsDoNotCountAsNativeExecutionEvidence(int skippedCase) { var (discovery, trx) = WindowsFixture(); var name = WindowsCropCases[skippedCase]; var record = trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == name); record.SetAttributeValue("outcome", "NotExecuted"); record.Descendants(Trx + "StdOut").Single().Value = "Requires Windows System.Drawing bitmap rendering."; var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("executed", 10); counters.SetAttributeValue("passed", 10); var failure = Assert.Throws(() => PlatformTestVerification.Verify("windows", discovery, trx)); Assert.Contains(name, failure.Message); Assert.Contains("Passed", failure.Message); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(2)] [InlineData(3)] [InlineData(4)] public void RequiresEachExistingOutlookCase(int missingCase) { var (discovery, trx) = WindowsFixture(); var name = OutlookCases[missingCase]; discovery = discovery.Replace(name, "", StringComparison.Ordinal); trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == name).Remove(); var failure = Assert.Throws(() => PlatformTestVerification.Verify("windows", discovery, trx)); Assert.Contains(name, failure.Message); } [Theory] [InlineData("NotExecuted")] [InlineData("Failed")] public void RequiresExecutedPassedOutlookAssertions(string outcome) { var (discovery, trx) = WindowsFixture(); trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == OutlookCases[0]) .SetAttributeValue("outcome", outcome); var failure = Assert.Throws(() => PlatformTestVerification.Verify("windows", discovery, trx)); Assert.Contains(OutlookCases[0], failure.Message); } [Fact] public void PortableEvidenceRejectsOutlookCasesEvenWithWindowsRuntime() { var (discovery, trx) = WindowsFixture(); trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard) .Descendants(Trx + "StdOut").Single().Value = "platform-assurance: target=portable; host=windows"; var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); Assert.Contains("Outlook", failure.Message); } [Theory] [InlineData("linux")] [InlineData("windows")] public void PortableEvidenceRejectsWindowsCropClassRegardlessOfRuntimeHost(string host) { const string cropCase = "MeetingAssistant.Tests.WindowsScreenshotImageCropperTests.AdditionalNativeCropCase"; var (discovery, trx) = PortableFixture(); trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard) .Descendants(Trx + "StdOut").Single().Value = $"platform-assurance: target=portable; host={host}"; if (host == "windows") { foreach (var record in trx.Descendants(Trx + "UnitTestResult")) { record.SetAttributeValue("outcome", "Passed"); } } discovery += '\n' + cropCase; trx.Root!.Element(Trx + "Results")!.Add(Result(cropCase, "Passed", "")); var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("total", 4); counters.SetAttributeValue("executed", host == "windows" ? 4 : 2); counters.SetAttributeValue("passed", host == "windows" ? 4 : 2); var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); Assert.Contains("Windows crop", failure.Message); } [Theory] [InlineData("duplicate discovery")] [InlineData("duplicate execution")] [InlineData("missing execution")] [InlineData("unlisted execution")] [InlineData("failed execution")] [InlineData("unrecognized outcome")] [InlineData("empty discovery")] public void RejectsIncompleteDuplicateOrFailedArtifactSets(string corruption) { const string example = "MeetingAssistant.Tests.Example.Passes"; var (discovery, trx) = PortableFixture(); var record = Result(example, "Passed", ""); trx.Root!.Element(Trx + "Results")!.Add(record); discovery += '\n' + example; var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("total", 4); counters.SetAttributeValue("executed", 2); counters.SetAttributeValue("passed", 2); switch (corruption) { case "duplicate discovery": discovery += '\n' + example; break; case "duplicate execution": record.AddAfterSelf(new XElement(record)); break; case "missing execution": record.Remove(); break; case "unlisted execution": discovery = discovery.Replace(example, "", StringComparison.Ordinal); break; case "failed execution": record.SetAttributeValue("outcome", "Failed"); break; case "unrecognized outcome": record.SetAttributeValue("outcome", "Aborted"); break; case "empty discovery": discovery = ""; break; } Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); } [Theory] [InlineData("total", "602")] [InlineData("executed", "602")] [InlineData("passed", "602")] [InlineData("failed", "1")] [InlineData("total", null)] [InlineData("total", "invalid")] [InlineData("aborted", "1")] public void RejectsInconsistentSummaryCounters(string counter, string? value) { var (discovery, trx) = PortableFixture(); trx.Descendants(Trx + "Counters").Single().SetAttributeValue(counter, value); var failure = Assert.Throws(() => PlatformTestVerification.Verify("portable", discovery, trx)); Assert.Contains("summary", failure.Message); } [Fact] public void WindowsTargetRequiresWindowsRuntimeEvidence() { var (discovery, trx) = WindowsFixture(); trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard) .Descendants(Trx + "StdOut").Single().Value = "platform-assurance: target=windows; host=linux"; foreach (var record in trx.Descendants(Trx + "UnitTestResult") .Where(record => (string?)record.Attribute("testName") is UserEnvironment or Glyphs)) { record.SetAttributeValue("outcome", "NotExecuted"); record.Descendants(Trx + "StdOut").Single().Value = "Requires Windows runtime."; } var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("executed", 9); counters.SetAttributeValue("passed", 9); var failure = Assert.Throws(() => PlatformTestVerification.Verify("windows", discovery, trx)); Assert.Contains("Windows runtime", failure.Message); } private static (string Discovery, XDocument Results) WindowsFixture() { var (discovery, trx) = PortableFixture(); foreach (var record in trx.Descendants(Trx + "UnitTestResult")) { record.SetAttributeValue("outcome", "Passed"); record.Descendants(Trx + "StdOut").Single().Value = ""; } trx.Descendants(Trx + "UnitTestResult").Single(record => (string?)record.Attribute("testName") == Guard) .Descendants(Trx + "StdOut").Single().Value = "platform-assurance: target=windows; host=windows"; trx.Root!.Element(Trx + "Results")!.Add(OutlookCases.Select(name => Result(name, "Passed", ""))); trx.Root!.Element(Trx + "Results")!.Add(WindowsCropCases.Select(name => Result(name, "Passed", ""))); var counters = trx.Descendants(Trx + "Counters").Single(); counters.SetAttributeValue("total", 11); counters.SetAttributeValue("executed", 11); counters.SetAttributeValue("passed", 11); return (discovery + '\n' + string.Join('\n', OutlookCases) + '\n' + string.Join('\n', WindowsCropCases), trx); } private static (string Discovery, XDocument Results) PortableFixture() { var results = new[] { Result(Guard, "Passed", "platform-assurance: target=portable; host=linux"), Result(UserEnvironment, "NotExecuted", "Requires Windows per-user environment variables; run on Windows."), Result(Glyphs, "NotExecuted", "Requires Windows System.Drawing bitmap rendering; run on Windows.") }; return ("The following Tests are available:\n" + string.Join('\n', new[] { Guard, UserEnvironment, Glyphs }), new XDocument(new XElement(Trx + "TestRun", new XElement(Trx + "Results", results), new XElement(Trx + "ResultSummary", new XAttribute("outcome", "Completed"), new XElement(Trx + "Counters", new XAttribute("total", 3), new XAttribute("executed", 1), new XAttribute("passed", 1), new XAttribute("failed", 0), new XAttribute("notExecuted", 0)))))); } private static XElement Result(string name, string outcome, string output) => new(Trx + "UnitTestResult", new XAttribute("testName", name), new XAttribute("outcome", outcome), new XElement(Trx + "Output", new XElement(Trx + "StdOut", output))); }