File: TestUtilities\TestReporter.cs
Web Access
Project: ..\..\..\test\dotnet-watch.Tests\dotnet-watch.Tests.csproj (dotnet-watch.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.Extensions.Logging;
 
namespace Microsoft.DotNet.Watch.UnitTests
{
    internal class TestReporter(ITestOutputHelper output) : IReporter, IProcessOutputReporter
    {
        private readonly Dictionary<EventId, Action> _actions = [];
        public readonly List<string> ProcessOutput = [];
        public readonly List<(MessageSeverity severity, string text)> Messages = [];
 
        public bool IsVerbose
            => true;
 
        bool IProcessOutputReporter.PrefixProcessOutput
            => true;
 
        public event Action<OutputLine>? OnProcessOutput;
 
        void IProcessOutputReporter.ReportOutput(OutputLine line)
        {
            WriteTestOutput(line.Content);
            ProcessOutput.Add(line.Content);
 
            OnProcessOutput?.Invoke(line);
        }
 
        public SemaphoreSlim RegisterSemaphore(MessageDescriptor descriptor)
        {
            var semaphore = new SemaphoreSlim(initialCount: 0);
            RegisterAction(descriptor, () => semaphore.Release());
            return semaphore;
        }
 
        public void RegisterAction(MessageDescriptor eventId, Action action)
            => RegisterAction(eventId.Id, action);
 
        public void RegisterAction(EventId eventId, Action action)
        {
            if (_actions.TryGetValue(eventId, out var existing))
            {
                existing += action;
            }
            else
            {
                existing = action;
            }
 
            _actions[eventId] = existing;
        }
 
        public void Report(EventId id, Emoji emoji, MessageSeverity severity, string message)
        {
            if (severity != MessageSeverity.None)
            {
                Messages.Add((severity, message));
                WriteTestOutput($"{ToString(severity)} {emoji.ToDisplay()} {message}");
            }
 
            if (_actions.TryGetValue(id, out var action))
            {
                action();
            }
        }
 
        private void WriteTestOutput(string line)
        {
            try
            {
                output.WriteLine(line);
            }
            catch (InvalidOperationException)
            {
                // May happen when a test is aborted and no longer running.
            }
        }
 
        private static string ToString(MessageSeverity severity)
            => severity switch
            {
                MessageSeverity.Verbose => "verbose",
                MessageSeverity.Output => "output",
                MessageSeverity.Warning => "warning",
                MessageSeverity.Error => "error",
                _ => throw new InvalidOperationException()
            };
    }
}