mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 09:59:48 -05:00
* Switch to the unified SMO NuGet so all binaries are strong named and signed. * use one AssemblyLoader instance for all loads * Revert "use one AssemblyLoader instance for all loads" This reverts commit 48c59ffd5c57152de281c87acdbcad7ddf7ab760. * Stop creating multiple AssemblyLoadContext objects during composition, per https://github.com/dotnet/coreclr/issues/19632 * restore high entropyva property * Improve the comment * Update SMO to 150 and fix scripting for objects with a single quote in their name. * restore newtonsoft reference
171 lines
6.8 KiB
C#
171 lines
6.8 KiB
C#
//
|
|
// Copyright (c) Microsoft. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
//
|
|
|
|
using Microsoft.SqlTools.Utility;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
|
|
{
|
|
public class TestLogger
|
|
{
|
|
private string logFilePath;
|
|
private string logMessage;
|
|
private string logContents;
|
|
private string logFileName;
|
|
private string topFrame;
|
|
|
|
public bool ShouldVerifyCallstack { get; set; } = false;
|
|
public string TestName { get => testName ?? TraceSource; set => testName = value; }
|
|
public string TraceSource { get; set; } = "sqltoolsTest";
|
|
public string LogMessage { get => logMessage ?? $"{TestName} test message"; set => logMessage = value; }
|
|
public string LogFilePath { get => logFilePath ?? Logger.GenerateLogFilePath(Path.Combine(Directory.GetCurrentDirectory(), TraceSource)); set => logFilePath = value; }
|
|
public TraceEventType EventType { get; set; } = TraceEventType.Information;
|
|
public SourceLevels TracingLevel { get; set; } = SourceLevels.Critical;
|
|
public bool DoNotUseTraceSource { get; set; } = false;
|
|
|
|
private List<Action> pendingVerifications;
|
|
private string testName;
|
|
|
|
public string CallstackMessage { get => $"Callstack=\\s*{TopFrame}"; }
|
|
|
|
public string LogFileName { get => logFileName ?? Logger.LogFileFullPath; set => logFileName = value; }
|
|
public void Initialize() =>
|
|
Logger.Initialize(TracingLevel, LogFilePath, TraceSource); // initialize the logger
|
|
public string LogContents
|
|
{
|
|
get
|
|
{
|
|
if (logContents == null)
|
|
{
|
|
Logger.Close();
|
|
Assert.True(!string.IsNullOrWhiteSpace(LogFileName));
|
|
Assert.True(LogFileName.Length > "{TraceSource}_.log".Length);
|
|
Assert.True(File.Exists(LogFileName));
|
|
logContents = File.ReadAllText(LogFileName);
|
|
}
|
|
return logContents;
|
|
}
|
|
set => logContents = value;
|
|
}
|
|
|
|
public string TopFrame { get => topFrame ?? "at System.Environment.get_StackTrace()"; set => topFrame = value; }
|
|
|
|
public List<Action> PendingVerifications
|
|
{
|
|
get
|
|
{
|
|
if (pendingVerifications == null)
|
|
{
|
|
pendingVerifications = new List<Action>();
|
|
}
|
|
return pendingVerifications;
|
|
}
|
|
set => pendingVerifications = value;
|
|
}
|
|
|
|
public void Write()
|
|
{
|
|
// write test log
|
|
if (DoNotUseTraceSource)
|
|
{
|
|
TraceSource savedTraceSource = Logger.TraceSource;
|
|
Logger.TraceSource = null;
|
|
Logger.Write(EventType, LogMessage);
|
|
Logger.TraceSource = savedTraceSource;
|
|
}
|
|
else
|
|
Logger.Write(EventType, LogMessage);
|
|
}
|
|
|
|
public void WriteWithCallstack()
|
|
{
|
|
// write test log with callstack
|
|
Logger.WriteWithCallstack(EventType, LogMessage);
|
|
ShouldVerifyCallstack = true;
|
|
}
|
|
|
|
public void Verify(bool expectLogMessage = true) => Verify(ShouldVerifyCallstack, expectLogMessage);
|
|
|
|
public void Verify(bool shouldVerifyCallstack, bool expectLogMessage = true) => Verify(EventType, LogMessage, CallstackMessage, shouldVerifyCallstack, expectLogMessage);
|
|
|
|
public void Verify(TraceEventType eventType, string message, string callstackMessage, bool shouldVerifyCallstack = false, bool expectLogMessage = true)
|
|
{
|
|
Logger.Flush();
|
|
// The Regex uses .* between the severity and the message to allow SMO to vary the content. 140 SMO has nothing there, 150 has a timestamp
|
|
if (expectLogMessage)
|
|
{
|
|
Assert.True(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $@"\b{eventType}:.*{message}", RegexOptions.Compiled));
|
|
}
|
|
else
|
|
{
|
|
Assert.False(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $@"\b{eventType}:.*{message}", RegexOptions.Compiled));
|
|
}
|
|
if (shouldVerifyCallstack)
|
|
{
|
|
VerifyCallstack(callstackMessage, expectLogMessage);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform all the pending verifications
|
|
/// </summary>
|
|
public void VerifyPending()
|
|
{
|
|
foreach (var pv in PendingVerifications)
|
|
{
|
|
pv.Invoke();
|
|
}
|
|
}
|
|
|
|
public void VerifyCallstack(bool expectLogMessage = true) => VerifyCallstack(CallstackMessage, expectLogMessage);
|
|
|
|
public void VerifyCallstack(string message, bool expectLogMessage = true)
|
|
{
|
|
if (expectLogMessage)
|
|
{
|
|
Assert.True(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $"{message}", RegexOptions.Compiled));
|
|
}
|
|
else
|
|
{
|
|
Assert.False(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $"{message}", RegexOptions.Compiled));
|
|
}
|
|
}
|
|
|
|
|
|
public static void VerifyInitialization(SourceLevels expectedTracingLevel, string expectedTraceSource, string logFilePath, bool isLogFileExpectedToExist, int? testNo = null)
|
|
{
|
|
string FailureMessagePrefix = testNo.HasValue ? $"For Test No:{testNo.Value.ToString()}," : string.Empty;
|
|
Assert.False(string.IsNullOrWhiteSpace(logFilePath), $"{FailureMessagePrefix} LogFilePath should not be null or whitespaces");
|
|
Assert.True(expectedTracingLevel == Logger.TracingLevel, $"{FailureMessagePrefix} expected Tracing Level did not match the configured value");
|
|
if (isLogFileExpectedToExist)
|
|
{
|
|
Assert.True(File.Exists(logFilePath), $"{FailureMessagePrefix} logFilePath:{logFilePath} must exist");
|
|
}
|
|
else
|
|
{
|
|
Assert.False(File.Exists(logFilePath), $"{FailureMessagePrefix} {logFilePath} must not exist");
|
|
}
|
|
Assert.True(string.Compare(expectedTraceSource, Logger.TraceSource.Name, ignoreCase: true) == 0, $"{FailureMessagePrefix} expected Trace Source Name did not match the configured value");
|
|
}
|
|
|
|
public void Cleanup() => Cleanup(Logger.LogFileFullPath);
|
|
|
|
public static void Cleanup(string logFileName)
|
|
{
|
|
if (File.Exists(logFileName))
|
|
{
|
|
Logger.Close();
|
|
File.Delete(logFileName);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|