// // Copyright (c) 2004-2024 Jaroslaw Kowalski , Kim Christensen, Julian Verdurmen // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * Neither the name of Jaroslaw Kowalski nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // using NLog.Config; namespace NLog.UnitTests.LayoutRenderers.Wrappers { using System; using System.Linq; using NLog; using NLog.Layouts; using Xunit; public class CachedTests : NLogTestBase { [Fact] public void CachedLayoutRendererWrapper() { SimpleLayout l = "${guid}"; string s1 = l.Render(LogEventInfo.CreateNullEvent()); string s2 = l.Render(LogEventInfo.CreateNullEvent()); string s3; // normally GUIDs are never the same Assert.NotEqual(s1, s2); // but when you apply ${cached}, the guid will only be generated once l = "${cached:${guid}:cached=true}"; s1 = l.Render(LogEventInfo.CreateNullEvent()); s2 = l.Render(LogEventInfo.CreateNullEvent()); Assert.Equal(s1, s2); // calling Close() on Layout Renderer will reset the cached value l.LayoutRenderers.First().Close(); s3 = l.Render(LogEventInfo.CreateNullEvent()); Assert.NotEqual(s2, s3); // unless we use clearcache=none l = "${cached:${guid}:cached=true:clearcache=none}"; s1 = l.Render(LogEventInfo.CreateNullEvent()); l.LayoutRenderers.First().Close(); s2 = l.Render(LogEventInfo.CreateNullEvent()); Assert.Equal(s1, s2); // another way to achieve the same thing is using cached=true l = "${guid:cached=true}"; s1 = l.Render(LogEventInfo.CreateNullEvent()); s2 = l.Render(LogEventInfo.CreateNullEvent()); Assert.Equal(s1, s2); // another way to achieve the same thing is using cached=true l = "${guid:cached=false}"; s1 = l.Render(LogEventInfo.CreateNullEvent()); s2 = l.Render(LogEventInfo.CreateNullEvent()); Assert.NotEqual(s1, s2); } /// /// test the cachekey /// [Fact] public void CacheKeyTest() { LogManager.Configuration = XmlLoggingConfiguration.CreateFromXmlString(@" "); LogManager.Configuration.Variables["var1"] = "a"; var logger = LogManager.GetLogger("A"); logger.Debug("msg"); var s1 = GetDebugLastMessage("debug"); logger.Debug("msg"); var s2 = GetDebugLastMessage("debug"); Assert.NotEmpty(s1); Assert.Equal(s1, s2); //change var will reset cache LogManager.Configuration.Variables["var1"] = "b"; logger.Debug("msg"); var s3 = GetDebugLastMessage("debug"); Assert.NotEmpty(s3); Assert.NotEqual(s1, s3); } [Fact] public void CachedSecondsTimeoutTest() { SimpleLayout l = "${guid:cachedSeconds=60}"; var s1 = l.Render(LogEventInfo.CreateNullEvent()); var s2 = l.Render(new LogEventInfo()); Assert.Equal(s1, s2); var s3 = l.Render(new LogEventInfo() { TimeStamp = NLog.Time.TimeSource.Current.Time.AddMinutes(2) }); Assert.NotEqual(s2, s3); } [Fact] public void CachedUntilHourChangeTest() { SimpleLayout l = "${guid:cachedUntil=HourChange}"; var timeStamp = new DateTime(2021, 2, 27, 17, 30, 0); var s1 = l.Render(new LogEventInfo() { TimeStamp = timeStamp }); var s2 = l.Render(new LogEventInfo() { TimeStamp = timeStamp.AddMinutes(29) }); Assert.Equal(s1, s2); var s3 = l.Render(new LogEventInfo() { TimeStamp = timeStamp.AddMinutes(30) }); Assert.NotEqual(s2, s3); } [Fact] public void CachedUntilDayChangeTest() { SimpleLayout l = "${guid:cachedUntil=DayChange}"; var timeStamp = new DateTime(2021, 2, 27, 17, 30, 0); var s1 = l.Render(new LogEventInfo() { TimeStamp = timeStamp }); var s2 = l.Render(new LogEventInfo() { TimeStamp = timeStamp.AddHours(6) }); Assert.Equal(s1, s2); var s3 = l.Render(new LogEventInfo() { TimeStamp = timeStamp.AddHours(6.5) }); Assert.NotEqual(s2, s3); } [Theory] [InlineData("cachedUntil=HourChange")] [InlineData("cachedUntil=DayChange")] [InlineData("cachedSeconds=3600")] [InlineData("cachedUntil=DayChange:cachedSeconds=3600")] public void CachedLastPeriodTest(string cachedOptions) { SimpleLayout l = "${guid:" + cachedOptions + "}"; var s1 = l.Render(new LogEventInfo() { TimeStamp = DateTime.MaxValue.AddMinutes(-30) }); var s2 = l.Render(new LogEventInfo() { TimeStamp = DateTime.MaxValue }); Assert.NotEmpty(s1); Assert.Equal(s1, s2); } } }