#region Apache License
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.IO;
#if !NETSTANDARD1_3
using System.Globalization;
#endif
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Layout.Pattern;
using log4net.Repository;
using log4net.Tests.Appender;
using log4net.Util;
using NUnit.Framework;
namespace log4net.Tests.Layout
{
///
/// Used for internal unit testing the class.
///
///
/// Used for internal unit testing the class.
///
[TestFixture]
public class PatternLayoutTest
{
#if !NETSTANDARD1_3
private CultureInfo _currentCulture;
private CultureInfo _currentUICulture;
[SetUp]
public void SetUp()
{
// set correct thread culture
_currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
_currentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
System.Threading.Thread.CurrentThread.CurrentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
}
[TearDown]
public void TearDown() {
Utils.RemovePropertyFromAllContexts();
// restore previous culture
System.Threading.Thread.CurrentThread.CurrentCulture = _currentCulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = _currentUICulture;
}
#endif
protected virtual PatternLayout NewPatternLayout() {
return new PatternLayout();
}
protected virtual PatternLayout NewPatternLayout(string pattern) {
return new PatternLayout(pattern);
}
[Test]
public void TestThreadPropertiesPattern()
{
StringAppender stringAppender = new StringAppender();
stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}");
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestThreadProperiesPattern");
log1.Info("TestMessage");
Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no thread properties value set");
stringAppender.Reset();
ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1";
log1.Info("TestMessage");
Assert.AreEqual("val1", stringAppender.GetString(), "Test thread properties value set");
stringAppender.Reset();
ThreadContext.Properties.Remove(Utils.PROPERTY_KEY);
log1.Info("TestMessage");
Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test thread properties value removed");
stringAppender.Reset();
}
#if !NETSTANDARD1_3
[Test]
public void TestStackTracePattern()
{
StringAppender stringAppender = new StringAppender();
stringAppender.Layout = NewPatternLayout("%stacktrace{2}");
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestStackTracePattern");
log1.Info("TestMessage");
StringAssert.EndsWith("PatternLayoutTest.TestStackTracePattern", stringAppender.GetString(), "stack trace value set");
stringAppender.Reset();
}
#endif
[Test]
public void TestGlobalPropertiesPattern()
{
StringAppender stringAppender = new StringAppender();
stringAppender.Layout = NewPatternLayout("%property{" + Utils.PROPERTY_KEY + "}");
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestGlobalProperiesPattern");
log1.Info("TestMessage");
Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test no global properties value set");
stringAppender.Reset();
GlobalContext.Properties[Utils.PROPERTY_KEY] = "val1";
log1.Info("TestMessage");
Assert.AreEqual("val1", stringAppender.GetString(), "Test global properties value set");
stringAppender.Reset();
GlobalContext.Properties.Remove(Utils.PROPERTY_KEY);
log1.Info("TestMessage");
Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), "Test global properties value removed");
stringAppender.Reset();
}
[Test]
public void TestAddingCustomPattern()
{
StringAppender stringAppender = new StringAppender();
PatternLayout layout = NewPatternLayout();
layout.AddConverter("TestAddingCustomPattern", typeof(TestMessagePatternConverter));
layout.ConversionPattern = "%TestAddingCustomPattern";
layout.ActivateOptions();
stringAppender.Layout = layout;
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern");
log1.Info("TestMessage");
Assert.AreEqual("TestMessage", stringAppender.GetString(), "%TestAddingCustomPattern not registered");
stringAppender.Reset();
}
[Test]
public void NamedPatternConverterWithoutPrecisionShouldReturnFullName()
{
StringAppender stringAppender = new StringAppender();
PatternLayout layout = NewPatternLayout();
layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter));
layout.ConversionPattern = "%message-as-name";
layout.ActivateOptions();
stringAppender.Layout = layout;
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern");
log1.Info("NoDots");
Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("One.Dot");
Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("Tw.o.Dots");
Assert.AreEqual("Tw.o.Dots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("TrailingDot.");
Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".LeadingDot");
Assert.AreEqual(".LeadingDot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
// empty string and other evil combinations as tests for of-by-one mistakes in index calculations
log1.Info(string.Empty);
Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".");
Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("x");
Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
}
[Test]
public void NamedPatternConverterWithPrecision1ShouldStripLeadingStuffIfPresent()
{
StringAppender stringAppender = new StringAppender();
PatternLayout layout = NewPatternLayout();
layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter));
layout.ConversionPattern = "%message-as-name{1}";
layout.ActivateOptions();
stringAppender.Layout = layout;
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern");
log1.Info("NoDots");
Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("One.Dot");
Assert.AreEqual("Dot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("Tw.o.Dots");
Assert.AreEqual("Dots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("TrailingDot.");
Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".LeadingDot");
Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
// empty string and other evil combinations as tests for of-by-one mistakes in index calculations
log1.Info(string.Empty);
Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("x");
Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".");
Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
}
[Test]
public void NamedPatternConverterWithPrecision2ShouldStripLessLeadingStuffIfPresent() {
StringAppender stringAppender = new StringAppender();
PatternLayout layout = NewPatternLayout();
layout.AddConverter("message-as-name", typeof(MessageAsNamePatternConverter));
layout.ConversionPattern = "%message-as-name{2}";
layout.ActivateOptions();
stringAppender.Layout = layout;
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestAddingCustomPattern");
log1.Info("NoDots");
Assert.AreEqual("NoDots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("One.Dot");
Assert.AreEqual("One.Dot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("Tw.o.Dots");
Assert.AreEqual("o.Dots", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("TrailingDot.");
Assert.AreEqual("TrailingDot.", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".LeadingDot");
Assert.AreEqual("LeadingDot", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
// empty string and other evil combinations as tests for of-by-one mistakes in index calculations
log1.Info(string.Empty);
Assert.AreEqual(string.Empty, stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info("x");
Assert.AreEqual("x", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
log1.Info(".");
Assert.AreEqual(".", stringAppender.GetString(), "%message-as-name not registered");
stringAppender.Reset();
}
///
/// Converter to include event message
///
private class TestMessagePatternConverter : PatternLayoutConverter
{
///
/// Convert the pattern to the rendered message
///
/// that will receive the formatted result.
/// the event being logged
/// the relevant location information
protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
loggingEvent.WriteRenderedMessage(writer);
}
}
[Test]
public void TestExceptionPattern()
{
StringAppender stringAppender = new StringAppender();
PatternLayout layout = NewPatternLayout("%exception{stacktrace}");
stringAppender.Layout = layout;
ILoggerRepository rep = LogManager.CreateRepository(Guid.NewGuid().ToString());
BasicConfigurator.Configure(rep, stringAppender);
ILog log1 = LogManager.GetLogger(rep.Name, "TestExceptionPattern");
Exception exception = new Exception("Oh no!");
log1.Info("TestMessage", exception);
Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString());
stringAppender.Reset();
}
private class MessageAsNamePatternConverter : NamedPatternConverter
{
protected override string GetFullyQualifiedName(LoggingEvent loggingEvent)
{
return loggingEvent.MessageObject.ToString();
}
}
}
}