This is an automated email from the ASF dual-hosted git repository.

davydm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git

commit dd6e40acf8e53c507cd1d22a352a53495f3c44f8
Author: Davyd McColl <[email protected]>
AuthorDate: Fri Jul 22 14:35:32 2022 +0200

    :white_check_mark: add test trying to repro LOG4NET-684, but the issue 
doesn't repro
---
 src/log4net.Tests/Context/ThreadContextTest.cs | 352 ++++++++++++++-----------
 1 file changed, 203 insertions(+), 149 deletions(-)

diff --git a/src/log4net.Tests/Context/ThreadContextTest.cs 
b/src/log4net.Tests/Context/ThreadContextTest.cs
index e489efc4..951d32d2 100644
--- a/src/log4net.Tests/Context/ThreadContextTest.cs
+++ b/src/log4net.Tests/Context/ThreadContextTest.cs
@@ -1,4 +1,5 @@
 #region Apache License
+
 //
 // Licensed to the Apache Software Foundation (ASF) under one or more 
 // contributor license agreements. See the NOTICE file distributed with
@@ -15,213 +16,266 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
+
 #endregion
 
 using System;
+using System.Collections.Generic;
 using System.Threading;
-
 using log4net.Config;
 using log4net.Layout;
 using log4net.Repository;
 using log4net.Tests.Appender;
 using log4net.Util;
-
 using NUnit.Framework;
+using static NExpect.Expectations;
+using NExpect;
 
 namespace log4net.Tests.Context
 {
-       /// <summary>
-       /// Used for internal unit testing the <see cref="ThreadContext"/> 
class.
-       /// </summary>
-       /// <remarks>
-       /// Used for internal unit testing the <see cref="ThreadContext"/> 
class.
-       /// </remarks>
-       [TestFixture]
-       public class ThreadContextTest
-       {
+    /// <summary>
+    /// Used for internal unit testing the <see cref="ThreadContext"/> class.
+    /// </summary>
+    /// <remarks>
+    /// Used for internal unit testing the <see cref="ThreadContext"/> class.
+    /// </remarks>
+    [TestFixture]
+    public class ThreadContextTest
+    {
         [TearDown]
-        public void TearDown() {
+        public void TearDown()
+        {
             Utils.RemovePropertyFromAllContexts();
         }
 
         [Test]
-               public void TestThreadPropertiesPattern()
-               {
-                       StringAppender stringAppender = new StringAppender();
-                       stringAppender.Layout = new PatternLayout("%property{" 
+  Utils.PROPERTY_KEY + "}");
+        public void TestThreadPropertiesPattern()
+        {
+            StringAppender stringAppender = new StringAppender();
+            stringAppender.Layout = new PatternLayout("%property{" + 
Utils.PROPERTY_KEY + "}");
 
-                       ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
 
-                       ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadProperiesPattern");
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadProperiesPattern");
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test no thread properties value set");
-                       stringAppender.Reset();
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test no thread properties value set");
+            stringAppender.Reset();
 
-                       ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1";
+            ThreadContext.Properties[Utils.PROPERTY_KEY] = "val1";
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual("val1", stringAppender.GetString(), 
"Test thread properties value set");
-                       stringAppender.Reset();
+            log1.Info("TestMessage");
+            Assert.AreEqual("val1", stringAppender.GetString(), "Test thread 
properties value set");
+            stringAppender.Reset();
 
-                       ThreadContext.Properties.Remove(Utils.PROPERTY_KEY);
+            ThreadContext.Properties.Remove(Utils.PROPERTY_KEY);
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread properties value removed");
-                       stringAppender.Reset();
-               }
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test thread properties value removed");
+            stringAppender.Reset();
+        }
 
-               [Test]
-               public void TestThreadStackPattern()
-               {
-                       StringAppender stringAppender = new StringAppender();
+        [Test]
+        public void TestThreadStackPattern()
+        {
+            StringAppender stringAppender = new StringAppender();
             stringAppender.Layout = new PatternLayout("%property{" + 
Utils.PROPERTY_KEY + "}");
 
-                       ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
 
-                       ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test no thread stack value set");
-                       stringAppender.Reset();
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test no thread stack value set");
+            stringAppender.Reset();
 
-                       
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
-                       {
-                               log1.Info("TestMessage");
-                               Assert.AreEqual("val1", 
stringAppender.GetString(), "Test thread stack value set");
-                               stringAppender.Reset();
-                       }
+            using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
+            {
+                log1.Info("TestMessage");
+                Assert.AreEqual("val1", stringAppender.GetString(), "Test 
thread stack value set");
+                stringAppender.Reset();
+            }
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value removed");
-                       stringAppender.Reset();
-               }
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test thread stack value removed");
+            stringAppender.Reset();
+        }
 
-               [Test]
-               public void TestThreadStackPattern2()
-               {
-                       StringAppender stringAppender = new StringAppender();
+        [Test]
+        public void TestThreadStackPattern2()
+        {
+            StringAppender stringAppender = new StringAppender();
             stringAppender.Layout = new PatternLayout("%property{" + 
Utils.PROPERTY_KEY + "}");
 
-                       ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
-
-                       ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
-
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test no thread stack value set");
-                       stringAppender.Reset();
-
-                       
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
-                       {
-                               log1.Info("TestMessage");
-                               Assert.AreEqual("val1", 
stringAppender.GetString(), "Test thread stack value set");
-                               stringAppender.Reset();
-
-                               
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2"))
-                               {
-                                       log1.Info("TestMessage");
-                                       Assert.AreEqual("val1 val2", 
stringAppender.GetString(), "Test thread stack value pushed 2nd val");
-                                       stringAppender.Reset();
-                               }
-                       }
-
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value removed");
-                       stringAppender.Reset();
-               }
-
-               [Test]
-               public void TestThreadStackPatternNullVal()
-               {
-                       StringAppender stringAppender = new StringAppender();
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
+
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
+
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test no thread stack value set");
+            stringAppender.Reset();
+
+            using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
+            {
+                log1.Info("TestMessage");
+                Assert.AreEqual("val1", stringAppender.GetString(), "Test 
thread stack value set");
+                stringAppender.Reset();
+
+                using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val2"))
+                {
+                    log1.Info("TestMessage");
+                    Assert.AreEqual("val1 val2", stringAppender.GetString(), 
"Test thread stack value pushed 2nd val");
+                    stringAppender.Reset();
+                }
+            }
+
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test thread stack value removed");
+            stringAppender.Reset();
+        }
+
+        [Test]
+        public void TestThreadStackPatternNullVal()
+        {
+            StringAppender stringAppender = new StringAppender();
             stringAppender.Layout = new PatternLayout("%property{" + 
Utils.PROPERTY_KEY + "}");
 
-                       ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
 
-                       ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test no thread stack value set");
-                       stringAppender.Reset();
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test no thread stack value set");
+            stringAppender.Reset();
 
-                       
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null))
-                       {
-                               log1.Info("TestMessage");
-                               Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value set");
-                               stringAppender.Reset();
-                       }
+            using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null))
+            {
+                log1.Info("TestMessage");
+                Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value set");
+                stringAppender.Reset();
+            }
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value removed");
-                       stringAppender.Reset();
-               }
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test thread stack value removed");
+            stringAppender.Reset();
+        }
 
-               [Test]
-               public void TestThreadStackPatternNullVal2()
-               {
-                       StringAppender stringAppender = new StringAppender();
+        [Test]
+        public void TestThreadStackPatternNullVal2()
+        {
+            StringAppender stringAppender = new StringAppender();
             stringAppender.Layout = new PatternLayout("%property{" + 
Utils.PROPERTY_KEY + "}");
 
-                       ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
+            ILoggerRepository rep = 
LogManager.CreateRepository(Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
 
-                       ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
+            ILog log1 = LogManager.GetLogger(rep.Name, 
"TestThreadStackPattern");
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test no thread stack value set");
-                       stringAppender.Reset();
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test no thread stack value set");
+            stringAppender.Reset();
 
-                       
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
-                       {
-                               log1.Info("TestMessage");
-                               Assert.AreEqual("val1", 
stringAppender.GetString(), "Test thread stack value set");
-                               stringAppender.Reset();
+            using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push("val1"))
+            {
+                log1.Info("TestMessage");
+                Assert.AreEqual("val1", stringAppender.GetString(), "Test 
thread stack value set");
+                stringAppender.Reset();
 
-                               
using(ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null))
-                               {
-                                       log1.Info("TestMessage");
-                                       Assert.AreEqual("val1 ", 
stringAppender.GetString(), "Test thread stack value pushed null");
-                                       stringAppender.Reset();
-                               }
-                       }
+                using (ThreadContext.Stacks[Utils.PROPERTY_KEY].Push(null))
+                {
+                    log1.Info("TestMessage");
+                    Assert.AreEqual("val1 ", stringAppender.GetString(), "Test 
thread stack value pushed null");
+                    stringAppender.Reset();
+                }
+            }
 
-                       log1.Info("TestMessage");
-                       Assert.AreEqual(SystemInfo.NullText, 
stringAppender.GetString(), "Test thread stack value removed");
-                       stringAppender.Reset();
-               }
+            log1.Info("TestMessage");
+            Assert.AreEqual(SystemInfo.NullText, stringAppender.GetString(), 
"Test thread stack value removed");
+            stringAppender.Reset();
+        }
 
         private static string TestBackgroundThreadContextPropertyRepository;
 
-               [Test]
-               public void TestBackgroundThreadContextProperty()
-               {
-                       StringAppender stringAppender = new StringAppender();
-                       stringAppender.Layout = new 
PatternLayout("%property{DateTimeTodayToString}");
+        [Test]
+        public void TestBackgroundThreadContextProperty()
+        {
+            StringAppender stringAppender = new StringAppender();
+            stringAppender.Layout = new 
PatternLayout("%property{DateTimeTodayToString}");
 
-            ILoggerRepository rep = 
LogManager.CreateRepository(TestBackgroundThreadContextPropertyRepository = 
"TestBackgroundThreadContextPropertyRepository" + Guid.NewGuid().ToString());
-                       BasicConfigurator.Configure(rep, stringAppender);
+            ILoggerRepository rep = 
LogManager.CreateRepository(TestBackgroundThreadContextPropertyRepository =
+                "TestBackgroundThreadContextPropertyRepository" + 
Guid.NewGuid().ToString());
+            BasicConfigurator.Configure(rep, stringAppender);
 
-                       Thread thread = new Thread(new 
ThreadStart(ExecuteBackgroundThread));
-                       thread.Start();
+            Thread thread = new Thread(new 
ThreadStart(ExecuteBackgroundThread));
+            thread.Start();
 
-                       Thread.CurrentThread.Join(2000);
-               }
+            Thread.CurrentThread.Join(2000);
+        }
 
-               private static void ExecuteBackgroundThread()
-               {
+        private static void ExecuteBackgroundThread()
+        {
             ILog log = 
LogManager.GetLogger(TestBackgroundThreadContextPropertyRepository, 
"ExecuteBackGroundThread");
-                       ThreadContext.Properties["DateTimeTodayToString"] = 
DateTime.Today.ToString();
+            ThreadContext.Properties["DateTimeTodayToString"] = 
DateTime.Today.ToString();
 
-                       log.Info("TestMessage");
+            log.Info("TestMessage");
 
-                       Repository.Hierarchy.Hierarchy 
hierarchyLoggingRepository = 
(Repository.Hierarchy.Hierarchy)log.Logger.Repository;
-                       StringAppender stringAppender = 
(StringAppender)hierarchyLoggingRepository.Root.Appenders[0];
+            Repository.Hierarchy.Hierarchy hierarchyLoggingRepository =
+                (Repository.Hierarchy.Hierarchy) log.Logger.Repository;
+            StringAppender stringAppender = (StringAppender) 
hierarchyLoggingRepository.Root.Appenders[0];
 
-                       Assert.AreEqual(DateTime.Today.ToString(), 
stringAppender.GetString());
-               }
-       }
+            Assert.AreEqual(DateTime.Today.ToString(), 
stringAppender.GetString());
+        }
+
+        [Test]
+        public void PropertiesShouldBeThreadSafe()
+        {
+            // Arrange
+            var threads = new List<Thread>();
+            var flags = new List<FlagContainer>();
+            
+            // Act
+            for (var i = 0; i < 256; i++)
+            {
+                var t = new Thread(SpinAndCheck);
+                var flag = new FlagContainer();
+                t.Start(flag);
+                flags.Add(flag);
+                threads.Add(t);
+            }
+
+            foreach (var t in threads)
+            {
+                t.Join();
+            }
+
+            // Assert
+            Expect(flags)
+                .To.Contain.All.Matched.By(o => o.Flag == false);
+        }
+
+        public class FlagContainer
+        {
+            public bool Flag { get; set; }
+        }
+
+        private void SpinAndCheck(object obj)
+        {
+            var container = obj as FlagContainer;
+            var threadid = Thread.CurrentThread.ManagedThreadId;
+            for (var i = 0; i < 100000; i++)
+            {
+                ThreadContext.Properties["threadid"] = threadid;
+                Thread.Sleep(0);
+                if ((int) ThreadContext.Properties["threadid"] != threadid)
+                {
+                    container.Flag = true;
+                    break;
+                }
+            }
+        }
+    }
 }
\ No newline at end of file

Reply via email to