This is an automated email from the ASF dual-hosted git repository.
FreeAndNil pushed a commit to branch Feature/AVSS-Fixes
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git
The following commit(s) were added to refs/heads/Feature/AVSS-Fixes by this
push:
new f4ac35ca added unit tests
f4ac35ca is described below
commit f4ac35ca95d486f36a5df6ff7cfcd51dae2a0c95
Author: Jan Friedrich <[email protected]>
AuthorDate: Mon Jun 22 00:14:51 2026 +0200
added unit tests
---
src/log4net.Tests/Appender/AppenderSkeletonTest.cs | 77 ++++++++++++++++++++++
src/log4net.Tests/Appender/FileAppenderTest.cs | 31 +++++++++
src/log4net/Appender/AppenderSkeleton.cs | 5 +-
3 files changed, 111 insertions(+), 2 deletions(-)
diff --git a/src/log4net.Tests/Appender/AppenderSkeletonTest.cs
b/src/log4net.Tests/Appender/AppenderSkeletonTest.cs
new file mode 100644
index 00000000..4792afd6
--- /dev/null
+++ b/src/log4net.Tests/Appender/AppenderSkeletonTest.cs
@@ -0,0 +1,77 @@
+#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 log4net.Filter;
+using NUnit.Framework;
+
+namespace log4net.Tests.Appender;
+
+/// <summary>Unit tests for <see cref="AppenderSkeleton"/> filter chain
management.</summary>
+[TestFixture]
+public sealed class AppenderSkeletonTest
+{
+ private CountingAppender _appender = null!;
+
+ [SetUp]
+ public void SetUp() => _appender = new CountingAppender();
+
+ [TearDown]
+ public void TearDown() => _appender.Close();
+
+ /// <summary>Verifies that <see cref="AppenderSkeleton.AddFilter"/> sets
<see cref="AppenderSkeleton.FilterHead"/> when the chain is empty.</summary>
+ [Test]
+ public void AddFilter_FirstFilter_SetsFilterHead()
+ {
+ DenyAllFilter filter = new();
+ _appender.AddFilter(filter);
+ Assert.That(_appender.FilterHead, Is.SameAs(filter));
+ }
+
+ /// <summary>Verifies that a second <see cref="AppenderSkeleton.AddFilter"/>
call appends the filter via <see cref="Filter.IFilter.Next"/>.</summary>
+ [Test]
+ public void AddFilter_SecondFilter_LinksToChain()
+ {
+ DenyAllFilter first = new();
+ DenyAllFilter second = new();
+ _appender.AddFilter(first);
+ _appender.AddFilter(second);
+ Assert.That(_appender.FilterHead, Is.SameAs(first));
+ Assert.That(_appender.FilterHead!.Next, Is.SameAs(second));
+ }
+
+ /// <summary>Verifies that <see cref="AppenderSkeleton.ClearFilters"/>
resets <see cref="AppenderSkeleton.FilterHead"/> to null.</summary>
+ [Test]
+ public void ClearFilters_ResetsFilterHead()
+ {
+ _appender.AddFilter(new DenyAllFilter());
+ _appender.ClearFilters();
+ Assert.That(_appender.FilterHead, Is.Null);
+ }
+
+ /// <summary>Verifies that filters can be added again after <see
cref="AppenderSkeleton.ClearFilters"/>.</summary>
+ [Test]
+ public void ClearFilters_AllowsAddingFiltersAgain()
+ {
+ _appender.AddFilter(new DenyAllFilter());
+ _appender.ClearFilters();
+ DenyAllFilter filter = new();
+ _appender.AddFilter(filter);
+ Assert.That(_appender.FilterHead, Is.SameAs(filter));
+ }
+}
diff --git a/src/log4net.Tests/Appender/FileAppenderTest.cs
b/src/log4net.Tests/Appender/FileAppenderTest.cs
index 9cebdcef..8c11af35 100644
--- a/src/log4net.Tests/Appender/FileAppenderTest.cs
+++ b/src/log4net.Tests/Appender/FileAppenderTest.cs
@@ -29,6 +29,8 @@
using log4net.Core;
using System.IO;
using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
namespace log4net.Tests.Appender;
@@ -151,4 +153,33 @@ public void FilenameWithGlobalContextPatternStringTest()
logs.Refresh();
Assert.That(logs.GetFiles().Any(file =>
file.Name.StartsWith("file_custom_log_issue_193")));
}
+
+ /// <summary>
+ /// Verifies that <see cref="FileAppender.InterProcessLock"/> releases the
mutex
+ /// when the underlying file stream is null.
+ /// </summary>
+ [Test]
+ public void InterProcessLock_AcquireLock_ReleasesMutexWhenStreamIsNull()
+ {
+ FileAppender appender = new() { File = "log4net_ipl_test" };
+ FileAppender.InterProcessLock lockingModel = new() { CurrentAppender =
appender };
+ lockingModel.ActivateOptions();
+ // null byte is illegal in paths on all platforms; OpenFile catches the
exception and _stream stays null
+ const string invalidPath = "/tmp/invalid\0/test.log";
+ lockingModel.OpenFile(invalidPath, false, Encoding.UTF8);
+ try
+ {
+ Stream? stream = lockingModel.AcquireLock();
+ Assert.That(stream, Is.Null);
+
+ // if the mutex was released, a second thread can acquire the lock
without blocking
+ Task task = Task.Run(lockingModel.AcquireLock);
+ Assert.That(task.Wait(TimeSpan.FromSeconds(2)), Is.True,
+ "Mutex was not released by AcquireLock when stream is null");
+ }
+ finally
+ {
+ lockingModel.OnClose();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/log4net/Appender/AppenderSkeleton.cs
b/src/log4net/Appender/AppenderSkeleton.cs
index adf34128..fb0987b1 100644
--- a/src/log4net/Appender/AppenderSkeleton.cs
+++ b/src/log4net/Appender/AppenderSkeleton.cs
@@ -119,6 +119,7 @@ public virtual IErrorHandler ErrorHandler
{
lock (LockObj)
{
+ // ReSharper disable once
ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (value is null)
{
// We do not throw exception here since the cause is probably a
@@ -262,7 +263,7 @@ public void Close()
public void DoAppend(LoggingEvent loggingEvent)
{
// This lock is absolutely critical for correct formatting
- // of the message in a multi-threaded environment. Without
+ // of the message in a multithreaded environment. Without
// this, the message may be broken up into elements from
// multiple thread contexts (like get the wrong thread ID).
@@ -346,7 +347,7 @@ public void DoAppend(LoggingEvent[] loggingEvents)
loggingEvents.EnsureNotNull();
// This lock is absolutely critical for correct formatting
- // of the message in a multi-threaded environment. Without
+ // of the message in a multithreaded environment. Without
// this, the message may be broken up into elements from
// multiple thread contexts (like get the wrong thread ID).
lock (LockObj)