|
|
@ -21,39 +21,63 @@ |
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/ |
|
|
|
using System; |
|
|
|
using System.Collections.Concurrent; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Reflection; |
|
|
|
using System.Threading; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using NUnit.Framework; |
|
|
|
|
|
|
|
namespace iText.Test |
|
|
|
{ |
|
|
|
internal class ITextTestLoggerFactory : ILoggerFactory |
|
|
|
{ |
|
|
|
private readonly Dictionary<String, Boolean> expectedTemplates = new Dictionary<String, Boolean>(); |
|
|
|
private readonly IDictionary<int, IDictionary<string, bool>> expectedTemplates = new ConcurrentDictionary<int, IDictionary<string, bool>>(); |
|
|
|
|
|
|
|
private readonly IList<ITextTestLogEvent> logEvents = new List<ITextTestLogEvent>(); |
|
|
|
|
|
|
|
public void SetExpectedTemplates(Dictionary<String, Boolean> expectedTemplates) { |
|
|
|
this.expectedTemplates.Clear(); |
|
|
|
foreach (KeyValuePair<String, Boolean> item in expectedTemplates) |
|
|
|
private readonly IDictionary<int, IList<ITextTestLogEvent>> logEvents = new ConcurrentDictionary<int, IList<ITextTestLogEvent>>(); |
|
|
|
|
|
|
|
private static readonly int DEFAULT_THREAD_ID = 1; |
|
|
|
private static bool threadsAware = false; |
|
|
|
|
|
|
|
public ITextTestLoggerFactory() |
|
|
|
{ |
|
|
|
InitThreadAwareness(); |
|
|
|
} |
|
|
|
|
|
|
|
public void SetExpectedTemplates(Dictionary<string, bool> expectedTemplates) { |
|
|
|
var threadId = GetThreadID(); |
|
|
|
|
|
|
|
if (!this.expectedTemplates.ContainsKey(threadId)) |
|
|
|
{ |
|
|
|
this.expectedTemplates[item.Key] = item.Value; |
|
|
|
this.expectedTemplates.Add(threadId, new Dictionary<string, bool>()); |
|
|
|
} |
|
|
|
this.expectedTemplates[threadId] = expectedTemplates; |
|
|
|
} |
|
|
|
|
|
|
|
public IList<ITextTestLogEvent> GetLogEvents() |
|
|
|
{ |
|
|
|
return logEvents; |
|
|
|
var threadId = GetThreadID(); |
|
|
|
|
|
|
|
return logEvents.ContainsKey(threadId) ? logEvents[threadId] : new List<ITextTestLogEvent>(); |
|
|
|
} |
|
|
|
|
|
|
|
public void Dispose() |
|
|
|
{ |
|
|
|
expectedTemplates.Clear(); |
|
|
|
logEvents.Clear(); |
|
|
|
var threadId = GetThreadID(); |
|
|
|
if (expectedTemplates.ContainsKey(threadId)) |
|
|
|
{ |
|
|
|
expectedTemplates[threadId].Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
if (logEvents.ContainsKey(threadId)) |
|
|
|
{ |
|
|
|
logEvents[threadId].Clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public ILogger CreateLogger(string categoryName) |
|
|
|
{ |
|
|
|
|
|
|
|
return new ITextTestLogger(categoryName, this); |
|
|
|
} |
|
|
|
|
|
|
@ -64,10 +88,10 @@ namespace iText.Test |
|
|
|
throw new NotImplementedException(); |
|
|
|
} |
|
|
|
|
|
|
|
private bool IsExpectedMessage(String message) { |
|
|
|
if (message != null) { |
|
|
|
foreach (var template in expectedTemplates) { |
|
|
|
if (LogListenerHelper.EqualsMessageByTemplate(message, template.Key)) { |
|
|
|
private bool IsExpectedMessage(string message, int threadId) { |
|
|
|
if (message != null && expectedTemplates.ContainsKey(threadId)) { |
|
|
|
foreach (var template in expectedTemplates[threadId].Keys) { |
|
|
|
if (LogListenerHelper.EqualsMessageByTemplate(message, template)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -75,10 +99,10 @@ namespace iText.Test |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private bool IsExpectedMessageQuiet(String message) { |
|
|
|
if (message != null) { |
|
|
|
foreach (String template in expectedTemplates.Keys) { |
|
|
|
if (LogListenerHelper.EqualsMessageByTemplate(message, template) && expectedTemplates[template]) { |
|
|
|
private bool IsExpectedMessageQuiet(string message, int threadId) { |
|
|
|
if (message != null && expectedTemplates.ContainsKey(threadId)) { |
|
|
|
foreach (var template in expectedTemplates[threadId].Keys) { |
|
|
|
if (LogListenerHelper.EqualsMessageByTemplate(message, template) && expectedTemplates[threadId][template]) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -88,7 +112,46 @@ namespace iText.Test |
|
|
|
|
|
|
|
private void AddLogEvent(ITextTestLogEvent testLogEvent) |
|
|
|
{ |
|
|
|
logEvents.Add(testLogEvent); |
|
|
|
var threadId = GetThreadID(); |
|
|
|
|
|
|
|
if (!logEvents.ContainsKey(threadId)) |
|
|
|
{ |
|
|
|
logEvents.Add(threadId, new List<ITextTestLogEvent>()); |
|
|
|
} |
|
|
|
|
|
|
|
logEvents[threadId].Add(testLogEvent); |
|
|
|
} |
|
|
|
|
|
|
|
private static void InitThreadAwareness() |
|
|
|
{ |
|
|
|
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); |
|
|
|
foreach (var asm in loadedAssemblies) |
|
|
|
{ |
|
|
|
if (asm.IsDynamic || !asm.CodeBase.ToLower().EndsWith("tests.dll")) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var attrs = asm.GetCustomAttributes(true); |
|
|
|
int parallel = attrs.Count(t => t is ParallelizableAttribute); |
|
|
|
if (parallel > 0) |
|
|
|
{ |
|
|
|
threadsAware = true; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static int GetThreadID() |
|
|
|
{ |
|
|
|
if (threadsAware) |
|
|
|
{ |
|
|
|
return Thread.CurrentThread.ManagedThreadId; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return DEFAULT_THREAD_ID; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class ITextTestLogEvent |
|
|
@ -102,35 +165,34 @@ namespace iText.Test |
|
|
|
this.message = message; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private class ITextTestLogger : ILogger |
|
|
|
|
|
|
|
internal class ITextTestLogger : ILogger |
|
|
|
{ |
|
|
|
private readonly string categoryName; |
|
|
|
private readonly ITextTestLoggerFactory factory; |
|
|
|
private bool runInSilentMode = false; |
|
|
|
private bool runInSilentMode; |
|
|
|
|
|
|
|
private static readonly string TOKEN_ITEXT_SILENT_MODE = "ITEXT_SILENT_MODE"; |
|
|
|
private static readonly string ITEXT_LICENCING_PACKAGE = "iText.Licensing"; |
|
|
|
private static readonly string ITEXT_ACTIONS_PACKAGE = "iText.Commons.Actions.Processors"; |
|
|
|
|
|
|
|
|
|
|
|
public ITextTestLogger(string categoryName, ITextTestLoggerFactory factory) |
|
|
|
{ |
|
|
|
this.categoryName = categoryName; |
|
|
|
this.factory = factory; |
|
|
|
SetupRunInSilentMode(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) |
|
|
|
{ |
|
|
|
if (!factory.IsExpectedMessageQuiet(state.ToString())) |
|
|
|
if (!factory.IsExpectedMessageQuiet(state.ToString(), GetThreadID())) |
|
|
|
{ |
|
|
|
if (ShouldPrintMessage(categoryName)) |
|
|
|
{ |
|
|
|
Console.WriteLine( categoryName + ": " + state); |
|
|
|
} |
|
|
|
} |
|
|
|
if (logLevel >= LogLevel.Warning || factory.IsExpectedMessage(state.ToString())) |
|
|
|
if (logLevel >= LogLevel.Warning || factory.IsExpectedMessage(state.ToString(), GetThreadID())) |
|
|
|
{ |
|
|
|
factory.AddLogEvent(new ITextTestLogEvent(logLevel, state.ToString())); |
|
|
|
} |
|
|
@ -161,7 +223,7 @@ namespace iText.Test |
|
|
|
} |
|
|
|
|
|
|
|
private void SetupRunInSilentMode() { |
|
|
|
string envIsSilentModeEnabled = Environment.GetEnvironmentVariable(TOKEN_ITEXT_SILENT_MODE); |
|
|
|
var envIsSilentModeEnabled = Environment.GetEnvironmentVariable(TOKEN_ITEXT_SILENT_MODE); |
|
|
|
if (string.IsNullOrEmpty(envIsSilentModeEnabled)) { |
|
|
|
runInSilentMode = false; |
|
|
|
return; |
|
|
|