| File: Internal\ProgressIndicator.cs | Web Access |
| Project: src\vstest\src\vstest.console\vstest.console.csproj (vstest.console) |
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Globalization; using Microsoft.VisualStudio.TestPlatform.Utilities; namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Internal; /// <summary> /// Indicates the test run progress /// </summary> internal sealed class ProgressIndicator : IProgressIndicator, IDisposable { private readonly object _syncObject = new(); private readonly ISystemTimersTimer _timer; private readonly string _testRunProgressString; private int _dotCounter; /// <summary> /// Used to output to the console /// </summary> public IOutput ConsoleOutput { get; private set; } /// <summary> /// Wrapper over the System Console class /// </summary> public IConsoleHelper ConsoleHelper { get; private set; } /// <summary> /// True is the indicator is to be displayed /// </summary> public bool IsRunning { get; private set; } public ProgressIndicator(IOutput output, IConsoleHelper consoleHelper, ISystemTimersTimer? timer = null) { _timer = timer ?? new SystemTimersTimer(1000); ConsoleOutput = output; ConsoleHelper = consoleHelper; _testRunProgressString = string.Format(CultureInfo.CurrentCulture, "{0}...", Resources.Resources.ProgressIndicatorString); } /// <inheritdoc /> public void Start() { lock (_syncObject) { _timer.Elapsed += Timer_Elapsed; _timer.Start(); // Print the string based on the previous state, that is dotCounter // This is required for smooth transition ConsoleOutput.Write(_testRunProgressString.Substring(0, _testRunProgressString.Length + _dotCounter - 2), OutputLevel.Information); IsRunning = true; } } /// <summary> /// Get the current cursor position /// Clear the console starting given position /// Reset the cursor position back /// </summary> /// <param name="startPos">the starting position</param> private void Clear(int startPos) { var currentLineCursor = ConsoleHelper.CursorTop; ConsoleHelper.SetCursorPosition(startPos, ConsoleHelper.CursorTop); ConsoleOutput.Write(new string(' ', ConsoleHelper.WindowWidth - startPos), OutputLevel.Information); ConsoleHelper.SetCursorPosition(startPos, currentLineCursor); } /// <summary> /// Sets the isRunning flag to false so that indicator is not shown. /// </summary> public void Pause() { lock (_syncObject) { IsRunning = false; Clear(0); } } /// <summary> /// Stops the indicator and clears the current line. /// </summary> public void Stop() { lock (_syncObject) { IsRunning = false; _timer?.Stop(); Clear(0); } } private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) { if (IsRunning) { // If running, prints dot every second. ConsoleOutput.Write(".", OutputLevel.Information); _dotCounter = ++_dotCounter % 3; // When counter reaches 3, that is 3 dots have been printed // Clear and start printing again if (_dotCounter == 0) { Clear(ConsoleHelper.CursorLeft - 3); } } } public void Dispose() { _timer?.Dispose(); } }